197 lines
6.6 KiB
Svelte
197 lines
6.6 KiB
Svelte
<script lang="ts">
|
|
import { onMount } from "svelte";
|
|
import { supabase } from "$lib/supabaseClient";
|
|
|
|
type StatKey =
|
|
| "purchase_orders"
|
|
| "issues"
|
|
| "villas"
|
|
| "inventories"
|
|
| "projects"
|
|
| "vendors";
|
|
|
|
let stats: Record<StatKey, number> = {
|
|
purchase_orders: 0,
|
|
issues: 0,
|
|
villas: 0,
|
|
inventories: 0,
|
|
projects: 0,
|
|
vendors: 0,
|
|
};
|
|
|
|
const items: {
|
|
label: string;
|
|
key: StatKey;
|
|
color: string;
|
|
icon: string;
|
|
}[] = [
|
|
{
|
|
label: "Total Issue",
|
|
key: "issues",
|
|
color: "text-red-600",
|
|
icon: "exclamation-triangle",
|
|
},
|
|
{
|
|
label: "Total Project",
|
|
key: "projects",
|
|
color: "text-purple-600",
|
|
icon: "folder",
|
|
},
|
|
{
|
|
label: "Total PO",
|
|
key: "purchase_orders",
|
|
color: "text-blue-600",
|
|
icon: "document",
|
|
},
|
|
{
|
|
label: "Total Villa",
|
|
key: "villas",
|
|
color: "text-green-600",
|
|
icon: "home",
|
|
},
|
|
{
|
|
label: "Total Inventories",
|
|
key: "inventories",
|
|
color: "text-yellow-600",
|
|
icon: "cube",
|
|
},
|
|
{
|
|
label: "Total Vendor",
|
|
key: "vendors",
|
|
color: "text-orange-600",
|
|
icon: "building-storefront",
|
|
},
|
|
];
|
|
|
|
onMount(async () => {
|
|
const fetchCount = async (table: string) => {
|
|
const { count } = await supabase
|
|
.from(table)
|
|
.select("*", { count: "exact", head: true });
|
|
return count || 0;
|
|
};
|
|
|
|
for (const key of Object.keys(stats) as StatKey[]) {
|
|
stats[key] = await fetchCount(key);
|
|
}
|
|
|
|
console.log("Dashboard data fetched successfully");
|
|
});
|
|
</script>
|
|
|
|
<!-- You can extract SVGs from https://heroicons.com or install them via a package for better maintainability -->
|
|
|
|
<div class="max-w-6xl mx-auto p-6">
|
|
<h1 class="text-3xl font-bold mb-6 text-gray-800">Dashboard</h1>
|
|
<div
|
|
class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-5 gap-6"
|
|
>
|
|
{#each items as item}
|
|
<div
|
|
class="bg-white p-6 rounded-xl shadow text-center flex flex-col items-center"
|
|
>
|
|
<!-- ICON -->
|
|
{#if item.icon === "exclamation-triangle"}
|
|
<svg
|
|
class="w-8 h-8 mb-2 text-red-500"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
viewBox="0 0 24 24"
|
|
>
|
|
<path
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
stroke-width="2"
|
|
d="M12 9v2m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
|
|
/>
|
|
</svg>
|
|
{:else if item.icon === "folder"}
|
|
<svg
|
|
class="w-8 h-8 mb-2 text-purple-500"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
viewBox="0 0 24 24"
|
|
>
|
|
<path
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
stroke-width="2"
|
|
d="M3 7h4l2 3h10a1 1 0 011 1v6a2 2 0 01-2 2H5a2 2 0 01-2-2V7z"
|
|
/>
|
|
</svg>
|
|
{:else if item.icon === "document"}
|
|
<svg
|
|
class="w-8 h-8 mb-2 text-blue-500"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
viewBox="0 0 24 24"
|
|
>
|
|
<path
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
stroke-width="2"
|
|
d="M8 16h8M8 12h8m-6-8h4a2 2 0 012 2v12a2 2 0 01-2 2h-4a2 2 0 01-2-2V6a2 2 0 012-2z"
|
|
/>
|
|
</svg>
|
|
{:else if item.icon === "home"}
|
|
<svg
|
|
class="w-8 h-8 mb-2 text-green-500"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
viewBox="0 0 24 24"
|
|
>
|
|
<path
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
stroke-width="2"
|
|
d="M3 12l2-2m0 0l7-7 7 7m-9 2v6m0 0H5a2 2 0 01-2-2v-4a2 2 0 012-2h3m4 6h4a2 2 0 002-2v-4a2 2 0 00-2-2h-3"
|
|
/>
|
|
</svg>
|
|
{:else if item.icon === "cube"}
|
|
<svg
|
|
class="w-8 h-8 mb-2 text-yellow-500"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
viewBox="0 0 24 24"
|
|
>
|
|
<path
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
stroke-width="2"
|
|
d="M20 7l-8-4-8 4v10l8 4 8-4V7z"
|
|
/>
|
|
<path
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
stroke-width="2"
|
|
d="M12 3v18"
|
|
/>
|
|
</svg>
|
|
{:else if item.icon === "building-storefront"}
|
|
<svg
|
|
class="w-8 h-8 mb-2 text-orange-500"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
viewBox="0 0 24 24"
|
|
>
|
|
<path
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
stroke-width="2"
|
|
d="M4 4h16v4H4V4zm0 4v12h16V8m-2 4h-4v4h4v-4z"
|
|
/>
|
|
</svg>
|
|
{/if}
|
|
|
|
<!-- LABEL & VALUE -->
|
|
<h2 class="text-lg font-semibold text-gray-700 mb-1">
|
|
{item.label}
|
|
</h2>
|
|
<p class={`text-2xl font-bold ${item.color}`}>
|
|
{stats[item.key]}
|
|
</p>
|
|
</div>
|
|
{/each}
|
|
</div>
|
|
</div>
|