447 lines
13 KiB
Plaintext
447 lines
13 KiB
Plaintext
---
|
|
import ComponentLayout from "../layouts/ComponentLayout.astro";
|
|
import Table from "../components/Table.astro";
|
|
|
|
export const columns = [
|
|
{ key: "id", label: "ID", sortable: true, searchable: true },
|
|
{ key: "name", label: "Name", searchable: true, sortable: true },
|
|
{ key: "email", label: "Email", searchable: true, sortable: true },
|
|
{ key: "role", label: "Role", sortable: true },
|
|
{ key: "status", label: "Status", sortable: true },
|
|
{ key: "created_at", label: "Created At", sortable: true },
|
|
{ key: "actions", label: "Actions" },
|
|
];
|
|
|
|
const data = [
|
|
{
|
|
id: 1,
|
|
name: "Ajay Ghanwat",
|
|
email: "ajay.gh@example.com",
|
|
role: "Admin",
|
|
status: "Active",
|
|
created_at: "2025-10-10 09:32",
|
|
avatar: "https://i.pravatar.cc/40?img=1",
|
|
},
|
|
{
|
|
id: 2,
|
|
name: "Rahul Sharma",
|
|
email: "rahul.sharma@example.com",
|
|
role: "Member",
|
|
status: "Pending",
|
|
created_at: "2025-10-15 11:42",
|
|
avatar: "https://i.pravatar.cc/40?img=2",
|
|
},
|
|
{
|
|
id: 3,
|
|
name: "Sophia Patel",
|
|
email: "sophia.patel@example.com",
|
|
role: "Manager",
|
|
status: "Active",
|
|
created_at: "2025-10-11 15:20",
|
|
avatar: "https://i.pravatar.cc/40?img=3",
|
|
},
|
|
{
|
|
id: 4,
|
|
name: "Liam Brown",
|
|
email: "liam.brown@example.com",
|
|
role: "Member",
|
|
status: "Suspended",
|
|
created_at: "2025-10-12 08:45",
|
|
avatar: "https://i.pravatar.cc/40?img=4",
|
|
},
|
|
{
|
|
id: 5,
|
|
name: "Olivia Smith",
|
|
email: "olivia.smith@example.com",
|
|
role: "Admin",
|
|
status: "Active",
|
|
created_at: "2025-10-09 18:12",
|
|
avatar: "https://i.pravatar.cc/40?img=5",
|
|
},
|
|
{
|
|
id: 6,
|
|
name: "Noah Wilson",
|
|
email: "noah.wilson@example.com",
|
|
role: "Member",
|
|
status: "Pending",
|
|
created_at: "2025-10-13 10:18",
|
|
avatar: "https://i.pravatar.cc/40?img=6",
|
|
},
|
|
{
|
|
id: 7,
|
|
name: "Emma Johnson",
|
|
email: "emma.johnson@example.com",
|
|
role: "Member",
|
|
status: "Active",
|
|
created_at: "2025-10-14 13:55",
|
|
avatar: "https://i.pravatar.cc/40?img=7",
|
|
},
|
|
{
|
|
id: 8,
|
|
name: "William Lee",
|
|
email: "william.lee@example.com",
|
|
role: "Manager",
|
|
status: "Inactive",
|
|
created_at: "2025-10-12 17:44",
|
|
avatar: "https://i.pravatar.cc/40?img=8",
|
|
},
|
|
{
|
|
id: 9,
|
|
name: "Isabella Taylor",
|
|
email: "isabella.taylor@example.com",
|
|
role: "Member",
|
|
status: "Active",
|
|
created_at: "2025-10-10 07:31",
|
|
avatar: "https://i.pravatar.cc/40?img=9",
|
|
},
|
|
{
|
|
id: 10,
|
|
name: "Ethan Martinez",
|
|
email: "ethan.martinez@example.com",
|
|
role: "Admin",
|
|
status: "Suspended",
|
|
created_at: "2025-10-08 19:22",
|
|
avatar: "https://i.pravatar.cc/40?img=10",
|
|
},
|
|
{
|
|
id: 11,
|
|
name: "Mia Thompson",
|
|
email: "mia.thompson@example.com",
|
|
role: "Member",
|
|
status: "Active",
|
|
created_at: "2025-10-09 09:45",
|
|
avatar: "https://i.pravatar.cc/40?img=11",
|
|
},
|
|
{
|
|
id: 12,
|
|
name: "Alexander Davis",
|
|
email: "alex.davis@example.com",
|
|
role: "Manager",
|
|
status: "Pending",
|
|
created_at: "2025-10-15 14:10",
|
|
avatar: "https://i.pravatar.cc/40?img=12",
|
|
},
|
|
{
|
|
id: 13,
|
|
name: "Charlotte Moore",
|
|
email: "charlotte.moore@example.com",
|
|
role: "Member",
|
|
status: "Active",
|
|
created_at: "2025-10-14 10:01",
|
|
avatar: "https://i.pravatar.cc/40?img=13",
|
|
},
|
|
{
|
|
id: 14,
|
|
name: "Benjamin Anderson",
|
|
email: "benjamin.anderson@example.com",
|
|
role: "Member",
|
|
status: "Suspended",
|
|
created_at: "2025-10-08 11:32",
|
|
avatar: "https://i.pravatar.cc/40?img=14",
|
|
},
|
|
{
|
|
id: 15,
|
|
name: "Amelia Harris",
|
|
email: "amelia.harris@example.com",
|
|
role: "Manager",
|
|
status: "Active",
|
|
created_at: "2025-10-13 08:50",
|
|
avatar: "https://i.pravatar.cc/40?img=15",
|
|
},
|
|
{
|
|
id: 16,
|
|
name: "Lucas White",
|
|
email: "lucas.white@example.com",
|
|
role: "Member",
|
|
status: "Active",
|
|
created_at: "2025-10-10 17:10",
|
|
avatar: "https://i.pravatar.cc/40?img=16",
|
|
},
|
|
{
|
|
id: 17,
|
|
name: "Harper Lewis",
|
|
email: "harper.lewis@example.com",
|
|
role: "Member",
|
|
status: "Pending",
|
|
created_at: "2025-10-14 09:00",
|
|
avatar: "https://i.pravatar.cc/40?img=17",
|
|
},
|
|
{
|
|
id: 18,
|
|
name: "Evelyn Hall",
|
|
email: "evelyn.hall@example.com",
|
|
role: "Manager",
|
|
status: "Active",
|
|
created_at: "2025-10-11 16:42",
|
|
avatar: "https://i.pravatar.cc/40?img=18",
|
|
},
|
|
{
|
|
id: 19,
|
|
name: "Henry Allen",
|
|
email: "henry.allen@example.com",
|
|
role: "Member",
|
|
status: "Inactive",
|
|
created_at: "2025-10-09 13:25",
|
|
avatar: "https://i.pravatar.cc/40?img=19",
|
|
},
|
|
{
|
|
id: 20,
|
|
name: "Ava Scott",
|
|
email: "ava.scott@example.com",
|
|
role: "Admin",
|
|
status: "Active",
|
|
created_at: "2025-10-15 15:33",
|
|
avatar: "https://i.pravatar.cc/40?img=20",
|
|
},
|
|
{
|
|
id: 21,
|
|
name: "Michael Young",
|
|
email: "michael.young@example.com",
|
|
role: "Member",
|
|
status: "Pending",
|
|
created_at: "2025-10-13 10:20",
|
|
avatar: "https://i.pravatar.cc/40?img=21",
|
|
},
|
|
{
|
|
id: 22,
|
|
name: "Ella King",
|
|
email: "ella.king@example.com",
|
|
role: "Manager",
|
|
status: "Active",
|
|
created_at: "2025-10-14 08:45",
|
|
avatar: "https://i.pravatar.cc/40?img=22",
|
|
},
|
|
{
|
|
id: 23,
|
|
name: "Daniel Clark",
|
|
email: "daniel.clark@example.com",
|
|
role: "Member",
|
|
status: "Active",
|
|
created_at: "2025-10-12 12:05",
|
|
avatar: "https://i.pravatar.cc/40?img=23",
|
|
},
|
|
{
|
|
id: 24,
|
|
name: "Luna Wright",
|
|
email: "luna.wright@example.com",
|
|
role: "Member",
|
|
status: "Pending",
|
|
created_at: "2025-10-15 11:18",
|
|
avatar: "https://i.pravatar.cc/40?img=24",
|
|
},
|
|
{
|
|
id: 25,
|
|
name: "Jack Turner",
|
|
email: "jack.turner@example.com",
|
|
role: "Admin",
|
|
status: "Active",
|
|
created_at: "2025-10-13 09:50",
|
|
avatar: "https://i.pravatar.cc/40?img=25",
|
|
},
|
|
];
|
|
|
|
const studentData = [
|
|
{ id: 1, name: "Alice", age: 24, role: "Engineer" },
|
|
{ id: 2, name: "Bob", age: 29, role: "Designer" },
|
|
{ id: 3, name: "Carol", age: 35, role: "Manager" },
|
|
];
|
|
|
|
const studentColumns = [
|
|
{ key: "name", label: "Name", sortable: true },
|
|
{ key: "age", label: "Age", sortable: true, align: "right" },
|
|
{ key: "role", label: "Role" },
|
|
];
|
|
---
|
|
|
|
<ComponentLayout>
|
|
<div class="wr:p-4">
|
|
<Table
|
|
columns={columns}
|
|
data={data}
|
|
columnsRendererKey="columnsRenderer"
|
|
hideHeader={true}
|
|
/>
|
|
|
|
<br />
|
|
|
|
<Table
|
|
columns={columns}
|
|
fetchData="fetchData"
|
|
columnsRendererKey="columnsRenderer"
|
|
/>
|
|
|
|
<br />
|
|
|
|
<Table
|
|
data={studentData}
|
|
columns={studentColumns}
|
|
search
|
|
pagignations
|
|
classInfos="classNames"
|
|
tableClassNames="wr:rounded-2xl wr:border-2 wr:border-red-500"
|
|
rowClick="checkDetails"
|
|
/>
|
|
</div>
|
|
</ComponentLayout>
|
|
|
|
<script>
|
|
document.addEventListener("DOMContentLoaded", () => {
|
|
const buttons = document.querySelectorAll(
|
|
"button[id^='view-'], button[id^='edit-'], button[id^='delete-']",
|
|
);
|
|
|
|
buttons.forEach((button) => {
|
|
const id = button.getAttribute("data-id");
|
|
|
|
if (button.id.startsWith("view-")) {
|
|
button.addEventListener("click", () => {
|
|
console.log(`👁️ View user ${id}`);
|
|
});
|
|
}
|
|
|
|
if (button.id.startsWith("edit-")) {
|
|
button.addEventListener("click", () => {
|
|
console.log(`✏️ Edit user ${id}`);
|
|
});
|
|
}
|
|
|
|
if (button.id.startsWith("delete-")) {
|
|
button.addEventListener("click", () => {
|
|
if (
|
|
confirm(`Are you sure you want to delete user ${id}?`)
|
|
) {
|
|
console.log(`🗑️ Deleted user ${id}`);
|
|
}
|
|
});
|
|
}
|
|
});
|
|
});
|
|
|
|
window.columnsRenderer = {
|
|
name: (v: any, row: any) => `
|
|
<div class="wr:flex wr:items-center wr:gap-2">
|
|
<img src="${row.avatar}" alt="${v}" class="wr:w-8 wr:h-8 wr:rounded-full" />
|
|
<span class="wr:font-medium">${v}</span>
|
|
</div>
|
|
`,
|
|
|
|
role: (v: string) => `
|
|
<span class="wr:rounded-full wr:px-2 wr:py-1 wr:text-xs ${
|
|
v === "Admin"
|
|
? "wr:bg-indigo-100 wr:text-indigo-700"
|
|
: v === "Owner"
|
|
? "wr:bg-yellow-100 wr:text-yellow-700"
|
|
: "wr:bg-gray-100 wr:text-gray-600"
|
|
}">${v}</span>
|
|
`,
|
|
|
|
status: (v: string) => `
|
|
<span class="wr:flex wr:items-center wr:gap-1 wr:font-medium">
|
|
<span class="wr:w-2 wr:h-2 wr:rounded-full ${
|
|
v === "Active"
|
|
? "wr:bg-green-500"
|
|
: v === "Inactive"
|
|
? "wr:bg-red-500"
|
|
: "wr:bg-yellow-500"
|
|
}"></span>
|
|
${v}
|
|
</span>
|
|
`,
|
|
|
|
actions: (v: any, row: any) => `
|
|
<div class="wr:flex wr:gap-2 wr:justify-end">
|
|
<button id="view-${row.id}" data-id="${row.id}" class="wr:px-2 wr:py-1 wr:bg-blue-500 wr:text-white wr:rounded wr:hover:bg-blue-600">View</button>
|
|
<button id="edit-${row.id}" data-id="${row.id}" class="wr:px-2 wr:py-1 wr:bg-amber-500 wr:text-white wr:rounded wr:hover:bg-amber-600">Edit</button>
|
|
<button id="delete-${row.id}" data-id="${row.id}" class="wr:px-2 wr:py-1 wr:bg-red-500 wr:text-white wr:rounded wr:hover:bg-red-600">Delete</button>
|
|
</div>
|
|
`,
|
|
};
|
|
|
|
window.fetchData = ({
|
|
page,
|
|
pageSize,
|
|
sortKey,
|
|
sortOrder,
|
|
search,
|
|
}: {
|
|
page: number;
|
|
pageSize: number;
|
|
sortKey?: string | null;
|
|
sortOrder?: "asc" | "desc";
|
|
search?: string;
|
|
}) => {
|
|
// 🧪 Generate 100 fake users
|
|
const demoData = Array.from({ length: 100 }).map((_, i) => ({
|
|
id: i + 1,
|
|
name: `User ${i + 1}`,
|
|
avatar: `https://i.pravatar.cc/40?img=${i + 1}`,
|
|
email: `user${i + 1}@example.com`,
|
|
role: ["Admin", "Manager", "Member"][i % 3],
|
|
status: ["Active", "Pending", "Suspended"][i % 3],
|
|
created_at: new Date(
|
|
2025,
|
|
0,
|
|
1 + (i % 28),
|
|
12,
|
|
i % 60,
|
|
).toLocaleString(),
|
|
}));
|
|
|
|
// 🔍 Searching
|
|
let filtered = demoData;
|
|
if (search && search.trim() !== "") {
|
|
const lower = search.toLowerCase();
|
|
filtered = demoData.filter((row) =>
|
|
Object.values(row).some((val) =>
|
|
String(val).toLowerCase().includes(lower),
|
|
),
|
|
);
|
|
}
|
|
|
|
// 🧭 Sorting
|
|
if (sortKey) {
|
|
filtered.sort((a, b) => {
|
|
const aVal = String(a[sortKey as keyof typeof a]);
|
|
const bVal = String(b[sortKey as keyof typeof b]);
|
|
if (aVal < bVal) return sortOrder === "asc" ? -1 : 1;
|
|
if (aVal > bVal) return sortOrder === "asc" ? 1 : -1;
|
|
return 0;
|
|
});
|
|
}
|
|
|
|
// 📄 Pagination
|
|
const total = filtered.length;
|
|
const start = (page - 1) * pageSize;
|
|
const end = start + pageSize;
|
|
const pageData = filtered.slice(start, end);
|
|
|
|
// ✅ Return object data, not HTML
|
|
return {
|
|
data: pageData,
|
|
total,
|
|
};
|
|
};
|
|
|
|
window.classNames = {
|
|
row: (_row: any, idx: number) => ({
|
|
"wr:!bg-gray-50 wr:!text-black": _row.role === "Engineer",
|
|
}),
|
|
|
|
column: (col: any) =>
|
|
col.key === "age"
|
|
? "wr:text-right wr:font-bold wr:bg-yellow-100 wr:text-black"
|
|
: "",
|
|
|
|
cell: ({ value, col }: { value: any; col: any }) =>
|
|
typeof value === "number" && col.key === "age" && value > 30
|
|
? "wr:text-green-600"
|
|
: "",
|
|
};
|
|
|
|
window.checkDetails = (row: any) => {
|
|
alert(
|
|
`Student Details:\n\nName: ${row.name}\nAge: ${row.age}\nRole: ${row.role}`,
|
|
);
|
|
};
|
|
</script>
|