Files
ember-market-frontend/components/tables/product-table.tsx
NotII 130ecac208 Add Chromebook compatibility fixes and optimizations
Implemented comprehensive Chromebook-specific fixes including viewport adjustments, enhanced touch and keyboard detection, improved scrolling and keyboard navigation hooks, and extensive CSS optimizations for better usability. Updated chat and dashboard interfaces for larger touch targets, better focus management, and responsive layouts. Added documentation in docs/CHROMEBOOK-FIXES.md and new hooks for Chromebook scroll and keyboard handling.
2025-10-26 18:29:23 +00:00

140 lines
5.8 KiB
TypeScript

import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import { Edit, Trash, AlertTriangle, CheckCircle, AlertCircle, Calculator } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Product } from "@/models/products";
import { Badge } from "@/components/ui/badge";
import { Switch } from "@/components/ui/switch";
interface ProductTableProps {
products: Product[];
loading: boolean;
onEdit: (product: Product) => void;
onDelete: (productId: string) => void;
onToggleEnabled: (productId: string, enabled: boolean) => void;
onProfitAnalysis?: (productId: string, productName: string) => void;
getCategoryNameById: (categoryId: string) => string;
}
const ProductTable = ({
products,
loading,
onEdit,
onDelete,
onToggleEnabled,
onProfitAnalysis,
getCategoryNameById
}: ProductTableProps) => {
const sortedProducts = [...products].sort((a, b) => {
const categoryNameA = getCategoryNameById(a.category);
const categoryNameB = getCategoryNameById(b.category);
return categoryNameA.localeCompare(categoryNameB);
});
const getStockIcon = (product: Product) => {
if (!product.stockTracking) return null;
if (product.stockStatus === 'out_of_stock') {
return <AlertTriangle className="h-4 w-4 text-red-500" />;
} else if (product.stockStatus === 'low_stock') {
return <AlertCircle className="h-4 w-4 text-amber-500" />;
} else {
return <CheckCircle className="h-4 w-4 text-green-500" />;
}
};
return (
<div className="rounded-lg border dark:border-zinc-700 shadow-sm overflow-hidden">
<Table className="relative">
<TableHeader className="bg-gray-50 dark:bg-zinc-800/50">
<TableRow className="hover:bg-transparent">
<TableHead className="w-[200px]">Product</TableHead>
<TableHead className="hidden sm:table-cell text-center">Category</TableHead>
<TableHead className="hidden md:table-cell text-center">Unit</TableHead>
<TableHead className="text-center">Stock</TableHead>
<TableHead className="hidden lg:table-cell text-center">Enabled</TableHead>
<TableHead className="text-right">Actions</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{loading ? (
Array.from({ length: 1 }).map((_, index) => (
<TableRow key={index}>
<TableCell>Loading...</TableCell>
<TableCell>Loading...</TableCell>
<TableCell>Loading...</TableCell>
<TableCell>Loading...</TableCell>
<TableCell>Loading...</TableCell>
<TableCell>Loading...</TableCell>
</TableRow>
))
) : sortedProducts.length > 0 ? (
sortedProducts.map((product) => (
<TableRow key={product._id} className="transition-colors hover:bg-gray-50 dark:hover:bg-zinc-800/70">
<TableCell>
<div className="font-medium truncate max-w-[180px]">{product.name}</div>
<div className="hidden sm:block text-sm text-muted-foreground mt-1">
{getCategoryNameById(product.category)}
</div>
</TableCell>
<TableCell className="hidden sm:table-cell text-center">{getCategoryNameById(product.category)}</TableCell>
<TableCell className="hidden md:table-cell text-center">{product.unitType}</TableCell>
<TableCell className="text-center">
{product.stockTracking ? (
<div className="flex items-center justify-center gap-1">
{getStockIcon(product)}
<span className="text-sm">
{product.currentStock !== undefined ? product.currentStock : 0} {product.unitType}
</span>
</div>
) : (
<Badge variant="outline" className="text-xs">Not Tracked</Badge>
)}
</TableCell>
<TableCell className="hidden lg:table-cell text-center">
<Switch
checked={product.enabled !== false}
onCheckedChange={(checked) => onToggleEnabled(product._id as string, checked)}
/>
</TableCell>
<TableCell className="text-right flex justify-end space-x-1">
{onProfitAnalysis && (
<Button
variant="ghost"
size="sm"
onClick={() => onProfitAnalysis(product._id as string, product.name)}
className="text-green-600 hover:text-green-700 hover:bg-green-50 dark:hover:bg-green-950/20"
title="Profit Analysis"
>
<Calculator className="h-4 w-4" />
</Button>
)}
<Button variant="ghost" size="sm" onClick={() => onEdit(product)}>
<Edit className="h-4 w-4" />
</Button>
<Button
variant="ghost"
size="sm"
onClick={() => onDelete(product._id as string)}
className="text-red-500 hover:text-red-600 hover:bg-red-50 dark:hover:bg-red-950/20"
>
<Trash className="h-4 w-4" />
</Button>
</TableCell>
</TableRow>
))
) : (
<TableRow>
<TableCell colSpan={6} className="h-24 text-center">
No products found.
</TableCell>
</TableRow>
)}
</TableBody>
</Table>
</div>
);
};
export default ProductTable;