updates on the admin and zone things and minor changes

This commit is contained in:
2026-10-06 19:21:06 +05:30
parent 6e73b59ca9
commit 7aca6a6a48
14 changed files with 589 additions and 90 deletions

View File

@@ -3,7 +3,8 @@ import { KeyRound, Pencil, Trash2 } from 'lucide-react';
import { Alert, Button, Field, Input, Modal, Switch } from '@/components/ds';
import { inputVariants } from '@/components/ui/input';
import { useDeleteOnboardedClient, useUpdateOnboardedClient } from '@/lib/doormileHooks';
import { generateClientPassword } from '@/lib/clientOnboarding';
import AddressAutocomplete from '@/components/doormile/AddressAutocomplete';
import { addressFromPlace, addressPayload, generateClientPassword, validateAddress } from '@/lib/clientOnboarding';
/**
* Edit and Remove for one onboarded client login (a row of "Clients with a
@@ -24,6 +25,28 @@ export function changedFields(row, form) {
if (form.status !== row.status) out.status = form.status;
if (Boolean(form.requiredeliveryotp) !== Boolean(row.requiredeliveryotp)) out.requiredeliveryotp = Boolean(form.requiredeliveryotp);
if (form.password) out.password = form.password;
// The address goes as one `location` object, and only when any part of it
// changed (a coordinate change alone counts: re-picking the same text moves
// the pin).
const addr = addressPayload(form);
const before = {
address: trim(row.address),
city: trim(row.city),
state: trim(row.state),
pincode: String(row.pincode || ''),
latitude: Number(row.latitude) || 0,
longitude: Number(row.longitude) || 0,
};
if (
addr.address !== before.address ||
addr.pincode !== before.pincode ||
addr.city !== before.city ||
addr.state !== before.state ||
(Number(addr.latitude) || 0) !== before.latitude ||
(Number(addr.longitude) || 0) !== before.longitude
) {
out.location = addr;
}
return out;
}
@@ -35,6 +58,7 @@ export function validateEdit(form, changes) {
if ('phone' in changes && !/^[6-9]\d{9}$/.test(changes.phone)) errors.phone = 'Enter a 10-digit mobile number';
if (form.password && form.password.length < 8) errors.password = 'At least 8 characters';
if (form.password && form.password.length > 72) errors.password = 'At most 72 characters';
if ('location' in changes) Object.assign(errors, validateAddress(form));
return errors;
}
@@ -47,6 +71,12 @@ function formFrom(row) {
status: STATUSES.includes(row?.status) ? row.status : 'Active',
requiredeliveryotp: Boolean(row?.requiredeliveryotp),
password: '',
address: row?.address || '',
city: row?.city || '',
state: row?.state || '',
pincode: row?.pincode || '',
latitude: row?.latitude || '',
longitude: row?.longitude || '',
};
}
@@ -172,6 +202,39 @@ export function EditClientModal({ row, onClose }) {
</Button>
)}
</div>
<div className="sm:col-span-2">
<AddressAutocomplete
id="edit-client-address"
label="Client address"
placeholder="Search the client's building, street or area…"
value={form.address}
onChange={(text) => set('address')(text)}
onPlaceSelected={(place) => {
setForm((f) => ({ ...f, ...addressFromPlace(place) }));
setErrors((e) => ({ ...e, address: undefined, pincode: undefined }));
}}
onPlaceCleared={() => setForm((f) => ({ ...f, latitude: '', longitude: '' }))}
/>
{errors.address ? (
<p className="mt-1 text-caption text-destructive" role="alert">
{errors.address}
</p>
) : (
!row?.address && (
<p className="mt-1 text-caption text-ink-3">No address on file yet. Add one so this client has a pickup point and zone.</p>
)
)}
</div>
<Field label="Pincode" error={errors.pincode}>
<Input
value={form.pincode}
inputMode="numeric"
onChange={(e) => set('pincode')(e.target.value.replace(/\D/g, '').slice(0, 6))}
/>
</Field>
<Field label="City">
<Input value={form.city} maxLength={80} onChange={(e) => set('city')(e.target.value)} />
</Field>
<Field label="Require delivery OTP" inline className="sm:col-span-2">
<Switch checked={form.requiredeliveryotp} onCheckedChange={set('requiredeliveryotp')} />
</Field>