Refactor/main flow #50

Merged
DeepnaPooja merged 2 commits from refactor/main_flow into dev 2026-09-29 17:34:26 +05:30
Showing only changes of commit d8ba956817 - Show all commits
@@ -25,6 +25,7 @@ import { Button } from '@/components/ui/button'
import { FieldGroup } from '@/components/ui/field'
import { Separator } from '@/components/ui/separator'
import { toast } from '@/components/ui/toast'
import { cn } from '@/lib/utils'
import {
shopPos as shopPosApi,
regions as regionsApi,
@@ -53,6 +54,39 @@ import type { LoadingSheetItemInput } from '@/lib/api/operations'
const ALL = '__all__'
const STEPS = [
{
n: 1,
label: 'Route & Warehouse',
title: 'Where is this load coming from?',
help: "Pick the route this ride will deliver (optional if you're only adding items manually below) and the warehouse every item will be dispatched from.",
},
{
n: 2,
label: 'Ride & Assignment',
title: 'Which vehicle, and who is populating this sheet?',
help: 'Choose the open ride whose vehicle gets loaded, and who is creating this sheet.',
},
{
n: 3,
label: 'Items',
title: 'What should be loaded from Shop POs?',
help: "Expand a shop to tick items and set quantities. If the main warehouse doesn't have enough stock, use \"Take remaining from another warehouse\" to top up the rest.",
},
{
n: 4,
label: 'Additional Items',
title: "Anything to load that's not on a PO?",
help: "Optional — add extra stock for the vehicle that isn't tied to any shop order.",
},
{
n: 5,
label: 'Review & Confirm',
title: 'Double-check before saving',
help: 'This is everything that will be saved to the sheet. Fix anything short before confirming later on the loading sheet list.',
},
] as const
interface ExtraAllocation {
warehouseId: string
quantity: number
@@ -115,6 +149,8 @@ function LoadingSheetForm() {
const [rideId, setRideId] = useState('')
const [populatedByUserId, setPopulatedByUserId] = useState('')
const [step, setStep] = useState<1 | 2 | 3 | 4 | 5>(1)
const [viewStoreId, setViewStoreId] = useState('')
const [itemsList, setItemsList] = useState<ItemSummaryResponse[]>([])
const [manualItems, setManualItems] = useState<ManualItem[]>([])
@@ -441,6 +477,34 @@ function LoadingSheetForm() {
updateExtras(line, line.extras.filter((_, i) => i !== index))
}
function goNext() {
if (step === 1) {
if (!warehouseId) {
toast.add({ title: 'Select a warehouse first', type: 'error' })
return
}
setStep(2)
return
}
if (step === 2) {
if (!rideId) {
toast.add({ title: 'Select a ride to load the vehicle', type: 'error' })
return
}
if (!populatedByUserId) {
toast.add({ title: 'Select who is populating this sheet', type: 'error' })
return
}
setStep(3)
return
}
if (step < 5) setStep((s) => (s + 1) as typeof step)
}
function goBack() {
setStep((s) => Math.max(1, s - 1) as typeof step)
}
async function handleSubmit() {
if (!routeId && manualItems.length === 0) {
toast.add({ title: 'Select a route first', type: 'error' })
@@ -541,13 +605,43 @@ function LoadingSheetForm() {
</Button>
<div>
<h1 className="text-2xl font-semibold text-foreground">{isEdit ? 'Edit Loading Sheet' : 'New Loading Sheet'}</h1>
<p className="text-sm text-muted-foreground">
Select a route first. Confirmed Shop POs for that route&apos;s shops will then be
available to pick items from. Pick the ride to load last.
</p>
<p className="text-sm text-muted-foreground">Work through the steps below to build the loading sheet.</p>
</div>
</div>
{/* Step indicator */}
<div className="flex flex-wrap items-center gap-2 text-xs">
{STEPS.map((s, idx) => (
<div key={s.n} className="flex items-center gap-2">
<button
type="button"
disabled={s.n > step}
onClick={() => s.n < step && setStep(s.n)}
className={cn(
'flex h-6 w-6 items-center justify-center rounded-full border font-semibold transition-colors',
step === s.n
? 'border-primary bg-primary text-primary-foreground'
: step > s.n
? 'border-primary/40 bg-primary/10 text-primary hover:bg-primary/20'
: 'border-muted-foreground/30 text-muted-foreground',
s.n < step && 'cursor-pointer'
)}
>
{step > s.n ? '✓' : s.n}
</button>
<span className={cn(step === s.n ? 'font-medium text-foreground' : 'text-muted-foreground')}>{s.label}</span>
{idx < STEPS.length - 1 && <div className="mx-1 h-px w-8 bg-border" />}
</div>
))}
</div>
{/* Step title & guidance */}
<div className="rounded-lg bg-muted/40 px-3 py-2">
<p className="text-sm font-medium">{STEPS[step - 1].title}</p>
<p className="mt-0.5 text-xs text-muted-foreground">{STEPS[step - 1].help}</p>
</div>
{step === 1 && (
<div className="rounded-2xl border p-6">
<h3 className="mb-4 text-sm font-medium text-foreground">Route &amp; Warehouse</h3>
<FieldGroup>
@@ -616,7 +710,9 @@ function LoadingSheetForm() {
</div>
</FieldGroup>
</div>
)}
{step === 3 && (
<div className="rounded-2xl border p-6">
<div className="mb-4">
<h3 className="text-sm font-medium text-foreground">Items</h3>
@@ -824,7 +920,9 @@ function LoadingSheetForm() {
</DialogContent>
</Dialog>
</div>
)}
{step === 4 && (
<div className="rounded-2xl border p-6">
<div className="mb-4 flex items-center justify-between gap-4">
<div>
@@ -897,7 +995,9 @@ function LoadingSheetForm() {
</div>
)}
</div>
)}
{step === 2 && (
<div className="rounded-2xl border p-6">
<h3 className="mb-4 text-sm font-medium text-foreground">Ride &amp; Assignment</h3>
<FieldGroup>
@@ -935,7 +1035,9 @@ function LoadingSheetForm() {
</div>
</FieldGroup>
</div>
)}
{step === 5 && (
<div>
<div className="w-full rounded-2xl border p-6">
<h3 className="text-sm font-medium text-foreground">Loading Sheet Summary</h3>
@@ -969,15 +1071,31 @@ function LoadingSheetForm() {
<p className="text-sm font-medium text-foreground">Total Quantity</p>
<p className="text-xl font-semibold text-foreground">{totalQuantity}</p>
</div>
</div>
</div>
)}
<div className="mt-6 flex justify-end gap-2">
<Button type="button" variant="outline" onClick={() => router.push('/operations/loading')}>
Cancel
<div className="flex items-center justify-between rounded-2xl border bg-muted/20 p-4">
<div>
{step > 1 && (
<Button type="button" variant="outline" onClick={goBack}>
Back
</Button>
)}
</div>
<div className="flex gap-2">
<Button type="button" variant="ghost" onClick={() => router.push('/operations/loading')}>
Cancel
</Button>
{step < 5 ? (
<Button type="button" onClick={goNext}>
{step === 1 ? 'Next: Ride & Assignment' : step === 4 ? `Next: Review${(selectedRows.length + manualItems.length) > 0 ? ` (${totalQuantity})` : ''}` : 'Next'}
</Button>
) : (
<Button type="button" disabled={submitting} onClick={handleSubmit}>
{submitting ? 'Saving…' : isEdit ? 'Save Changes' : 'Create Loading Sheet'}
</Button>
</div>
)}
</div>
</div>
</div>