@burdenoff/microfe-kadaikodi 2026.710.1 → 2026.716.1
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/pages/HomePage.d.ts.map +1 -1
- package/dist/kadaikodi/pages/HomePage.js.map +1 -1
- package/dist/kadaikodi/pages/admin/AdminAnalyticsPage.d.ts.map +1 -1
- package/dist/kadaikodi/pages/admin/AdminAnalyticsPage.js.map +1 -1
- package/dist/kadaikodi/pages/admin/AdminDashboard.d.ts.map +1 -1
- package/dist/kadaikodi/pages/admin/AdminDashboard.js.map +1 -1
- package/dist/kadaikodi/pages/admin/AdminFinancialPage.d.ts.map +1 -1
- package/dist/kadaikodi/pages/admin/AdminFinancialPage.js.map +1 -1
- package/dist/kadaikodi/pages/admin/AdminOrdersPage.d.ts.map +1 -1
- package/dist/kadaikodi/pages/admin/AdminOrdersPage.js.map +1 -1
- package/dist/kadaikodi/pages/admin/CartManagementPage.d.ts.map +1 -1
- package/dist/kadaikodi/pages/admin/CartManagementPage.js.map +1 -1
- package/dist/kadaikodi/pages/cart-owner/AnalyticsDashboard.d.ts.map +1 -1
- package/dist/kadaikodi/pages/cart-owner/AnalyticsDashboard.js.map +1 -1
- package/dist/kadaikodi/pages/cart-owner/InventoryManagementPage.d.ts.map +1 -1
- package/dist/kadaikodi/pages/cart-owner/InventoryManagementPage.js.map +1 -1
- package/dist/kadaikodi/pages/cart-owner/InvestmentListingPage.js.map +1 -1
- package/dist/kadaikodi/pages/cart-owner/MerchantOnboardingPage.d.ts.map +1 -1
- package/dist/kadaikodi/pages/cart-owner/MerchantOnboardingPage.js.map +1 -1
- package/dist/kadaikodi/pages/cart-owner/OrderManagementPage.d.ts.map +1 -1
- package/dist/kadaikodi/pages/cart-owner/OrderManagementPage.js.map +1 -1
- package/dist/kadaikodi/pages/cart-owner/StaffManagementPage.d.ts.map +1 -1
- package/dist/kadaikodi/pages/cart-owner/StaffManagementPage.js.map +1 -1
- package/dist/kadaikodi/pages/customer/BookingDetailsPage.d.ts.map +1 -1
- package/dist/kadaikodi/pages/customer/BookingDetailsPage.js.map +1 -1
- package/dist/kadaikodi/pages/customer/CartDetailPage.d.ts.map +1 -1
- package/dist/kadaikodi/pages/customer/CartDetailPage.js.map +1 -1
- package/dist/kadaikodi/pages/customer/CheckoutPage.js.map +1 -1
- package/dist/kadaikodi/pages/customer/FavoritesPage.d.ts.map +1 -1
- package/dist/kadaikodi/pages/customer/FavoritesPage.js.map +1 -1
- package/dist/kadaikodi/pages/customer/OrderTrackingPage.d.ts.map +1 -1
- package/dist/kadaikodi/pages/customer/OrderTrackingPage.js.map +1 -1
- package/dist/kadaikodi/pages/customer/ReviewsPage.d.ts.map +1 -1
- package/dist/kadaikodi/pages/customer/ReviewsPage.js.map +1 -1
- package/dist/kadaikodi/pages/customer/shared.d.ts.map +1 -1
- package/dist/kadaikodi/pages/customer/shared.js.map +1 -1
- package/dist/kadaikodi/pages/investor/InvestmentDetailsPage.d.ts.map +1 -1
- package/dist/kadaikodi/pages/investor/InvestmentDetailsPage.js +3 -3
- package/dist/kadaikodi/pages/investor/InvestmentDetailsPage.js.map +1 -1
- package/dist/kadaikodi/pages/investor/InvestmentOpportunitiesPage.d.ts.map +1 -1
- package/dist/kadaikodi/pages/investor/InvestmentOpportunitiesPage.js.map +1 -1
- package/dist/kadaikodi/pages/investor/InvestorPortfolioPage.d.ts.map +1 -1
- package/dist/kadaikodi/pages/investor/InvestorPortfolioPage.js.map +1 -1
- package/dist/kadaikodi/pages/worker/TaskDetailsPage.d.ts.map +1 -1
- package/dist/kadaikodi/pages/worker/TaskDetailsPage.js.map +1 -1
- package/dist/kadaikodi/pages/worker/WorkerDashboard.d.ts.map +1 -1
- package/dist/kadaikodi/pages/worker/WorkerDashboard.js.map +1 -1
- package/dist/kadaikodi/pages/worker/WorkerSchedulePage.d.ts.map +1 -1
- package/dist/kadaikodi/pages/worker/WorkerSchedulePage.js.map +1 -1
- package/dist/services/createSandboxAssistantTransport.d.ts +8 -27
- package/dist/services/createSandboxAssistantTransport.d.ts.map +1 -1
- package/dist/services/createSandboxAssistantTransport.js +7 -10
- package/dist/services/createSandboxAssistantTransport.js.map +1 -1
- package/dist/stories/EmptyState.stories.d.ts +10 -0
- package/dist/stories/EmptyState.stories.d.ts.map +1 -0
- package/dist/stories/MetricsCard.stories.d.ts +10 -0
- package/dist/stories/MetricsCard.stories.d.ts.map +1 -0
- package/dist/stories/StatusBadge.stories.d.ts +12 -0
- package/dist/stories/StatusBadge.stories.d.ts.map +1 -0
- package/package.json +15 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MerchantOnboardingPage.js","names":[],"sources":["../../../../src/kadaikodi/pages/cart-owner/MerchantOnboardingPage.tsx"],"sourcesContent":["/**\n * MerchantOnboardingPage — guided first-time merchant setup.\n *\n * A real StepProgress wizard that creates a live ServiceProvider (via\n * kadaikodiCreateServiceProvider) across Business details → Location & hours →\n * Fulfilment → Review & submit. Verification is honest: submitting creates the\n * provider (status DRAFT/ACTIVE) for admin review — no fabricated KYC upload.\n */\nimport { useMemo, useState } from 'react';\nimport { Store, MapPin, Truck, CheckCircle2, ShieldCheck, ArrowRight, ArrowLeft } from 'lucide-react';\nimport { GlassCard } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { useKadaikodi } from '../../context/KadaikodiContext';\nimport { useProviders, useCreateProvider } from '../../hooks/useKadaikodiApi';\nimport { StepProgress } from '../../components/viz';\n\nconst CATEGORIES = [\n ['FOOD_BEVERAGE', 'Food & Beverage'],\n ['GROCERY_ESSENTIALS', 'Grocery & Essentials'],\n ['CLOTHING_FASHION', 'Clothing & Fashion'],\n ['RETAIL_MERCHANDISE', 'Retail & Merchandise'],\n ['PERSONAL_CARE_BEAUTY', 'Personal Care & Beauty'],\n ['REPAIR_MAINTENANCE', 'Repair & Maintenance'],\n ['HOME_SERVICES', 'Home Services'],\n ['HEALTH_WELLNESS', 'Health & Wellness'],\n ['EDUCATION_SKILLS', 'Education & Skills'],\n] as const;\n\nconst FULFILMENTS = [\n ['PICKUP', 'Pickup'],\n ['DELIVERY', 'Delivery'],\n ['CART_DISPATCH', 'Cart dispatch'],\n ['ON_LOCATION', 'On-location'],\n ['HOME_SERVICE', 'Home service'],\n] as const;\n\nconst STEPS = [\n { label: 'Business details' },\n { label: 'Location & hours' },\n { label: 'Fulfilment' },\n { label: 'Review & submit' },\n];\n\nconst slugify = (s: string) =>\n s.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '').slice(0, 40) +\n '-' +\n Math.random().toString(36).slice(2, 7);\n\nexport function MerchantOnboardingPage() {\n const { navigateTo, currentUser } = useKadaikodi();\n const { data: providers = [] } = useProviders();\n const createProvider = useCreateProvider();\n const alreadyHasProvider = useMemo(\n () => providers.some((p) => p.ownerId === currentUser?.id),\n [providers, currentUser?.id]\n );\n\n const [step, setStep] = useState(0);\n const [done, setDone] = useState(false);\n const [error, setError] = useState('');\n const [form, setForm] = useState({\n name: '',\n category: 'FOOD_BEVERAGE' as (typeof CATEGORIES)[number][0],\n description: '',\n address: '',\n open: '08:00',\n close: '22:00',\n fulfilments: ['PICKUP', 'DELIVERY'] as string[],\n });\n const set = <K extends keyof typeof form>(k: K, v: (typeof form)[K]) => setForm((f) => ({ ...f, [k]: v }));\n const inputCls =\n 'w-full rounded-lg border border-border-subtle bg-bg-canvas px-3 py-2 text-sm text-text-primary outline-none focus:border-border-strong';\n\n const canNext =\n step === 0 ? form.name.trim().length > 1 : step === 1 ? form.address.trim().length > 3 : true;\n\n const submit = () => {\n setError('');\n createProvider.mutate(\n {\n ownerId: currentUser?.id,\n name: form.name.trim(),\n slug: slugify(form.name),\n description: form.description.trim() || undefined,\n category: form.category,\n offeringType: 'both',\n serviceTypes: [],\n location: { address: form.address.trim() },\n businessHours: { open: form.open, close: form.close },\n },\n {\n onSuccess: () => setDone(true),\n onError: (e) => setError(e instanceof Error ? e.message : 'Could not create your cart.'),\n }\n );\n };\n\n if (done) {\n return (\n <PageLayout title=\"You're all set\" description=\"Your cart has been submitted\">\n <div className=\"mx-auto max-w-xl\">\n <GlassCard treatment=\"glass\" className=\"p-8 text-center\">\n <div className=\"mx-auto mb-4 flex h-14 w-14 items-center justify-center rounded-full bg-status-success-bg-subtle\">\n <CheckCircle2 className=\"h-7 w-7 text-status-success-text\" />\n </div>\n <h3 className=\"text-lg font-semibold text-text-primary\">Submitted for verification</h3>\n <p className=\"mx-auto mt-2 max-w-md text-sm text-text-secondary\">\n “{form.name}” has been created and sent for admin review. You can add offerings, set detailed\n hours and open your service from the dashboard now.\n </p>\n <div className=\"mt-6 flex flex-col justify-center gap-3 sm:flex-row\">\n <button\n type=\"button\"\n onClick={() => navigateTo('/cart-owner/inventory')}\n className=\"rounded-lg border border-border-default bg-bg-surface px-5 py-2.5 text-sm font-medium text-text-secondary hover:bg-bg-sunken\"\n >\n Add offerings\n </button>\n <button\n type=\"button\"\n onClick={() => navigateTo('/cart-owner/dashboard')}\n className=\"rounded-lg bg-action-primary-bg px-5 py-2.5 text-sm font-semibold text-action-primary-text hover:bg-action-primary-bg-hover\"\n >\n Go to Dashboard\n </button>\n </div>\n </GlassCard>\n </div>\n </PageLayout>\n );\n }\n\n return (\n <PageLayout title=\"Set up your cart\" description=\"Get your business live and discoverable on the marketplace\">\n <div className=\"mx-auto max-w-2xl space-y-6\">\n {alreadyHasProvider && (\n <div className=\"flex items-center gap-2 rounded-lg border border-status-info-text/30 bg-status-info-bg-subtle p-3 text-sm text-text-secondary\">\n <ShieldCheck className=\"h-4 w-4 text-status-info-text\" />\n You already have a cart — this creates an additional one.\n </div>\n )}\n\n <StepProgress steps={STEPS} current={step} />\n\n <GlassCard treatment=\"plain\" className=\"p-6\">\n {step === 0 && (\n <div className=\"space-y-4\">\n <div className=\"flex items-center gap-2 text-text-primary\">\n <Store className=\"h-5 w-5 text-accent-primary\" /> <h3 className=\"font-semibold\">Business details</h3>\n </div>\n <div>\n <label className=\"mb-1 block text-sm font-medium text-text-secondary\">Business name</label>\n <input className={inputCls} value={form.name} onChange={(e) => set('name', e.target.value)} placeholder=\"Anna Nagar Tiffin Cart\" />\n </div>\n <div>\n <label className=\"mb-1 block text-sm font-medium text-text-secondary\">Category</label>\n <div className=\"grid grid-cols-2 gap-2 sm:grid-cols-3\">\n {CATEGORIES.map(([val, label]) => (\n <button\n key={val}\n type=\"button\"\n onClick={() => set('category', val)}\n className={\n 'rounded-lg border px-3 py-2 text-xs font-medium transition ' +\n (form.category === val\n ? 'border-accent-primary bg-accent-primary/10 text-accent-primary'\n : 'border-border-subtle bg-bg-canvas text-text-secondary hover:bg-bg-sunken')\n }\n >\n {label}\n </button>\n ))}\n </div>\n </div>\n <div>\n <label className=\"mb-1 block text-sm font-medium text-text-secondary\">Description</label>\n <textarea className={inputCls} rows={3} value={form.description} onChange={(e) => set('description', e.target.value)} placeholder=\"What you sell and what makes you special.\" />\n </div>\n </div>\n )}\n\n {step === 1 && (\n <div className=\"space-y-4\">\n <div className=\"flex items-center gap-2 text-text-primary\">\n <MapPin className=\"h-5 w-5 text-accent-primary\" /> <h3 className=\"font-semibold\">Location & hours</h3>\n </div>\n <div>\n <label className=\"mb-1 block text-sm font-medium text-text-secondary\">Address</label>\n <input className={inputCls} value={form.address} onChange={(e) => set('address', e.target.value)} placeholder=\"24 North Usman Rd, Anna Nagar, Chennai\" />\n </div>\n <div className=\"grid grid-cols-2 gap-4\">\n <div>\n <label className=\"mb-1 block text-sm font-medium text-text-secondary\">Opens</label>\n <input type=\"time\" className={inputCls} value={form.open} onChange={(e) => set('open', e.target.value)} />\n </div>\n <div>\n <label className=\"mb-1 block text-sm font-medium text-text-secondary\">Closes</label>\n <input type=\"time\" className={inputCls} value={form.close} onChange={(e) => set('close', e.target.value)} />\n </div>\n </div>\n <p className=\"text-xs text-text-muted\">You can set detailed per-day hours later in Service Config.</p>\n </div>\n )}\n\n {step === 2 && (\n <div className=\"space-y-4\">\n <div className=\"flex items-center gap-2 text-text-primary\">\n <Truck className=\"h-5 w-5 text-accent-primary\" /> <h3 className=\"font-semibold\">Fulfilment modes</h3>\n </div>\n <p className=\"text-sm text-text-secondary\">How will customers receive their orders?</p>\n <div className=\"grid grid-cols-2 gap-2 sm:grid-cols-3\">\n {FULFILMENTS.map(([val, label]) => {\n const on = form.fulfilments.includes(val);\n return (\n <button\n key={val}\n type=\"button\"\n onClick={() =>\n set('fulfilments', on ? form.fulfilments.filter((x) => x !== val) : [...form.fulfilments, val])\n }\n className={\n 'rounded-lg border px-3 py-2 text-sm font-medium transition ' +\n (on\n ? 'border-accent-primary bg-accent-primary/10 text-accent-primary'\n : 'border-border-subtle bg-bg-canvas text-text-secondary hover:bg-bg-sunken')\n }\n >\n {label}\n </button>\n );\n })}\n </div>\n </div>\n )}\n\n {step === 3 && (\n <div className=\"space-y-4\">\n <div className=\"flex items-center gap-2 text-text-primary\">\n <ShieldCheck className=\"h-5 w-5 text-accent-primary\" /> <h3 className=\"font-semibold\">Review & submit</h3>\n </div>\n <dl className=\"space-y-2 text-sm\">\n <div className=\"flex justify-between border-b border-border-subtle py-2\"><dt className=\"text-text-secondary\">Business</dt><dd className=\"font-medium text-text-primary\">{form.name || '—'}</dd></div>\n <div className=\"flex justify-between border-b border-border-subtle py-2\"><dt className=\"text-text-secondary\">Category</dt><dd className=\"font-medium text-text-primary\">{CATEGORIES.find((c) => c[0] === form.category)?.[1]}</dd></div>\n <div className=\"flex justify-between border-b border-border-subtle py-2\"><dt className=\"text-text-secondary\">Address</dt><dd className=\"max-w-[60%] text-right font-medium text-text-primary\">{form.address || '—'}</dd></div>\n <div className=\"flex justify-between border-b border-border-subtle py-2\"><dt className=\"text-text-secondary\">Hours</dt><dd className=\"font-medium text-text-primary\">{form.open}–{form.close}</dd></div>\n <div className=\"flex justify-between py-2\"><dt className=\"text-text-secondary\">Fulfilment</dt><dd className=\"max-w-[60%] text-right font-medium text-text-primary\">{form.fulfilments.map((f) => FULFILMENTS.find((x) => x[0] === f)?.[1]).join(', ') || '—'}</dd></div>\n </dl>\n <div className=\"rounded-lg border border-border-subtle bg-bg-sunken/50 p-3 text-xs text-text-secondary\">\n On submit, your cart is created and sent to platform admins for verification. Verification documents\n (GST, licences) can be added from your profile once that step is enabled.\n </div>\n {error && <p className=\"text-sm text-status-error-text\">{error}</p>}\n </div>\n )}\n\n {/* Wizard controls */}\n <div className=\"mt-6 flex items-center justify-between border-t border-border-subtle pt-4\">\n <button\n type=\"button\"\n onClick={() => (step === 0 ? navigateTo('/cart-owner/dashboard') : setStep((s) => s - 1))}\n className=\"inline-flex items-center gap-1.5 rounded-lg border border-border-default bg-bg-surface px-4 py-2 text-sm font-medium text-text-secondary hover:bg-bg-sunken\"\n >\n <ArrowLeft className=\"h-4 w-4\" /> {step === 0 ? 'Cancel' : 'Back'}\n </button>\n {step < STEPS.length - 1 ? (\n <button\n type=\"button\"\n disabled={!canNext}\n onClick={() => setStep((s) => s + 1)}\n className=\"inline-flex items-center gap-1.5 rounded-lg bg-action-primary-bg px-5 py-2 text-sm font-semibold text-action-primary-text hover:bg-action-primary-bg-hover disabled:opacity-50\"\n >\n Continue <ArrowRight className=\"h-4 w-4\" />\n </button>\n ) : (\n <button\n type=\"button\"\n disabled={createProvider.isPending}\n onClick={submit}\n className=\"inline-flex items-center gap-1.5 rounded-lg bg-action-primary-bg px-5 py-2 text-sm font-semibold text-action-primary-text hover:bg-action-primary-bg-hover disabled:opacity-60\"\n >\n <ShieldCheck className=\"h-4 w-4\" /> {createProvider.isPending ? 'Submitting…' : 'Submit for Verification'}\n </button>\n )}\n </div>\n </GlassCard>\n </div>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"MerchantOnboardingPage.js","names":[],"sources":["../../../../src/kadaikodi/pages/cart-owner/MerchantOnboardingPage.tsx"],"sourcesContent":["/**\n * MerchantOnboardingPage — guided first-time merchant setup.\n *\n * A real StepProgress wizard that creates a live ServiceProvider (via\n * kadaikodiCreateServiceProvider) across Business details → Location & hours →\n * Fulfilment → Review & submit. Verification is honest: submitting creates the\n * provider (status DRAFT/ACTIVE) for admin review — no fabricated KYC upload.\n */\nimport { useMemo, useState } from 'react';\nimport {\n Store,\n MapPin,\n Truck,\n CheckCircle2,\n ShieldCheck,\n ArrowRight,\n ArrowLeft,\n} from 'lucide-react';\nimport { GlassCard } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { useKadaikodi } from '../../context/KadaikodiContext';\nimport { useProviders, useCreateProvider } from '../../hooks/useKadaikodiApi';\nimport { StepProgress } from '../../components/viz';\n\nconst CATEGORIES = [\n ['FOOD_BEVERAGE', 'Food & Beverage'],\n ['GROCERY_ESSENTIALS', 'Grocery & Essentials'],\n ['CLOTHING_FASHION', 'Clothing & Fashion'],\n ['RETAIL_MERCHANDISE', 'Retail & Merchandise'],\n ['PERSONAL_CARE_BEAUTY', 'Personal Care & Beauty'],\n ['REPAIR_MAINTENANCE', 'Repair & Maintenance'],\n ['HOME_SERVICES', 'Home Services'],\n ['HEALTH_WELLNESS', 'Health & Wellness'],\n ['EDUCATION_SKILLS', 'Education & Skills'],\n] as const;\n\nconst FULFILMENTS = [\n ['PICKUP', 'Pickup'],\n ['DELIVERY', 'Delivery'],\n ['CART_DISPATCH', 'Cart dispatch'],\n ['ON_LOCATION', 'On-location'],\n ['HOME_SERVICE', 'Home service'],\n] as const;\n\nconst STEPS = [\n { label: 'Business details' },\n { label: 'Location & hours' },\n { label: 'Fulfilment' },\n { label: 'Review & submit' },\n];\n\nconst slugify = (s: string) =>\n s\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-|-$/g, '')\n .slice(0, 40) +\n '-' +\n Math.random().toString(36).slice(2, 7);\n\nexport function MerchantOnboardingPage() {\n const { navigateTo, currentUser } = useKadaikodi();\n const { data: providers = [] } = useProviders();\n const createProvider = useCreateProvider();\n const alreadyHasProvider = useMemo(\n () => providers.some((p) => p.ownerId === currentUser?.id),\n [providers, currentUser?.id]\n );\n\n const [step, setStep] = useState(0);\n const [done, setDone] = useState(false);\n const [error, setError] = useState('');\n const [form, setForm] = useState({\n name: '',\n category: 'FOOD_BEVERAGE' as (typeof CATEGORIES)[number][0],\n description: '',\n address: '',\n open: '08:00',\n close: '22:00',\n fulfilments: ['PICKUP', 'DELIVERY'] as string[],\n });\n const set = <K extends keyof typeof form>(k: K, v: (typeof form)[K]) =>\n setForm((f) => ({ ...f, [k]: v }));\n const inputCls =\n 'w-full rounded-lg border border-border-subtle bg-bg-canvas px-3 py-2 text-sm text-text-primary outline-none focus:border-border-strong';\n\n const canNext =\n step === 0 ? form.name.trim().length > 1 : step === 1 ? form.address.trim().length > 3 : true;\n\n const submit = () => {\n setError('');\n createProvider.mutate(\n {\n ownerId: currentUser?.id,\n name: form.name.trim(),\n slug: slugify(form.name),\n description: form.description.trim() || undefined,\n category: form.category,\n offeringType: 'both',\n serviceTypes: [],\n location: { address: form.address.trim() },\n businessHours: { open: form.open, close: form.close },\n },\n {\n onSuccess: () => setDone(true),\n onError: (e) => setError(e instanceof Error ? e.message : 'Could not create your cart.'),\n }\n );\n };\n\n if (done) {\n return (\n <PageLayout title=\"You're all set\" description=\"Your cart has been submitted\">\n <div className=\"mx-auto max-w-xl\">\n <GlassCard treatment=\"glass\" className=\"p-8 text-center\">\n <div className=\"mx-auto mb-4 flex h-14 w-14 items-center justify-center rounded-full bg-status-success-bg-subtle\">\n <CheckCircle2 className=\"h-7 w-7 text-status-success-text\" />\n </div>\n <h3 className=\"text-lg font-semibold text-text-primary\">Submitted for verification</h3>\n <p className=\"mx-auto mt-2 max-w-md text-sm text-text-secondary\">\n “{form.name}” has been created and sent for admin review. You can add offerings, set\n detailed hours and open your service from the dashboard now.\n </p>\n <div className=\"mt-6 flex flex-col justify-center gap-3 sm:flex-row\">\n <button\n type=\"button\"\n onClick={() => navigateTo('/cart-owner/inventory')}\n className=\"rounded-lg border border-border-default bg-bg-surface px-5 py-2.5 text-sm font-medium text-text-secondary hover:bg-bg-sunken\"\n >\n Add offerings\n </button>\n <button\n type=\"button\"\n onClick={() => navigateTo('/cart-owner/dashboard')}\n className=\"rounded-lg bg-action-primary-bg px-5 py-2.5 text-sm font-semibold text-action-primary-text hover:bg-action-primary-bg-hover\"\n >\n Go to Dashboard\n </button>\n </div>\n </GlassCard>\n </div>\n </PageLayout>\n );\n }\n\n return (\n <PageLayout\n title=\"Set up your cart\"\n description=\"Get your business live and discoverable on the marketplace\"\n >\n <div className=\"mx-auto max-w-2xl space-y-6\">\n {alreadyHasProvider && (\n <div className=\"flex items-center gap-2 rounded-lg border border-status-info-text/30 bg-status-info-bg-subtle p-3 text-sm text-text-secondary\">\n <ShieldCheck className=\"h-4 w-4 text-status-info-text\" />\n You already have a cart — this creates an additional one.\n </div>\n )}\n\n <StepProgress steps={STEPS} current={step} />\n\n <GlassCard treatment=\"plain\" className=\"p-6\">\n {step === 0 && (\n <div className=\"space-y-4\">\n <div className=\"flex items-center gap-2 text-text-primary\">\n <Store className=\"h-5 w-5 text-accent-primary\" />{' '}\n <h3 className=\"font-semibold\">Business details</h3>\n </div>\n <div>\n <label className=\"mb-1 block text-sm font-medium text-text-secondary\">\n Business name\n </label>\n <input\n className={inputCls}\n value={form.name}\n onChange={(e) => set('name', e.target.value)}\n placeholder=\"Anna Nagar Tiffin Cart\"\n />\n </div>\n <div>\n <label className=\"mb-1 block text-sm font-medium text-text-secondary\">\n Category\n </label>\n <div className=\"grid grid-cols-2 gap-2 sm:grid-cols-3\">\n {CATEGORIES.map(([val, label]) => (\n <button\n key={val}\n type=\"button\"\n onClick={() => set('category', val)}\n className={\n 'rounded-lg border px-3 py-2 text-xs font-medium transition ' +\n (form.category === val\n ? 'border-accent-primary bg-accent-primary/10 text-accent-primary'\n : 'border-border-subtle bg-bg-canvas text-text-secondary hover:bg-bg-sunken')\n }\n >\n {label}\n </button>\n ))}\n </div>\n </div>\n <div>\n <label className=\"mb-1 block text-sm font-medium text-text-secondary\">\n Description\n </label>\n <textarea\n className={inputCls}\n rows={3}\n value={form.description}\n onChange={(e) => set('description', e.target.value)}\n placeholder=\"What you sell and what makes you special.\"\n />\n </div>\n </div>\n )}\n\n {step === 1 && (\n <div className=\"space-y-4\">\n <div className=\"flex items-center gap-2 text-text-primary\">\n <MapPin className=\"h-5 w-5 text-accent-primary\" />{' '}\n <h3 className=\"font-semibold\">Location & hours</h3>\n </div>\n <div>\n <label className=\"mb-1 block text-sm font-medium text-text-secondary\">\n Address\n </label>\n <input\n className={inputCls}\n value={form.address}\n onChange={(e) => set('address', e.target.value)}\n placeholder=\"24 North Usman Rd, Anna Nagar, Chennai\"\n />\n </div>\n <div className=\"grid grid-cols-2 gap-4\">\n <div>\n <label className=\"mb-1 block text-sm font-medium text-text-secondary\">\n Opens\n </label>\n <input\n type=\"time\"\n className={inputCls}\n value={form.open}\n onChange={(e) => set('open', e.target.value)}\n />\n </div>\n <div>\n <label className=\"mb-1 block text-sm font-medium text-text-secondary\">\n Closes\n </label>\n <input\n type=\"time\"\n className={inputCls}\n value={form.close}\n onChange={(e) => set('close', e.target.value)}\n />\n </div>\n </div>\n <p className=\"text-xs text-text-muted\">\n You can set detailed per-day hours later in Service Config.\n </p>\n </div>\n )}\n\n {step === 2 && (\n <div className=\"space-y-4\">\n <div className=\"flex items-center gap-2 text-text-primary\">\n <Truck className=\"h-5 w-5 text-accent-primary\" />{' '}\n <h3 className=\"font-semibold\">Fulfilment modes</h3>\n </div>\n <p className=\"text-sm text-text-secondary\">\n How will customers receive their orders?\n </p>\n <div className=\"grid grid-cols-2 gap-2 sm:grid-cols-3\">\n {FULFILMENTS.map(([val, label]) => {\n const on = form.fulfilments.includes(val);\n return (\n <button\n key={val}\n type=\"button\"\n onClick={() =>\n set(\n 'fulfilments',\n on\n ? form.fulfilments.filter((x) => x !== val)\n : [...form.fulfilments, val]\n )\n }\n className={\n 'rounded-lg border px-3 py-2 text-sm font-medium transition ' +\n (on\n ? 'border-accent-primary bg-accent-primary/10 text-accent-primary'\n : 'border-border-subtle bg-bg-canvas text-text-secondary hover:bg-bg-sunken')\n }\n >\n {label}\n </button>\n );\n })}\n </div>\n </div>\n )}\n\n {step === 3 && (\n <div className=\"space-y-4\">\n <div className=\"flex items-center gap-2 text-text-primary\">\n <ShieldCheck className=\"h-5 w-5 text-accent-primary\" />{' '}\n <h3 className=\"font-semibold\">Review & submit</h3>\n </div>\n <dl className=\"space-y-2 text-sm\">\n <div className=\"flex justify-between border-b border-border-subtle py-2\">\n <dt className=\"text-text-secondary\">Business</dt>\n <dd className=\"font-medium text-text-primary\">{form.name || '—'}</dd>\n </div>\n <div className=\"flex justify-between border-b border-border-subtle py-2\">\n <dt className=\"text-text-secondary\">Category</dt>\n <dd className=\"font-medium text-text-primary\">\n {CATEGORIES.find((c) => c[0] === form.category)?.[1]}\n </dd>\n </div>\n <div className=\"flex justify-between border-b border-border-subtle py-2\">\n <dt className=\"text-text-secondary\">Address</dt>\n <dd className=\"max-w-[60%] text-right font-medium text-text-primary\">\n {form.address || '—'}\n </dd>\n </div>\n <div className=\"flex justify-between border-b border-border-subtle py-2\">\n <dt className=\"text-text-secondary\">Hours</dt>\n <dd className=\"font-medium text-text-primary\">\n {form.open}–{form.close}\n </dd>\n </div>\n <div className=\"flex justify-between py-2\">\n <dt className=\"text-text-secondary\">Fulfilment</dt>\n <dd className=\"max-w-[60%] text-right font-medium text-text-primary\">\n {form.fulfilments\n .map((f) => FULFILMENTS.find((x) => x[0] === f)?.[1])\n .join(', ') || '—'}\n </dd>\n </div>\n </dl>\n <div className=\"rounded-lg border border-border-subtle bg-bg-sunken/50 p-3 text-xs text-text-secondary\">\n On submit, your cart is created and sent to platform admins for verification.\n Verification documents (GST, licences) can be added from your profile once that step\n is enabled.\n </div>\n {error && <p className=\"text-sm text-status-error-text\">{error}</p>}\n </div>\n )}\n\n {/* Wizard controls */}\n <div className=\"mt-6 flex items-center justify-between border-t border-border-subtle pt-4\">\n <button\n type=\"button\"\n onClick={() =>\n step === 0 ? navigateTo('/cart-owner/dashboard') : setStep((s) => s - 1)\n }\n className=\"inline-flex items-center gap-1.5 rounded-lg border border-border-default bg-bg-surface px-4 py-2 text-sm font-medium text-text-secondary hover:bg-bg-sunken\"\n >\n <ArrowLeft className=\"h-4 w-4\" /> {step === 0 ? 'Cancel' : 'Back'}\n </button>\n {step < STEPS.length - 1 ? (\n <button\n type=\"button\"\n disabled={!canNext}\n onClick={() => setStep((s) => s + 1)}\n className=\"inline-flex items-center gap-1.5 rounded-lg bg-action-primary-bg px-5 py-2 text-sm font-semibold text-action-primary-text hover:bg-action-primary-bg-hover disabled:opacity-50\"\n >\n Continue <ArrowRight className=\"h-4 w-4\" />\n </button>\n ) : (\n <button\n type=\"button\"\n disabled={createProvider.isPending}\n onClick={submit}\n className=\"inline-flex items-center gap-1.5 rounded-lg bg-action-primary-bg px-5 py-2 text-sm font-semibold text-action-primary-text hover:bg-action-primary-bg-hover disabled:opacity-60\"\n >\n <ShieldCheck className=\"h-4 w-4\" />{' '}\n {createProvider.isPending ? 'Submitting…' : 'Submit for Verification'}\n </button>\n )}\n </div>\n </GlassCard>\n </div>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OrderManagementPage.d.ts","sourceRoot":"","sources":["../../../../src/kadaikodi/pages/cart-owner/OrderManagementPage.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AA2HH,eAAO,MAAM,mBAAmB,
|
|
1
|
+
{"version":3,"file":"OrderManagementPage.d.ts","sourceRoot":"","sources":["../../../../src/kadaikodi/pages/cart-owner/OrderManagementPage.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AA2HH,eAAO,MAAM,mBAAmB,mCAkxB/B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OrderManagementPage.js","names":[],"sources":["../../../../src/kadaikodi/pages/cart-owner/OrderManagementPage.tsx"],"sourcesContent":["/**\n * Order Management Page\n *\n * Stats overview, status-filtered order list with search/date/sort/fulfillment filters,\n * order detail modal, accept/reject/ready/complete actions, priority highlighting.\n *\n * @module kadaikodi/pages/cart-owner\n */\n\nimport { useState, useMemo, useEffect } from 'react';\nimport {\n Search,\n Clock,\n CheckCircle2,\n XCircle,\n ChefHat,\n PackageCheck,\n Phone,\n MapPin,\n User,\n RefreshCw,\n Truck,\n ShoppingBag,\n X,\n AlertCircle,\n Filter,\n ChevronDown,\n} from 'lucide-react';\nimport { EmphasisPanel, PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { EmptyState } from '../../components/EmptyState';\nimport { StatCard, KanbanBoard, SegmentedTabs, STATUS } from '../../components/viz';\nimport type { KanbanColumnData } from '../../components/viz';\nimport { useKadaikodi } from '../../context/KadaikodiContext';\nimport { useOrders, useUpdateOrderStatus, useProviders } from '../../hooks/useKadaikodiApi';\nimport { formatCurrency } from '../../utils/formatters';\nimport { cn } from '../../utils/cn';\nimport type { MockOrder, OrderStatus } from '../../types';\n\n// ============================================================================\n// Types\n// ============================================================================\n\ninterface StatusMessage {\n text: string;\n type: 'success' | 'error';\n}\n\ninterface OrderFilters {\n status: string;\n dateRange: string;\n searchQuery: string;\n sortBy: string;\n fulfillmentType: string;\n}\n\n/** Extended order type with cart-owner specific fields */\ninterface ExtendedOrder extends MockOrder {\n customerName?: string;\n customerPhone?: string;\n fulfillmentType?: 'delivery' | 'pickup' | 'cart_dispatch';\n specialInstructions?: string;\n}\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nconst statusConfig: Record<string, { color: string; label: string }> = {\n pending: { color: 'bg-status-warning-bg-subtle text-status-warning-text', label: 'New Order' },\n confirmed: { color: 'bg-[var(--color-accent-soft)] text-text-primary', label: 'Confirmed' },\n preparing: { color: 'bg-status-warning-bg-subtle text-status-warning-text', label: 'Preparing' },\n ready: { color: 'bg-status-success-bg-subtle text-status-success-text', label: 'Ready' },\n out_for_delivery: {\n color: 'bg-[var(--color-accent-soft)] text-text-primary',\n label: 'Out for Delivery',\n },\n delivered: { color: 'bg-status-success-bg-subtle text-status-success-text', label: 'Completed' },\n cancelled: { color: 'bg-status-error-bg-subtle text-status-error-text', label: 'Cancelled' },\n};\n\nconst fulfillmentBadge: Record<string, { icon: typeof Truck; label: string; color: string }> = {\n delivery: {\n icon: Truck,\n label: 'Delivery',\n color: 'bg-accent-purple-subtle text-text-primary',\n },\n pickup: {\n icon: ShoppingBag,\n label: 'Pickup',\n color: 'bg-[var(--color-accent-soft)] text-text-primary',\n },\n cart_dispatch: {\n icon: MapPin,\n label: 'Cart Dispatch',\n color: 'bg-bg-sunken text-text-secondary',\n },\n};\n\nconst formatTimeAgo = (dateString: string) => {\n const date = new Date(dateString);\n const now = new Date();\n const diffMin = Math.floor((now.getTime() - date.getTime()) / (1000 * 60));\n if (diffMin < 1) return 'Just now';\n if (diffMin < 60) return `${diffMin} min ago`;\n if (diffMin < 1440) return `${Math.floor(diffMin / 60)} hours ago`;\n return date.toLocaleDateString('en-IN', { day: '2-digit', month: 'short' });\n};\n\nconst formatTime = (dateString: string) => {\n return new Date(dateString).toLocaleTimeString('en-IN', {\n hour: 'numeric',\n minute: '2-digit',\n hour12: true,\n });\n};\n\nconst getPriorityColor = (order: ExtendedOrder) => {\n const ageMin = (new Date().getTime() - new Date(order.orderDate).getTime()) / (1000 * 60);\n if (order.status === 'pending' && ageMin > 10)\n return 'border-status-error-text/50 bg-status-error-bg-subtle';\n if (order.status === 'preparing' && ageMin > 30)\n return 'border-status-warning-text/50 bg-status-warning-bg-subtle';\n return 'border-border-subtle';\n};\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport const OrderManagementPage = () => {\n const { navigateTo, currentUser } = useKadaikodi();\n\n // Resolve the signed-in owner's provider, then load its real orders.\n const { data: providers = [] } = useProviders();\n const myProvider = useMemo(\n () => providers.find((p) => p.ownerId === currentUser?.id) ?? providers[0],\n [providers, currentUser?.id]\n );\n const {\n data: fetchedOrders = [],\n isLoading: isLoadingOrders,\n refetch: refetchOrders,\n isFetching: isFetchingOrders,\n } = useOrders({\n providerId: myProvider?.id,\n });\n const updateOrderStatus = useUpdateOrderStatus();\n\n // Local working copy so status actions feel instant; kept in sync with the query.\n const [orders, setOrders] = useState<ExtendedOrder[]>([]);\n useEffect(() => {\n setOrders(fetchedOrders);\n }, [fetchedOrders]);\n\n // Filters\n const [filters, setFilters] = useState<OrderFilters>({\n status: '',\n dateRange: 'all',\n searchQuery: '',\n sortBy: 'recent',\n fulfillmentType: '',\n });\n\n // View: live board (kanban) vs detailed list\n const [view, setView] = useState<'board' | 'list'>('board');\n\n // Modal\n const [selectedOrder, setSelectedOrder] = useState<ExtendedOrder | null>(null);\n const [showOrderDetails, setShowOrderDetails] = useState(false);\n\n // Status\n const [statusMessage, setStatusMessage] = useState<StatusMessage | null>(null);\n\n const showStatus = (text: string, type: 'success' | 'error') => {\n setStatusMessage({ text, type });\n setTimeout(() => setStatusMessage(null), 3000);\n };\n\n // ---- Stats ----\n const stats = useMemo(() => {\n const total = orders.length;\n const pending = orders.filter((o) => o.status === 'pending').length;\n const active = orders.filter((o) =>\n ['confirmed', 'preparing', 'ready', 'out_for_delivery'].includes(o.status)\n ).length;\n const completed = orders.filter((o) => o.status === 'delivered').length;\n const totalRevenue = orders\n .filter((o) => o.status === 'delivered')\n .reduce((s, o) => s + o.total, 0);\n const avgOrder = completed > 0 ? Math.round(totalRevenue / completed) : 0;\n return { total, pending, active, completed, totalRevenue, avgOrder };\n }, [orders]);\n\n // ---- Filtered orders ----\n const filteredOrders = useMemo(() => {\n let result = [...orders];\n\n if (filters.status) {\n result = result.filter((o) => o.status === filters.status);\n }\n if (filters.fulfillmentType) {\n result = result.filter((o) => o.fulfillmentType === filters.fulfillmentType);\n }\n if (filters.searchQuery) {\n const q = filters.searchQuery.toLowerCase();\n result = result.filter(\n (o) =>\n o.id.toLowerCase().includes(q) ||\n (o.customerName || '').toLowerCase().includes(q) ||\n o.items.some((item) => item.name.toLowerCase().includes(q))\n );\n }\n if (filters.dateRange !== 'all') {\n const now = new Date();\n const limit = new Date();\n if (filters.dateRange === 'today') limit.setHours(0, 0, 0, 0);\n else if (filters.dateRange === '7days') limit.setDate(now.getDate() - 7);\n else if (filters.dateRange === '30days') limit.setDate(now.getDate() - 30);\n result = result.filter((o) => new Date(o.orderDate) >= limit);\n }\n\n switch (filters.sortBy) {\n case 'recent':\n result.sort((a, b) => new Date(b.orderDate).getTime() - new Date(a.orderDate).getTime());\n break;\n case 'oldest':\n result.sort((a, b) => new Date(a.orderDate).getTime() - new Date(b.orderDate).getTime());\n break;\n case 'amount_high':\n result.sort((a, b) => b.total - a.total);\n break;\n case 'amount_low':\n result.sort((a, b) => a.total - b.total);\n break;\n }\n\n return result;\n }, [orders, filters]);\n\n // ---- Board orders: same search/type/date filters, but every status kept so\n // each lifecycle column is populated (status is expressed by the column). ----\n const boardOrders = useMemo(() => {\n let result = [...orders];\n if (filters.fulfillmentType) {\n result = result.filter((o) => o.fulfillmentType === filters.fulfillmentType);\n }\n if (filters.searchQuery) {\n const q = filters.searchQuery.toLowerCase();\n result = result.filter(\n (o) =>\n o.id.toLowerCase().includes(q) ||\n (o.customerName || '').toLowerCase().includes(q) ||\n o.items.some((item) => item.name.toLowerCase().includes(q))\n );\n }\n if (filters.dateRange !== 'all') {\n const now = new Date();\n const limit = new Date();\n if (filters.dateRange === 'today') limit.setHours(0, 0, 0, 0);\n else if (filters.dateRange === '7days') limit.setDate(now.getDate() - 7);\n else if (filters.dateRange === '30days') limit.setDate(now.getDate() - 30);\n result = result.filter((o) => new Date(o.orderDate) >= limit);\n }\n return result.sort(\n (a, b) => new Date(b.orderDate).getTime() - new Date(a.orderDate).getTime()\n );\n }, [orders, filters.fulfillmentType, filters.searchQuery, filters.dateRange]);\n\n // ---- Actions ----\n const handleRefresh = async () => {\n await refetchOrders();\n showStatus('Orders refreshed', 'success');\n };\n\n const handleOrderAction = (\n orderId: string,\n action: 'accept' | 'reject' | 'prepare' | 'ready' | 'complete'\n ) => {\n const statusMap: Record<string, OrderStatus> = {\n accept: 'confirmed',\n reject: 'cancelled',\n prepare: 'preparing',\n ready: 'ready',\n complete: 'delivered',\n };\n const backendStatusMap: Record<string, string> = {\n accept: 'CONFIRMED',\n reject: 'CANCELLED',\n prepare: 'PREPARING',\n ready: 'READY',\n complete: 'DELIVERED',\n };\n const messages: Record<string, string> = {\n accept: 'Order accepted',\n reject: 'Order rejected',\n prepare: 'Order moved to preparing',\n ready: 'Order marked as ready',\n complete: 'Order completed',\n };\n\n setOrders((prev) =>\n prev.map((o) => (o.id === orderId ? { ...o, status: statusMap[action] } : o))\n );\n updateOrderStatus.mutate(\n { id: orderId, status: backendStatusMap[action] },\n { onError: () => showStatus('Could not update the order on the server', 'error') }\n );\n showStatus(messages[action], 'success');\n if (showOrderDetails && selectedOrder?.id === orderId) {\n setShowOrderDetails(false);\n }\n };\n\n // ---- Kanban card + columns ----\n const renderBoardCard = (order: ExtendedOrder) => {\n const fulfillment =\n fulfillmentBadge[order.fulfillmentType || 'delivery'] || fulfillmentBadge.delivery;\n const FulfillmentIcon = fulfillment.icon;\n const primaryAction: { label: string; action: Parameters<typeof handleOrderAction>[1] } | null =\n order.status === 'pending'\n ? { label: 'Accept', action: 'accept' }\n : order.status === 'confirmed'\n ? { label: 'Start Preparing', action: 'prepare' }\n : order.status === 'preparing'\n ? { label: 'Mark Ready', action: 'ready' }\n : order.status === 'ready'\n ? { label: 'Complete', action: 'complete' }\n : null;\n\n return (\n <div className=\"rounded-[var(--radius-input)] border border-border-subtle bg-bg-surface p-3 shadow-sm\">\n <div className=\"mb-1.5 flex items-center justify-between gap-2\">\n <span className=\"truncate text-xs font-medium text-text-secondary\">\n Order #{order.id.slice(0, 8)}\n </span>\n <span className=\"shrink-0 text-[11px] text-text-muted\">\n {formatTimeAgo(order.orderDate)}\n </span>\n </div>\n <div className=\"mb-1.5 flex items-center justify-between gap-2\">\n <span className=\"truncate text-sm font-semibold text-text-primary\">\n {order.customerName || 'Customer'}\n </span>\n <span className=\"shrink-0 text-sm font-bold text-text-primary\">\n {formatCurrency(order.total, { minimumFractionDigits: 0 })}\n </span>\n </div>\n <p className=\"mb-2 line-clamp-2 text-xs text-text-secondary\">\n {order.items.map((i) => `${i.name} ×${i.quantity}`).join(', ')}\n </p>\n <div className=\"mb-2 flex items-center gap-1.5\">\n <span\n className={cn(\n 'inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-[10px] font-medium',\n fulfillment.color\n )}\n >\n <FulfillmentIcon className=\"h-3 w-3\" />\n {fulfillment.label}\n </span>\n </div>\n <div className=\"flex gap-1.5\">\n {primaryAction && (\n <button\n type=\"button\"\n onClick={() => handleOrderAction(order.id, primaryAction.action)}\n className=\"flex-1 rounded-md bg-action-primary-bg px-2.5 py-1.5 text-xs font-medium text-action-primary-text transition-colors hover:bg-action-primary-bg-hover\"\n >\n {primaryAction.label}\n </button>\n )}\n <button\n type=\"button\"\n onClick={() => {\n setSelectedOrder(order);\n setShowOrderDetails(true);\n }}\n className=\"rounded-md border border-border-subtle px-2.5 py-1.5 text-xs font-medium text-text-primary transition-colors hover:bg-bg-sunken\"\n >\n Details\n </button>\n {order.status === 'pending' && (\n <button\n type=\"button\"\n onClick={() => handleOrderAction(order.id, 'reject')}\n aria-label=\"Reject order\"\n className=\"rounded-md border border-border-subtle px-2 py-1.5 text-status-error-text transition-colors hover:bg-status-error-bg-subtle\"\n >\n <XCircle className=\"h-3.5 w-3.5\" />\n </button>\n )}\n </div>\n </div>\n );\n };\n\n const boardColumns: KanbanColumnData[] = [\n {\n id: 'new',\n title: 'New',\n accent: STATUS.warning,\n items: boardOrders.filter((o) => o.status === 'pending').map(renderBoardCard),\n },\n {\n id: 'preparing',\n title: 'Preparing',\n accent: STATUS.info,\n items: boardOrders\n .filter((o) => o.status === 'confirmed' || o.status === 'preparing')\n .map(renderBoardCard),\n },\n {\n id: 'ready',\n title: 'Ready',\n accent: STATUS.success,\n items: boardOrders\n .filter((o) => o.status === 'ready' || o.status === 'out_for_delivery')\n .map(renderBoardCard),\n },\n {\n id: 'completed',\n title: 'Completed',\n items: boardOrders.filter((o) => o.status === 'delivered').map(renderBoardCard),\n },\n ];\n\n return (\n <PageLayout\n title=\"Order Management\"\n description=\"Manage incoming and active orders\"\n actions={\n <button\n type=\"button\"\n onClick={handleRefresh}\n disabled={isFetchingOrders}\n className=\"inline-flex items-center gap-2 rounded-md border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken transition-colors disabled:opacity-60 disabled:cursor-not-allowed\"\n >\n <RefreshCw className={cn('h-4 w-4', isFetchingOrders && 'animate-spin')} />\n Refresh\n </button>\n }\n >\n <PagePurpose className=\"mb-6\">\n Your live order queue. Use this page to run service as it happens — accept new orders, move\n them through preparing and ready, hand off for pickup, delivery or cart dispatch, and keep\n customers updated. Filter by status or type to focus on what needs doing right now, and\n watch today's totals so you know how the day is going.\n </PagePurpose>\n\n <div className=\"space-y-4\">\n {/* Status Message */}\n {statusMessage && (\n <div\n className={cn(\n 'flex items-center gap-2 rounded-lg border p-3',\n statusMessage.type === 'success'\n ? 'border-status-success-text/30 bg-status-success-bg-subtle'\n : 'border-status-error-text/30 bg-status-error-bg-subtle'\n )}\n >\n {statusMessage.type === 'success' ? (\n <CheckCircle2 className=\"h-4 w-4 text-status-success-text\" />\n ) : (\n <AlertCircle className=\"h-4 w-4 text-status-error-text\" />\n )}\n <span\n className={cn(\n 'text-sm font-medium',\n statusMessage.type === 'success'\n ? 'text-status-success-text'\n : 'text-status-error-text'\n )}\n >\n {statusMessage.text}\n </span>\n </div>\n )}\n\n {/* Stats Overview — the one emphasis zone for this page */}\n <EmphasisPanel>\n <h2 className=\"mb-4 text-base font-semibold text-text-primary\">Orders Overview</h2>\n <div className=\"grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-6 gap-3\">\n <StatCard label=\"Total Orders\" value={stats.total} icon={<ShoppingBag className=\"h-4 w-4\" />} />\n <StatCard\n label=\"Pending\"\n value={<span className=\"text-status-warning-text\">{stats.pending}</span>}\n icon={<Clock className=\"h-4 w-4\" />}\n />\n <StatCard\n label=\"Active\"\n value={stats.active}\n icon={<ChefHat className=\"h-4 w-4\" />}\n />\n <StatCard\n label=\"Completed\"\n value={<span className=\"text-status-success-text\">{stats.completed}</span>}\n icon={<CheckCircle2 className=\"h-4 w-4\" />}\n />\n <StatCard\n label=\"Total Revenue\"\n value={formatCurrency(stats.totalRevenue, { minimumFractionDigits: 0 })}\n icon={<PackageCheck className=\"h-4 w-4\" />}\n />\n <StatCard\n label=\"Avg Order\"\n value={formatCurrency(stats.avgOrder, { minimumFractionDigits: 0 })}\n icon={<Truck className=\"h-4 w-4\" />}\n />\n </div>\n </EmphasisPanel>\n\n {/* View toggle: live board vs detailed list */}\n <div className=\"flex items-center justify-between gap-3\">\n <SegmentedTabs\n aria-label=\"Order view\"\n value={view}\n onChange={(id) => setView(id as 'board' | 'list')}\n tabs={[\n { id: 'board', label: 'Board' },\n { id: 'list', label: 'List' },\n ]}\n />\n <p className=\"text-xs text-text-secondary\">\n {boardOrders.length} order{boardOrders.length === 1 ? '' : 's'} in view\n </p>\n </div>\n\n {/* Filters */}\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-4 shadow-sm\">\n <div className=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-5 gap-3\">\n <div className=\"relative sm:col-span-2 lg:col-span-1\">\n <Search className=\"absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-text-secondary\" />\n <input\n type=\"text\"\n placeholder=\"Search orders...\"\n value={filters.searchQuery}\n onChange={(e) => setFilters((p) => ({ ...p, searchQuery: e.target.value }))}\n className=\"w-full rounded-md border border-border-subtle bg-bg-surface pl-10 pr-4 py-2 text-sm text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n />\n </div>\n <select\n value={filters.status}\n onChange={(e) => setFilters((p) => ({ ...p, status: e.target.value }))}\n className=\"rounded-md border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary\"\n >\n <option value=\"\">All Orders</option>\n <option value=\"pending\">New Orders</option>\n <option value=\"confirmed\">Confirmed</option>\n <option value=\"preparing\">Preparing</option>\n <option value=\"ready\">Ready</option>\n <option value=\"delivered\">Completed</option>\n <option value=\"cancelled\">Cancelled</option>\n </select>\n <select\n value={filters.fulfillmentType}\n onChange={(e) => setFilters((p) => ({ ...p, fulfillmentType: e.target.value }))}\n className=\"rounded-md border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary\"\n >\n <option value=\"\">All Types</option>\n <option value=\"pickup\">Pickup</option>\n <option value=\"delivery\">Delivery</option>\n <option value=\"cart_dispatch\">Cart Dispatch</option>\n </select>\n <select\n value={filters.dateRange}\n onChange={(e) => setFilters((p) => ({ ...p, dateRange: e.target.value }))}\n className=\"rounded-md border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary\"\n >\n <option value=\"today\">Today</option>\n <option value=\"7days\">Last 7 Days</option>\n <option value=\"30days\">Last 30 Days</option>\n <option value=\"all\">All Time</option>\n </select>\n <select\n value={filters.sortBy}\n onChange={(e) => setFilters((p) => ({ ...p, sortBy: e.target.value }))}\n className=\"rounded-md border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary\"\n >\n <option value=\"recent\">Most Recent</option>\n <option value=\"oldest\">Oldest First</option>\n <option value=\"amount_high\">Amount: High to Low</option>\n <option value=\"amount_low\">Amount: Low to High</option>\n </select>\n </div>\n </div>\n\n {/* Orders */}\n {isLoadingOrders ? (\n <div className=\"flex items-center justify-center py-16\">\n <div className=\"h-10 w-10 animate-spin rounded-full border-b-2 border-foreground\" />\n </div>\n ) : view === 'board' ? (\n boardOrders.length === 0 ? (\n <EmptyState\n illustration={filters.searchQuery ? 'empty-search' : 'empty-data'}\n title=\"No orders found\"\n description=\"New orders from customers appear on the board in real time. Make sure your cart is open and accepting orders.\"\n />\n ) : (\n <KanbanBoard columns={boardColumns} emptyColumnHint=\"No orders\" />\n )\n ) : filteredOrders.length === 0 ? (\n <EmptyState\n illustration={filters.searchQuery || filters.status ? 'empty-search' : 'empty-data'}\n title=\"No orders found\"\n description={\n filters.searchQuery || filters.status\n ? 'No orders match your current filters. Try adjusting the status, type or date range.'\n : 'New orders from customers will appear here in real time. Make sure your cart is open and accepting orders.'\n }\n />\n ) : (\n <div className=\"space-y-4\">\n {filteredOrders.map((order) => {\n const status = statusConfig[order.status] || {\n color: 'bg-bg-sunken text-text-secondary',\n label: order.status,\n };\n const fulfillment =\n fulfillmentBadge[order.fulfillmentType || 'delivery'] || fulfillmentBadge.delivery;\n const FulfillmentIcon = fulfillment.icon;\n\n return (\n <div\n key={order.id}\n className={cn(\n 'rounded-lg border bg-bg-surface shadow-sm transition-shadow hover:shadow-md',\n getPriorityColor(order)\n )}\n >\n <div className=\"p-4 sm:p-5\">\n {/* Header */}\n <div className=\"flex flex-col lg:flex-row lg:items-center lg:justify-between gap-3 mb-3\">\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex flex-wrap items-center gap-2 mb-1\">\n <h3 className=\"text-sm sm:text-base font-semibold text-text-primary\">\n Order #{order.id}\n </h3>\n <span\n className={cn(\n 'inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium',\n status.color\n )}\n >\n {status.label}\n </span>\n <span\n className={cn(\n 'inline-flex items-center gap-1 rounded-full px-2.5 py-0.5 text-xs font-medium',\n fulfillment.color\n )}\n >\n <FulfillmentIcon className=\"h-3 w-3\" />\n {fulfillment.label}\n </span>\n </div>\n <p className=\"text-xs text-text-secondary\">\n {order.customerName || 'Customer'} | {formatTimeAgo(order.orderDate)}\n </p>\n </div>\n <div className=\"flex items-center gap-3\">\n <p className=\"text-lg font-bold text-text-primary\">\n {formatCurrency(order.total, { minimumFractionDigits: 0 })}\n </p>\n <button\n type=\"button\"\n onClick={() => {\n setSelectedOrder(order);\n setShowOrderDetails(true);\n }}\n className=\"rounded-md border border-border-subtle px-3 py-1.5 text-xs font-medium text-text-primary hover:bg-bg-sunken transition-colors\"\n >\n View Details\n </button>\n </div>\n </div>\n\n {/* Items */}\n <div className=\"border-t border-border-subtle pt-3 mb-3\">\n <div className=\"flex flex-wrap gap-2\">\n {order.items.map((item, idx) => (\n <span\n key={idx}\n className=\"inline-flex items-center rounded bg-bg-sunken px-2 py-1 text-xs text-text-primary\"\n >\n {item.quantity}x {item.name}\n </span>\n ))}\n </div>\n </div>\n\n {/* Actions */}\n <div className=\"flex flex-wrap gap-2\">\n {order.status === 'pending' && (\n <>\n <button\n type=\"button\"\n onClick={() => handleOrderAction(order.id, 'accept')}\n className=\"inline-flex items-center gap-1.5 rounded-md bg-status-success-bg-subtle px-3 py-2 text-xs font-medium text-status-success-text hover:bg-status-success-bg-subtle transition-colors\"\n >\n <CheckCircle2 className=\"h-3.5 w-3.5\" />\n Accept Order\n </button>\n <button\n type=\"button\"\n onClick={() => handleOrderAction(order.id, 'reject')}\n className=\"inline-flex items-center gap-1.5 rounded-md bg-status-error-bg-subtle px-3 py-2 text-xs font-medium text-status-error-text hover:bg-status-error-bg-subtle transition-colors\"\n >\n <XCircle className=\"h-3.5 w-3.5\" />\n Reject\n </button>\n </>\n )}\n {order.status === 'confirmed' && (\n <button\n type=\"button\"\n onClick={() => handleOrderAction(order.id, 'prepare')}\n className=\"inline-flex items-center gap-1.5 rounded-md bg-status-warning-bg-subtle px-3 py-2 text-xs font-medium text-status-warning-text hover:bg-status-warning-bg-subtle transition-colors\"\n >\n <ChefHat className=\"h-3.5 w-3.5\" />\n Start Preparing\n </button>\n )}\n {order.status === 'preparing' && (\n <button\n type=\"button\"\n onClick={() => handleOrderAction(order.id, 'ready')}\n className=\"inline-flex items-center gap-1.5 rounded-md bg-status-success-bg-subtle px-3 py-2 text-xs font-medium text-status-success-text hover:bg-status-success-bg-subtle transition-colors\"\n >\n <PackageCheck className=\"h-3.5 w-3.5\" />\n Mark as Ready\n </button>\n )}\n {order.status === 'ready' && order.fulfillmentType === 'pickup' && (\n <button\n type=\"button\"\n onClick={() => handleOrderAction(order.id, 'complete')}\n className=\"inline-flex items-center gap-1.5 rounded-md bg-status-success-bg-subtle px-3 py-2 text-xs font-medium text-status-success-text hover:bg-status-success-bg-subtle transition-colors\"\n >\n <CheckCircle2 className=\"h-3.5 w-3.5\" />\n Complete Order\n </button>\n )}\n {['confirmed', 'preparing', 'ready'].includes(order.status) &&\n order.customerPhone && (\n <a\n href={`tel:${order.customerPhone}`}\n className=\"inline-flex items-center gap-1.5 rounded-md border border-border-subtle px-3 py-2 text-xs font-medium text-text-primary hover:bg-bg-sunken transition-colors\"\n >\n <Phone className=\"h-3.5 w-3.5\" />\n Contact Customer\n </a>\n )}\n </div>\n\n {/* Special Instructions */}\n {order.specialInstructions && (\n <div className=\"mt-3 rounded-md border border-status-warning-text/30 bg-status-warning-bg-subtle p-3\">\n <p className=\"text-xs font-medium text-status-warning-text\">\n Special Instructions:\n </p>\n <p className=\"text-xs text-status-warning-text mt-0.5\">\n {order.specialInstructions}\n </p>\n </div>\n )}\n </div>\n </div>\n );\n })}\n </div>\n )}\n </div>\n\n {/* Order Details Modal */}\n {showOrderDetails && selectedOrder && (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4\">\n <div className=\"w-full max-w-2xl max-h-[90vh] overflow-y-auto rounded-lg border border-border-subtle bg-bg-surface shadow-xl\">\n <div className=\"p-6\">\n <div className=\"flex items-center justify-between mb-4\">\n <h3 className=\"text-lg font-semibold text-text-primary\">Order Details</h3>\n <button\n type=\"button\"\n onClick={() => setShowOrderDetails(false)}\n className=\"rounded p-1.5 text-text-secondary hover:text-text-primary hover:bg-bg-sunken transition-colors\"\n >\n <X className=\"h-5 w-5\" />\n </button>\n </div>\n\n <div className=\"space-y-4\">\n {/* Order Meta */}\n <div className=\"grid grid-cols-2 gap-4\">\n <div>\n <p className=\"text-xs text-text-secondary\">Order ID</p>\n <p className=\"text-sm font-medium text-text-primary\">#{selectedOrder.id}</p>\n </div>\n <div>\n <p className=\"text-xs text-text-secondary\">Status</p>\n <span\n className={cn(\n 'inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium mt-0.5',\n (statusConfig[selectedOrder.status] || statusConfig.pending).color\n )}\n >\n {(statusConfig[selectedOrder.status] || statusConfig.pending).label}\n </span>\n </div>\n <div>\n <p className=\"text-xs text-text-secondary\">Customer</p>\n <p className=\"text-sm font-medium text-text-primary\">\n {selectedOrder.customerName || 'N/A'}\n </p>\n </div>\n <div>\n <p className=\"text-xs text-text-secondary\">Order Time</p>\n <p className=\"text-sm font-medium text-text-primary\">\n {formatTime(selectedOrder.orderDate)}\n </p>\n </div>\n </div>\n\n {/* Items */}\n <div className=\"border-t border-border-subtle pt-4\">\n <h4 className=\"text-sm font-medium text-text-primary mb-3\">Order Items</h4>\n <div className=\"space-y-2\">\n {selectedOrder.items.map((item, idx) => (\n <div key={idx} className=\"flex justify-between items-start\">\n <div>\n <p className=\"text-sm font-medium text-text-primary\">{item.name}</p>\n <p className=\"text-xs text-text-secondary\">\n {formatCurrency(item.price, { minimumFractionDigits: 0 })} x{' '}\n {item.quantity}\n </p>\n </div>\n <p className=\"text-sm font-medium text-text-primary\">\n {formatCurrency(item.price * item.quantity, { minimumFractionDigits: 0 })}\n </p>\n </div>\n ))}\n </div>\n </div>\n\n {/* Totals */}\n <div className=\"border-t border-border-subtle pt-4 space-y-2\">\n <div className=\"flex justify-between text-sm text-text-secondary\">\n <span>Subtotal</span>\n <span>\n {formatCurrency(selectedOrder.subtotal, { minimumFractionDigits: 0 })}\n </span>\n </div>\n <div className=\"flex justify-between text-sm text-text-secondary\">\n <span>Delivery Fee</span>\n <span>\n {formatCurrency(selectedOrder.deliveryFee, { minimumFractionDigits: 0 })}\n </span>\n </div>\n <div className=\"flex justify-between text-sm text-text-secondary\">\n <span>Tax</span>\n <span>{formatCurrency(selectedOrder.taxes, { minimumFractionDigits: 0 })}</span>\n </div>\n <div className=\"flex justify-between font-semibold text-text-primary pt-2 border-t border-border-subtle\">\n <span>Total</span>\n <span>{formatCurrency(selectedOrder.total, { minimumFractionDigits: 0 })}</span>\n </div>\n </div>\n\n {/* Delivery Address */}\n {selectedOrder.fulfillmentType === 'delivery' && selectedOrder.deliveryAddress && (\n <div className=\"border-t border-border-subtle pt-4\">\n <h4 className=\"text-sm font-medium text-text-primary mb-2 flex items-center gap-1.5\">\n <MapPin className=\"h-4 w-4 text-text-secondary\" />\n Delivery Address\n </h4>\n <p className=\"text-sm text-text-secondary\">\n {selectedOrder.deliveryAddress.street}, {selectedOrder.deliveryAddress.area}\n <br />\n {selectedOrder.deliveryAddress.city} - {selectedOrder.deliveryAddress.pincode}\n </p>\n </div>\n )}\n\n {/* Modal Actions */}\n <div className=\"flex gap-3 mt-6\">\n <button\n type=\"button\"\n onClick={() => setShowOrderDetails(false)}\n className=\"flex-1 rounded-md border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken transition-colors\"\n >\n Close\n </button>\n {selectedOrder.status === 'pending' && (\n <>\n <button\n type=\"button\"\n onClick={() => handleOrderAction(selectedOrder.id, 'accept')}\n className=\"flex-1 rounded-md bg-status-success-bg-subtle px-4 py-2 text-sm font-medium text-status-success-text hover:bg-status-success-bg-subtle transition-colors\"\n >\n Accept Order\n </button>\n <button\n type=\"button\"\n onClick={() => handleOrderAction(selectedOrder.id, 'reject')}\n className=\"flex-1 rounded-md bg-status-error-bg-subtle px-4 py-2 text-sm font-medium text-status-error-text hover:bg-status-error-bg-subtle transition-colors\"\n >\n Reject Order\n </button>\n </>\n )}\n </div>\n </div>\n </div>\n </div>\n </div>\n )}\n </PageLayout>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"OrderManagementPage.js","names":[],"sources":["../../../../src/kadaikodi/pages/cart-owner/OrderManagementPage.tsx"],"sourcesContent":["/**\n * Order Management Page\n *\n * Stats overview, status-filtered order list with search/date/sort/fulfillment filters,\n * order detail modal, accept/reject/ready/complete actions, priority highlighting.\n *\n * @module kadaikodi/pages/cart-owner\n */\n\nimport { useState, useMemo, useEffect } from 'react';\nimport {\n Search,\n Clock,\n CheckCircle2,\n XCircle,\n ChefHat,\n PackageCheck,\n Phone,\n MapPin,\n User,\n RefreshCw,\n Truck,\n ShoppingBag,\n X,\n AlertCircle,\n Filter,\n ChevronDown,\n} from 'lucide-react';\nimport { EmphasisPanel, PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { EmptyState } from '../../components/EmptyState';\nimport { StatCard, KanbanBoard, SegmentedTabs, STATUS } from '../../components/viz';\nimport type { KanbanColumnData } from '../../components/viz';\nimport { useKadaikodi } from '../../context/KadaikodiContext';\nimport { useOrders, useUpdateOrderStatus, useProviders } from '../../hooks/useKadaikodiApi';\nimport { formatCurrency } from '../../utils/formatters';\nimport { cn } from '../../utils/cn';\nimport type { MockOrder, OrderStatus } from '../../types';\n\n// ============================================================================\n// Types\n// ============================================================================\n\ninterface StatusMessage {\n text: string;\n type: 'success' | 'error';\n}\n\ninterface OrderFilters {\n status: string;\n dateRange: string;\n searchQuery: string;\n sortBy: string;\n fulfillmentType: string;\n}\n\n/** Extended order type with cart-owner specific fields */\ninterface ExtendedOrder extends MockOrder {\n customerName?: string;\n customerPhone?: string;\n fulfillmentType?: 'delivery' | 'pickup' | 'cart_dispatch';\n specialInstructions?: string;\n}\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nconst statusConfig: Record<string, { color: string; label: string }> = {\n pending: { color: 'bg-status-warning-bg-subtle text-status-warning-text', label: 'New Order' },\n confirmed: { color: 'bg-[var(--color-accent-soft)] text-text-primary', label: 'Confirmed' },\n preparing: { color: 'bg-status-warning-bg-subtle text-status-warning-text', label: 'Preparing' },\n ready: { color: 'bg-status-success-bg-subtle text-status-success-text', label: 'Ready' },\n out_for_delivery: {\n color: 'bg-[var(--color-accent-soft)] text-text-primary',\n label: 'Out for Delivery',\n },\n delivered: { color: 'bg-status-success-bg-subtle text-status-success-text', label: 'Completed' },\n cancelled: { color: 'bg-status-error-bg-subtle text-status-error-text', label: 'Cancelled' },\n};\n\nconst fulfillmentBadge: Record<string, { icon: typeof Truck; label: string; color: string }> = {\n delivery: {\n icon: Truck,\n label: 'Delivery',\n color: 'bg-accent-purple-subtle text-text-primary',\n },\n pickup: {\n icon: ShoppingBag,\n label: 'Pickup',\n color: 'bg-[var(--color-accent-soft)] text-text-primary',\n },\n cart_dispatch: {\n icon: MapPin,\n label: 'Cart Dispatch',\n color: 'bg-bg-sunken text-text-secondary',\n },\n};\n\nconst formatTimeAgo = (dateString: string) => {\n const date = new Date(dateString);\n const now = new Date();\n const diffMin = Math.floor((now.getTime() - date.getTime()) / (1000 * 60));\n if (diffMin < 1) return 'Just now';\n if (diffMin < 60) return `${diffMin} min ago`;\n if (diffMin < 1440) return `${Math.floor(diffMin / 60)} hours ago`;\n return date.toLocaleDateString('en-IN', { day: '2-digit', month: 'short' });\n};\n\nconst formatTime = (dateString: string) => {\n return new Date(dateString).toLocaleTimeString('en-IN', {\n hour: 'numeric',\n minute: '2-digit',\n hour12: true,\n });\n};\n\nconst getPriorityColor = (order: ExtendedOrder) => {\n const ageMin = (new Date().getTime() - new Date(order.orderDate).getTime()) / (1000 * 60);\n if (order.status === 'pending' && ageMin > 10)\n return 'border-status-error-text/50 bg-status-error-bg-subtle';\n if (order.status === 'preparing' && ageMin > 30)\n return 'border-status-warning-text/50 bg-status-warning-bg-subtle';\n return 'border-border-subtle';\n};\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport const OrderManagementPage = () => {\n const { navigateTo, currentUser } = useKadaikodi();\n\n // Resolve the signed-in owner's provider, then load its real orders.\n const { data: providers = [] } = useProviders();\n const myProvider = useMemo(\n () => providers.find((p) => p.ownerId === currentUser?.id) ?? providers[0],\n [providers, currentUser?.id]\n );\n const {\n data: fetchedOrders = [],\n isLoading: isLoadingOrders,\n refetch: refetchOrders,\n isFetching: isFetchingOrders,\n } = useOrders({\n providerId: myProvider?.id,\n });\n const updateOrderStatus = useUpdateOrderStatus();\n\n // Local working copy so status actions feel instant; kept in sync with the query.\n const [orders, setOrders] = useState<ExtendedOrder[]>([]);\n useEffect(() => {\n setOrders(fetchedOrders);\n }, [fetchedOrders]);\n\n // Filters\n const [filters, setFilters] = useState<OrderFilters>({\n status: '',\n dateRange: 'all',\n searchQuery: '',\n sortBy: 'recent',\n fulfillmentType: '',\n });\n\n // View: live board (kanban) vs detailed list\n const [view, setView] = useState<'board' | 'list'>('board');\n\n // Modal\n const [selectedOrder, setSelectedOrder] = useState<ExtendedOrder | null>(null);\n const [showOrderDetails, setShowOrderDetails] = useState(false);\n\n // Status\n const [statusMessage, setStatusMessage] = useState<StatusMessage | null>(null);\n\n const showStatus = (text: string, type: 'success' | 'error') => {\n setStatusMessage({ text, type });\n setTimeout(() => setStatusMessage(null), 3000);\n };\n\n // ---- Stats ----\n const stats = useMemo(() => {\n const total = orders.length;\n const pending = orders.filter((o) => o.status === 'pending').length;\n const active = orders.filter((o) =>\n ['confirmed', 'preparing', 'ready', 'out_for_delivery'].includes(o.status)\n ).length;\n const completed = orders.filter((o) => o.status === 'delivered').length;\n const totalRevenue = orders\n .filter((o) => o.status === 'delivered')\n .reduce((s, o) => s + o.total, 0);\n const avgOrder = completed > 0 ? Math.round(totalRevenue / completed) : 0;\n return { total, pending, active, completed, totalRevenue, avgOrder };\n }, [orders]);\n\n // ---- Filtered orders ----\n const filteredOrders = useMemo(() => {\n let result = [...orders];\n\n if (filters.status) {\n result = result.filter((o) => o.status === filters.status);\n }\n if (filters.fulfillmentType) {\n result = result.filter((o) => o.fulfillmentType === filters.fulfillmentType);\n }\n if (filters.searchQuery) {\n const q = filters.searchQuery.toLowerCase();\n result = result.filter(\n (o) =>\n o.id.toLowerCase().includes(q) ||\n (o.customerName || '').toLowerCase().includes(q) ||\n o.items.some((item) => item.name.toLowerCase().includes(q))\n );\n }\n if (filters.dateRange !== 'all') {\n const now = new Date();\n const limit = new Date();\n if (filters.dateRange === 'today') limit.setHours(0, 0, 0, 0);\n else if (filters.dateRange === '7days') limit.setDate(now.getDate() - 7);\n else if (filters.dateRange === '30days') limit.setDate(now.getDate() - 30);\n result = result.filter((o) => new Date(o.orderDate) >= limit);\n }\n\n switch (filters.sortBy) {\n case 'recent':\n result.sort((a, b) => new Date(b.orderDate).getTime() - new Date(a.orderDate).getTime());\n break;\n case 'oldest':\n result.sort((a, b) => new Date(a.orderDate).getTime() - new Date(b.orderDate).getTime());\n break;\n case 'amount_high':\n result.sort((a, b) => b.total - a.total);\n break;\n case 'amount_low':\n result.sort((a, b) => a.total - b.total);\n break;\n }\n\n return result;\n }, [orders, filters]);\n\n // ---- Board orders: same search/type/date filters, but every status kept so\n // each lifecycle column is populated (status is expressed by the column). ----\n const boardOrders = useMemo(() => {\n let result = [...orders];\n if (filters.fulfillmentType) {\n result = result.filter((o) => o.fulfillmentType === filters.fulfillmentType);\n }\n if (filters.searchQuery) {\n const q = filters.searchQuery.toLowerCase();\n result = result.filter(\n (o) =>\n o.id.toLowerCase().includes(q) ||\n (o.customerName || '').toLowerCase().includes(q) ||\n o.items.some((item) => item.name.toLowerCase().includes(q))\n );\n }\n if (filters.dateRange !== 'all') {\n const now = new Date();\n const limit = new Date();\n if (filters.dateRange === 'today') limit.setHours(0, 0, 0, 0);\n else if (filters.dateRange === '7days') limit.setDate(now.getDate() - 7);\n else if (filters.dateRange === '30days') limit.setDate(now.getDate() - 30);\n result = result.filter((o) => new Date(o.orderDate) >= limit);\n }\n return result.sort((a, b) => new Date(b.orderDate).getTime() - new Date(a.orderDate).getTime());\n }, [orders, filters.fulfillmentType, filters.searchQuery, filters.dateRange]);\n\n // ---- Actions ----\n const handleRefresh = async () => {\n await refetchOrders();\n showStatus('Orders refreshed', 'success');\n };\n\n const handleOrderAction = (\n orderId: string,\n action: 'accept' | 'reject' | 'prepare' | 'ready' | 'complete'\n ) => {\n const statusMap: Record<string, OrderStatus> = {\n accept: 'confirmed',\n reject: 'cancelled',\n prepare: 'preparing',\n ready: 'ready',\n complete: 'delivered',\n };\n const backendStatusMap: Record<string, string> = {\n accept: 'CONFIRMED',\n reject: 'CANCELLED',\n prepare: 'PREPARING',\n ready: 'READY',\n complete: 'DELIVERED',\n };\n const messages: Record<string, string> = {\n accept: 'Order accepted',\n reject: 'Order rejected',\n prepare: 'Order moved to preparing',\n ready: 'Order marked as ready',\n complete: 'Order completed',\n };\n\n setOrders((prev) =>\n prev.map((o) => (o.id === orderId ? { ...o, status: statusMap[action] } : o))\n );\n updateOrderStatus.mutate(\n { id: orderId, status: backendStatusMap[action] },\n { onError: () => showStatus('Could not update the order on the server', 'error') }\n );\n showStatus(messages[action], 'success');\n if (showOrderDetails && selectedOrder?.id === orderId) {\n setShowOrderDetails(false);\n }\n };\n\n // ---- Kanban card + columns ----\n const renderBoardCard = (order: ExtendedOrder) => {\n const fulfillment =\n fulfillmentBadge[order.fulfillmentType || 'delivery'] || fulfillmentBadge.delivery;\n const FulfillmentIcon = fulfillment.icon;\n const primaryAction: { label: string; action: Parameters<typeof handleOrderAction>[1] } | null =\n order.status === 'pending'\n ? { label: 'Accept', action: 'accept' }\n : order.status === 'confirmed'\n ? { label: 'Start Preparing', action: 'prepare' }\n : order.status === 'preparing'\n ? { label: 'Mark Ready', action: 'ready' }\n : order.status === 'ready'\n ? { label: 'Complete', action: 'complete' }\n : null;\n\n return (\n <div className=\"rounded-[var(--radius-input)] border border-border-subtle bg-bg-surface p-3 shadow-sm\">\n <div className=\"mb-1.5 flex items-center justify-between gap-2\">\n <span className=\"truncate text-xs font-medium text-text-secondary\">\n Order #{order.id.slice(0, 8)}\n </span>\n <span className=\"shrink-0 text-[11px] text-text-muted\">\n {formatTimeAgo(order.orderDate)}\n </span>\n </div>\n <div className=\"mb-1.5 flex items-center justify-between gap-2\">\n <span className=\"truncate text-sm font-semibold text-text-primary\">\n {order.customerName || 'Customer'}\n </span>\n <span className=\"shrink-0 text-sm font-bold text-text-primary\">\n {formatCurrency(order.total, { minimumFractionDigits: 0 })}\n </span>\n </div>\n <p className=\"mb-2 line-clamp-2 text-xs text-text-secondary\">\n {order.items.map((i) => `${i.name} ×${i.quantity}`).join(', ')}\n </p>\n <div className=\"mb-2 flex items-center gap-1.5\">\n <span\n className={cn(\n 'inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-[10px] font-medium',\n fulfillment.color\n )}\n >\n <FulfillmentIcon className=\"h-3 w-3\" />\n {fulfillment.label}\n </span>\n </div>\n <div className=\"flex gap-1.5\">\n {primaryAction && (\n <button\n type=\"button\"\n onClick={() => handleOrderAction(order.id, primaryAction.action)}\n className=\"flex-1 rounded-md bg-action-primary-bg px-2.5 py-1.5 text-xs font-medium text-action-primary-text transition-colors hover:bg-action-primary-bg-hover\"\n >\n {primaryAction.label}\n </button>\n )}\n <button\n type=\"button\"\n onClick={() => {\n setSelectedOrder(order);\n setShowOrderDetails(true);\n }}\n className=\"rounded-md border border-border-subtle px-2.5 py-1.5 text-xs font-medium text-text-primary transition-colors hover:bg-bg-sunken\"\n >\n Details\n </button>\n {order.status === 'pending' && (\n <button\n type=\"button\"\n onClick={() => handleOrderAction(order.id, 'reject')}\n aria-label=\"Reject order\"\n className=\"rounded-md border border-border-subtle px-2 py-1.5 text-status-error-text transition-colors hover:bg-status-error-bg-subtle\"\n >\n <XCircle className=\"h-3.5 w-3.5\" />\n </button>\n )}\n </div>\n </div>\n );\n };\n\n const boardColumns: KanbanColumnData[] = [\n {\n id: 'new',\n title: 'New',\n accent: STATUS.warning,\n items: boardOrders.filter((o) => o.status === 'pending').map(renderBoardCard),\n },\n {\n id: 'preparing',\n title: 'Preparing',\n accent: STATUS.info,\n items: boardOrders\n .filter((o) => o.status === 'confirmed' || o.status === 'preparing')\n .map(renderBoardCard),\n },\n {\n id: 'ready',\n title: 'Ready',\n accent: STATUS.success,\n items: boardOrders\n .filter((o) => o.status === 'ready' || o.status === 'out_for_delivery')\n .map(renderBoardCard),\n },\n {\n id: 'completed',\n title: 'Completed',\n items: boardOrders.filter((o) => o.status === 'delivered').map(renderBoardCard),\n },\n ];\n\n return (\n <PageLayout\n title=\"Order Management\"\n description=\"Manage incoming and active orders\"\n actions={\n <button\n type=\"button\"\n onClick={handleRefresh}\n disabled={isFetchingOrders}\n className=\"inline-flex items-center gap-2 rounded-md border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken transition-colors disabled:opacity-60 disabled:cursor-not-allowed\"\n >\n <RefreshCw className={cn('h-4 w-4', isFetchingOrders && 'animate-spin')} />\n Refresh\n </button>\n }\n >\n <PagePurpose className=\"mb-6\">\n Your live order queue. Use this page to run service as it happens — accept new orders, move\n them through preparing and ready, hand off for pickup, delivery or cart dispatch, and keep\n customers updated. Filter by status or type to focus on what needs doing right now, and\n watch today's totals so you know how the day is going.\n </PagePurpose>\n\n <div className=\"space-y-4\">\n {/* Status Message */}\n {statusMessage && (\n <div\n className={cn(\n 'flex items-center gap-2 rounded-lg border p-3',\n statusMessage.type === 'success'\n ? 'border-status-success-text/30 bg-status-success-bg-subtle'\n : 'border-status-error-text/30 bg-status-error-bg-subtle'\n )}\n >\n {statusMessage.type === 'success' ? (\n <CheckCircle2 className=\"h-4 w-4 text-status-success-text\" />\n ) : (\n <AlertCircle className=\"h-4 w-4 text-status-error-text\" />\n )}\n <span\n className={cn(\n 'text-sm font-medium',\n statusMessage.type === 'success'\n ? 'text-status-success-text'\n : 'text-status-error-text'\n )}\n >\n {statusMessage.text}\n </span>\n </div>\n )}\n\n {/* Stats Overview — the one emphasis zone for this page */}\n <EmphasisPanel>\n <h2 className=\"mb-4 text-base font-semibold text-text-primary\">Orders Overview</h2>\n <div className=\"grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-6 gap-3\">\n <StatCard\n label=\"Total Orders\"\n value={stats.total}\n icon={<ShoppingBag className=\"h-4 w-4\" />}\n />\n <StatCard\n label=\"Pending\"\n value={<span className=\"text-status-warning-text\">{stats.pending}</span>}\n icon={<Clock className=\"h-4 w-4\" />}\n />\n <StatCard label=\"Active\" value={stats.active} icon={<ChefHat className=\"h-4 w-4\" />} />\n <StatCard\n label=\"Completed\"\n value={<span className=\"text-status-success-text\">{stats.completed}</span>}\n icon={<CheckCircle2 className=\"h-4 w-4\" />}\n />\n <StatCard\n label=\"Total Revenue\"\n value={formatCurrency(stats.totalRevenue, { minimumFractionDigits: 0 })}\n icon={<PackageCheck className=\"h-4 w-4\" />}\n />\n <StatCard\n label=\"Avg Order\"\n value={formatCurrency(stats.avgOrder, { minimumFractionDigits: 0 })}\n icon={<Truck className=\"h-4 w-4\" />}\n />\n </div>\n </EmphasisPanel>\n\n {/* View toggle: live board vs detailed list */}\n <div className=\"flex items-center justify-between gap-3\">\n <SegmentedTabs\n aria-label=\"Order view\"\n value={view}\n onChange={(id) => setView(id as 'board' | 'list')}\n tabs={[\n { id: 'board', label: 'Board' },\n { id: 'list', label: 'List' },\n ]}\n />\n <p className=\"text-xs text-text-secondary\">\n {boardOrders.length} order{boardOrders.length === 1 ? '' : 's'} in view\n </p>\n </div>\n\n {/* Filters */}\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-4 shadow-sm\">\n <div className=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-5 gap-3\">\n <div className=\"relative sm:col-span-2 lg:col-span-1\">\n <Search className=\"absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-text-secondary\" />\n <input\n type=\"text\"\n placeholder=\"Search orders...\"\n value={filters.searchQuery}\n onChange={(e) => setFilters((p) => ({ ...p, searchQuery: e.target.value }))}\n className=\"w-full rounded-md border border-border-subtle bg-bg-surface pl-10 pr-4 py-2 text-sm text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n />\n </div>\n <select\n value={filters.status}\n onChange={(e) => setFilters((p) => ({ ...p, status: e.target.value }))}\n className=\"rounded-md border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary\"\n >\n <option value=\"\">All Orders</option>\n <option value=\"pending\">New Orders</option>\n <option value=\"confirmed\">Confirmed</option>\n <option value=\"preparing\">Preparing</option>\n <option value=\"ready\">Ready</option>\n <option value=\"delivered\">Completed</option>\n <option value=\"cancelled\">Cancelled</option>\n </select>\n <select\n value={filters.fulfillmentType}\n onChange={(e) => setFilters((p) => ({ ...p, fulfillmentType: e.target.value }))}\n className=\"rounded-md border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary\"\n >\n <option value=\"\">All Types</option>\n <option value=\"pickup\">Pickup</option>\n <option value=\"delivery\">Delivery</option>\n <option value=\"cart_dispatch\">Cart Dispatch</option>\n </select>\n <select\n value={filters.dateRange}\n onChange={(e) => setFilters((p) => ({ ...p, dateRange: e.target.value }))}\n className=\"rounded-md border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary\"\n >\n <option value=\"today\">Today</option>\n <option value=\"7days\">Last 7 Days</option>\n <option value=\"30days\">Last 30 Days</option>\n <option value=\"all\">All Time</option>\n </select>\n <select\n value={filters.sortBy}\n onChange={(e) => setFilters((p) => ({ ...p, sortBy: e.target.value }))}\n className=\"rounded-md border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary\"\n >\n <option value=\"recent\">Most Recent</option>\n <option value=\"oldest\">Oldest First</option>\n <option value=\"amount_high\">Amount: High to Low</option>\n <option value=\"amount_low\">Amount: Low to High</option>\n </select>\n </div>\n </div>\n\n {/* Orders */}\n {isLoadingOrders ? (\n <div className=\"flex items-center justify-center py-16\">\n <div className=\"h-10 w-10 animate-spin rounded-full border-b-2 border-foreground\" />\n </div>\n ) : view === 'board' ? (\n boardOrders.length === 0 ? (\n <EmptyState\n illustration={filters.searchQuery ? 'empty-search' : 'empty-data'}\n title=\"No orders found\"\n description=\"New orders from customers appear on the board in real time. Make sure your cart is open and accepting orders.\"\n />\n ) : (\n <KanbanBoard columns={boardColumns} emptyColumnHint=\"No orders\" />\n )\n ) : filteredOrders.length === 0 ? (\n <EmptyState\n illustration={filters.searchQuery || filters.status ? 'empty-search' : 'empty-data'}\n title=\"No orders found\"\n description={\n filters.searchQuery || filters.status\n ? 'No orders match your current filters. Try adjusting the status, type or date range.'\n : 'New orders from customers will appear here in real time. Make sure your cart is open and accepting orders.'\n }\n />\n ) : (\n <div className=\"space-y-4\">\n {filteredOrders.map((order) => {\n const status = statusConfig[order.status] || {\n color: 'bg-bg-sunken text-text-secondary',\n label: order.status,\n };\n const fulfillment =\n fulfillmentBadge[order.fulfillmentType || 'delivery'] || fulfillmentBadge.delivery;\n const FulfillmentIcon = fulfillment.icon;\n\n return (\n <div\n key={order.id}\n className={cn(\n 'rounded-lg border bg-bg-surface shadow-sm transition-shadow hover:shadow-md',\n getPriorityColor(order)\n )}\n >\n <div className=\"p-4 sm:p-5\">\n {/* Header */}\n <div className=\"flex flex-col lg:flex-row lg:items-center lg:justify-between gap-3 mb-3\">\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex flex-wrap items-center gap-2 mb-1\">\n <h3 className=\"text-sm sm:text-base font-semibold text-text-primary\">\n Order #{order.id}\n </h3>\n <span\n className={cn(\n 'inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium',\n status.color\n )}\n >\n {status.label}\n </span>\n <span\n className={cn(\n 'inline-flex items-center gap-1 rounded-full px-2.5 py-0.5 text-xs font-medium',\n fulfillment.color\n )}\n >\n <FulfillmentIcon className=\"h-3 w-3\" />\n {fulfillment.label}\n </span>\n </div>\n <p className=\"text-xs text-text-secondary\">\n {order.customerName || 'Customer'} | {formatTimeAgo(order.orderDate)}\n </p>\n </div>\n <div className=\"flex items-center gap-3\">\n <p className=\"text-lg font-bold text-text-primary\">\n {formatCurrency(order.total, { minimumFractionDigits: 0 })}\n </p>\n <button\n type=\"button\"\n onClick={() => {\n setSelectedOrder(order);\n setShowOrderDetails(true);\n }}\n className=\"rounded-md border border-border-subtle px-3 py-1.5 text-xs font-medium text-text-primary hover:bg-bg-sunken transition-colors\"\n >\n View Details\n </button>\n </div>\n </div>\n\n {/* Items */}\n <div className=\"border-t border-border-subtle pt-3 mb-3\">\n <div className=\"flex flex-wrap gap-2\">\n {order.items.map((item, idx) => (\n <span\n key={idx}\n className=\"inline-flex items-center rounded bg-bg-sunken px-2 py-1 text-xs text-text-primary\"\n >\n {item.quantity}x {item.name}\n </span>\n ))}\n </div>\n </div>\n\n {/* Actions */}\n <div className=\"flex flex-wrap gap-2\">\n {order.status === 'pending' && (\n <>\n <button\n type=\"button\"\n onClick={() => handleOrderAction(order.id, 'accept')}\n className=\"inline-flex items-center gap-1.5 rounded-md bg-status-success-bg-subtle px-3 py-2 text-xs font-medium text-status-success-text hover:bg-status-success-bg-subtle transition-colors\"\n >\n <CheckCircle2 className=\"h-3.5 w-3.5\" />\n Accept Order\n </button>\n <button\n type=\"button\"\n onClick={() => handleOrderAction(order.id, 'reject')}\n className=\"inline-flex items-center gap-1.5 rounded-md bg-status-error-bg-subtle px-3 py-2 text-xs font-medium text-status-error-text hover:bg-status-error-bg-subtle transition-colors\"\n >\n <XCircle className=\"h-3.5 w-3.5\" />\n Reject\n </button>\n </>\n )}\n {order.status === 'confirmed' && (\n <button\n type=\"button\"\n onClick={() => handleOrderAction(order.id, 'prepare')}\n className=\"inline-flex items-center gap-1.5 rounded-md bg-status-warning-bg-subtle px-3 py-2 text-xs font-medium text-status-warning-text hover:bg-status-warning-bg-subtle transition-colors\"\n >\n <ChefHat className=\"h-3.5 w-3.5\" />\n Start Preparing\n </button>\n )}\n {order.status === 'preparing' && (\n <button\n type=\"button\"\n onClick={() => handleOrderAction(order.id, 'ready')}\n className=\"inline-flex items-center gap-1.5 rounded-md bg-status-success-bg-subtle px-3 py-2 text-xs font-medium text-status-success-text hover:bg-status-success-bg-subtle transition-colors\"\n >\n <PackageCheck className=\"h-3.5 w-3.5\" />\n Mark as Ready\n </button>\n )}\n {order.status === 'ready' && order.fulfillmentType === 'pickup' && (\n <button\n type=\"button\"\n onClick={() => handleOrderAction(order.id, 'complete')}\n className=\"inline-flex items-center gap-1.5 rounded-md bg-status-success-bg-subtle px-3 py-2 text-xs font-medium text-status-success-text hover:bg-status-success-bg-subtle transition-colors\"\n >\n <CheckCircle2 className=\"h-3.5 w-3.5\" />\n Complete Order\n </button>\n )}\n {['confirmed', 'preparing', 'ready'].includes(order.status) &&\n order.customerPhone && (\n <a\n href={`tel:${order.customerPhone}`}\n className=\"inline-flex items-center gap-1.5 rounded-md border border-border-subtle px-3 py-2 text-xs font-medium text-text-primary hover:bg-bg-sunken transition-colors\"\n >\n <Phone className=\"h-3.5 w-3.5\" />\n Contact Customer\n </a>\n )}\n </div>\n\n {/* Special Instructions */}\n {order.specialInstructions && (\n <div className=\"mt-3 rounded-md border border-status-warning-text/30 bg-status-warning-bg-subtle p-3\">\n <p className=\"text-xs font-medium text-status-warning-text\">\n Special Instructions:\n </p>\n <p className=\"text-xs text-status-warning-text mt-0.5\">\n {order.specialInstructions}\n </p>\n </div>\n )}\n </div>\n </div>\n );\n })}\n </div>\n )}\n </div>\n\n {/* Order Details Modal */}\n {showOrderDetails && selectedOrder && (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4\">\n <div className=\"w-full max-w-2xl max-h-[90vh] overflow-y-auto rounded-lg border border-border-subtle bg-bg-surface shadow-xl\">\n <div className=\"p-6\">\n <div className=\"flex items-center justify-between mb-4\">\n <h3 className=\"text-lg font-semibold text-text-primary\">Order Details</h3>\n <button\n type=\"button\"\n onClick={() => setShowOrderDetails(false)}\n className=\"rounded p-1.5 text-text-secondary hover:text-text-primary hover:bg-bg-sunken transition-colors\"\n >\n <X className=\"h-5 w-5\" />\n </button>\n </div>\n\n <div className=\"space-y-4\">\n {/* Order Meta */}\n <div className=\"grid grid-cols-2 gap-4\">\n <div>\n <p className=\"text-xs text-text-secondary\">Order ID</p>\n <p className=\"text-sm font-medium text-text-primary\">#{selectedOrder.id}</p>\n </div>\n <div>\n <p className=\"text-xs text-text-secondary\">Status</p>\n <span\n className={cn(\n 'inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium mt-0.5',\n (statusConfig[selectedOrder.status] || statusConfig.pending).color\n )}\n >\n {(statusConfig[selectedOrder.status] || statusConfig.pending).label}\n </span>\n </div>\n <div>\n <p className=\"text-xs text-text-secondary\">Customer</p>\n <p className=\"text-sm font-medium text-text-primary\">\n {selectedOrder.customerName || 'N/A'}\n </p>\n </div>\n <div>\n <p className=\"text-xs text-text-secondary\">Order Time</p>\n <p className=\"text-sm font-medium text-text-primary\">\n {formatTime(selectedOrder.orderDate)}\n </p>\n </div>\n </div>\n\n {/* Items */}\n <div className=\"border-t border-border-subtle pt-4\">\n <h4 className=\"text-sm font-medium text-text-primary mb-3\">Order Items</h4>\n <div className=\"space-y-2\">\n {selectedOrder.items.map((item, idx) => (\n <div key={idx} className=\"flex justify-between items-start\">\n <div>\n <p className=\"text-sm font-medium text-text-primary\">{item.name}</p>\n <p className=\"text-xs text-text-secondary\">\n {formatCurrency(item.price, { minimumFractionDigits: 0 })} x{' '}\n {item.quantity}\n </p>\n </div>\n <p className=\"text-sm font-medium text-text-primary\">\n {formatCurrency(item.price * item.quantity, { minimumFractionDigits: 0 })}\n </p>\n </div>\n ))}\n </div>\n </div>\n\n {/* Totals */}\n <div className=\"border-t border-border-subtle pt-4 space-y-2\">\n <div className=\"flex justify-between text-sm text-text-secondary\">\n <span>Subtotal</span>\n <span>\n {formatCurrency(selectedOrder.subtotal, { minimumFractionDigits: 0 })}\n </span>\n </div>\n <div className=\"flex justify-between text-sm text-text-secondary\">\n <span>Delivery Fee</span>\n <span>\n {formatCurrency(selectedOrder.deliveryFee, { minimumFractionDigits: 0 })}\n </span>\n </div>\n <div className=\"flex justify-between text-sm text-text-secondary\">\n <span>Tax</span>\n <span>{formatCurrency(selectedOrder.taxes, { minimumFractionDigits: 0 })}</span>\n </div>\n <div className=\"flex justify-between font-semibold text-text-primary pt-2 border-t border-border-subtle\">\n <span>Total</span>\n <span>{formatCurrency(selectedOrder.total, { minimumFractionDigits: 0 })}</span>\n </div>\n </div>\n\n {/* Delivery Address */}\n {selectedOrder.fulfillmentType === 'delivery' && selectedOrder.deliveryAddress && (\n <div className=\"border-t border-border-subtle pt-4\">\n <h4 className=\"text-sm font-medium text-text-primary mb-2 flex items-center gap-1.5\">\n <MapPin className=\"h-4 w-4 text-text-secondary\" />\n Delivery Address\n </h4>\n <p className=\"text-sm text-text-secondary\">\n {selectedOrder.deliveryAddress.street}, {selectedOrder.deliveryAddress.area}\n <br />\n {selectedOrder.deliveryAddress.city} - {selectedOrder.deliveryAddress.pincode}\n </p>\n </div>\n )}\n\n {/* Modal Actions */}\n <div className=\"flex gap-3 mt-6\">\n <button\n type=\"button\"\n onClick={() => setShowOrderDetails(false)}\n className=\"flex-1 rounded-md border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken transition-colors\"\n >\n Close\n </button>\n {selectedOrder.status === 'pending' && (\n <>\n <button\n type=\"button\"\n onClick={() => handleOrderAction(selectedOrder.id, 'accept')}\n className=\"flex-1 rounded-md bg-status-success-bg-subtle px-4 py-2 text-sm font-medium text-status-success-text hover:bg-status-success-bg-subtle transition-colors\"\n >\n Accept Order\n </button>\n <button\n type=\"button\"\n onClick={() => handleOrderAction(selectedOrder.id, 'reject')}\n className=\"flex-1 rounded-md bg-status-error-bg-subtle px-4 py-2 text-sm font-medium text-status-error-text hover:bg-status-error-bg-subtle transition-colors\"\n >\n Reject Order\n </button>\n </>\n )}\n </div>\n </div>\n </div>\n </div>\n </div>\n )}\n </PageLayout>\n );\n};\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StaffManagementPage.d.ts","sourceRoot":"","sources":["../../../../src/kadaikodi/pages/cart-owner/StaffManagementPage.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAmGH,eAAO,MAAM,mBAAmB,
|
|
1
|
+
{"version":3,"file":"StaffManagementPage.d.ts","sourceRoot":"","sources":["../../../../src/kadaikodi/pages/cart-owner/StaffManagementPage.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAmGH,eAAO,MAAM,mBAAmB,mCA2b/B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StaffManagementPage.js","names":[],"sources":["../../../../src/kadaikodi/pages/cart-owner/StaffManagementPage.tsx"],"sourcesContent":["/**\n * Staff Management Page\n *\n * Team overview and roster for the signed-in owner's own service provider (cart).\n * Lists the provider's real workers (useProviderWorkers) with role/status filters\n * and search, and invites new workers (useCreateProviderWorker). No fabricated\n * staff, performance metrics, or earnings.\n *\n * @module kadaikodi/pages/cart-owner\n */\n\nimport { useState, useMemo } from 'react';\nimport {\n UserPlus,\n Phone,\n Search,\n X,\n Mail,\n CheckCircle2,\n AlertCircle,\n Users,\n Clock,\n Briefcase,\n} from 'lucide-react';\nimport { EmphasisPanel, PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { EmptyState } from '../../components/EmptyState';\nimport { StatCard, AvatarStack } from '../../components/viz';\nimport type { Person } from '../../components/viz';\nimport { useKadaikodi } from '../../context/KadaikodiContext';\nimport {\n useProviders,\n useProviderWorkers,\n useCreateProviderWorker,\n type KadaikodiProviderWorkerRow,\n} from '../../hooks/useKadaikodiApi';\nimport { cn } from '../../utils/cn';\n\n// ============================================================================\n// Types\n// ============================================================================\n\ninterface InviteForm {\n name: string;\n email: string;\n phone: string;\n role: string;\n}\n\ninterface StatusMessage {\n text: string;\n type: 'success' | 'error';\n}\n\ninterface WorkerMetadata {\n email?: string;\n phone?: string;\n}\n\n// ============================================================================\n// Constants & helpers\n// ============================================================================\n\nconst ROLE_OPTIONS = ['MANAGER', 'CHEF', 'SERVER', 'DELIVERY', 'CASHIER'] as const;\n\nconst prettify = (s: string): string =>\n s\n .replace(/_/g, ' ')\n .toLowerCase()\n .replace(/\\b\\w/g, (c) => c.toUpperCase());\n\nconst statusColor = (status: string): { label: string; color: string; dot: string } => {\n const s = status.toUpperCase();\n if (s === 'ACTIVE')\n return {\n label: prettify(status),\n color: 'text-status-success-text',\n dot: 'bg-status-success-text',\n };\n if (s === 'ON_LEAVE' || s === 'ON-LEAVE')\n return {\n label: prettify(status),\n color: 'text-status-warning-text',\n dot: 'bg-status-warning-text',\n };\n return { label: prettify(status), color: 'text-text-secondary', dot: 'bg-muted-foreground' };\n};\n\nconst readMetadata = (metadata: Record<string, unknown> | null | undefined): WorkerMetadata => {\n if (!metadata || typeof metadata !== 'object') return {};\n const m = metadata as Record<string, unknown>;\n return {\n email: typeof m.email === 'string' ? m.email : undefined,\n phone: typeof m.phone === 'string' ? m.phone : undefined,\n };\n};\n\nconst emptyInviteForm: InviteForm = {\n name: '',\n email: '',\n phone: '',\n role: 'SERVER',\n};\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport const StaffManagementPage = () => {\n const { currentUser } = useKadaikodi();\n\n // Resolve the signed-in owner's provider (\"my cart\"), then load its workers.\n const { data: providers = [], isLoading: providersLoading } = useProviders();\n const myProvider = useMemo(\n () => providers.find((p) => p.ownerId === currentUser?.id) ?? providers[0],\n [providers, currentUser?.id]\n );\n const providerId = myProvider?.id;\n const { data: workers = [], isLoading: workersLoading } = useProviderWorkers(providerId);\n const createWorker = useCreateProviderWorker();\n\n // Filters\n const [searchQuery, setSearchQuery] = useState('');\n const [roleFilter, setRoleFilter] = useState('');\n const [statusFilter, setStatusFilter] = useState('');\n\n // Invite modal\n const [showInviteModal, setShowInviteModal] = useState(false);\n const [inviteForm, setInviteForm] = useState<InviteForm>(emptyInviteForm);\n\n // Status\n const [statusMessage, setStatusMessage] = useState<StatusMessage | null>(null);\n\n const showStatus = (text: string, type: 'success' | 'error') => {\n setStatusMessage({ text, type });\n setTimeout(() => setStatusMessage(null), 3000);\n };\n\n // ---- Derived ----\n const roles = useMemo(() => [...new Set(workers.map((w) => w.role))].sort(), [workers]);\n const statuses = useMemo(() => [...new Set(workers.map((w) => w.status))].sort(), [workers]);\n\n const activeCount = workers.filter((w) => w.status.toUpperCase() === 'ACTIVE').length;\n const onLeaveCount = workers.filter((w) => {\n const s = w.status.toUpperCase();\n return s === 'ON_LEAVE' || s === 'ON-LEAVE';\n }).length;\n\n const filteredStaff = useMemo(() => {\n let result = [...workers];\n if (searchQuery) {\n const q = searchQuery.toLowerCase();\n result = result.filter((w) => {\n const meta = readMetadata(w.metadata);\n return (\n w.name.toLowerCase().includes(q) ||\n w.role.toLowerCase().includes(q) ||\n (meta.email ?? '').toLowerCase().includes(q) ||\n (meta.phone ?? '').includes(q)\n );\n });\n }\n if (roleFilter) result = result.filter((w) => w.role === roleFilter);\n if (statusFilter) result = result.filter((w) => w.status === statusFilter);\n result.sort((a, b) => a.name.localeCompare(b.name));\n return result;\n }, [workers, searchQuery, roleFilter, statusFilter]);\n\n const hasActiveFilters = Boolean(searchQuery || roleFilter || statusFilter);\n\n // ---- Handlers ----\n const handleInvite = () => {\n if (!inviteForm.name.trim() || !inviteForm.role) {\n showStatus('Please provide a name and role', 'error');\n return;\n }\n if (!providerId) {\n showStatus('No cart found to add staff to', 'error');\n return;\n }\n createWorker.mutate(\n {\n providerId,\n name: inviteForm.name.trim(),\n role: inviteForm.role,\n workerId: inviteForm.email.trim() || inviteForm.name.trim(),\n metadata: {\n email: inviteForm.email.trim() || undefined,\n phone: inviteForm.phone.trim() || undefined,\n },\n },\n {\n onSuccess: () => {\n setShowInviteModal(false);\n setInviteForm(emptyInviteForm);\n showStatus('Staff member added successfully', 'success');\n },\n onError: () => showStatus('Could not add staff member. Please try again.', 'error'),\n }\n );\n };\n\n const renderWorkerRow = (member: KadaikodiProviderWorkerRow) => {\n const status = statusColor(member.status);\n const meta = readMetadata(member.metadata);\n const initials = member.name\n .split(' ')\n .map((p) => p[0])\n .filter(Boolean)\n .slice(0, 2)\n .join('')\n .toUpperCase();\n\n return (\n <div key={member.id} className=\"p-4 sm:p-5 hover:bg-bg-sunken/30 transition-colors\">\n <div className=\"flex flex-col sm:flex-row sm:items-center gap-4\">\n <div className=\"flex items-center gap-4 flex-1 min-w-0\">\n <div className=\"relative shrink-0\">\n <div className=\"flex h-12 w-12 items-center justify-center rounded-full bg-bg-sunken text-sm font-semibold text-text-primary\">\n {initials || '?'}\n </div>\n <span\n className={cn(\n 'absolute -bottom-0.5 -right-0.5 h-3.5 w-3.5 rounded-full border-2 border-card',\n status.dot\n )}\n />\n </div>\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2 flex-wrap\">\n <p className=\"text-sm font-medium text-text-primary\">{member.name}</p>\n <span className=\"inline-flex items-center rounded-full px-2 py-0.5 text-[10px] font-medium bg-[var(--color-accent-soft)] text-text-primary\">\n {prettify(member.role)}\n </span>\n <span className={cn('text-xs', status.color)}>{status.label}</span>\n </div>\n {(meta.email || meta.phone) && (\n <div className=\"flex items-center gap-3 mt-1 text-xs text-text-secondary flex-wrap\">\n {meta.email && (\n <span className=\"flex items-center gap-1\">\n <Mail className=\"h-3 w-3\" />\n {meta.email}\n </span>\n )}\n {meta.phone && (\n <span className=\"flex items-center gap-1\">\n <Phone className=\"h-3 w-3\" />\n {meta.phone}\n </span>\n )}\n </div>\n )}\n </div>\n </div>\n </div>\n </div>\n );\n };\n\n return (\n <PageLayout\n title=\"Staff Management\"\n description=\"Manage your workers and delivery partners\"\n actions={\n <button\n type=\"button\"\n onClick={() => {\n setInviteForm(emptyInviteForm);\n setShowInviteModal(true);\n }}\n disabled={!providerId}\n className={cn(\n 'inline-flex items-center gap-2 rounded-md px-4 py-2 text-sm font-medium transition-colors',\n providerId\n ? 'bg-accent text-text-primary hover:bg-accent/80'\n : 'bg-bg-sunken text-text-secondary cursor-not-allowed'\n )}\n >\n <UserPlus className=\"h-4 w-4\" />\n Add Staff\n </button>\n }\n >\n <PagePurpose className=\"mb-6\">\n Your team in one place. Use this page to add workers and delivery partners to your cart, see\n who's active, and keep your roster organised so orders go out on time. Build a reliable\n crew around your cart.\n </PagePurpose>\n\n <div className=\"space-y-4\">\n {/* Status Message */}\n {statusMessage && (\n <div\n className={cn(\n 'flex items-center gap-2 rounded-lg border p-3',\n statusMessage.type === 'success'\n ? 'border-status-success-text/30 bg-status-success-bg-subtle'\n : 'border-status-error-text/30 bg-status-error-bg-subtle'\n )}\n >\n {statusMessage.type === 'success' ? (\n <CheckCircle2 className=\"h-4 w-4 text-status-success-text\" />\n ) : (\n <AlertCircle className=\"h-4 w-4 text-status-error-text\" />\n )}\n <span\n className={cn(\n 'text-sm font-medium',\n statusMessage.type === 'success'\n ? 'text-status-success-text'\n : 'text-status-error-text'\n )}\n >\n {statusMessage.text}\n </span>\n </div>\n )}\n\n {providersLoading ? (\n <div className=\"flex items-center justify-center py-24\">\n <div className=\"h-10 w-10 animate-spin rounded-full border-b-2 border-foreground\" />\n </div>\n ) : !myProvider ? (\n <EmptyState\n illustration=\"empty-people\"\n title=\"Create your cart first\"\n description=\"You need a service provider before you can add staff. Set up your cart to get started.\"\n />\n ) : (\n <>\n {/* Summary Stats — the one emphasis zone for this page */}\n <EmphasisPanel>\n <div className=\"mb-4 flex items-center justify-between gap-3\">\n <h2 className=\"text-base font-semibold text-text-primary\">Team Overview</h2>\n {workers.length > 0 && (\n <AvatarStack\n people={workers.map((w): Person => ({ name: w.name, role: w.role }))}\n max={6}\n size={30}\n />\n )}\n </div>\n <div className=\"grid grid-cols-2 sm:grid-cols-4 gap-3\">\n <StatCard label=\"Total Staff\" value={workers.length} icon={<Users className=\"h-4 w-4\" />} />\n <StatCard\n label=\"Active\"\n value={<span className=\"text-status-success-text\">{activeCount}</span>}\n icon={<CheckCircle2 className=\"h-4 w-4\" />}\n />\n <StatCard\n label=\"On Leave\"\n value={<span className=\"text-status-warning-text\">{onLeaveCount}</span>}\n icon={<Clock className=\"h-4 w-4\" />}\n />\n <StatCard label=\"Roles\" value={roles.length} icon={<Briefcase className=\"h-4 w-4\" />} />\n </div>\n </EmphasisPanel>\n\n {/* Filters */}\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-4 shadow-sm\">\n <div className=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3\">\n <div className=\"relative\">\n <Search className=\"absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-text-secondary\" />\n <input\n type=\"text\"\n placeholder=\"Search staff...\"\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n className=\"w-full rounded-md border border-border-subtle bg-bg-surface pl-10 pr-4 py-2 text-sm text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n />\n </div>\n <select\n value={roleFilter}\n onChange={(e) => setRoleFilter(e.target.value)}\n className=\"rounded-md border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary\"\n >\n <option value=\"\">All Roles</option>\n {roles.map((r) => (\n <option key={r} value={r}>\n {prettify(r)}\n </option>\n ))}\n </select>\n <select\n value={statusFilter}\n onChange={(e) => setStatusFilter(e.target.value)}\n className=\"rounded-md border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary\"\n >\n <option value=\"\">All Status</option>\n {statuses.map((s) => (\n <option key={s} value={s}>\n {prettify(s)}\n </option>\n ))}\n </select>\n </div>\n </div>\n\n {/* Staff List */}\n {workersLoading ? (\n <div className=\"flex items-center justify-center py-16\">\n <div className=\"h-10 w-10 animate-spin rounded-full border-b-2 border-foreground\" />\n </div>\n ) : filteredStaff.length === 0 ? (\n <EmptyState\n illustration={hasActiveFilters ? 'empty-search' : 'empty-people'}\n title=\"No staff members found\"\n description={\n hasActiveFilters\n ? 'No team members match your current filters. Try clearing them or searching for a different name.'\n : 'You have no staff yet. Add your first worker or delivery partner to start building your team.'\n }\n action={\n hasActiveFilters ? (\n <button\n type=\"button\"\n onClick={() => {\n setSearchQuery('');\n setRoleFilter('');\n setStatusFilter('');\n }}\n className=\"rounded-md border border-border-subtle px-4 py-2 text-sm text-text-primary hover:bg-bg-sunken\"\n >\n Clear filters\n </button>\n ) : (\n <button\n type=\"button\"\n onClick={() => {\n setInviteForm(emptyInviteForm);\n setShowInviteModal(true);\n }}\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\"\n >\n <UserPlus className=\"h-4 w-4\" />\n Add Staff\n </button>\n )\n }\n />\n ) : (\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface shadow-sm divide-y divide-border\">\n {filteredStaff.map(renderWorkerRow)}\n </div>\n )}\n </>\n )}\n </div>\n\n {/* Invite Staff Modal */}\n {showInviteModal && (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4\">\n <div className=\"w-full max-w-lg rounded-lg border border-border-subtle bg-bg-surface shadow-xl\">\n <div className=\"p-6\">\n <div className=\"flex items-center justify-between mb-4\">\n <h3 className=\"text-lg font-semibold text-text-primary\">Add Staff Member</h3>\n <button\n type=\"button\"\n onClick={() => setShowInviteModal(false)}\n className=\"rounded p-1.5 text-text-secondary hover:text-text-primary hover:bg-bg-sunken\"\n >\n <X className=\"h-5 w-5\" />\n </button>\n </div>\n <div className=\"space-y-4\">\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n Full Name *\n </label>\n <input\n type=\"text\"\n value={inviteForm.name}\n onChange={(e) => setInviteForm((p) => ({ ...p, name: e.target.value }))}\n className=\"w-full rounded-md border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary\"\n />\n </div>\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">Email</label>\n <input\n type=\"email\"\n value={inviteForm.email}\n onChange={(e) => setInviteForm((p) => ({ ...p, email: e.target.value }))}\n className=\"w-full rounded-md border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary\"\n />\n </div>\n <div className=\"grid grid-cols-2 gap-4\">\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n Phone\n </label>\n <input\n type=\"tel\"\n value={inviteForm.phone}\n onChange={(e) => setInviteForm((p) => ({ ...p, phone: e.target.value }))}\n className=\"w-full rounded-md border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary\"\n />\n </div>\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n Role *\n </label>\n <select\n value={inviteForm.role}\n onChange={(e) => setInviteForm((p) => ({ ...p, role: e.target.value }))}\n className=\"w-full rounded-md border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary\"\n >\n {ROLE_OPTIONS.map((r) => (\n <option key={r} value={r}>\n {prettify(r)}\n </option>\n ))}\n </select>\n </div>\n </div>\n </div>\n <div className=\"flex gap-3 mt-6\">\n <button\n type=\"button\"\n onClick={() => setShowInviteModal(false)}\n className=\"flex-1 rounded-md border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken\"\n >\n Cancel\n </button>\n <button\n type=\"button\"\n onClick={handleInvite}\n disabled={createWorker.isPending}\n className={cn(\n 'flex-1 rounded-md px-4 py-2 text-sm font-medium transition-colors',\n createWorker.isPending\n ? 'bg-bg-sunken text-text-secondary cursor-not-allowed'\n : 'bg-accent text-text-primary hover:bg-accent/80'\n )}\n >\n {createWorker.isPending ? 'Adding...' : 'Add Staff'}\n </button>\n </div>\n </div>\n </div>\n </div>\n )}\n </PageLayout>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"StaffManagementPage.js","names":[],"sources":["../../../../src/kadaikodi/pages/cart-owner/StaffManagementPage.tsx"],"sourcesContent":["/**\n * Staff Management Page\n *\n * Team overview and roster for the signed-in owner's own service provider (cart).\n * Lists the provider's real workers (useProviderWorkers) with role/status filters\n * and search, and invites new workers (useCreateProviderWorker). No fabricated\n * staff, performance metrics, or earnings.\n *\n * @module kadaikodi/pages/cart-owner\n */\n\nimport { useState, useMemo } from 'react';\nimport {\n UserPlus,\n Phone,\n Search,\n X,\n Mail,\n CheckCircle2,\n AlertCircle,\n Users,\n Clock,\n Briefcase,\n} from 'lucide-react';\nimport { EmphasisPanel, PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { EmptyState } from '../../components/EmptyState';\nimport { StatCard, AvatarStack } from '../../components/viz';\nimport type { Person } from '../../components/viz';\nimport { useKadaikodi } from '../../context/KadaikodiContext';\nimport {\n useProviders,\n useProviderWorkers,\n useCreateProviderWorker,\n type KadaikodiProviderWorkerRow,\n} from '../../hooks/useKadaikodiApi';\nimport { cn } from '../../utils/cn';\n\n// ============================================================================\n// Types\n// ============================================================================\n\ninterface InviteForm {\n name: string;\n email: string;\n phone: string;\n role: string;\n}\n\ninterface StatusMessage {\n text: string;\n type: 'success' | 'error';\n}\n\ninterface WorkerMetadata {\n email?: string;\n phone?: string;\n}\n\n// ============================================================================\n// Constants & helpers\n// ============================================================================\n\nconst ROLE_OPTIONS = ['MANAGER', 'CHEF', 'SERVER', 'DELIVERY', 'CASHIER'] as const;\n\nconst prettify = (s: string): string =>\n s\n .replace(/_/g, ' ')\n .toLowerCase()\n .replace(/\\b\\w/g, (c) => c.toUpperCase());\n\nconst statusColor = (status: string): { label: string; color: string; dot: string } => {\n const s = status.toUpperCase();\n if (s === 'ACTIVE')\n return {\n label: prettify(status),\n color: 'text-status-success-text',\n dot: 'bg-status-success-text',\n };\n if (s === 'ON_LEAVE' || s === 'ON-LEAVE')\n return {\n label: prettify(status),\n color: 'text-status-warning-text',\n dot: 'bg-status-warning-text',\n };\n return { label: prettify(status), color: 'text-text-secondary', dot: 'bg-muted-foreground' };\n};\n\nconst readMetadata = (metadata: Record<string, unknown> | null | undefined): WorkerMetadata => {\n if (!metadata || typeof metadata !== 'object') return {};\n const m = metadata as Record<string, unknown>;\n return {\n email: typeof m.email === 'string' ? m.email : undefined,\n phone: typeof m.phone === 'string' ? m.phone : undefined,\n };\n};\n\nconst emptyInviteForm: InviteForm = {\n name: '',\n email: '',\n phone: '',\n role: 'SERVER',\n};\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport const StaffManagementPage = () => {\n const { currentUser } = useKadaikodi();\n\n // Resolve the signed-in owner's provider (\"my cart\"), then load its workers.\n const { data: providers = [], isLoading: providersLoading } = useProviders();\n const myProvider = useMemo(\n () => providers.find((p) => p.ownerId === currentUser?.id) ?? providers[0],\n [providers, currentUser?.id]\n );\n const providerId = myProvider?.id;\n const { data: workers = [], isLoading: workersLoading } = useProviderWorkers(providerId);\n const createWorker = useCreateProviderWorker();\n\n // Filters\n const [searchQuery, setSearchQuery] = useState('');\n const [roleFilter, setRoleFilter] = useState('');\n const [statusFilter, setStatusFilter] = useState('');\n\n // Invite modal\n const [showInviteModal, setShowInviteModal] = useState(false);\n const [inviteForm, setInviteForm] = useState<InviteForm>(emptyInviteForm);\n\n // Status\n const [statusMessage, setStatusMessage] = useState<StatusMessage | null>(null);\n\n const showStatus = (text: string, type: 'success' | 'error') => {\n setStatusMessage({ text, type });\n setTimeout(() => setStatusMessage(null), 3000);\n };\n\n // ---- Derived ----\n const roles = useMemo(() => [...new Set(workers.map((w) => w.role))].sort(), [workers]);\n const statuses = useMemo(() => [...new Set(workers.map((w) => w.status))].sort(), [workers]);\n\n const activeCount = workers.filter((w) => w.status.toUpperCase() === 'ACTIVE').length;\n const onLeaveCount = workers.filter((w) => {\n const s = w.status.toUpperCase();\n return s === 'ON_LEAVE' || s === 'ON-LEAVE';\n }).length;\n\n const filteredStaff = useMemo(() => {\n let result = [...workers];\n if (searchQuery) {\n const q = searchQuery.toLowerCase();\n result = result.filter((w) => {\n const meta = readMetadata(w.metadata);\n return (\n w.name.toLowerCase().includes(q) ||\n w.role.toLowerCase().includes(q) ||\n (meta.email ?? '').toLowerCase().includes(q) ||\n (meta.phone ?? '').includes(q)\n );\n });\n }\n if (roleFilter) result = result.filter((w) => w.role === roleFilter);\n if (statusFilter) result = result.filter((w) => w.status === statusFilter);\n result.sort((a, b) => a.name.localeCompare(b.name));\n return result;\n }, [workers, searchQuery, roleFilter, statusFilter]);\n\n const hasActiveFilters = Boolean(searchQuery || roleFilter || statusFilter);\n\n // ---- Handlers ----\n const handleInvite = () => {\n if (!inviteForm.name.trim() || !inviteForm.role) {\n showStatus('Please provide a name and role', 'error');\n return;\n }\n if (!providerId) {\n showStatus('No cart found to add staff to', 'error');\n return;\n }\n createWorker.mutate(\n {\n providerId,\n name: inviteForm.name.trim(),\n role: inviteForm.role,\n workerId: inviteForm.email.trim() || inviteForm.name.trim(),\n metadata: {\n email: inviteForm.email.trim() || undefined,\n phone: inviteForm.phone.trim() || undefined,\n },\n },\n {\n onSuccess: () => {\n setShowInviteModal(false);\n setInviteForm(emptyInviteForm);\n showStatus('Staff member added successfully', 'success');\n },\n onError: () => showStatus('Could not add staff member. Please try again.', 'error'),\n }\n );\n };\n\n const renderWorkerRow = (member: KadaikodiProviderWorkerRow) => {\n const status = statusColor(member.status);\n const meta = readMetadata(member.metadata);\n const initials = member.name\n .split(' ')\n .map((p) => p[0])\n .filter(Boolean)\n .slice(0, 2)\n .join('')\n .toUpperCase();\n\n return (\n <div key={member.id} className=\"p-4 sm:p-5 hover:bg-bg-sunken/30 transition-colors\">\n <div className=\"flex flex-col sm:flex-row sm:items-center gap-4\">\n <div className=\"flex items-center gap-4 flex-1 min-w-0\">\n <div className=\"relative shrink-0\">\n <div className=\"flex h-12 w-12 items-center justify-center rounded-full bg-bg-sunken text-sm font-semibold text-text-primary\">\n {initials || '?'}\n </div>\n <span\n className={cn(\n 'absolute -bottom-0.5 -right-0.5 h-3.5 w-3.5 rounded-full border-2 border-card',\n status.dot\n )}\n />\n </div>\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2 flex-wrap\">\n <p className=\"text-sm font-medium text-text-primary\">{member.name}</p>\n <span className=\"inline-flex items-center rounded-full px-2 py-0.5 text-[10px] font-medium bg-[var(--color-accent-soft)] text-text-primary\">\n {prettify(member.role)}\n </span>\n <span className={cn('text-xs', status.color)}>{status.label}</span>\n </div>\n {(meta.email || meta.phone) && (\n <div className=\"flex items-center gap-3 mt-1 text-xs text-text-secondary flex-wrap\">\n {meta.email && (\n <span className=\"flex items-center gap-1\">\n <Mail className=\"h-3 w-3\" />\n {meta.email}\n </span>\n )}\n {meta.phone && (\n <span className=\"flex items-center gap-1\">\n <Phone className=\"h-3 w-3\" />\n {meta.phone}\n </span>\n )}\n </div>\n )}\n </div>\n </div>\n </div>\n </div>\n );\n };\n\n return (\n <PageLayout\n title=\"Staff Management\"\n description=\"Manage your workers and delivery partners\"\n actions={\n <button\n type=\"button\"\n onClick={() => {\n setInviteForm(emptyInviteForm);\n setShowInviteModal(true);\n }}\n disabled={!providerId}\n className={cn(\n 'inline-flex items-center gap-2 rounded-md px-4 py-2 text-sm font-medium transition-colors',\n providerId\n ? 'bg-accent text-text-primary hover:bg-accent/80'\n : 'bg-bg-sunken text-text-secondary cursor-not-allowed'\n )}\n >\n <UserPlus className=\"h-4 w-4\" />\n Add Staff\n </button>\n }\n >\n <PagePurpose className=\"mb-6\">\n Your team in one place. Use this page to add workers and delivery partners to your cart, see\n who's active, and keep your roster organised so orders go out on time. Build a reliable\n crew around your cart.\n </PagePurpose>\n\n <div className=\"space-y-4\">\n {/* Status Message */}\n {statusMessage && (\n <div\n className={cn(\n 'flex items-center gap-2 rounded-lg border p-3',\n statusMessage.type === 'success'\n ? 'border-status-success-text/30 bg-status-success-bg-subtle'\n : 'border-status-error-text/30 bg-status-error-bg-subtle'\n )}\n >\n {statusMessage.type === 'success' ? (\n <CheckCircle2 className=\"h-4 w-4 text-status-success-text\" />\n ) : (\n <AlertCircle className=\"h-4 w-4 text-status-error-text\" />\n )}\n <span\n className={cn(\n 'text-sm font-medium',\n statusMessage.type === 'success'\n ? 'text-status-success-text'\n : 'text-status-error-text'\n )}\n >\n {statusMessage.text}\n </span>\n </div>\n )}\n\n {providersLoading ? (\n <div className=\"flex items-center justify-center py-24\">\n <div className=\"h-10 w-10 animate-spin rounded-full border-b-2 border-foreground\" />\n </div>\n ) : !myProvider ? (\n <EmptyState\n illustration=\"empty-people\"\n title=\"Create your cart first\"\n description=\"You need a service provider before you can add staff. Set up your cart to get started.\"\n />\n ) : (\n <>\n {/* Summary Stats — the one emphasis zone for this page */}\n <EmphasisPanel>\n <div className=\"mb-4 flex items-center justify-between gap-3\">\n <h2 className=\"text-base font-semibold text-text-primary\">Team Overview</h2>\n {workers.length > 0 && (\n <AvatarStack\n people={workers.map((w): Person => ({ name: w.name, role: w.role }))}\n max={6}\n size={30}\n />\n )}\n </div>\n <div className=\"grid grid-cols-2 sm:grid-cols-4 gap-3\">\n <StatCard\n label=\"Total Staff\"\n value={workers.length}\n icon={<Users className=\"h-4 w-4\" />}\n />\n <StatCard\n label=\"Active\"\n value={<span className=\"text-status-success-text\">{activeCount}</span>}\n icon={<CheckCircle2 className=\"h-4 w-4\" />}\n />\n <StatCard\n label=\"On Leave\"\n value={<span className=\"text-status-warning-text\">{onLeaveCount}</span>}\n icon={<Clock className=\"h-4 w-4\" />}\n />\n <StatCard\n label=\"Roles\"\n value={roles.length}\n icon={<Briefcase className=\"h-4 w-4\" />}\n />\n </div>\n </EmphasisPanel>\n\n {/* Filters */}\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-4 shadow-sm\">\n <div className=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3\">\n <div className=\"relative\">\n <Search className=\"absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-text-secondary\" />\n <input\n type=\"text\"\n placeholder=\"Search staff...\"\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n className=\"w-full rounded-md border border-border-subtle bg-bg-surface pl-10 pr-4 py-2 text-sm text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n />\n </div>\n <select\n value={roleFilter}\n onChange={(e) => setRoleFilter(e.target.value)}\n className=\"rounded-md border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary\"\n >\n <option value=\"\">All Roles</option>\n {roles.map((r) => (\n <option key={r} value={r}>\n {prettify(r)}\n </option>\n ))}\n </select>\n <select\n value={statusFilter}\n onChange={(e) => setStatusFilter(e.target.value)}\n className=\"rounded-md border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary\"\n >\n <option value=\"\">All Status</option>\n {statuses.map((s) => (\n <option key={s} value={s}>\n {prettify(s)}\n </option>\n ))}\n </select>\n </div>\n </div>\n\n {/* Staff List */}\n {workersLoading ? (\n <div className=\"flex items-center justify-center py-16\">\n <div className=\"h-10 w-10 animate-spin rounded-full border-b-2 border-foreground\" />\n </div>\n ) : filteredStaff.length === 0 ? (\n <EmptyState\n illustration={hasActiveFilters ? 'empty-search' : 'empty-people'}\n title=\"No staff members found\"\n description={\n hasActiveFilters\n ? 'No team members match your current filters. Try clearing them or searching for a different name.'\n : 'You have no staff yet. Add your first worker or delivery partner to start building your team.'\n }\n action={\n hasActiveFilters ? (\n <button\n type=\"button\"\n onClick={() => {\n setSearchQuery('');\n setRoleFilter('');\n setStatusFilter('');\n }}\n className=\"rounded-md border border-border-subtle px-4 py-2 text-sm text-text-primary hover:bg-bg-sunken\"\n >\n Clear filters\n </button>\n ) : (\n <button\n type=\"button\"\n onClick={() => {\n setInviteForm(emptyInviteForm);\n setShowInviteModal(true);\n }}\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\"\n >\n <UserPlus className=\"h-4 w-4\" />\n Add Staff\n </button>\n )\n }\n />\n ) : (\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface shadow-sm divide-y divide-border\">\n {filteredStaff.map(renderWorkerRow)}\n </div>\n )}\n </>\n )}\n </div>\n\n {/* Invite Staff Modal */}\n {showInviteModal && (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4\">\n <div className=\"w-full max-w-lg rounded-lg border border-border-subtle bg-bg-surface shadow-xl\">\n <div className=\"p-6\">\n <div className=\"flex items-center justify-between mb-4\">\n <h3 className=\"text-lg font-semibold text-text-primary\">Add Staff Member</h3>\n <button\n type=\"button\"\n onClick={() => setShowInviteModal(false)}\n className=\"rounded p-1.5 text-text-secondary hover:text-text-primary hover:bg-bg-sunken\"\n >\n <X className=\"h-5 w-5\" />\n </button>\n </div>\n <div className=\"space-y-4\">\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n Full Name *\n </label>\n <input\n type=\"text\"\n value={inviteForm.name}\n onChange={(e) => setInviteForm((p) => ({ ...p, name: e.target.value }))}\n className=\"w-full rounded-md border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary\"\n />\n </div>\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">Email</label>\n <input\n type=\"email\"\n value={inviteForm.email}\n onChange={(e) => setInviteForm((p) => ({ ...p, email: e.target.value }))}\n className=\"w-full rounded-md border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary\"\n />\n </div>\n <div className=\"grid grid-cols-2 gap-4\">\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n Phone\n </label>\n <input\n type=\"tel\"\n value={inviteForm.phone}\n onChange={(e) => setInviteForm((p) => ({ ...p, phone: e.target.value }))}\n className=\"w-full rounded-md border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary\"\n />\n </div>\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n Role *\n </label>\n <select\n value={inviteForm.role}\n onChange={(e) => setInviteForm((p) => ({ ...p, role: e.target.value }))}\n className=\"w-full rounded-md border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary\"\n >\n {ROLE_OPTIONS.map((r) => (\n <option key={r} value={r}>\n {prettify(r)}\n </option>\n ))}\n </select>\n </div>\n </div>\n </div>\n <div className=\"flex gap-3 mt-6\">\n <button\n type=\"button\"\n onClick={() => setShowInviteModal(false)}\n className=\"flex-1 rounded-md border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken\"\n >\n Cancel\n </button>\n <button\n type=\"button\"\n onClick={handleInvite}\n disabled={createWorker.isPending}\n className={cn(\n 'flex-1 rounded-md px-4 py-2 text-sm font-medium transition-colors',\n createWorker.isPending\n ? 'bg-bg-sunken text-text-secondary cursor-not-allowed'\n : 'bg-accent text-text-primary hover:bg-accent/80'\n )}\n >\n {createWorker.isPending ? 'Adding...' : 'Add Staff'}\n </button>\n </div>\n </div>\n </div>\n </div>\n )}\n </PageLayout>\n );\n};\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BookingDetailsPage.d.ts","sourceRoot":"","sources":["../../../../src/kadaikodi/pages/customer/BookingDetailsPage.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AA2CH,wBAAgB,kBAAkB,
|
|
1
|
+
{"version":3,"file":"BookingDetailsPage.d.ts","sourceRoot":"","sources":["../../../../src/kadaikodi/pages/customer/BookingDetailsPage.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AA2CH,wBAAgB,kBAAkB,gCA0bjC"}
|