Some checks failed
Build Frontend / build (push) Failing after 7s
Replaces imports from 'components/ui' with 'components/common' across the app and dashboard pages, and updates model and API imports to use new paths under 'lib'. Removes redundant authentication checks from several dashboard pages. Adds new dashboard components and utility files, and reorganizes hooks and services into the 'lib' directory for improved structure.
189 lines
8.4 KiB
TypeScript
189 lines
8.4 KiB
TypeScript
import React, { useState, useEffect } from "react";
|
|
import { Skeleton } from "@/components/common/skeleton";
|
|
import {
|
|
Table,
|
|
TableBody,
|
|
TableCell,
|
|
TableHead,
|
|
TableHeader,
|
|
TableRow,
|
|
} from "@/components/common/table";
|
|
import { Button } from "@/components/common/button";
|
|
import { Edit, Trash, Truck, PackageX } from "lucide-react";
|
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/common/card";
|
|
import { motion, AnimatePresence } from "framer-motion";
|
|
import { ShippingMethod } from "@/lib/types";
|
|
|
|
interface ShippingTableProps {
|
|
shippingMethods: ShippingMethod[];
|
|
loading: boolean;
|
|
onEditShipping: (method: ShippingMethod) => void;
|
|
onDeleteShipping: (_id: string) => void;
|
|
}
|
|
|
|
export const ShippingTable: React.FC<ShippingTableProps> = ({
|
|
shippingMethods,
|
|
loading,
|
|
onEditShipping,
|
|
onDeleteShipping,
|
|
}) => {
|
|
// Browser detection
|
|
const [isFirefox, setIsFirefox] = useState(false);
|
|
|
|
useEffect(() => {
|
|
const ua = navigator.userAgent.toLowerCase();
|
|
setIsFirefox(ua.includes("firefox") && !ua.includes("chrome"));
|
|
}, []);
|
|
|
|
return (
|
|
<Card className="border-border/40 bg-background/50 backdrop-blur-sm shadow-sm overflow-hidden">
|
|
<CardHeader className="py-4 px-6 border-b border-border/50 bg-muted/30">
|
|
<CardTitle className="text-lg font-medium flex items-center gap-2">
|
|
<Truck className="h-5 w-5 text-primary" />
|
|
Available Methods
|
|
</CardTitle>
|
|
</CardHeader>
|
|
<CardContent className="p-0">
|
|
<div className="overflow-auto">
|
|
<Table>
|
|
<TableHeader className="bg-muted/50 sticky top-0 z-10">
|
|
<TableRow className="hover:bg-transparent border-border/50">
|
|
<TableHead className="w-[60%] pl-6">Method Name</TableHead>
|
|
<TableHead className="text-center">Price</TableHead>
|
|
<TableHead className="text-right pr-6">Actions</TableHead>
|
|
</TableRow>
|
|
</TableHeader>
|
|
<TableBody>
|
|
{isFirefox ? (
|
|
loading ? (
|
|
<TableRow>
|
|
<TableCell colSpan={3} className="h-24 text-center">
|
|
<div className="flex items-center justify-center gap-2 text-muted-foreground">
|
|
<Skeleton className="h-4 w-4 rounded-full" />
|
|
Loading methods...
|
|
</div>
|
|
</TableCell>
|
|
</TableRow>
|
|
) : shippingMethods.length > 0 ? (
|
|
shippingMethods.map((method, index) => (
|
|
<motion.tr
|
|
key={method._id}
|
|
initial={{ opacity: 0, y: 10 }}
|
|
animate={{ opacity: 1, y: 0 }}
|
|
transition={{ duration: 0.2, delay: index * 0.05 }}
|
|
className="group hover:bg-muted/40 border-b border-border/50 transition-colors"
|
|
>
|
|
<TableCell className="font-medium pl-6">
|
|
<div className="flex items-center gap-3">
|
|
<div className="h-8 w-8 rounded bg-primary/10 flex items-center justify-center">
|
|
<Truck className="h-4 w-4 text-primary" />
|
|
</div>
|
|
{method.name}
|
|
</div>
|
|
</TableCell>
|
|
<TableCell className="text-center font-mono">£{method.price}</TableCell>
|
|
<TableCell className="text-right pr-6">
|
|
<div className="flex justify-end gap-1">
|
|
<Button
|
|
size="icon"
|
|
variant="ghost"
|
|
className="h-8 w-8 text-muted-foreground hover:text-primary hover:bg-primary/10 transition-colors"
|
|
onClick={() => onEditShipping(method)}
|
|
>
|
|
<Edit className="h-4 w-4" />
|
|
</Button>
|
|
<Button
|
|
size="icon"
|
|
variant="ghost"
|
|
className="h-8 w-8 text-muted-foreground hover:text-destructive hover:bg-destructive/10 transition-colors"
|
|
onClick={() => onDeleteShipping(method._id ?? "")}
|
|
>
|
|
<Trash className="h-4 w-4" />
|
|
</Button>
|
|
</div>
|
|
</TableCell>
|
|
</motion.tr>
|
|
))
|
|
) : (
|
|
<TableRow>
|
|
<TableCell colSpan={3} className="h-32 text-center text-muted-foreground">
|
|
<div className="flex flex-col items-center justify-center gap-2">
|
|
<PackageX className="h-8 w-8 opacity-20" />
|
|
<p>No shipping methods found</p>
|
|
</div>
|
|
</TableCell>
|
|
</TableRow>
|
|
)
|
|
) : (
|
|
<AnimatePresence mode="popLayout">
|
|
{loading ? (
|
|
<TableRow>
|
|
<TableCell colSpan={3} className="h-24 text-center">
|
|
<div className="flex items-center justify-center gap-2 text-muted-foreground">
|
|
<Skeleton className="h-4 w-4 rounded-full" />
|
|
Loading methods...
|
|
</div>
|
|
</TableCell>
|
|
</TableRow>
|
|
) : shippingMethods.length > 0 ? (
|
|
shippingMethods.map((method, index) => (
|
|
<motion.tr
|
|
key={method._id}
|
|
initial={{ opacity: 0, y: 10 }}
|
|
animate={{ opacity: 1, y: 0 }}
|
|
exit={{ opacity: 0 }}
|
|
transition={{ duration: 0.2, delay: index * 0.05 }}
|
|
className="group hover:bg-muted/40 border-b border-border/50 transition-colors"
|
|
>
|
|
<TableCell className="font-medium pl-6">
|
|
<div className="flex items-center gap-3">
|
|
<div className="h-8 w-8 rounded bg-primary/10 flex items-center justify-center">
|
|
<Truck className="h-4 w-4 text-primary" />
|
|
</div>
|
|
{method.name}
|
|
</div>
|
|
</TableCell>
|
|
<TableCell className="text-center font-mono">£{method.price}</TableCell>
|
|
<TableCell className="text-right pr-6">
|
|
<div className="flex justify-end gap-1">
|
|
<Button
|
|
size="icon"
|
|
variant="ghost"
|
|
className="h-8 w-8 text-muted-foreground hover:text-primary hover:bg-primary/10 transition-colors"
|
|
onClick={() => onEditShipping(method)}
|
|
>
|
|
<Edit className="h-4 w-4" />
|
|
</Button>
|
|
<Button
|
|
size="icon"
|
|
variant="ghost"
|
|
className="h-8 w-8 text-muted-foreground hover:text-destructive hover:bg-destructive/10 transition-colors"
|
|
onClick={() => onDeleteShipping(method._id ?? "")}
|
|
>
|
|
<Trash className="h-4 w-4" />
|
|
</Button>
|
|
</div>
|
|
</TableCell>
|
|
</motion.tr>
|
|
))
|
|
) : (
|
|
<TableRow>
|
|
<TableCell colSpan={3} className="h-32 text-center text-muted-foreground">
|
|
<div className="flex flex-col items-center justify-center gap-2">
|
|
<PackageX className="h-8 w-8 opacity-20" />
|
|
<p>No shipping methods found</p>
|
|
</div>
|
|
</TableCell>
|
|
</TableRow>
|
|
)}
|
|
</AnimatePresence>
|
|
)}
|
|
</TableBody>
|
|
</Table>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
);
|
|
};
|
|
|