upates on the toast and createorder and allthose things

This commit is contained in:
2026-09-25 16:02:57 +05:30
parent 3e7aaf1e25
commit f86e4b853b
16 changed files with 1274 additions and 133 deletions

View File

@@ -6,6 +6,7 @@ import {
Modal, Stack,
} from '@/components/ds';
import { ListToolbar } from '@/components/doormile/ListToolbar';
import { OpenToast } from '@/components/third-party/OpenToast';
import { useTenantCustomers, useUpdateTenantCustomer } from '@/lib/doormileHooks';
import { matchesQuery, number, percentOf, useDebouncedValue } from '@/lib/doormileFormat';
@@ -114,42 +115,64 @@ export default function Customers({ embedded = false }) {
const save = () => {
const id = custId(editRow);
// If it's a locally saved contact, update localStorage directly
const name = String(form.name || '').trim();
const cleanPhone = String(form.phone || '').replace(/\D/g, '').replace(/^(?:91|0)(?=\d{10}$)/, '');
if (name.length < 2) {
OpenToast('Enter the customer’s name (at least 2 letters).', 'warning', 4000);
return;
}
if (!/^\d{10}$/.test(cleanPhone)) {
OpenToast('Mobile number must be exactly 10 digits, without +91 or a leading 0.', 'warning', 4000);
return;
}
// A contact saved from Create Order lives only in this browser, so it is
// edited in localStorage rather than through the API.
if (String(id).startsWith('saved_')) {
const cleanPhone = String(form.phone || '').replace(/\D/g, '').slice(-10);
try {
const stored = JSON.parse(localStorage.getItem('doormile_saved_contacts') || '[]');
const updated = stored.map((item) => {
if (item.id === id || String(item.phone || item.contactno).replace(/\D/g, '').slice(-10) === cleanPhone) {
return {
...item,
name: form.name,
firstname: form.name,
phone: form.phone,
contactno: form.phone,
email: form.email
};
}
return item;
});
const isThis = (item) => item.id === id || item.appcustomerid === id;
// Match on the id ONLY. Matching on the new phone number as well used
// to overwrite a second, unrelated contact whenever the number was
// changed to one already on file.
const clash = stored.find(
(item) => !isThis(item) && String(item.phone || item.contactno || '').replace(/\D/g, '').slice(-10) === cleanPhone
);
if (clash) {
OpenToast(
`${clash.name || clash.firstname || 'Another saved contact'} already uses ${cleanPhone}. Use a different number, or edit that contact instead.`,
'warning',
6000
);
return;
}
const updated = stored.map((item) =>
isThis(item)
? { ...item, name, firstname: name, phone: cleanPhone, contactno: cleanPhone, email: String(form.email || '').trim(), updatedAt: new Date().toISOString() }
: item
);
localStorage.setItem('doormile_saved_contacts', JSON.stringify(updated));
window.dispatchEvent(new Event('doormile_saved_contacts_updated'));
} catch {}
setEditRow(null);
OpenToast(`${name}'s details have been updated.`, 'success', 3000);
setEditRow(null);
} catch {
OpenToast("We couldn't save this change in your browser. Please try again, or check that site storage isn't blocked.", 'error', 6000);
}
return;
}
/* The record stores firstname/lastname but the dialog edits one name field.
Splitting on the first space keeps the surname through a round trip
instead of blanking it. */
const [firstname, ...rest] = String(form.name || '').trim().split(/\s+/);
const [firstname, ...rest] = name.split(/\s+/);
updateCustomer.mutate(
{
id,
data: {
firstname: firstname || '',
lastname: rest.join(' '),
phone: form.phone || '',
phone: cleanPhone,
email: form.email || '',
},
},
@@ -180,7 +203,7 @@ export default function Customers({ embedded = false }) {
)}
</div>
<p className="text-caption text-ink-3 truncate max-w-xs" title={addr || `ID #${custId(row) ?? '—'}`}>
{addr ? `📍 ${addr}` : `ID #${custId(row) ?? '—'}`}
{addr || `ID #${custId(row) ?? '—'}`}
</p>
</div>
</div>
@@ -273,7 +296,7 @@ export default function Customers({ embedded = false }) {
<ListToolbar
search={search}
onSearchChange={setSearch}
placeholder="Search by name, phone or email"
placeholder="Search by name, phone, email or address"
count={{ shown: rows.length, total: mergedCustomers.length, noun: 'customers' }}
actions={
<Button onClick={() => navigate('/doormile/customer/create')}>