updates on the ui changes and changed into doormile
This commit is contained in:
191
src/pages/doormile/riders/EditRider.jsx
Normal file
191
src/pages/doormile/riders/EditRider.jsx
Normal file
@@ -0,0 +1,191 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useLocation, useNavigate } from 'react-router-dom';
|
||||
import { ArrowLeft, Bike } from 'lucide-react';
|
||||
import {
|
||||
Alert, Breadcrumb, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage,
|
||||
BreadcrumbSeparator, Button, Field, Input, LoadingState, PageHeader, Select,
|
||||
SelectContent, SelectItem, SelectTrigger, SelectValue, Stack, Surface,
|
||||
} from '@/components/ds';
|
||||
import { useAppLocations, useMiler, useTenants, useUpdateMiler } from '@/lib/doormileHooks';
|
||||
|
||||
/**
|
||||
* Edit a rider.
|
||||
*
|
||||
* Reached from the Riders table, which passes the row along in navigation
|
||||
* state; the record is then re-fetched by `milerprofileid`, because every
|
||||
* `/admin/milers/:id` route keys on that and 404s on the `userid` the same row
|
||||
* also carries.
|
||||
*
|
||||
* Only identity, contact, client and zone are writable. `PUT /admin/milers/:id`
|
||||
* documents no fields for bank details, vehicle settings or shift times, so
|
||||
* those are not offered here rather than shown as inputs that quietly discard
|
||||
* what is typed into them. A miler has a single `displayname` — there is no
|
||||
* first/last split anywhere on this resource.
|
||||
*/
|
||||
|
||||
const NO_TENANT = 'none';
|
||||
|
||||
export default function EditRider() {
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
|
||||
const passed = location.state?.rider;
|
||||
const milerProfileId = passed?.milerprofileid;
|
||||
|
||||
const { data: rider, isLoading } = useMiler(milerProfileId);
|
||||
const { data: tenants = [] } = useTenants();
|
||||
const { data: locations = [] } = useAppLocations();
|
||||
const updateMiler = useUpdateMiler();
|
||||
|
||||
const [form, setForm] = useState(null);
|
||||
|
||||
/* Seeded from the row that was clicked so the fields are populated on the
|
||||
first paint, then reconciled with the fetched record when it lands. */
|
||||
useEffect(() => {
|
||||
const source = rider || passed;
|
||||
if (!source) return;
|
||||
setForm({
|
||||
displayname: source.displayname || source.authname || '',
|
||||
phone: source.phone || source.contactno || '',
|
||||
email: source.email || '',
|
||||
tenantid: source.tenantid ?? '',
|
||||
applocationid: source.applocationid ?? '',
|
||||
});
|
||||
}, [rider, passed]);
|
||||
|
||||
const set = (key) => (value) => setForm((current) => ({ ...current, [key]: value }));
|
||||
|
||||
if (!milerProfileId) {
|
||||
return (
|
||||
<Stack space="lg">
|
||||
<PageHeader icon={Bike} title="Edit rider" />
|
||||
<Alert
|
||||
tone="warning"
|
||||
title="No rider selected"
|
||||
action={<Button onClick={() => navigate('/doormile/riders')}>Go to Riders</Button>}
|
||||
>
|
||||
Open a rider from the Riders table — this page needs the record that was clicked.
|
||||
</Alert>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
const submit = (event) => {
|
||||
event.preventDefault();
|
||||
updateMiler.mutate(
|
||||
{
|
||||
id: milerProfileId,
|
||||
data: {
|
||||
displayname: form.displayname,
|
||||
contactno: form.phone,
|
||||
email: form.email,
|
||||
tenantid: form.tenantid === '' ? undefined : Number(form.tenantid),
|
||||
applocationid: form.applocationid === '' ? undefined : Number(form.applocationid),
|
||||
},
|
||||
},
|
||||
{ onSuccess: (res) => res?.success !== false && navigate('/doormile/riders') }
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<Stack space="lg">
|
||||
<PageHeader
|
||||
icon={Bike}
|
||||
title={form?.displayname || 'Edit rider'}
|
||||
subtitle="Identity, contact, client and zone"
|
||||
breadcrumb={
|
||||
<Breadcrumb>
|
||||
<BreadcrumbList>
|
||||
<BreadcrumbItem>
|
||||
<BreadcrumbLink href="/doormile/riders">Riders</BreadcrumbLink>
|
||||
</BreadcrumbItem>
|
||||
<BreadcrumbSeparator />
|
||||
<BreadcrumbItem>
|
||||
<BreadcrumbPage>Edit</BreadcrumbPage>
|
||||
</BreadcrumbItem>
|
||||
</BreadcrumbList>
|
||||
</Breadcrumb>
|
||||
}
|
||||
actions={
|
||||
<Button variant="outline" onClick={() => navigate('/doormile/riders')}>
|
||||
<ArrowLeft className="mr-1.5 h-4 w-4" /> Back
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
|
||||
{isLoading && !form ? (
|
||||
<LoadingState message="Loading rider…" />
|
||||
) : (
|
||||
<form onSubmit={submit}>
|
||||
<Surface radius="xl" padding="lg">
|
||||
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3">
|
||||
<Field label="Display name">
|
||||
<Input value={form?.displayname || ''} onChange={(e) => set('displayname')(e.target.value)} />
|
||||
</Field>
|
||||
|
||||
<Field label="Mobile number">
|
||||
<Input
|
||||
value={form?.phone || ''}
|
||||
onChange={(e) => set('phone')(e.target.value.replace(/\D/g, '').slice(0, 10))}
|
||||
inputMode="numeric"
|
||||
/>
|
||||
</Field>
|
||||
|
||||
<Field label="Email">
|
||||
<Input type="email" value={form?.email || ''} onChange={(e) => set('email')(e.target.value)} />
|
||||
</Field>
|
||||
|
||||
<Field label="Client">
|
||||
<Select
|
||||
value={form?.tenantid === '' ? NO_TENANT : String(form?.tenantid ?? '')}
|
||||
onValueChange={(value) => set('tenantid')(value === NO_TENANT ? '' : value)}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="No client" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value={NO_TENANT}>No client</SelectItem>
|
||||
{(tenants || []).map((tenant) => (
|
||||
<SelectItem key={tenant.tenantid} value={String(tenant.tenantid)}>
|
||||
{tenant.tenantname || `Tenant #${tenant.tenantid}`}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</Field>
|
||||
|
||||
<Field label="City">
|
||||
<Select
|
||||
value={String(form?.applocationid ?? '')}
|
||||
onValueChange={set('applocationid')}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="Choose a city" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{(locations || [])
|
||||
.filter((entry) => entry.applocationid)
|
||||
.map((entry) => (
|
||||
<SelectItem key={entry.applocationid} value={String(entry.applocationid)}>
|
||||
{entry.locationname || `Location #${entry.applocationid}`}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</Field>
|
||||
</div>
|
||||
|
||||
<div className="mt-6 flex justify-end gap-2 border-t border-border pt-5">
|
||||
<Button type="button" variant="ghost" onClick={() => navigate('/doormile/riders')}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button type="submit" loading={updateMiler.isPending}>
|
||||
Save changes
|
||||
</Button>
|
||||
</div>
|
||||
</Surface>
|
||||
</form>
|
||||
)}
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user