implemenation on the bot
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useNavigate } from 'react-router';
|
||||
import { useMutation, useQuery } from '@tanstack/react-query';
|
||||
import { useMutation } from '@tanstack/react-query';
|
||||
import { enqueueSnackbar } from 'notistack';
|
||||
import { MdPersonAddAlt1 } from 'react-icons/md';
|
||||
|
||||
@@ -11,7 +11,6 @@ import { Card } from '@astryxdesign/core/Card';
|
||||
import { Text } from '@astryxdesign/core/Text';
|
||||
import { Button } from '@astryxdesign/core/Button';
|
||||
import { TextInput } from '@astryxdesign/core/TextInput';
|
||||
import { Selector } from '@astryxdesign/core/Selector';
|
||||
import { Divider } from '@astryxdesign/core/Divider';
|
||||
|
||||
import Loader from 'components/Loader';
|
||||
@@ -19,34 +18,32 @@ import PageHeader from 'components/nearle_components/PageHeader';
|
||||
import { PageShell } from 'components/nearle_components/PageLayout';
|
||||
import AddressAutocomplete from 'components/nearle_components/AddressAutocomplete';
|
||||
import LocationAutocomplete from 'components/nearle_components/LocationAutocomplete';
|
||||
import { createTenantCustomer, getAdminTenants } from 'pages/api/doormileApi';
|
||||
import { createAdminCustomer } from 'pages/api/doormileApi';
|
||||
import { DT } from 'themes/dt/tokens';
|
||||
import { AccentAvatar } from 'themes/dt/primitives';
|
||||
|
||||
const BRAND = DT.brand;
|
||||
|
||||
// Same field set as nearle_console_express's createCustomer.js (Location,
|
||||
// Choose Client, Name, Phone, Email, Door No, Address, Location/City/State/
|
||||
// Postcode, Landmark) — but POST /admin/tenantcustomers only persists
|
||||
// { firstname, lastname, phone, email }. There is no address/coordinate
|
||||
// storage anywhere on the new API for a customer record (confirmed against
|
||||
// express-console-api.md — the old jupiter /customers/create body doesn't
|
||||
// exist here at all). The address section below is collected and shown so
|
||||
// the form matches the reference 1:1, but it is NOT sent on submit — see the
|
||||
// note under that section. `tenantid` isn't in the documented POST body
|
||||
// either; it's included speculatively for staff logins (every other create
|
||||
// endpoint on this API takes tenantid explicitly) and may be silently
|
||||
// ignored server-side — unconfirmed, this endpoint isn't in the "confirmed
|
||||
// end-to-end" list.
|
||||
// Writes to POST /admin/customers — the same resource the Customers page
|
||||
// (customers.js) reads via getAdminCustomers(), so a customer created here
|
||||
// shows up there immediately. This used to call createTenantCustomer
|
||||
// (POST /admin/tenantcustomers), a different store with its own id
|
||||
// sequence — a customer created that way never appeared on the Customers
|
||||
// list. See src/pages/nearle/assistant/CLAUDE.md ("Customer creation writes
|
||||
// to /admin/customers") for the full history; the Doormile AI assistant's
|
||||
// executeCreateCustomer was fixed first, this page now matches it.
|
||||
//
|
||||
// This resource carries no tenantid (confirmed against a real
|
||||
// GET /admin/customers response), so there's no tenant picker here — unlike
|
||||
// Tenants/Riders/etc, a customer isn't scoped to a client at creation time.
|
||||
// A real GET /admin/customers response does carry address, doorno, landmark,
|
||||
// suburb, city, state, postcode, latitude and longitude, so the address
|
||||
// section below is sent (empty fields dropped) rather than discarded.
|
||||
const Createcustomer = () => {
|
||||
const navigate = useNavigate();
|
||||
|
||||
const loggedInTenantId = localStorage.getItem('tenantid');
|
||||
const isStaffLogin = !loggedInTenantId || loggedInTenantId === '0';
|
||||
|
||||
const [appId, setAppId] = useState(0);
|
||||
const [locaName, setLocoName] = useState('Select Location');
|
||||
const [tid, setTid] = useState(isStaffLogin ? '' : loggedInTenantId);
|
||||
|
||||
const [firstname, setFirstname] = useState('');
|
||||
const [lastname, setLastname] = useState('');
|
||||
@@ -60,13 +57,6 @@ const Createcustomer = () => {
|
||||
const [appLocaLat, setAppLocaLat] = useState();
|
||||
const [appLocaLng, setAppLocaLng] = useState();
|
||||
|
||||
const { data: tenantList = [] } = useQuery({
|
||||
queryKey: ['admin-tenants-picker'],
|
||||
queryFn: getAdminTenants,
|
||||
enabled: isStaffLogin
|
||||
});
|
||||
const tenantOptions = (tenantList || []).map((t) => ({ value: String(t.tenantid), label: t.tenantname || `Tenant #${t.tenantid}` }));
|
||||
|
||||
// LocationAutocomplete only reports back applocationid/locationname — it
|
||||
// caches the full hub list (with lat/lng) in localStorage under a
|
||||
// tenant-scoped key (applocations_<tenantid>, see LocationAutocomplete.js)
|
||||
@@ -123,8 +113,13 @@ const Createcustomer = () => {
|
||||
const opentoast = (message) =>
|
||||
enqueueSnackbar(message, { variant: 'error', anchorOrigin: { vertical: 'top', horizontal: 'right' }, autoHideDuration: 2000 });
|
||||
|
||||
// Empty fields are dropped rather than sent as noise — mirrors
|
||||
// buildCustomerPayload in assistant/actions.js, the other caller of this
|
||||
// same endpoint.
|
||||
const clean = (obj) => Object.fromEntries(Object.entries(obj).filter(([, v]) => v !== undefined && v !== null && v !== ''));
|
||||
|
||||
const createCustomerMutation = useMutation({
|
||||
mutationFn: (payload) => createTenantCustomer(payload),
|
||||
mutationFn: (payload) => createAdminCustomer(payload),
|
||||
onSuccess: (res) => {
|
||||
if (res.success) {
|
||||
enqueueSnackbar('Customer created successfully', {
|
||||
@@ -141,20 +136,28 @@ const Createcustomer = () => {
|
||||
});
|
||||
|
||||
const createprofile = () => {
|
||||
if (isStaffLogin && !tid) {
|
||||
opentoast('Select Tenant');
|
||||
} else if (!firstname) {
|
||||
if (!firstname) {
|
||||
opentoast('Enter Name');
|
||||
} else if (!phone || phone.length !== 10) {
|
||||
opentoast('Enter a valid 10-digit Mobile Number');
|
||||
} else {
|
||||
createCustomerMutation.mutate({
|
||||
firstname,
|
||||
lastname,
|
||||
phone,
|
||||
email,
|
||||
...(isStaffLogin && tid ? { tenantid: +tid } : {})
|
||||
});
|
||||
createCustomerMutation.mutate(
|
||||
clean({
|
||||
firstname,
|
||||
lastname,
|
||||
phone,
|
||||
email,
|
||||
address: pickCust.address,
|
||||
doorno,
|
||||
landmark,
|
||||
suburb: pickCust.suburb,
|
||||
city: pickCust.city,
|
||||
state: pickCust.state,
|
||||
postcode: pickCust.postcode,
|
||||
latitude: startPoint.latitude || undefined,
|
||||
longitude: startPoint.longitude || undefined
|
||||
})
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -182,16 +185,6 @@ const Createcustomer = () => {
|
||||
</Text>
|
||||
<LocationAutocomplete locaName={locaName} setAppId={setAppId} setLocoName={setLocoName} />
|
||||
</VStack>
|
||||
{isStaffLogin && (
|
||||
<Selector
|
||||
label="Choose Client"
|
||||
options={tenantOptions}
|
||||
value={tid ? String(tid) : ''}
|
||||
onChange={(v) => setTid(v || '')}
|
||||
placeholder="Choose Client"
|
||||
hasSearch
|
||||
/>
|
||||
)}
|
||||
<TextInput label="Name" placeholder="First Name" value={firstname} onChange={setFirstname} isRequired />
|
||||
<TextInput label="Last Name" placeholder="Last Name" value={lastname} onChange={setLastname} isOptional />
|
||||
<TextInput
|
||||
@@ -210,11 +203,6 @@ const Createcustomer = () => {
|
||||
|
||||
<Divider />
|
||||
|
||||
<Text type="supporting" color="secondary" style={{ fontStyle: 'italic' }}>
|
||||
The backend doesn't store an address against a customer yet — these fields aren't required and won't be saved
|
||||
on submit.
|
||||
</Text>
|
||||
|
||||
<AddressAutocomplete
|
||||
id="customer-address"
|
||||
label="Address"
|
||||
|
||||
Reference in New Issue
Block a user