233 lines
6.8 KiB
JavaScript
233 lines
6.8 KiB
JavaScript
import React from "react";
|
|
|
|
|
|
const SkeletonLine = ({ height = 20, width = "100%", className = "" }) => (
|
|
<div
|
|
className={`skeleton mb-2 ${className}`}
|
|
style={{
|
|
height,
|
|
width,
|
|
}}
|
|
></div>
|
|
);
|
|
|
|
|
|
const ExpenseSkeleton = () => {
|
|
return (
|
|
<div className="container p-3">
|
|
<div className="d-flex justify-content-center">
|
|
<SkeletonLine height={20} width="200px" />
|
|
</div>
|
|
|
|
{[...Array(5)].map((_, idx) => (
|
|
<div className="row my-2" key={idx}>
|
|
<div className="col-md-6">
|
|
<SkeletonLine />
|
|
</div>
|
|
<div className="col-md-6">
|
|
<SkeletonLine />
|
|
</div>
|
|
</div>
|
|
))}
|
|
|
|
<div className="row my-2">
|
|
<div className="col-md-12">
|
|
<SkeletonLine height={60} />
|
|
</div>
|
|
</div>
|
|
|
|
<div className="row my-2">
|
|
<div className="col-md-12">
|
|
<SkeletonLine height={120} />
|
|
</div>
|
|
</div>
|
|
|
|
<div className="d-flex justify-content-center gap-2 mt-3">
|
|
<SkeletonLine height={35} width="100px" />
|
|
<SkeletonLine height={35} width="100px" />
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default ExpenseSkeleton;
|
|
|
|
|
|
|
|
|
|
export const ExpenseDetailsSkeleton = () => {
|
|
return (
|
|
<div className="container px-3">
|
|
<div className="row mb-3">
|
|
<div className="d-flex justify-content-center mb-3">
|
|
<SkeletonLine height={20} width="180px" className="mb-2" />
|
|
</div>
|
|
|
|
{[...Array(3)].map((_, i) => (
|
|
<div className="col-12 col-md-4 mb-3" key={`row-1-${i}`}>
|
|
<SkeletonLine height={14} className="mb-1" />
|
|
<SkeletonLine />
|
|
</div>
|
|
))}
|
|
|
|
{[...Array(6)].map((_, i) => (
|
|
<div className="col-12 col-md-4 mb-3" key={`row-2-${i}`}>
|
|
<SkeletonLine height={14} className="mb-1" />
|
|
<SkeletonLine />
|
|
</div>
|
|
))}
|
|
|
|
|
|
|
|
<div className="col-12 my-2">
|
|
<SkeletonLine height={14} width="100px" className="mb-2" />
|
|
{[...Array(2)].map((_, i) => (
|
|
<div
|
|
className="list-group-item d-flex align-items-center mb-2"
|
|
key={i}
|
|
>
|
|
<div
|
|
className="rounded me-2"
|
|
style={{
|
|
height: "50px",
|
|
width: "80px",
|
|
backgroundColor: "#dcdcdc",
|
|
borderRadius: "4px",
|
|
}}
|
|
/>
|
|
<div className="w-100">
|
|
<SkeletonLine height={14} width="60%" className="mb-1" />
|
|
<SkeletonLine height={14} width="20%" />
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
|
|
<hr className="divider my-1" />
|
|
|
|
<div className="col-12 mb-3">
|
|
<SkeletonLine height={14} width="80px" className="mb-1" />
|
|
<SkeletonLine height={60} className="mb-2" />
|
|
<div className="d-flex gap-2 flex-wrap">
|
|
{[...Array(2)].map((_, i) => (
|
|
<SkeletonLine
|
|
key={i}
|
|
height={30}
|
|
width="100px"
|
|
className="rounded"
|
|
/>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
const SkeletonCell = ({ width = "100%", height = 20, className = "", style = {} }) => (
|
|
<div
|
|
className={`skeleton ${className}`}
|
|
style={{
|
|
width,
|
|
height,
|
|
borderRadius: 4,
|
|
...style,
|
|
}}
|
|
/>
|
|
);
|
|
|
|
export const ExpenseTableSkeleton = ({ groups = 3, rowsPerGroup = 3 }) => {
|
|
return (
|
|
<table
|
|
className="card-body table border-top dataTable no-footer dtr-column text-nowrap"
|
|
aria-describedby="DataTables_Table_0_info"
|
|
id="horizontal-example"
|
|
>
|
|
<thead>
|
|
<tr>
|
|
<th colSpan={2}>
|
|
<div className="text-start ms-6">Date Time</div>
|
|
</th>
|
|
<th className="d-none d-sm-table-cell">
|
|
<div className="text-start ms-5">Expense Type</div>
|
|
</th>
|
|
<th className="d-none d-sm-table-cell">
|
|
<div className="text-start ms-5">Payment Mode</div>
|
|
</th>
|
|
<th className="d-none d-sm-table-cell">Paid By</th>
|
|
<th className="d-none d-md-table-cell">Amount</th>
|
|
<th>Status</th>
|
|
<th>Action</th>
|
|
</tr>
|
|
</thead>
|
|
|
|
<tbody>
|
|
{[...Array(groups)].map((_, groupIdx) => (
|
|
<React.Fragment key={`group-${groupIdx}`}>
|
|
{/* Fake Date Group Header Row */}
|
|
<tr className="bg-light">
|
|
<td colSpan={8}>
|
|
<SkeletonCell width="150px" height={20} />
|
|
</td>
|
|
</tr>
|
|
|
|
{/* Rows under this group */}
|
|
{[...Array(rowsPerGroup)].map((__, rowIdx) => (
|
|
<tr key={`row-${groupIdx}-${rowIdx}`} className={rowIdx % 2 === 0 ? "odd" : "even"}>
|
|
{/* Date Time colSpan=2 */}
|
|
<td colSpan={2} className="sorting_1">
|
|
<div className="d-flex justify-content-start align-items-center user-name ms-6">
|
|
<SkeletonCell width="120px" height={18} />
|
|
</div>
|
|
</td>
|
|
|
|
{/* Expense Type */}
|
|
<td className="text-start d-none d-sm-table-cell ms-5">
|
|
<SkeletonCell width="90px" height={16} />
|
|
</td>
|
|
|
|
{/* Payment Mode */}
|
|
<td className="text-start d-none d-sm-table-cell ms-5">
|
|
<SkeletonCell width="90px" height={16} />
|
|
</td>
|
|
|
|
{/* Paid By (Avatar + name) */}
|
|
<td className="text-start d-none d-sm-table-cell ms-5">
|
|
<div className="d-flex align-items-center gap-2">
|
|
<SkeletonCell width="30px" height={30} className="rounded-circle" />
|
|
<SkeletonCell width="80px" height={16} />
|
|
</div>
|
|
</td>
|
|
|
|
{/* Amount */}
|
|
<td className="d-none d-md-table-cell text-end">
|
|
<SkeletonCell width="60px" height={16} />
|
|
</td>
|
|
|
|
{/* Status */}
|
|
<td>
|
|
<SkeletonCell width="80px" height={22} className="rounded" />
|
|
</td>
|
|
|
|
{/* Action */}
|
|
<td>
|
|
<div className="d-flex justify-content-center align-items-center gap-2">
|
|
{[...Array(3)].map((__, i) => (
|
|
<SkeletonCell
|
|
key={i}
|
|
width={20}
|
|
height={20}
|
|
className="rounded"
|
|
style={{ display: "inline-block" }}
|
|
/>
|
|
))}
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
))}
|
|
</React.Fragment>
|
|
))}
|
|
</tbody>
|
|
</table>
|
|
);
|
|
};
|