diff --git a/frontend/package/components/ResponsiveShipmentList/ResponsiveShipmentList.tsx b/frontend/package/components/ResponsiveShipmentList/ResponsiveShipmentList.tsx new file mode 100644 index 00000000..71b5af7f --- /dev/null +++ b/frontend/package/components/ResponsiveShipmentList/ResponsiveShipmentList.tsx @@ -0,0 +1,56 @@ +'use client'; + +import type { Shipment } from '@/types/shipment.types'; + +interface Props { + shipments: Shipment[]; + onViewDetails?: (id: string) => void; +} + +export function ResponsiveShipmentList({ shipments, onViewDetails }: Props) { + if (shipments.length === 0) { + return

No shipments found.

; + } + + return ( + <> + {/* Desktop table */} +
+ + + + {['ID', 'Origin', 'Destination', 'Status', 'Weight'].map((h) => ( + + ))} + + + + {shipments.map((s) => ( + onViewDetails?.(s.id)}> + + + + + + + ))} + +
{h}
{s.id.slice(0, 8)}{s.origin}{s.destination}{s.status}{s.weight} kg
+
+ + {/* Mobile cards */} +
+ {shipments.map((s) => ( +
onViewDetails?.(s.id)}> +

{s.id.slice(0, 8)}

+

{s.origin} → {s.destination}

+
+ {s.status} + {s.weight} kg +
+
+ ))} +
+ + ); +} diff --git a/frontend/package/components/ResponsiveShipmentList/index.ts b/frontend/package/components/ResponsiveShipmentList/index.ts new file mode 100644 index 00000000..8a2b0457 --- /dev/null +++ b/frontend/package/components/ResponsiveShipmentList/index.ts @@ -0,0 +1 @@ +export { ResponsiveShipmentList } from './ResponsiveShipmentList'; diff --git a/frontend/package/components/Skeletons/Skeletons.tsx b/frontend/package/components/Skeletons/Skeletons.tsx new file mode 100644 index 00000000..07a91699 --- /dev/null +++ b/frontend/package/components/Skeletons/Skeletons.tsx @@ -0,0 +1,64 @@ +const base = 'animate-pulse rounded bg-gray-200'; + +export function SkeletonText({ className = '' }: { className?: string }) { + return
; +} + +export function SkeletonBox({ className = '' }: { className?: string }) { + return
; +} + +export function SkeletonAvatar({ size = 40 }: { size?: number }) { + return
; +} + +export function SkeletonCard() { + return ( +
+
+ +
+ + +
+
+
+ + + +
+
+ ); +} + +export function SkeletonTable({ rows = 5, cols = 4 }: { rows?: number; cols?: number }) { + return ( +
+
+ {Array.from({ length: cols }).map((_, i) => ( + + ))} +
+ {Array.from({ length: rows }).map((_, r) => ( +
+ {Array.from({ length: cols }).map((_, c) => ( + + ))} +
+ ))} +
+ ); +} + +export function SkeletonShipmentCard() { + return ( +
+ + +
+ + +
+
+ ); +} diff --git a/frontend/package/components/Skeletons/index.ts b/frontend/package/components/Skeletons/index.ts new file mode 100644 index 00000000..c9dd7c35 --- /dev/null +++ b/frontend/package/components/Skeletons/index.ts @@ -0,0 +1 @@ +export { SkeletonText, SkeletonBox, SkeletonAvatar, SkeletonCard, SkeletonTable, SkeletonShipmentCard } from './Skeletons';