@burdenoff/microfe-kadaikodi 2026.704.3 → 2026.704.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/kadaikodi/KadaikodiRoutes.js +34 -26
- package/dist/kadaikodi/KadaikodiRoutes.js.map +1 -1
- package/dist/kadaikodi/components/viz/AllocationBar.js +68 -0
- package/dist/kadaikodi/components/viz/AllocationBar.js.map +1 -0
- package/dist/kadaikodi/components/viz/AreaChart.js +102 -0
- package/dist/kadaikodi/components/viz/AreaChart.js.map +1 -0
- package/dist/kadaikodi/components/viz/AvatarStack.js +36 -0
- package/dist/kadaikodi/components/viz/AvatarStack.js.map +1 -0
- package/dist/kadaikodi/components/viz/BarChart.js +83 -0
- package/dist/kadaikodi/components/viz/BarChart.js.map +1 -0
- package/dist/kadaikodi/components/viz/CertificateCard.js +4 -0
- package/dist/kadaikodi/components/viz/DonutChart.js +109 -0
- package/dist/kadaikodi/components/viz/DonutChart.js.map +1 -0
- package/dist/kadaikodi/components/viz/HBarFunnel.js +54 -0
- package/dist/kadaikodi/components/viz/HBarFunnel.js.map +1 -0
- package/dist/kadaikodi/components/viz/Heatmap.js +3 -0
- package/dist/kadaikodi/components/viz/KanbanBoard.js +50 -0
- package/dist/kadaikodi/components/viz/KanbanBoard.js.map +1 -0
- package/dist/kadaikodi/components/viz/LineChart.js +4 -0
- package/dist/kadaikodi/components/viz/OrgTree.js +2 -0
- package/dist/kadaikodi/components/viz/PathSteps.js +3 -0
- package/dist/kadaikodi/components/viz/ProgressRing.js +68 -0
- package/dist/kadaikodi/components/viz/ProgressRing.js.map +1 -0
- package/dist/kadaikodi/components/viz/RatingStars.js +51 -0
- package/dist/kadaikodi/components/viz/RatingStars.js.map +1 -0
- package/dist/kadaikodi/components/viz/SegmentedTabs.js +69 -0
- package/dist/kadaikodi/components/viz/SegmentedTabs.js.map +1 -0
- package/dist/kadaikodi/components/viz/SkillBar.js +3 -0
- package/dist/kadaikodi/components/viz/Sparkline.js +74 -0
- package/dist/kadaikodi/components/viz/Sparkline.js.map +1 -0
- package/dist/kadaikodi/components/viz/StatCard.js +60 -0
- package/dist/kadaikodi/components/viz/StatCard.js.map +1 -0
- package/dist/kadaikodi/components/viz/StepProgress.js +64 -0
- package/dist/kadaikodi/components/viz/StepProgress.js.map +1 -0
- package/dist/kadaikodi/components/viz/Timeline.js +66 -0
- package/dist/kadaikodi/components/viz/Timeline.js.map +1 -0
- package/dist/kadaikodi/components/viz/index.js +23 -0
- package/dist/kadaikodi/components/viz/lib/Avatar.js +30 -0
- package/dist/kadaikodi/components/viz/lib/Avatar.js.map +1 -0
- package/dist/kadaikodi/components/viz/lib/CartesianFrame.js +119 -0
- package/dist/kadaikodi/components/viz/lib/CartesianFrame.js.map +1 -0
- package/dist/kadaikodi/components/viz/lib/ResponsiveSvg.js +35 -0
- package/dist/kadaikodi/components/viz/lib/ResponsiveSvg.js.map +1 -0
- package/dist/kadaikodi/components/viz/lib/format.js +21 -0
- package/dist/kadaikodi/components/viz/lib/format.js.map +1 -0
- package/dist/kadaikodi/components/viz/lib/geometry.js +61 -0
- package/dist/kadaikodi/components/viz/lib/geometry.js.map +1 -0
- package/dist/kadaikodi/components/viz/lib/hooks.js +39 -0
- package/dist/kadaikodi/components/viz/lib/hooks.js.map +1 -0
- package/dist/kadaikodi/components/viz/lib/palette.js +27 -0
- package/dist/kadaikodi/components/viz/lib/palette.js.map +1 -0
- package/dist/kadaikodi/hooks/useKadaikodiApi.js +84 -6
- package/dist/kadaikodi/hooks/useKadaikodiApi.js.map +1 -1
- package/dist/kadaikodi/pages/HomePage.js +373 -631
- package/dist/kadaikodi/pages/HomePage.js.map +1 -1
- package/dist/kadaikodi/pages/admin/AdminAnalyticsPage.js +304 -169
- package/dist/kadaikodi/pages/admin/AdminAnalyticsPage.js.map +1 -1
- package/dist/kadaikodi/pages/admin/AdminDashboard.js +255 -271
- package/dist/kadaikodi/pages/admin/AdminDashboard.js.map +1 -1
- package/dist/kadaikodi/pages/admin/AdminFinancialPage.js +185 -125
- package/dist/kadaikodi/pages/admin/AdminFinancialPage.js.map +1 -1
- package/dist/kadaikodi/pages/admin/AdminOrdersPage.js +141 -102
- package/dist/kadaikodi/pages/admin/AdminOrdersPage.js.map +1 -1
- package/dist/kadaikodi/pages/admin/AdminProfilePage.js.map +1 -1
- package/dist/kadaikodi/pages/admin/AdminSettingsPage.js +332 -276
- package/dist/kadaikodi/pages/admin/AdminSettingsPage.js.map +1 -1
- package/dist/kadaikodi/pages/admin/CartManagementPage.js +564 -729
- package/dist/kadaikodi/pages/admin/CartManagementPage.js.map +1 -1
- package/dist/kadaikodi/pages/admin/UserManagementPage.js +310 -366
- package/dist/kadaikodi/pages/admin/UserManagementPage.js.map +1 -1
- package/dist/kadaikodi/pages/cart-owner/AnalyticsDashboard.js +201 -120
- package/dist/kadaikodi/pages/cart-owner/AnalyticsDashboard.js.map +1 -1
- package/dist/kadaikodi/pages/cart-owner/BusinessSettingsPage.js +290 -257
- package/dist/kadaikodi/pages/cart-owner/BusinessSettingsPage.js.map +1 -1
- package/dist/kadaikodi/pages/cart-owner/CartOwnerDashboard.js +173 -194
- package/dist/kadaikodi/pages/cart-owner/CartOwnerDashboard.js.map +1 -1
- package/dist/kadaikodi/pages/cart-owner/CartOwnerProfilePage.js +270 -228
- package/dist/kadaikodi/pages/cart-owner/CartOwnerProfilePage.js.map +1 -1
- package/dist/kadaikodi/pages/cart-owner/CartServiceConfigPage.js +194 -173
- package/dist/kadaikodi/pages/cart-owner/CartServiceConfigPage.js.map +1 -1
- package/dist/kadaikodi/pages/cart-owner/InventoryManagementPage.js +428 -347
- package/dist/kadaikodi/pages/cart-owner/InventoryManagementPage.js.map +1 -1
- package/dist/kadaikodi/pages/cart-owner/InvestmentListingPage.js +332 -0
- package/dist/kadaikodi/pages/cart-owner/InvestmentListingPage.js.map +1 -0
- package/dist/kadaikodi/pages/cart-owner/MerchantOnboardingPage.js +373 -0
- package/dist/kadaikodi/pages/cart-owner/MerchantOnboardingPage.js.map +1 -0
- package/dist/kadaikodi/pages/cart-owner/OrderManagementPage.js +294 -162
- package/dist/kadaikodi/pages/cart-owner/OrderManagementPage.js.map +1 -1
- package/dist/kadaikodi/pages/cart-owner/StaffManagementPage.js +180 -181
- package/dist/kadaikodi/pages/cart-owner/StaffManagementPage.js.map +1 -1
- package/dist/kadaikodi/pages/common/HelpSupportPage.js +310 -317
- package/dist/kadaikodi/pages/common/HelpSupportPage.js.map +1 -1
- package/dist/kadaikodi/pages/common/NotificationCenterPage.js.map +1 -1
- package/dist/kadaikodi/pages/common/SettingsPage.js +502 -586
- package/dist/kadaikodi/pages/common/SettingsPage.js.map +1 -1
- package/dist/kadaikodi/pages/customer/BookingDetailsPage.js +239 -156
- package/dist/kadaikodi/pages/customer/BookingDetailsPage.js.map +1 -1
- package/dist/kadaikodi/pages/customer/CartDetailPage.js +405 -248
- package/dist/kadaikodi/pages/customer/CartDetailPage.js.map +1 -1
- package/dist/kadaikodi/pages/customer/CartDiscoveryPage.js +258 -232
- package/dist/kadaikodi/pages/customer/CartDiscoveryPage.js.map +1 -1
- package/dist/kadaikodi/pages/customer/CheckoutPage.js +254 -205
- package/dist/kadaikodi/pages/customer/CheckoutPage.js.map +1 -1
- package/dist/kadaikodi/pages/customer/CustomerDashboard.js +5 -5
- package/dist/kadaikodi/pages/customer/CustomerDashboard.js.map +1 -1
- package/dist/kadaikodi/pages/customer/CustomerProfilePage.js +189 -199
- package/dist/kadaikodi/pages/customer/CustomerProfilePage.js.map +1 -1
- package/dist/kadaikodi/pages/customer/DirectServiceBookingPage.js +272 -230
- package/dist/kadaikodi/pages/customer/DirectServiceBookingPage.js.map +1 -1
- package/dist/kadaikodi/pages/customer/FavoritesPage.js +150 -413
- package/dist/kadaikodi/pages/customer/FavoritesPage.js.map +1 -1
- package/dist/kadaikodi/pages/customer/OrderHistoryPage.js +173 -134
- package/dist/kadaikodi/pages/customer/OrderHistoryPage.js.map +1 -1
- package/dist/kadaikodi/pages/customer/OrderTrackingPage.js +411 -305
- package/dist/kadaikodi/pages/customer/OrderTrackingPage.js.map +1 -1
- package/dist/kadaikodi/pages/customer/ReviewsPage.js +310 -406
- package/dist/kadaikodi/pages/customer/ReviewsPage.js.map +1 -1
- package/dist/kadaikodi/pages/customer/SavedAddressesPage.js.map +1 -1
- package/dist/kadaikodi/pages/customer/shared.js +181 -0
- package/dist/kadaikodi/pages/customer/shared.js.map +1 -0
- package/dist/kadaikodi/pages/investor/InvestmentDetailsPage.js +438 -311
- package/dist/kadaikodi/pages/investor/InvestmentDetailsPage.js.map +1 -1
- package/dist/kadaikodi/pages/investor/InvestmentOpportunitiesPage.js +320 -293
- package/dist/kadaikodi/pages/investor/InvestmentOpportunitiesPage.js.map +1 -1
- package/dist/kadaikodi/pages/investor/InvestorAnalyticsPage.js +159 -91
- package/dist/kadaikodi/pages/investor/InvestorAnalyticsPage.js.map +1 -1
- package/dist/kadaikodi/pages/investor/InvestorDashboard.js +137 -107
- package/dist/kadaikodi/pages/investor/InvestorDashboard.js.map +1 -1
- package/dist/kadaikodi/pages/investor/InvestorInvestmentsPage.js +157 -135
- package/dist/kadaikodi/pages/investor/InvestorInvestmentsPage.js.map +1 -1
- package/dist/kadaikodi/pages/investor/InvestorPortfolioPage.js +280 -206
- package/dist/kadaikodi/pages/investor/InvestorPortfolioPage.js.map +1 -1
- package/dist/kadaikodi/pages/investor/InvestorProfilePage.js +441 -514
- package/dist/kadaikodi/pages/investor/InvestorProfilePage.js.map +1 -1
- package/dist/kadaikodi/pages/worker/TaskDetailsPage.js +428 -431
- package/dist/kadaikodi/pages/worker/TaskDetailsPage.js.map +1 -1
- package/dist/kadaikodi/pages/worker/WorkerDashboard.js +328 -445
- package/dist/kadaikodi/pages/worker/WorkerDashboard.js.map +1 -1
- package/dist/kadaikodi/pages/worker/WorkerOrdersPage.js +141 -164
- package/dist/kadaikodi/pages/worker/WorkerOrdersPage.js.map +1 -1
- package/dist/kadaikodi/pages/worker/WorkerProfilePage.js +360 -288
- package/dist/kadaikodi/pages/worker/WorkerProfilePage.js.map +1 -1
- package/dist/kadaikodi/pages/worker/WorkerSchedulePage.js +303 -281
- package/dist/kadaikodi/pages/worker/WorkerSchedulePage.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WorkerDashboard.js","names":[],"sources":["../../../../src/kadaikodi/pages/worker/WorkerDashboard.tsx"],"sourcesContent":["/**\n * Worker Dashboard Page\n *\n * Full-featured worker dashboard with:\n * - Loading state with spinner\n * - Clock In/Out toggle with time tracking\n * - Quick Actions bar\n * - 6 stat cards (Completed, In Progress, Pending, Hours Worked, Efficiency, Rating)\n * - Current Task section with complete/pause buttons\n * - Assigned Tasks list sorted by priority\n * - Recently Completed section\n * - Performance Metrics grid\n * - Shift Information section\n *\n * @module kadaikodi/pages/worker\n */\n\nimport { useState } from 'react';\nimport {\n CheckCircle2,\n Star,\n ClipboardList,\n Clock,\n MapPin,\n ChevronRight,\n Package,\n Loader2,\n Timer,\n Pause,\n Play,\n Truck,\n ChefHat,\n Boxes,\n Sparkles,\n CalendarDays,\n User,\n Zap,\n} from 'lucide-react';\nimport { EmphasisPanel, PagePurpose, NextSteps } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { useKadaikodi } from '../../context/KadaikodiContext';\nimport {\n useWorkerTasks,\n useWorkerStats,\n useUpdateWorkerTaskStatus,\n useWorkerClockInOut,\n} from '../../hooks/useKadaikodiApi';\nimport { cn } from '../../utils/cn';\nimport { formatCurrency } from '../../utils/formatters';\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nconst priorityStyles: Record<string, string> = {\n high: 'bg-status-error-bg-subtle text-status-error-text',\n medium: 'bg-status-warning-bg-subtle text-status-warning-text',\n low: 'bg-status-success-bg-subtle text-status-success-text',\n};\n\nconst statusStyles: Record<string, string> = {\n pending: 'bg-bg-sunken text-text-secondary',\n in_progress: 'bg-[var(--color-accent-soft)] text-text-primary',\n completed: 'bg-status-success-bg-subtle text-status-success-text',\n};\n\nfunction getTaskIcon(type: string) {\n switch (type) {\n case 'delivery':\n return Truck;\n case 'preparation':\n return ChefHat;\n case 'inventory':\n return Boxes;\n case 'cleanup':\n return Sparkles;\n default:\n return ClipboardList;\n }\n}\n\nconst priorityOrder: Record<string, number> = { high: 3, medium: 2, low: 1 };\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport const WorkerDashboard = () => {\n const { navigateTo, currentUser } = useKadaikodi();\n const workerId = currentUser?.id || '';\n\n const { data: tasks = [], isLoading: isLoadingTasks } = useWorkerTasks(workerId);\n const { data: stats, isLoading: isLoadingStats } = useWorkerStats(workerId);\n const updateTaskStatus = useUpdateWorkerTaskStatus();\n const clockInOut = useWorkerClockInOut();\n\n const [activeTaskId, setActiveTaskId] = useState<string | null>(null);\n const [isClockedIn, setIsClockedIn] = useState(false);\n const [clockInTime, setClockInTime] = useState<string | null>(null);\n\n const handleTaskAction = async (taskId: string, action: 'start' | 'complete' | 'pause') => {\n let status = '';\n switch (action) {\n case 'start':\n status = 'IN_PROGRESS';\n setActiveTaskId(taskId);\n break;\n case 'complete':\n status = 'COMPLETED';\n if (activeTaskId === taskId) setActiveTaskId(null);\n break;\n case 'pause':\n status = 'PENDING';\n if (activeTaskId === taskId) setActiveTaskId(null);\n break;\n }\n\n try {\n await updateTaskStatus.mutateAsync({ taskId, status });\n } catch (error) {\n console.error('Failed to update task status:', error);\n alert('Failed to update task status. Please try again.');\n }\n };\n\n const handleClockToggle = async () => {\n const action = isClockedIn ? 'CLOCK_OUT' : 'CLOCK_IN';\n try {\n const result = await clockInOut.mutateAsync({ workerId, action });\n if (result.success) {\n if (isClockedIn) {\n setIsClockedIn(false);\n setClockInTime(null);\n } else {\n const now = new Date().toLocaleTimeString('en-IN', {\n hour: '2-digit',\n minute: '2-digit',\n hour12: true,\n });\n setIsClockedIn(true);\n setClockInTime(now);\n }\n alert(result.message || `${isClockedIn ? 'Clocked out' : 'Clocked in'} successfully`);\n }\n } catch (error) {\n console.error('Failed to clock in/out:', error);\n alert('Action failed. Please try again.');\n }\n };\n\n // Loading state\n if (isLoadingTasks || isLoadingStats) {\n return (\n <PageLayout title=\"Dashboard\" description=\"Your work overview for today\">\n <div className=\"flex items-center justify-center py-24\">\n <div className=\"text-center\">\n <Loader2 className=\"h-10 w-10 animate-spin text-text-secondary mx-auto mb-4\" />\n <p className=\"text-sm text-text-secondary\">Loading your dashboard...</p>\n </div>\n </div>\n </PageLayout>\n );\n }\n\n const currentTask = activeTaskId ? tasks.find((t) => t.id === activeTaskId) : null;\n const assignedTasks = tasks\n .filter((t) => t.status !== 'completed')\n .sort((a, b) => (priorityOrder[b.priority] ?? 0) - (priorityOrder[a.priority] ?? 0));\n const completedTasks = tasks.filter((t) => t.status === 'completed');\n\n return (\n <PageLayout\n title=\"Dashboard\"\n description=\"Manage your tasks and assignments\"\n actions={\n <button\n type=\"button\"\n onClick={() => navigateTo('/worker/orders')}\n className=\"inline-flex items-center gap-2 rounded-md bg-accent px-4 py-2 text-sm font-medium text-text-primary hover:bg-accent/80 transition-colors\"\n >\n View All Orders\n <ChevronRight className=\"h-4 w-4\" />\n </button>\n }\n >\n <div className=\"space-y-6\">\n <PagePurpose>\n Your shift command centre — see today's assigned deliveries and tasks at a glance, clock\n in/out, and jump straight into the order you're working on. Clock in first, then pick up\n your next task below.\n </PagePurpose>\n\n <NextSteps\n storageKey=\"kadaikodi-worker-dashboard\"\n steps={[\n {\n id: 'clock-in',\n label: 'Clock in to start your shift',\n description: 'Track your hours and let dispatch know you are available.',\n onClick: () => {\n if (!isClockedIn) handleClockToggle();\n },\n done: isClockedIn,\n },\n {\n id: 'orders',\n label: 'Review assigned orders',\n description: 'See what needs picking up and delivering today.',\n onClick: () => navigateTo('/worker/orders'),\n },\n {\n id: 'schedule',\n label: 'Check your schedule',\n description: 'Know your upcoming shifts and plan ahead.',\n onClick: () => navigateTo('/worker/schedule'),\n },\n ]}\n />\n\n {/* Quick Actions */}\n <div>\n <h2 className=\"text-base font-semibold text-text-primary mb-3\">Quick Actions</h2>\n <div className=\"grid grid-cols-2 lg:grid-cols-4 gap-3\">\n <button\n type=\"button\"\n onClick={() => navigateTo('/worker/orders')}\n className=\"flex items-center justify-center gap-2 rounded-lg border border-border-subtle bg-bg-surface px-4 py-3 text-sm font-medium text-text-primary hover:bg-bg-sunken transition-colors\"\n >\n <Package className=\"h-4 w-4\" />\n My Orders\n </button>\n <button\n type=\"button\"\n onClick={() => navigateTo('/worker/schedule')}\n className=\"flex items-center justify-center gap-2 rounded-lg border border-border-subtle bg-bg-surface px-4 py-3 text-sm font-medium text-text-primary hover:bg-bg-sunken transition-colors\"\n >\n <CalendarDays className=\"h-4 w-4\" />\n Schedule\n </button>\n <button\n type=\"button\"\n onClick={() => navigateTo('/worker/profile')}\n className=\"flex items-center justify-center gap-2 rounded-lg border border-border-subtle bg-bg-surface px-4 py-3 text-sm font-medium text-text-primary hover:bg-bg-sunken transition-colors\"\n >\n <User className=\"h-4 w-4\" />\n Profile\n </button>\n <button\n type=\"button\"\n onClick={handleClockToggle}\n className={cn(\n 'flex items-center justify-center gap-2 rounded-lg px-4 py-3 text-sm font-medium transition-colors',\n isClockedIn\n ? 'bg-status-error-bg-subtle text-status-error-text border border-status-error-text/30 hover:bg-status-error-bg-subtle'\n : 'bg-status-success-bg-subtle text-status-success-text border border-status-success-text/30 hover:bg-status-success-bg-subtle'\n )}\n >\n <Timer className=\"h-4 w-4\" />\n {isClockedIn ? 'Clock Out' : 'Clock In'}\n </button>\n </div>\n </div>\n\n {/* Today's Overview + Clock-in status — the one emphasis zone */}\n {stats && (\n <EmphasisPanel>\n <div className=\"flex items-center justify-between mb-3\">\n <h2 className=\"text-base font-semibold text-text-primary\">Today's Overview</h2>\n {isClockedIn && clockInTime && (\n <div className=\"flex items-center gap-2 rounded-lg bg-status-success-bg-subtle border border-status-success-text/20 px-3 py-1.5\">\n <span className=\"relative flex h-2 w-2\">\n <span className=\"animate-ping absolute inline-flex h-full w-full rounded-full bg-status-success-text opacity-75\" />\n <span className=\"relative inline-flex rounded-full h-2 w-2 bg-status-success-text\" />\n </span>\n <span className=\"text-xs font-medium text-status-success-text\">\n Working since {clockInTime}\n </span>\n </div>\n )}\n </div>\n <div className=\"grid grid-cols-2 md:grid-cols-3 lg:grid-cols-6 gap-3\">\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-4 shadow-sm\">\n <div className=\"flex items-center gap-2 mb-2\">\n <div className=\"inline-flex rounded-md p-1.5 bg-status-success-bg-subtle text-status-success-text\">\n <CheckCircle2 className=\"h-4 w-4\" />\n </div>\n </div>\n <p className=\"text-2xl font-bold text-status-success-text\">\n {stats.totalDeliveries}\n </p>\n <p className=\"text-xs text-text-secondary\">Total Deliveries</p>\n </div>\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-4 shadow-sm\">\n <div className=\"flex items-center gap-2 mb-2\">\n <div className=\"inline-flex rounded-md p-1.5 bg-[var(--color-accent-soft)] text-text-primary\">\n <Play className=\"h-4 w-4\" />\n </div>\n </div>\n <p className=\"text-2xl font-bold text-text-primary\">{stats.todayTasks}</p>\n <p className=\"text-xs text-text-secondary\">Today's Tasks</p>\n </div>\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-4 shadow-sm\">\n <div className=\"flex items-center gap-2 mb-2\">\n <div className=\"inline-flex rounded-md p-1.5 bg-status-warning-bg-subtle text-status-warning-text\">\n <Clock className=\"h-4 w-4\" />\n </div>\n </div>\n <p className=\"text-2xl font-bold text-status-warning-text\">\n {stats.completionRate}%\n </p>\n <p className=\"text-xs text-text-secondary\">Completion</p>\n </div>\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-4 shadow-sm\">\n <div className=\"flex items-center gap-2 mb-2\">\n <div className=\"inline-flex rounded-md p-1.5 bg-accent-purple-subtle text-text-primary\">\n <Timer className=\"h-4 w-4\" />\n </div>\n </div>\n <p className=\"text-2xl font-bold text-text-primary\">\n {formatCurrency(stats.todayEarnings, { minimumFractionDigits: 0 })}\n </p>\n <p className=\"text-xs text-text-secondary\">Today's Earnings</p>\n </div>\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-4 shadow-sm\">\n <div className=\"flex items-center gap-2 mb-2\">\n <div className=\"inline-flex rounded-md p-1.5 bg-[var(--color-accent-soft)] text-text-primary\">\n <Zap className=\"h-4 w-4\" />\n </div>\n </div>\n <p className=\"text-2xl font-bold text-text-primary\">\n {formatCurrency(stats.totalEarnings, { minimumFractionDigits: 0 })}\n </p>\n <p className=\"text-xs text-text-secondary\">Total Earnings</p>\n </div>\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-4 shadow-sm\">\n <div className=\"flex items-center gap-2 mb-2\">\n <div className=\"inline-flex rounded-md p-1.5 bg-status-warning-bg-subtle text-status-warning-text\">\n <Star className=\"h-4 w-4\" />\n </div>\n </div>\n <p className=\"text-2xl font-bold text-status-warning-text\">\n {stats.averageRating}/5\n </p>\n <p className=\"text-xs text-text-secondary\">Rating</p>\n </div>\n </div>\n </EmphasisPanel>\n )}\n\n {/* Current Task */}\n {currentTask && (\n <div>\n <h2 className=\"text-base font-semibold text-text-primary mb-3\">Current Task</h2>\n <div className=\"rounded-lg border-2 border-border-focus/40 bg-[var(--color-accent-soft)] p-6\">\n <div className=\"flex items-start justify-between mb-4\">\n <div className=\"flex items-start gap-3\">\n {(() => {\n const TaskIcon = getTaskIcon(currentTask.type);\n return (\n <div className=\"flex h-10 w-10 items-center justify-center rounded-lg bg-[var(--color-accent-soft)]\">\n <TaskIcon className=\"h-5 w-5 text-text-primary\" />\n </div>\n );\n })()}\n <div>\n <h3 className=\"text-lg font-semibold text-text-primary\">\n {currentTask.title ?? currentTask.description}\n </h3>\n <p className=\"text-sm text-text-secondary mt-1\">{currentTask.description}</p>\n <div className=\"flex flex-wrap items-center gap-3 mt-2 text-sm text-text-secondary\">\n {currentTask.estimatedTime ? (\n <span className=\"flex items-center gap-1\">\n <Clock className=\"h-3.5 w-3.5\" />\n {currentTask.estimatedTime} min\n </span>\n ) : null}\n {currentTask.dueTime && (\n <span className=\"flex items-center gap-1\">\n <Timer className=\"h-3.5 w-3.5\" />\n Due: {currentTask.dueTime}\n </span>\n )}\n {currentTask.location && (\n <span className=\"flex items-center gap-1\">\n <MapPin className=\"h-3.5 w-3.5\" />\n {currentTask.location}\n </span>\n )}\n </div>\n </div>\n </div>\n <div className=\"flex gap-2 shrink-0\">\n <button\n type=\"button\"\n onClick={() => handleTaskAction(currentTask.id, 'complete')}\n className=\"inline-flex items-center gap-1.5 rounded-md bg-status-success-bg-subtle px-3 py-2 text-sm font-medium text-status-success-text hover:bg-status-success-bg-subtle transition-colors\"\n >\n <CheckCircle2 className=\"h-4 w-4\" />\n Complete\n </button>\n <button\n type=\"button\"\n onClick={() => handleTaskAction(currentTask.id, 'pause')}\n className=\"inline-flex items-center gap-1.5 rounded-md bg-accent px-3 py-2 text-sm font-medium text-text-primary hover:bg-accent/80 transition-colors\"\n >\n <Pause className=\"h-4 w-4\" />\n Pause\n </button>\n </div>\n </div>\n </div>\n </div>\n )}\n\n {/* Assigned Tasks */}\n <div>\n <h2 className=\"text-base font-semibold text-text-primary mb-3\">Assigned Tasks</h2>\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface shadow-sm overflow-hidden\">\n {assignedTasks.length > 0 ? (\n <div className=\"divide-y divide-border\">\n {assignedTasks.map((task) => {\n const TaskIcon = getTaskIcon(task.type);\n return (\n <div key={task.id} className=\"p-4 hover:bg-bg-sunken/30 transition-colors\">\n <div className=\"flex flex-col sm:flex-row sm:items-start sm:justify-between gap-3\">\n <div className=\"flex items-start gap-3 flex-1 min-w-0\">\n <div className=\"flex h-9 w-9 shrink-0 items-center justify-center rounded-lg bg-bg-sunken\">\n <TaskIcon className=\"h-4.5 w-4.5 text-text-secondary\" />\n </div>\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex flex-wrap items-center gap-2 mb-1\">\n <h3 className=\"text-sm font-medium text-text-primary\">\n {task.title ?? task.description}\n </h3>\n <span\n className={cn(\n 'inline-flex items-center rounded-full px-2 py-0.5 text-[10px] font-medium capitalize',\n priorityStyles[task.priority]\n )}\n >\n {task.priority}\n </span>\n <span\n className={cn(\n 'inline-flex items-center rounded-full px-2 py-0.5 text-[10px] font-medium',\n statusStyles[task.status]\n )}\n >\n {task.status.replace('_', ' ')}\n </span>\n </div>\n <p className=\"text-xs text-text-secondary line-clamp-1\">\n {task.description}\n </p>\n <div className=\"flex flex-wrap items-center gap-3 mt-1.5 text-xs text-text-secondary\">\n {task.assignedBy && (\n <span className=\"flex items-center gap-1\">\n <User className=\"h-3 w-3\" />\n {task.assignedBy}\n </span>\n )}\n {task.estimatedTime ? (\n <span className=\"flex items-center gap-1\">\n <Clock className=\"h-3 w-3\" />\n {task.estimatedTime} min\n </span>\n ) : null}\n {task.dueTime && (\n <span className=\"flex items-center gap-1\">\n <Timer className=\"h-3 w-3\" />\n Due: {task.dueTime}\n </span>\n )}\n {task.location && (\n <span className=\"flex items-center gap-1\">\n <MapPin className=\"h-3 w-3\" />\n {task.location}\n </span>\n )}\n </div>\n </div>\n </div>\n <div className=\"flex gap-2 shrink-0\">\n {task.status === 'pending' && (\n <button\n type=\"button\"\n onClick={() => handleTaskAction(task.id, 'start')}\n disabled={activeTaskId !== null}\n className={cn(\n 'inline-flex items-center gap-1.5 rounded-md px-3 py-1.5 text-xs font-medium transition-colors',\n activeTaskId !== null\n ? 'bg-bg-sunken text-text-secondary cursor-not-allowed'\n : 'bg-[var(--color-accent-soft)] text-text-primary hover:bg-[var(--color-accent-soft)]'\n )}\n >\n <Play className=\"h-3.5 w-3.5\" />\n Start\n </button>\n )}\n {task.status === 'in_progress' && task.id !== activeTaskId && (\n <button\n type=\"button\"\n onClick={() => setActiveTaskId(task.id)}\n className=\"inline-flex items-center gap-1.5 rounded-md bg-accent px-3 py-1.5 text-xs font-medium text-text-primary hover:bg-accent/80 transition-colors\"\n >\n <Play className=\"h-3.5 w-3.5\" />\n Resume\n </button>\n )}\n <button\n type=\"button\"\n onClick={() => navigateTo(`/worker/task/${task.id}`)}\n className=\"inline-flex items-center gap-1.5 rounded-md bg-accent px-3 py-1.5 text-xs font-medium text-text-primary hover:bg-accent/80 transition-colors\"\n >\n Details\n <ChevronRight className=\"h-3.5 w-3.5\" />\n </button>\n </div>\n </div>\n </div>\n );\n })}\n </div>\n ) : (\n <div className=\"p-8 text-center\">\n <CheckCircle2 className=\"h-10 w-10 text-status-success-text opacity-40 mx-auto mb-2\" />\n <p className=\"text-sm text-text-secondary\">All tasks completed!</p>\n </div>\n )}\n </div>\n </div>\n\n {/* Recently Completed */}\n <div>\n <h2 className=\"text-base font-semibold text-text-primary mb-3\">Recently Completed</h2>\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-5 shadow-sm\">\n {completedTasks.length > 0 ? (\n <div className=\"space-y-3\">\n {completedTasks.slice(0, 3).map((task) => {\n const TaskIcon = getTaskIcon(task.type);\n return (\n <div\n key={task.id}\n className=\"flex items-center gap-3 p-3 rounded-lg bg-status-success-bg-subtle border border-status-success-text/10\"\n >\n <div className=\"flex h-8 w-8 items-center justify-center rounded-md bg-status-success-bg-subtle\">\n <TaskIcon className=\"h-4 w-4 text-status-success-text\" />\n </div>\n <div className=\"flex-1 min-w-0\">\n <p className=\"text-sm font-medium text-text-primary\">\n {task.title ?? task.description}\n </p>\n {task.completedAt && (\n <p className=\"text-xs text-text-secondary\">\n Completed at{' '}\n {new Date(task.completedAt).toLocaleTimeString('en-IN', {\n hour: '2-digit',\n minute: '2-digit',\n hour12: true,\n })}\n </p>\n )}\n </div>\n <CheckCircle2 className=\"h-4 w-4 text-status-success-text shrink-0\" />\n </div>\n );\n })}\n </div>\n ) : (\n <p className=\"text-sm text-text-secondary text-center py-4\">\n No completed tasks yet today\n </p>\n )}\n </div>\n </div>\n\n {/* Overall Stats */}\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-5 shadow-sm\">\n <h2 className=\"text-base font-semibold text-text-primary mb-4\">Overall Performance</h2>\n <div className=\"grid grid-cols-2 gap-4 sm:grid-cols-4\">\n <div>\n <p className=\"text-xs text-text-secondary\">Total Deliveries</p>\n <p className=\"text-lg font-bold text-text-primary\">{stats?.totalDeliveries || 0}</p>\n </div>\n <div>\n <p className=\"text-xs text-text-secondary\">Total Earnings</p>\n <p className=\"text-lg font-bold text-text-primary\">\n {formatCurrency(stats?.totalEarnings || 0, { minimumFractionDigits: 0 })}\n </p>\n </div>\n <div>\n <p className=\"text-xs text-text-secondary\">Average Rating</p>\n <p className=\"text-lg font-bold text-text-primary flex items-center gap-1\">\n {stats?.averageRating || 0}\n <Star className=\"h-4 w-4 fill-status-warning-text text-status-warning-text\" />\n </p>\n </div>\n <div>\n <p className=\"text-xs text-text-secondary\">Completion Rate</p>\n <p className=\"text-lg font-bold text-text-primary\">{stats?.completionRate || 0}%</p>\n </div>\n </div>\n </div>\n </div>\n </PageLayout>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"WorkerDashboard.js","names":[],"sources":["../../../../src/kadaikodi/pages/worker/WorkerDashboard.tsx"],"sourcesContent":["/**\n * Worker Dashboard Page\n *\n * The signed-in worker's shift command centre, elevated to the delivery-driver\n * concept in kk-worker-01-dashboard: a greeting header with a live Clocked-In /\n * Clock-In pill, a row of KPI StatCards (earnings / deliveries / rating /\n * completion) and delivery-style assigned-task cards with a pickup → drop route\n * and a distance + earnings chip. All data is real (useWorkerStats /\n * useWorkerTasks); clock + task actions are wired to the real mutations.\n *\n * @module kadaikodi/pages/worker\n */\n\nimport { useState } from 'react';\nimport {\n CheckCircle2,\n Star,\n ClipboardList,\n Clock,\n MapPin,\n ChevronRight,\n Package,\n Loader2,\n Pause,\n Play,\n Truck,\n ChefHat,\n Boxes,\n Sparkles,\n IndianRupee,\n Wallet,\n} from 'lucide-react';\nimport { GlassCard, PagePurpose, NextSteps } from '@burdenoff/fe-libs/ui';\nimport { StatCard, ProgressRing, RatingStars } from '../../components/viz';\nimport { PageLayout } from '../../components/PageLayout';\nimport { useKadaikodi } from '../../context/KadaikodiContext';\nimport {\n useWorkerTasks,\n useWorkerStats,\n useUpdateWorkerTaskStatus,\n useWorkerClockInOut,\n} from '../../hooks/useKadaikodiApi';\nimport { cn } from '../../utils/cn';\nimport { formatCurrency } from '../../utils/formatters';\nimport type { WorkerTask } from '../../types';\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nconst priorityStyles: Record<string, string> = {\n urgent: 'bg-status-error-bg-subtle text-status-error-text',\n high: 'bg-status-error-bg-subtle text-status-error-text',\n medium: 'bg-status-warning-bg-subtle text-status-warning-text',\n low: 'bg-status-success-bg-subtle text-status-success-text',\n};\n\nconst typeStyles: Record<string, string> = {\n delivery: 'bg-accent-primary/12 text-accent-primary',\n pickup: 'bg-status-info-bg-subtle text-status-info-text',\n service: 'bg-status-success-bg-subtle text-status-success-text',\n};\n\nfunction getTaskIcon(type: string) {\n switch (type) {\n case 'delivery':\n return Truck;\n case 'preparation':\n return ChefHat;\n case 'inventory':\n return Boxes;\n case 'cleanup':\n return Sparkles;\n default:\n return ClipboardList;\n }\n}\n\nconst priorityOrder: Record<string, number> = { urgent: 4, high: 3, medium: 2, low: 1 };\n\nfunction formatAddress(task: WorkerTask): string {\n if (!task.deliveryAddress) return task.location ?? '';\n const a = task.deliveryAddress;\n return [a.street, a.area, a.city].filter(Boolean).join(', ');\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport const WorkerDashboard = () => {\n const { navigateTo, currentUser } = useKadaikodi();\n const workerId = currentUser?.id || '';\n\n const { data: tasks = [], isLoading: isLoadingTasks } = useWorkerTasks(workerId);\n const { data: stats, isLoading: isLoadingStats } = useWorkerStats(workerId);\n const updateTaskStatus = useUpdateWorkerTaskStatus();\n const clockInOut = useWorkerClockInOut();\n\n const [activeTaskId, setActiveTaskId] = useState<string | null>(null);\n const [isClockedIn, setIsClockedIn] = useState(false);\n const [clockInTime, setClockInTime] = useState<string | null>(null);\n const [actionError, setActionError] = useState<string | null>(null);\n\n const firstName =\n currentUser?.firstName ?? currentUser?.name?.split(' ')[0] ?? 'there';\n\n const handleTaskAction = async (taskId: string, action: 'start' | 'complete' | 'pause') => {\n setActionError(null);\n let status = '';\n switch (action) {\n case 'start':\n status = 'IN_PROGRESS';\n setActiveTaskId(taskId);\n break;\n case 'complete':\n status = 'COMPLETED';\n if (activeTaskId === taskId) setActiveTaskId(null);\n break;\n case 'pause':\n status = 'PENDING';\n if (activeTaskId === taskId) setActiveTaskId(null);\n break;\n }\n try {\n await updateTaskStatus.mutateAsync({ taskId, status });\n } catch {\n setActionError('Failed to update task. Please try again.');\n }\n };\n\n const handleClockToggle = async () => {\n setActionError(null);\n const action = isClockedIn ? 'CLOCK_OUT' : 'CLOCK_IN';\n try {\n const result = await clockInOut.mutateAsync({ workerId, action });\n if (result.success) {\n if (isClockedIn) {\n setIsClockedIn(false);\n setClockInTime(null);\n } else {\n const now = new Date().toLocaleTimeString('en-IN', {\n hour: '2-digit',\n minute: '2-digit',\n hour12: true,\n });\n setIsClockedIn(true);\n setClockInTime(now);\n }\n }\n } catch {\n setActionError('Clock action failed. Please try again.');\n }\n };\n\n // Loading state\n if (isLoadingTasks || isLoadingStats) {\n return (\n <PageLayout title={`Hi, ${firstName}`} description=\"Your shift at a glance\">\n <div className=\"flex items-center justify-center py-24\">\n <div className=\"text-center\">\n <Loader2 className=\"h-10 w-10 animate-spin text-text-secondary mx-auto mb-4\" />\n <p className=\"text-sm text-text-secondary\">Loading your dashboard...</p>\n </div>\n </div>\n </PageLayout>\n );\n }\n\n const currentTask = activeTaskId ? tasks.find((t) => t.id === activeTaskId) : null;\n const assignedTasks = tasks\n .filter((t) => t.status !== 'completed')\n .sort((a, b) => (priorityOrder[b.priority] ?? 0) - (priorityOrder[a.priority] ?? 0));\n const completedTasks = tasks.filter((t) => t.status === 'completed');\n\n return (\n <PageLayout\n title={`Hi, ${firstName}`}\n description=\"Your shift at a glance — clock in, then pick up your next delivery.\"\n actions={\n <button\n type=\"button\"\n onClick={handleClockToggle}\n disabled={clockInOut.isPending}\n className={cn(\n 'inline-flex items-center gap-2 rounded-full px-4 py-2 text-sm font-semibold shadow-sm transition-colors disabled:opacity-60',\n isClockedIn\n ? 'bg-status-success-bg-subtle text-status-success-text border border-status-success-text/30'\n : 'bg-action-primary-bg text-action-primary-text hover:bg-action-primary-bg-hover'\n )}\n >\n {clockInOut.isPending ? (\n <Loader2 className=\"h-4 w-4 animate-spin\" />\n ) : isClockedIn ? (\n <span className=\"relative flex h-2.5 w-2.5\">\n <span className=\"animate-ping absolute inline-flex h-full w-full rounded-full bg-status-success-text opacity-75\" />\n <span className=\"relative inline-flex rounded-full h-2.5 w-2.5 bg-status-success-text\" />\n </span>\n ) : (\n <Clock className=\"h-4 w-4\" />\n )}\n {isClockedIn ? 'Clocked In' : 'Clock In'}\n </button>\n }\n >\n <div className=\"space-y-6\">\n <PagePurpose>\n Your shift command centre — see today's assigned deliveries at a glance, clock in/out,\n and jump straight into the order you're working on. Clock in first, then start your\n next task below.\n </PagePurpose>\n\n {actionError && (\n <div className=\"rounded-lg border border-status-error-text/20 bg-status-error-bg-subtle p-3\">\n <p className=\"text-xs text-status-error-text\">{actionError}</p>\n </div>\n )}\n\n {/* KPI row — mirrors the mockup's earnings / deliveries / rating / on-time tiles */}\n {stats && (\n <div className=\"grid grid-cols-2 lg:grid-cols-4 gap-3 sm:gap-4\">\n <StatCard\n label=\"Today's Earnings\"\n value={formatCurrency(stats.todayEarnings, { minimumFractionDigits: 0 })}\n icon={<Wallet className=\"h-4 w-4\" />}\n />\n <StatCard\n label=\"Deliveries\"\n value={stats.totalDeliveries}\n icon={<Truck className=\"h-4 w-4\" />}\n />\n <StatCard\n label=\"Rating\"\n value={\n <span className=\"flex items-center gap-1.5\">\n {stats.averageRating.toFixed(1)}\n <Star className=\"h-5 w-5 fill-status-warning-text text-status-warning-text\" />\n </span>\n }\n icon={<Star className=\"h-4 w-4\" />}\n />\n <StatCard\n label=\"Completion\"\n value={`${stats.completionRate}%`}\n icon={<CheckCircle2 className=\"h-4 w-4\" />}\n />\n </div>\n )}\n\n {isClockedIn && clockInTime && (\n <div className=\"flex items-center gap-2 rounded-lg bg-status-success-bg-subtle border border-status-success-text/20 px-3 py-2 w-fit\">\n <span className=\"relative flex h-2 w-2\">\n <span className=\"animate-ping absolute inline-flex h-full w-full rounded-full bg-status-success-text opacity-75\" />\n <span className=\"relative inline-flex rounded-full h-2 w-2 bg-status-success-text\" />\n </span>\n <span className=\"text-xs font-medium text-status-success-text\">\n Working since {clockInTime}\n </span>\n </div>\n )}\n\n <NextSteps\n storageKey=\"kadaikodi-worker-dashboard\"\n steps={[\n {\n id: 'clock-in',\n label: 'Clock in to start your shift',\n description: 'Track your hours and let dispatch know you are available.',\n onClick: () => {\n if (!isClockedIn) handleClockToggle();\n },\n done: isClockedIn,\n },\n {\n id: 'orders',\n label: 'Review assigned orders',\n description: 'See what needs picking up and delivering today.',\n onClick: () => navigateTo('/worker/orders'),\n },\n {\n id: 'schedule',\n label: 'Check your schedule',\n description: 'Know your upcoming shifts and plan ahead.',\n onClick: () => navigateTo('/worker/schedule'),\n },\n ]}\n />\n\n {/* Current Task */}\n {currentTask && (\n <div>\n <h2 className=\"text-base font-semibold text-text-primary mb-3\">Current Task</h2>\n <GlassCard treatment=\"insight\" glow className=\"p-6\">\n <div className=\"flex flex-col sm:flex-row sm:items-start sm:justify-between gap-4\">\n <div className=\"flex items-start gap-3 min-w-0\">\n {(() => {\n const TaskIcon = getTaskIcon(currentTask.type);\n return (\n <div className=\"flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-accent-primary/12 text-accent-primary\">\n <TaskIcon className=\"h-5 w-5\" />\n </div>\n );\n })()}\n <div className=\"min-w-0\">\n <h3 className=\"text-lg font-semibold text-text-primary\">\n {currentTask.title ?? currentTask.description}\n </h3>\n <p className=\"text-sm text-text-secondary mt-1\">{currentTask.description}</p>\n <div className=\"flex flex-wrap items-center gap-3 mt-2 text-sm text-text-secondary\">\n {currentTask.customerName && (\n <span className=\"flex items-center gap-1\">\n <Package className=\"h-3.5 w-3.5\" />\n {currentTask.customerName}\n </span>\n )}\n {formatAddress(currentTask) && (\n <span className=\"flex items-center gap-1\">\n <MapPin className=\"h-3.5 w-3.5\" />\n {formatAddress(currentTask)}\n </span>\n )}\n </div>\n </div>\n </div>\n <div className=\"flex gap-2 shrink-0\">\n <button\n type=\"button\"\n onClick={() => handleTaskAction(currentTask.id, 'complete')}\n className=\"inline-flex items-center gap-1.5 rounded-md bg-status-success-bg-subtle px-3 py-2 text-sm font-medium text-status-success-text transition-colors\"\n >\n <CheckCircle2 className=\"h-4 w-4\" />\n Complete\n </button>\n <button\n type=\"button\"\n onClick={() => handleTaskAction(currentTask.id, 'pause')}\n className=\"inline-flex items-center gap-1.5 rounded-md border border-border-default bg-bg-surface px-3 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken transition-colors\"\n >\n <Pause className=\"h-4 w-4\" />\n Pause\n </button>\n </div>\n </div>\n </GlassCard>\n </div>\n )}\n\n {/* Assigned Tasks — delivery cards matching the mockup */}\n <div>\n <div className=\"flex items-center justify-between mb-3\">\n <h2 className=\"text-base font-semibold text-text-primary\">Assigned Tasks</h2>\n <button\n type=\"button\"\n onClick={() => navigateTo('/worker/orders')}\n className=\"inline-flex items-center gap-1 text-sm font-medium text-accent-primary hover:underline\"\n >\n View all\n <ChevronRight className=\"h-4 w-4\" />\n </button>\n </div>\n\n {assignedTasks.length > 0 ? (\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n {assignedTasks.map((task) => {\n const pickup = task.cartName || 'Pickup';\n const drop = formatAddress(task) || task.customerName || 'Drop-off';\n const isBusy = activeTaskId !== null && activeTaskId !== task.id;\n return (\n <GlassCard key={task.id} treatment=\"metric\" className=\"flex flex-col gap-4 p-5\">\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <span\n className={cn(\n 'inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-semibold capitalize',\n typeStyles[task.type] ?? 'bg-bg-sunken text-text-secondary'\n )}\n >\n {task.type}\n </span>\n <span\n className={cn(\n 'inline-flex items-center rounded-full px-2 py-0.5 text-[10px] font-medium capitalize',\n priorityStyles[task.priority] ?? 'bg-bg-sunken text-text-secondary'\n )}\n >\n {task.priority}\n </span>\n </div>\n {task.orderId && (\n <span className=\"text-sm font-bold text-text-primary tabular-nums\">\n #{task.orderId}\n </span>\n )}\n </div>\n\n {task.customerName && (\n <p className=\"-mt-1 text-sm text-text-secondary\">\n Customer:{' '}\n <span className=\"font-medium text-text-primary\">{task.customerName}</span>\n </p>\n )}\n\n {/* Pickup → Drop route */}\n <div className=\"flex items-stretch gap-3\">\n <div className=\"flex flex-col items-center pt-1\">\n <MapPin className=\"h-4 w-4 text-accent-primary shrink-0\" />\n <span className=\"my-1 w-px flex-1 border-l border-dashed border-border-strong\" />\n <MapPin className=\"h-4 w-4 text-status-success-text shrink-0\" />\n </div>\n <div className=\"flex flex-1 flex-col justify-between gap-3 min-w-0\">\n <p className=\"text-sm text-text-primary line-clamp-1\">{pickup}</p>\n <p className=\"text-sm text-text-primary line-clamp-1\">{drop}</p>\n </div>\n <div className=\"flex flex-col items-end justify-center rounded-lg bg-bg-sunken px-3 py-2 text-right shrink-0\">\n {task.distance != null && (\n <span className=\"text-xs text-text-secondary tabular-nums\">\n {task.distance} km\n </span>\n )}\n {task.earnings > 0 && (\n <span className=\"flex items-center text-base font-bold text-text-primary tabular-nums\">\n <IndianRupee className=\"h-3.5 w-3.5\" />\n {formatCurrency(task.earnings, {\n minimumFractionDigits: 0,\n style: 'decimal',\n })}\n </span>\n )}\n </div>\n </div>\n\n <div className=\"flex gap-2\">\n {task.status === 'pending' && (\n <button\n type=\"button\"\n onClick={() => handleTaskAction(task.id, 'start')}\n disabled={isBusy}\n className={cn(\n 'flex-1 inline-flex items-center justify-center gap-1.5 rounded-lg px-4 py-2.5 text-sm font-semibold transition-colors',\n isBusy\n ? 'bg-bg-sunken text-text-muted cursor-not-allowed'\n : 'bg-action-primary-bg text-action-primary-text hover:bg-action-primary-bg-hover'\n )}\n >\n <Play className=\"h-4 w-4\" />\n Start\n </button>\n )}\n {task.status === 'in_progress' && (\n <button\n type=\"button\"\n onClick={() => setActiveTaskId(task.id)}\n className=\"flex-1 inline-flex items-center justify-center gap-1.5 rounded-lg bg-action-primary-bg px-4 py-2.5 text-sm font-semibold text-action-primary-text hover:bg-action-primary-bg-hover transition-colors\"\n >\n <Play className=\"h-4 w-4\" />\n Resume\n </button>\n )}\n <button\n type=\"button\"\n onClick={() => navigateTo(`/worker/task/${task.id}`)}\n className=\"inline-flex items-center justify-center gap-1 rounded-lg border border-border-default bg-bg-surface px-4 py-2.5 text-sm font-medium text-text-primary hover:bg-bg-sunken transition-colors\"\n >\n Details\n <ChevronRight className=\"h-4 w-4\" />\n </button>\n </div>\n </GlassCard>\n );\n })}\n </div>\n ) : (\n <GlassCard className=\"p-8 text-center\">\n <CheckCircle2 className=\"h-10 w-10 text-status-success-text opacity-50 mx-auto mb-2\" />\n <p className=\"text-sm text-text-secondary\">All tasks completed. Nice work!</p>\n </GlassCard>\n )}\n </div>\n\n {/* Two-up: performance + recent completions */}\n <div className=\"grid grid-cols-1 lg:grid-cols-3 gap-4\">\n <GlassCard treatment=\"insight\" className=\"p-6 flex flex-col items-center text-center\">\n <h2 className=\"text-base font-semibold text-text-primary mb-4 self-start\">\n Completion Rate\n </h2>\n <ProgressRing\n value={stats?.completionRate ?? 0}\n max={100}\n label={`${stats?.completionRate ?? 0}%`}\n caption=\"on-time\"\n />\n <div className=\"mt-4\">\n <RatingStars value={stats?.averageRating ?? 0} showValue size={18} />\n </div>\n </GlassCard>\n\n <GlassCard className=\"p-6 lg:col-span-2\">\n <h2 className=\"text-base font-semibold text-text-primary mb-4\">Recently Completed</h2>\n {completedTasks.length > 0 ? (\n <div className=\"space-y-3\">\n {completedTasks.slice(0, 4).map((task) => {\n const TaskIcon = getTaskIcon(task.type);\n return (\n <div\n key={task.id}\n className=\"flex items-center gap-3 rounded-lg bg-status-success-bg-subtle border border-status-success-text/10 p-3\"\n >\n <div className=\"flex h-8 w-8 items-center justify-center rounded-md bg-status-success-bg-subtle\">\n <TaskIcon className=\"h-4 w-4 text-status-success-text\" />\n </div>\n <div className=\"flex-1 min-w-0\">\n <p className=\"text-sm font-medium text-text-primary truncate\">\n {task.title ?? task.description}\n </p>\n {task.completedAt && (\n <p className=\"text-xs text-text-secondary\">\n Completed at{' '}\n {new Date(task.completedAt).toLocaleTimeString('en-IN', {\n hour: '2-digit',\n minute: '2-digit',\n hour12: true,\n })}\n </p>\n )}\n </div>\n {task.earnings > 0 && (\n <span className=\"text-sm font-semibold text-text-primary tabular-nums\">\n {formatCurrency(task.earnings, { minimumFractionDigits: 0 })}\n </span>\n )}\n <CheckCircle2 className=\"h-4 w-4 text-status-success-text shrink-0\" />\n </div>\n );\n })}\n </div>\n ) : (\n <p className=\"text-sm text-text-secondary text-center py-8\">\n No completed tasks yet today.\n </p>\n )}\n </GlassCard>\n </div>\n </div>\n </PageLayout>\n );\n};\n"],"mappings":"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"}
|