Files
ERP_Distribution/distribution_fe/components/dashboard/widget-container.tsx
T
Kalana B. Thilakarathna 29f181d5e1 feat(dashboard): implement customizable dashboard with widget support
- 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.
2026-08-29 16:51:25 +05:30

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>
)
}