diff --git a/app/blocks/dashboard/dashboard-skeleton.tsx b/app/blocks/dashboard/dashboard-skeleton.tsx new file mode 100644 index 0000000..6d8661f --- /dev/null +++ b/app/blocks/dashboard/dashboard-skeleton.tsx @@ -0,0 +1,34 @@ +import { Skeleton } from "~/blocks/__global/skeleton"; + +export function DashboardSkeleton() { + return ( +
+ + {/* Stats cards row — 4 cards */} +
+ {Array.from({ length: 4 }).map((_, i) => ( +
+ +
+ ))} +
+ + {/* Cash flow chart */} + + + {/* 3 charts row */} +
+ + + +
+ + {/* Top selling items table */} + + + {/* Recent sales */} + + +
+ ); +} \ No newline at end of file diff --git a/app/blocks/inventory-management/inventory-table-skeleton.tsx b/app/blocks/inventory-management/inventory-table-skeleton.tsx new file mode 100644 index 0000000..28a58f5 --- /dev/null +++ b/app/blocks/inventory-management/inventory-table-skeleton.tsx @@ -0,0 +1,41 @@ +import { Skeleton } from "~/blocks/__global/skeleton"; +import styles from "./inventory-table.module.css"; + +export function InventoryTableSkeleton() { + return ( +
+
+ + + + + + + + + + + + + + + + {Array.from({ length: 8 }).map((_, i) => ( + + + + + + + + + + + + ))} + +
ItemSKUSizeBuy PriceMarket ValueP/LStatusActions
+
+
+ ); +} \ No newline at end of file diff --git a/app/blocks/sales-log/sales-log-skeleton.tsx b/app/blocks/sales-log/sales-log-skeleton.tsx new file mode 100644 index 0000000..18ac19a --- /dev/null +++ b/app/blocks/sales-log/sales-log-skeleton.tsx @@ -0,0 +1,35 @@ +import { Skeleton } from "~/blocks/__global/skeleton"; +import styles from "./sales-table.module.css"; + +export function SalesTableSkeleton() { + return ( +
+
+ ß + + + + + + + + + + + + {Array.from({ length: 6 }).map((_, i) => ( + + + + + + + + + ))} + +
ItemMarketplaceSale PriceDateMarginProfit
+
+
+ ); +} \ No newline at end of file diff --git a/app/routes/dashboard.tsx b/app/routes/dashboard.tsx index b72d4f6..0de1da9 100644 --- a/app/routes/dashboard.tsx +++ b/app/routes/dashboard.tsx @@ -1,4 +1,5 @@ -import { useLoaderData } from "react-router"; +import { Suspense } from "react"; +import { useLoaderData, Await } from "react-router"; import type { Route } from "./+types/dashboard"; import { getSupabaseServerClient } from "~/utils/supabase.server"; import { PrismaClient, Prisma } from "@prisma/client"; @@ -11,7 +12,6 @@ import { SalesByMarketplacePie } from "~/blocks/dashboard/sales-by-marketplace-p import { TopSellingItemsTable } from "~/blocks/dashboard/top-selling-items-table"; import { RecentSales } from "~/blocks/dashboard/recent-sales"; import { ExpenseCategoriesChart } from "~/blocks/dashboard/expense-categories-chart"; - import { AIInsightsPanel } from "~/blocks/dashboard/ai-insights-panel"; import { CACHE_PRIVATE_NO_STORE } from "~/utils/cache-headers"; @@ -30,7 +30,7 @@ export async function loader({ request }: Route.LoaderArgs) { } = await supabase.auth.getUser(); if (!user) { - return { inventoryStats: null, salesData: [], expensesData: [] }; + return { dashboardData: Promise.resolve({ inventoryStats: null, salesData: [], expensesData: [] }) }; } const url = new URL(request.url); @@ -129,7 +129,8 @@ export async function loader({ request }: Route.LoaderArgs) { } export default function DashboardPage() { - const { inventoryStats, salesData, expensesData } = useLoaderData(); + const { dashboardData } = useLoaderData(); + return (
@@ -152,4 +153,4 @@ export default function DashboardPage() {
); -} +} \ No newline at end of file diff --git a/app/routes/inventory-management.tsx b/app/routes/inventory-management.tsx index 0a1e94e..119551a 100644 --- a/app/routes/inventory-management.tsx +++ b/app/routes/inventory-management.tsx @@ -7,6 +7,7 @@ import { PrismaClient } from "@prisma/client"; import styles from "./inventory-management.module.css"; import { InventoryHeader } from "~/blocks/inventory-management/inventory-header"; import { InventoryTable } from "~/blocks/inventory-management/inventory-table"; +import { InventoryTableSkeleton } from "~/blocks/inventory-management/inventory-table-skeleton"; import { BulkActionsBar } from "~/blocks/inventory-management/bulk-actions-bar"; import { AddItemModal } from "~/blocks/inventory-management/add-item-modal"; import { ImportExcelModal } from "~/blocks/inventory-management/import-excel-modal"; @@ -87,15 +88,10 @@ export async function action({ request }: Route.ActionArgs) { const brand = formData.get("brand") as string; const size = formData.get("size") as string; const purchasePrice = Number(formData.get("purchasePrice")); - await prisma.inventoryItem.create({ data: { userId: user.id, - sku, - name, - brand, - size, - purchasePrice, + sku, name, brand, size, purchasePrice, purchaseDate: new Date(), condition: "DEADSTOCK", status: "IN_STOCK", @@ -201,4 +197,4 @@ export default function InventoryManagementPage() { {showImport && setShowImport(false)} />} ); -} +} \ No newline at end of file diff --git a/app/routes/sales-log.tsx b/app/routes/sales-log.tsx index 6f8d74c..22b5d16 100644 --- a/app/routes/sales-log.tsx +++ b/app/routes/sales-log.tsx @@ -1,5 +1,5 @@ -import { useState, useEffect } from "react"; -import { useLoaderData, useActionData } from "react-router"; +import { Suspense, useState, useEffect } from "react"; +import { useLoaderData, useActionData, Await } from "react-router"; import type { Route } from "./+types/sales-log"; import { toast } from "sonner"; import { getSupabaseServerClient } from "~/utils/supabase.server"; @@ -8,6 +8,7 @@ import styles from "./sales-log.module.css"; import { SalesHeader } from "~/blocks/sales-log/sales-header"; import { SalesSummaryCards } from "~/blocks/sales-log/sales-summary-cards"; import { SalesTable } from "~/blocks/sales-log/sales-table"; +import { SalesTableSkeleton } from "~/blocks/sales-log/sales-log-skeleton"; import { LogSaleModal } from "~/blocks/sales-log/log-sale-modal"; import { Pagination } from "~/blocks/__global/pagination"; import { CACHE_PRIVATE_NO_STORE } from "~/utils/cache-headers"; @@ -144,4 +145,4 @@ export default function SalesLogPage() { {showLogSale && setShowLogSale(false)} />} ); -} +} \ No newline at end of file