29f181d5e1
- Added `react-grid-layout` for drag-and-drop functionality. - Created `DashboardCanvas` component to manage layout and widget interactions. - Introduced `WidgetContainer` and `WidgetPicker` components for widget management. - Implemented various widgets: Active Rides, Today Sales, Pending Purchase Orders, Stock Alerts, Recent Orders, and Loading Sheets. - Integrated API calls for fetching and saving dashboard preferences. - Defined default layouts for different user roles. - Created a card component for consistent widget styling.
56 lines
2.0 KiB
TypeScript
56 lines
2.0 KiB
TypeScript
'use client'
|
|
|
|
import { WIDGET_REGISTRY } from '@/lib/widgets/registry'
|
|
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
|
|
import { Button } from '@/components/ui/button'
|
|
import { HugeiconsIcon } from '@hugeicons/react'
|
|
import { Cancel01Icon, DragDropVerticalIcon } from '@hugeicons/core-free-icons'
|
|
import { cn } from '@/lib/utils'
|
|
|
|
interface WidgetContainerProps {
|
|
widgetType: string
|
|
editMode: boolean
|
|
onRemove: () => void
|
|
}
|
|
|
|
export function WidgetContainer({ widgetType, editMode, onRemove }: WidgetContainerProps) {
|
|
const def = WIDGET_REGISTRY[widgetType]
|
|
const Component = def?.component
|
|
|
|
return (
|
|
<Card className={cn('flex h-full flex-col overflow-hidden transition-shadow', editMode && 'ring-1 ring-border')}>
|
|
<CardHeader className="flex-row items-center justify-between gap-2 pb-2 pt-3">
|
|
<div className="flex min-w-0 items-center gap-2">
|
|
{editMode && (
|
|
<span
|
|
className="drag-handle shrink-0 cursor-grab touch-none text-muted-foreground active:cursor-grabbing"
|
|
aria-hidden="true"
|
|
>
|
|
<HugeiconsIcon icon={DragDropVerticalIcon} size={14} strokeWidth={2} />
|
|
</span>
|
|
)}
|
|
<CardTitle className="truncate">{def?.label ?? widgetType}</CardTitle>
|
|
</div>
|
|
{editMode && (
|
|
<Button
|
|
variant="ghost"
|
|
size="icon-sm"
|
|
className="shrink-0 text-muted-foreground hover:text-destructive"
|
|
onClick={onRemove}
|
|
aria-label={`Remove ${def?.label ?? widgetType} widget`}
|
|
>
|
|
<HugeiconsIcon icon={Cancel01Icon} size={14} strokeWidth={2} />
|
|
</Button>
|
|
)}
|
|
</CardHeader>
|
|
<CardContent className="flex-1 overflow-hidden pt-0">
|
|
{Component ? (
|
|
<Component />
|
|
) : (
|
|
<p className="text-sm text-muted-foreground">Unknown widget type: {widgetType}</p>
|
|
)}
|
|
</CardContent>
|
|
</Card>
|
|
)
|
|
}
|