updates on the admin and zone things and minor changes
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import React, { useMemo, useState } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { ArrowLeft, Building2, Copy, Eye, EyeOff, KeyRound, Pencil, ShieldCheck, Trash2, UserPlus } from 'lucide-react';
|
||||
import { ArrowLeft, Building2, Copy, Eye, EyeOff, KeyRound, MapPin, Pencil, ShieldCheck, Trash2, UserPlus } from 'lucide-react';
|
||||
import {
|
||||
Alert, Breadcrumb, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage,
|
||||
BreadcrumbSeparator, Button, DataTable, EmptyState, Field, Input, PageHeader, Stack,
|
||||
@@ -9,9 +9,11 @@ import {
|
||||
import { inputVariants } from '@/components/ui/input';
|
||||
import { useAuth } from '@/lib/AuthContext';
|
||||
import { useOnboardClient, useOnboardedClients, useOnboardingCities } from '@/lib/doormileHooks';
|
||||
import AddressAutocomplete from '@/components/doormile/AddressAutocomplete';
|
||||
import { EditClientModal, RemoveClientModal } from './ClientLoginDialogs';
|
||||
import {
|
||||
canOnboardClients, generateClientPassword, onboardingUnavailableMessage, validateOnboarding,
|
||||
addressFromPlace, addressPayload, canOnboardClients, generateClientPassword, hasMapLocation,
|
||||
onboardingUnavailableMessage, validateOnboarding,
|
||||
} from '@/lib/clientOnboarding';
|
||||
|
||||
/**
|
||||
@@ -35,6 +37,14 @@ const EMPTY = {
|
||||
password: '',
|
||||
confirm: '',
|
||||
requiredeliveryotp: false,
|
||||
// Main address, saved as the client's primary location. Coordinates come
|
||||
// only from picking a suggestion.
|
||||
address: '',
|
||||
city: '',
|
||||
state: '',
|
||||
pincode: '',
|
||||
latitude: '',
|
||||
longitude: '',
|
||||
};
|
||||
|
||||
const SERVER_FIELD = [
|
||||
@@ -44,6 +54,9 @@ const SERVER_FIELD = [
|
||||
['mobile', 'phone'],
|
||||
['password', 'password'],
|
||||
['operating city', 'applocationid'],
|
||||
['pincode', 'pincode'],
|
||||
['address', 'address'],
|
||||
['map location', 'address'],
|
||||
];
|
||||
|
||||
/** Put a server message under the field it is about, when it names one. */
|
||||
@@ -65,6 +78,11 @@ function OnboardedList() {
|
||||
{ key: 'tenantname', header: 'Client', accessor: (r) => r.tenantname },
|
||||
{ key: 'loginemail', header: 'Console login', accessor: (r) => r.loginemail },
|
||||
{ key: 'primarycontact', header: 'Contact', accessor: (r) => r.primarycontact || '—' },
|
||||
{
|
||||
key: 'address',
|
||||
header: 'Address',
|
||||
accessor: (r) => (r.address ? [r.address, r.pincode].filter(Boolean).join(' · ') : '—'),
|
||||
},
|
||||
{ key: 'status', header: 'Status', cell: (r) => <StatusBadge status={r.status} size="sm" /> },
|
||||
{
|
||||
key: 'logincreatedat',
|
||||
@@ -181,6 +199,7 @@ export default function ClientOnboarding() {
|
||||
password,
|
||||
applocationid: Number(form.applocationid),
|
||||
requiredeliveryotp: form.requiredeliveryotp,
|
||||
...addressPayload(form),
|
||||
},
|
||||
{
|
||||
onSuccess: (res) => {
|
||||
@@ -286,7 +305,9 @@ export default function ClientOnboarding() {
|
||||
role="alert"
|
||||
title="Client onboarding is not available right now"
|
||||
action={
|
||||
<Button size="sm" variant="outline" onClick={() => citiesQ.refetch()}>
|
||||
// type="button": this sits inside the form, and a plain button
|
||||
// would also submit it, flashing every field's error.
|
||||
<Button type="button" size="sm" variant="outline" onClick={() => citiesQ.refetch()}>
|
||||
Try again
|
||||
</Button>
|
||||
}
|
||||
@@ -356,6 +377,47 @@ export default function ClientOnboarding() {
|
||||
</select>
|
||||
</Field>
|
||||
|
||||
<div className="sm:col-span-2">
|
||||
<AddressAutocomplete
|
||||
id="onboard-address"
|
||||
label="Client address"
|
||||
required
|
||||
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>
|
||||
) : (
|
||||
<p className="mt-1 flex items-center gap-1 text-caption text-ink-3">
|
||||
<MapPin className="h-3.5 w-3.5" />
|
||||
{hasMapLocation(form)
|
||||
? "Location pinned. This becomes the client's pickup point and zone."
|
||||
: 'Pick a suggestion so the address gets a map location.'}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<Field label="Pincode" required error={errors.pincode}>
|
||||
<Input
|
||||
value={form.pincode}
|
||||
onChange={(e) => set('pincode')(e.target.value.replace(/\D/g, '').slice(0, 6))}
|
||||
placeholder="641002"
|
||||
inputMode="numeric"
|
||||
/>
|
||||
</Field>
|
||||
|
||||
<Field label="City">
|
||||
<Input value={form.city} onChange={(e) => set('city')(e.target.value)} placeholder="Coimbatore" maxLength={80} />
|
||||
</Field>
|
||||
|
||||
<Field label="Password" required error={errors.password} hint="At least 8 characters" htmlFor="onboard-password">
|
||||
<Input
|
||||
id="onboard-password"
|
||||
|
||||
Reference in New Issue
Block a user