updates on the ui changes and table
This commit is contained in:
@@ -56,6 +56,7 @@ import DebounceSearchBar from 'components/nearle_components/DebounceSearchBar';
|
||||
import PageHeader from 'components/nearle_components/PageHeader';
|
||||
import StatCard from 'components/nearle_components/StatCard';
|
||||
import TableLoader from 'components/nearle_components/TableLoader';
|
||||
import { PageShell, KpiGrid, DataCard } from 'components/nearle_components/PageLayout';
|
||||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
||||
import { getalltenants } from 'pages/api/api';
|
||||
import {
|
||||
@@ -209,7 +210,14 @@ const TenantLocationsDialog = ({ tenant, open, onClose }) => {
|
||||
{[loc.address, loc.city, loc.state, loc.pincode].filter(Boolean).join(', ')}
|
||||
</Text>
|
||||
</VStack>
|
||||
<IconButton label="Edit location" tooltip="Edit location" size="sm" variant="ghost" icon={<MdEdit size={14} />} onClick={() => openEdit(loc)} />
|
||||
<IconButton
|
||||
label="Edit location"
|
||||
tooltip="Edit location"
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
icon={<MdEdit size={14} />}
|
||||
onClick={() => openEdit(loc)}
|
||||
/>
|
||||
</HStack>
|
||||
</Card>
|
||||
))}
|
||||
@@ -217,7 +225,11 @@ const TenantLocationsDialog = ({ tenant, open, onClose }) => {
|
||||
)}
|
||||
|
||||
{formOpen && (
|
||||
<Grid columns={{ minWidth: 200 }} gap={2} style={{ marginTop: 16, paddingTop: 16, borderTop: `1px solid ${DT.divider}` }}>
|
||||
<Grid
|
||||
columns={{ minWidth: 200, repeat: 'fit' }}
|
||||
gap={2}
|
||||
style={{ marginTop: 'var(--spacing-6)', paddingTop: 16, borderTop: `1px solid ${DT.divider}` }}
|
||||
>
|
||||
<TextInput label="Location Name" value={form.locationname} onChange={(v) => setForm((f) => ({ ...f, locationname: v }))} />
|
||||
<TextInput label="Pincode" value={form.pincode} onChange={(v) => setForm((f) => ({ ...f, pincode: v }))} />
|
||||
<TextInput label="Address" value={form.address} onChange={(v) => setForm((f) => ({ ...f, address: v }))} />
|
||||
@@ -393,7 +405,14 @@ const TenantCustomersDialog = ({ tenant, open, onClose }) => {
|
||||
</Text>
|
||||
</VStack>
|
||||
<HStack gap={1}>
|
||||
<IconButton label="Edit customer" tooltip="Edit customer" size="sm" variant="ghost" icon={<MdEdit size={14} />} onClick={() => openEdit(c)} />
|
||||
<IconButton
|
||||
label="Edit customer"
|
||||
tooltip="Edit customer"
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
icon={<MdEdit size={14} />}
|
||||
onClick={() => openEdit(c)}
|
||||
/>
|
||||
<IconButton
|
||||
label="Delete customer"
|
||||
tooltip="Delete customer"
|
||||
@@ -410,7 +429,11 @@ const TenantCustomersDialog = ({ tenant, open, onClose }) => {
|
||||
)}
|
||||
|
||||
{formOpen && (
|
||||
<Grid columns={{ minWidth: 200 }} gap={2} style={{ marginTop: 16, paddingTop: 16, borderTop: `1px solid ${DT.divider}` }}>
|
||||
<Grid
|
||||
columns={{ minWidth: 200, repeat: 'fit' }}
|
||||
gap={2}
|
||||
style={{ marginTop: 'var(--spacing-6)', paddingTop: 16, borderTop: `1px solid ${DT.divider}` }}
|
||||
>
|
||||
<TextInput label="First Name" value={form.firstname} onChange={(v) => setForm((f) => ({ ...f, firstname: v }))} />
|
||||
<TextInput label="Last Name" value={form.lastname} onChange={(v) => setForm((f) => ({ ...f, lastname: v }))} />
|
||||
<TextInput label="Phone" value={form.phone} onChange={(v) => setForm((f) => ({ ...f, phone: v }))} />
|
||||
@@ -670,9 +693,7 @@ const Clients1 = () => {
|
||||
if (String(t.status || '').toLowerCase() !== activeStatus) return false;
|
||||
if (!q) return true;
|
||||
return (
|
||||
t.tenantname?.toLowerCase().includes(q) ||
|
||||
t.primaryemail?.toLowerCase().includes(q) ||
|
||||
t.primarycontact?.includes(debouncedSearch)
|
||||
t.tenantname?.toLowerCase().includes(q) || t.primaryemail?.toLowerCase().includes(q) || t.primarycontact?.includes(debouncedSearch)
|
||||
);
|
||||
});
|
||||
}, [tenantList, value0, debouncedSearch]);
|
||||
@@ -913,12 +934,16 @@ const Clients1 = () => {
|
||||
>
|
||||
{value1 == '0' && (
|
||||
<VStack gap={0} padding={4}>
|
||||
<Grid columns={{ minWidth: 220 }} gap={3}>
|
||||
<Grid columns={{ minWidth: 220, repeat: 'fit' }} gap={3}>
|
||||
<InfoRow icon={FiUser} value={row.tenantname} caption="Tenant" />
|
||||
<InfoRow icon={FaRegCheckCircle} value={row.status || '—'} caption="Status" />
|
||||
<InfoRow icon={FiPhoneCall} value={row.primarycontact} caption="Phone" />
|
||||
<InfoRow icon={LuMail} value={row.primaryemail} caption="E-Mail" />
|
||||
<InfoRow icon={row.requiredeliveryotp ? MdCheckCircle : MdCancel} value={row.requiredeliveryotp ? 'Yes' : 'No'} caption="Delivery OTP Required" />
|
||||
<InfoRow
|
||||
icon={row.requiredeliveryotp ? MdCheckCircle : MdCancel}
|
||||
value={row.requiredeliveryotp ? 'Yes' : 'No'}
|
||||
caption="Delivery OTP Required"
|
||||
/>
|
||||
</Grid>
|
||||
</VStack>
|
||||
)}
|
||||
@@ -947,20 +972,14 @@ const Clients1 = () => {
|
||||
{value0 !== 1 && <Tab value="1" label="Edit Pricing" icon={<GiMoneyStack size={16} />} />}
|
||||
</TabList>
|
||||
{value2 == '1' && (
|
||||
<Button
|
||||
label="Add Pricing"
|
||||
variant="destructive"
|
||||
size="sm"
|
||||
icon={<MdEdit size={14} />}
|
||||
onClick={() => setDialogopen(true)}
|
||||
/>
|
||||
<Button label="Add Pricing" variant="destructive" size="sm" icon={<MdEdit size={14} />} onClick={() => setDialogopen(true)} />
|
||||
)}
|
||||
</HStack>
|
||||
}
|
||||
>
|
||||
{value2 == '0' && (
|
||||
<VStack gap={3} padding={4}>
|
||||
<Grid columns={{ minWidth: 240 }} gap={3}>
|
||||
<Grid columns={{ minWidth: 240, repeat: 'fit' }} gap={3}>
|
||||
<TextInput
|
||||
label="Tenant Name"
|
||||
value={editClient.tenantname ?? selectedCustomer.tenantname ?? ''}
|
||||
@@ -995,7 +1014,7 @@ const Clients1 = () => {
|
||||
onPlaceSelected={handleAddressPlaceSelected}
|
||||
/>
|
||||
|
||||
<Grid columns={{ minWidth: 200 }} gap={3}>
|
||||
<Grid columns={{ minWidth: 200, repeat: 'fit' }} gap={3}>
|
||||
<TextInput
|
||||
label="City"
|
||||
value={city == '' ? selectedCustomer.city || '' : city}
|
||||
@@ -1012,7 +1031,7 @@ const Clients1 = () => {
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
<Grid columns={{ minWidth: 200 }} gap={3}>
|
||||
<Grid columns={{ minWidth: 200, repeat: 'fit' }} gap={3}>
|
||||
<TextInput label="Latitude" value={latlong.lat ?? ''} isDisabled startIcon={TbWorldLatitude} />
|
||||
<TextInput label="Longitude" value={latlong.lng ?? ''} isDisabled startIcon={TbWorldLongitude} />
|
||||
</Grid>
|
||||
@@ -1034,70 +1053,92 @@ const Clients1 = () => {
|
||||
<>
|
||||
{(getalltenantsIsLoading || isloader) && <Loader />}
|
||||
|
||||
<PageHeader
|
||||
title="Tenants"
|
||||
subtitle={`Live · ${locaName || 'All Zones'}`}
|
||||
live
|
||||
action={<LocationAutocomplete locaName={locaName} setAppId={setAppId} setLocoName={setLocoName} setPage={setPage} placeholder="Select Zone" />}
|
||||
/>
|
||||
<PageShell>
|
||||
<PageHeader
|
||||
title="Tenants"
|
||||
subtitle={`Live · ${locaName || 'All Zones'}`}
|
||||
live
|
||||
action={
|
||||
<LocationAutocomplete
|
||||
locaName={locaName}
|
||||
setAppId={setAppId}
|
||||
setLocoName={setLocoName}
|
||||
setPage={setPage}
|
||||
placeholder="Select Zone"
|
||||
/>
|
||||
}
|
||||
/>
|
||||
|
||||
<Grid columns={{ minWidth: 200, max: 4, repeat: 'fit' }} gap={3}>
|
||||
{KPI_META.map((item) => {
|
||||
const Icon = item.icon;
|
||||
const value = tenantStatusCounts[item.countKey] ?? 0;
|
||||
// 'total' has no matching entry in STATUS_TABS (there's no "All"
|
||||
// tab) — only the three status tiles switch tabs when clicked.
|
||||
const tabIdx = STATUS_TABS.findIndex((t) => t.countKey === item.countKey);
|
||||
const clickable = tabIdx !== -1;
|
||||
return (
|
||||
<div
|
||||
key={item.key}
|
||||
role={clickable ? 'button' : undefined}
|
||||
tabIndex={clickable ? 0 : undefined}
|
||||
onClick={clickable ? () => handleChange(tabIdx) : undefined}
|
||||
onKeyDown={
|
||||
clickable
|
||||
? (e) => {
|
||||
if (e.key === 'Enter' || e.key === ' ') handleChange(tabIdx);
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
style={{ cursor: clickable ? 'pointer' : 'default', height: '100%' }}
|
||||
>
|
||||
<StatCard title={item.label} value={value ?? 0} icon={<Icon size={20} />} color={item.color} loading={getalltenantsIsLoading} />
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</Grid>
|
||||
<KpiGrid>
|
||||
{KPI_META.map((item) => {
|
||||
const Icon = item.icon;
|
||||
const value = tenantStatusCounts[item.countKey] ?? 0;
|
||||
// 'total' has no matching entry in STATUS_TABS (there's no "All"
|
||||
// tab) — only the three status tiles switch tabs when clicked.
|
||||
const tabIdx = STATUS_TABS.findIndex((t) => t.countKey === item.countKey);
|
||||
const clickable = tabIdx !== -1;
|
||||
return (
|
||||
<div
|
||||
key={item.key}
|
||||
role={clickable ? 'button' : undefined}
|
||||
tabIndex={clickable ? 0 : undefined}
|
||||
onClick={clickable ? () => handleChange(tabIdx) : undefined}
|
||||
onKeyDown={
|
||||
clickable
|
||||
? (e) => {
|
||||
if (e.key === 'Enter' || e.key === ' ') handleChange(tabIdx);
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
style={{ cursor: clickable ? 'pointer' : 'default', height: '100%' }}
|
||||
>
|
||||
<StatCard
|
||||
title={item.label}
|
||||
value={value ?? 0}
|
||||
icon={<Icon size={20} />}
|
||||
color={item.color}
|
||||
loading={getalltenantsIsLoading}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</KpiGrid>
|
||||
|
||||
<VStack gap={0} padding={0} style={{ marginTop: 16 }}>
|
||||
<Card padding={3} elevation="none" style={{ borderBottomLeftRadius: 0, borderBottomRightRadius: 0, borderBottom: 'none' }}>
|
||||
<HStack justify="between" vAlign="center" gap={2} wrap="wrap-reverse">
|
||||
<TabList
|
||||
value={String(value0)}
|
||||
onChange={(v) => {
|
||||
const idx = Number(v);
|
||||
setstatus(STATUS_TABS[idx].status);
|
||||
handleChange(idx);
|
||||
}}
|
||||
size="sm"
|
||||
hasDivider={false}
|
||||
>
|
||||
{STATUS_TABS.map((t, idx) => {
|
||||
const meta = STATUS_META[t.status];
|
||||
const Icon = meta.icon;
|
||||
const count = tenantStatusCounts[t.countKey] ?? 0;
|
||||
return <Tab key={t.status} value={String(idx)} label={meta.label} icon={<Icon size={15} />} endContent={<Badge variant="neutral" label={count} />} />;
|
||||
})}
|
||||
</TabList>
|
||||
<DataCard
|
||||
tabs={
|
||||
<HStack justify="between" vAlign="center" gap={2} wrap="wrap">
|
||||
<TabList
|
||||
value={String(value0)}
|
||||
onChange={(v) => {
|
||||
const idx = Number(v);
|
||||
setstatus(STATUS_TABS[idx].status);
|
||||
handleChange(idx);
|
||||
}}
|
||||
size="sm"
|
||||
hasDivider={false}
|
||||
>
|
||||
{STATUS_TABS.map((t, idx) => {
|
||||
const meta = STATUS_META[t.status];
|
||||
const Icon = meta.icon;
|
||||
const count = tenantStatusCounts[t.countKey] ?? 0;
|
||||
return (
|
||||
<Tab
|
||||
key={t.status}
|
||||
value={String(idx)}
|
||||
label={meta.label}
|
||||
icon={<Icon size={15} />}
|
||||
endContent={<Badge variant="neutral" label={count} />}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</TabList>
|
||||
|
||||
<div style={{ width: 280, maxWidth: '100%' }}>
|
||||
<DebounceSearchBar value={searchword} onChange={setSearchword} onDebouncedChange={setDebouncedSearch} />
|
||||
</div>
|
||||
</HStack>
|
||||
</Card>
|
||||
|
||||
<Card padding={0} elevation="none" style={{ borderTopLeftRadius: 0, borderTopRightRadius: 0, overflow: 'hidden' }}>
|
||||
<VStack width={280} padding={0} gap={0}>
|
||||
<DebounceSearchBar value={searchword} onChange={setSearchword} onDebouncedChange={setDebouncedSearch} />
|
||||
</VStack>
|
||||
</HStack>
|
||||
}
|
||||
>
|
||||
{!isMobile && (
|
||||
<TableScroll minWidth={960}>
|
||||
<Table density="balanced" dividers="rows" hasHover>
|
||||
@@ -1272,15 +1313,20 @@ const Clients1 = () => {
|
||||
</HStack>
|
||||
</>
|
||||
)}
|
||||
</Card>
|
||||
</VStack>
|
||||
</DataCard>
|
||||
</PageShell>
|
||||
|
||||
<Dialog isOpen={dialogopen} onOpenChange={(next) => !next && dialogclose()} width={640} purpose="form">
|
||||
<Layout
|
||||
header={<DialogHeader title={`Client Pricing - (${selectedCustomer.tenantname || ''})`} onOpenChange={(next) => !next && dialogclose()} />}
|
||||
header={
|
||||
<DialogHeader
|
||||
title={`Client Pricing - (${selectedCustomer.tenantname || ''})`}
|
||||
onOpenChange={(next) => !next && dialogclose()}
|
||||
/>
|
||||
}
|
||||
content={
|
||||
<LayoutContent padding={4}>
|
||||
<Grid columns={{ minWidth: 220 }} gap={3}>
|
||||
<Grid columns={{ minWidth: 220, repeat: 'fit' }} gap={3}>
|
||||
<Selector
|
||||
label="Select Slab"
|
||||
options={VEHICLE_TYPE_OPTIONS}
|
||||
|
||||
@@ -16,6 +16,7 @@ import { Divider } from '@astryxdesign/core/Divider';
|
||||
|
||||
import Loader from 'components/Loader';
|
||||
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';
|
||||
@@ -161,86 +162,104 @@ const Createcustomer = () => {
|
||||
<>
|
||||
{createCustomerMutation.isPending && <Loader />}
|
||||
|
||||
<PageHeader
|
||||
title="Create Customer"
|
||||
subtitle="Add a customer record"
|
||||
action={
|
||||
<AccentAvatar color={BRAND} selected size={40}>
|
||||
<MdPersonAddAlt1 size={20} />
|
||||
</AccentAvatar>
|
||||
}
|
||||
/>
|
||||
<PageShell>
|
||||
<PageHeader
|
||||
title="Create Customer"
|
||||
subtitle="Add a customer record"
|
||||
action={
|
||||
<AccentAvatar color={BRAND} selected size={40}>
|
||||
<MdPersonAddAlt1 size={20} />
|
||||
</AccentAvatar>
|
||||
}
|
||||
/>
|
||||
|
||||
<Card padding={4} elevation="none" style={{ marginTop: 16 }}>
|
||||
<VStack gap={4} padding={0}>
|
||||
<Grid columns={{ minWidth: 260 }} gap={3}>
|
||||
<VStack gap={1.25} padding={0}>
|
||||
<Text type="label" weight="semibold" color="secondary">
|
||||
Location
|
||||
</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
|
||||
<Card padding={4} elevation="none">
|
||||
<VStack gap={4} padding={0}>
|
||||
<Grid columns={{ minWidth: 260, repeat: 'fit' }} gap={3}>
|
||||
<VStack gap={1.25} padding={0}>
|
||||
<Text type="label" weight="semibold" color="secondary">
|
||||
Location
|
||||
</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
|
||||
label="Phone Number"
|
||||
placeholder="Phone Number"
|
||||
value={phone}
|
||||
onChange={(v) => {
|
||||
const digits = v.replace(/\D/g, '');
|
||||
if (digits.length <= 10) setPhone(digits);
|
||||
}}
|
||||
isRequired
|
||||
/>
|
||||
)}
|
||||
<TextInput label="Name" placeholder="First Name" value={firstname} onChange={setFirstname} isRequired />
|
||||
<TextInput label="Last Name" placeholder="Last Name" value={lastname} onChange={setLastname} isOptional />
|
||||
<TextInput
|
||||
label="Phone Number"
|
||||
placeholder="Phone Number"
|
||||
value={phone}
|
||||
onChange={(v) => {
|
||||
const digits = v.replace(/\D/g, '');
|
||||
if (digits.length <= 10) setPhone(digits);
|
||||
}}
|
||||
isRequired
|
||||
<TextInput label="Email" type="email" placeholder="Email Address" value={email} onChange={setEmail} isOptional />
|
||||
<TextInput label="Door No" placeholder="Door No" value={doorno} onChange={setDoorno} isOptional />
|
||||
</Grid>
|
||||
|
||||
<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"
|
||||
value={inputValue2}
|
||||
onChange={setInputValue2}
|
||||
onPlaceSelected={handlePlaceSelected}
|
||||
bias={{ lat: appLocaLat, lng: appLocaLng }}
|
||||
/>
|
||||
<TextInput label="Email" type="email" placeholder="Email Address" value={email} onChange={setEmail} isOptional />
|
||||
<TextInput label="Door No" placeholder="Door No" value={doorno} onChange={setDoorno} isOptional />
|
||||
</Grid>
|
||||
|
||||
<Divider />
|
||||
<Grid columns={{ minWidth: 220, repeat: 'fit' }} gap={3}>
|
||||
<TextInput
|
||||
label="Location"
|
||||
placeholder="Location"
|
||||
value={pickCust.suburb || ''}
|
||||
onChange={(v) => setPickCust((p) => ({ ...p, suburb: v }))}
|
||||
/>
|
||||
<TextInput
|
||||
label="City"
|
||||
placeholder="City"
|
||||
value={pickCust.city || ''}
|
||||
onChange={(v) => setPickCust((p) => ({ ...p, city: v }))}
|
||||
/>
|
||||
<TextInput
|
||||
label="State"
|
||||
placeholder="State"
|
||||
value={pickCust.state || ''}
|
||||
onChange={(v) => setPickCust((p) => ({ ...p, state: v }))}
|
||||
/>
|
||||
<TextInput
|
||||
label="Post Code"
|
||||
placeholder="Postcode"
|
||||
value={pickCust.postcode || ''}
|
||||
onChange={(v) => setPickCust((p) => ({ ...p, postcode: v.replace(/\D/g, '') }))}
|
||||
/>
|
||||
<TextInput label="Landmark" placeholder="Landmark" value={landmark} onChange={setLandmark} />
|
||||
<TextInput label="Latitude" value={startPoint.latitude || ''} isDisabled />
|
||||
<TextInput label="Longitude" value={startPoint.longitude || ''} isDisabled />
|
||||
</Grid>
|
||||
|
||||
<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"
|
||||
value={inputValue2}
|
||||
onChange={setInputValue2}
|
||||
onPlaceSelected={handlePlaceSelected}
|
||||
bias={{ lat: appLocaLat, lng: appLocaLng }}
|
||||
/>
|
||||
|
||||
<Grid columns={{ minWidth: 220 }} gap={3}>
|
||||
<TextInput label="Location" placeholder="Location" value={pickCust.suburb || ''} onChange={(v) => setPickCust((p) => ({ ...p, suburb: v }))} />
|
||||
<TextInput label="City" placeholder="City" value={pickCust.city || ''} onChange={(v) => setPickCust((p) => ({ ...p, city: v }))} />
|
||||
<TextInput label="State" placeholder="State" value={pickCust.state || ''} onChange={(v) => setPickCust((p) => ({ ...p, state: v }))} />
|
||||
<TextInput
|
||||
label="Post Code"
|
||||
placeholder="Postcode"
|
||||
value={pickCust.postcode || ''}
|
||||
onChange={(v) => setPickCust((p) => ({ ...p, postcode: v.replace(/\D/g, '') }))}
|
||||
/>
|
||||
<TextInput label="Landmark" placeholder="Landmark" value={landmark} onChange={setLandmark} />
|
||||
<TextInput label="Latitude" value={startPoint.latitude || ''} isDisabled />
|
||||
<TextInput label="Longitude" value={startPoint.longitude || ''} isDisabled />
|
||||
</Grid>
|
||||
|
||||
<HStack justify="end">
|
||||
<Button label="Create" variant="primary" onClick={createprofile} isLoading={createCustomerMutation.isPending} />
|
||||
</HStack>
|
||||
</VStack>
|
||||
</Card>
|
||||
<HStack justify="end">
|
||||
<Button label="Create" variant="primary" onClick={createprofile} isLoading={createCustomerMutation.isPending} />
|
||||
</HStack>
|
||||
</VStack>
|
||||
</Card>
|
||||
</PageShell>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -15,6 +15,7 @@ import { Switch } from '@astryxdesign/core/Switch';
|
||||
|
||||
import Loader from 'components/Loader';
|
||||
import PageHeader from 'components/nearle_components/PageHeader';
|
||||
import { PageShell } from 'components/nearle_components/PageLayout';
|
||||
import { createAdminTenant } from 'pages/api/doormileApi';
|
||||
import { DT } from 'themes/dt/tokens';
|
||||
import { AccentAvatar } from 'themes/dt/primitives';
|
||||
@@ -85,45 +86,60 @@ const Createclient = () => {
|
||||
<>
|
||||
{createTenantMutation.isPending && <Loader />}
|
||||
|
||||
<PageHeader
|
||||
title="Create Client"
|
||||
subtitle="Add a new tenant"
|
||||
action={
|
||||
<AccentAvatar color={BRAND} selected size={40}>
|
||||
<MdPersonAddAlt1 size={20} />
|
||||
</AccentAvatar>
|
||||
}
|
||||
/>
|
||||
<PageShell>
|
||||
<PageHeader
|
||||
title="Create Client"
|
||||
subtitle="Add a new tenant"
|
||||
action={
|
||||
<AccentAvatar color={BRAND} selected size={40}>
|
||||
<MdPersonAddAlt1 size={20} />
|
||||
</AccentAvatar>
|
||||
}
|
||||
/>
|
||||
|
||||
<Card padding={4} elevation="none" style={{ marginTop: 16 }}>
|
||||
<VStack gap={4} padding={0}>
|
||||
<Grid columns={{ minWidth: 260 }} gap={3}>
|
||||
<TextInput label="Client / Business Name" placeholder="e.g. DailyGrubs" value={tenantname} onChange={setTenantname} isRequired />
|
||||
<Selector label="Status" options={STATUS_OPTIONS} value={status} onChange={setStatus} />
|
||||
<TextInput
|
||||
label="Primary Contact Number"
|
||||
placeholder="Contact Number"
|
||||
value={primarycontact}
|
||||
onChange={(v) => {
|
||||
const digits = v.replace(/\D/g, '');
|
||||
if (digits.length <= 10) setPrimarycontact(digits);
|
||||
}}
|
||||
isRequired
|
||||
<Card padding={4} elevation="none">
|
||||
<VStack gap={4} padding={0}>
|
||||
<Grid columns={{ minWidth: 260, repeat: 'fit' }} gap={3}>
|
||||
<TextInput
|
||||
label="Client / Business Name"
|
||||
placeholder="e.g. DailyGrubs"
|
||||
value={tenantname}
|
||||
onChange={setTenantname}
|
||||
isRequired
|
||||
/>
|
||||
<Selector label="Status" options={STATUS_OPTIONS} value={status} onChange={setStatus} />
|
||||
<TextInput
|
||||
label="Primary Contact Number"
|
||||
placeholder="Contact Number"
|
||||
value={primarycontact}
|
||||
onChange={(v) => {
|
||||
const digits = v.replace(/\D/g, '');
|
||||
if (digits.length <= 10) setPrimarycontact(digits);
|
||||
}}
|
||||
isRequired
|
||||
/>
|
||||
<TextInput
|
||||
label="Primary Email"
|
||||
type="email"
|
||||
placeholder="Primary Email Address"
|
||||
value={primaryemail}
|
||||
onChange={setPrimaryemail}
|
||||
isRequired
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
<Switch
|
||||
label="Require delivery OTP for this client (off by default)"
|
||||
value={requiredeliveryotp}
|
||||
onChange={setRequiredeliveryotp}
|
||||
/>
|
||||
<TextInput label="Primary Email" type="email" placeholder="Primary Email Address" value={primaryemail} onChange={setPrimaryemail} isRequired />
|
||||
</Grid>
|
||||
|
||||
<Switch
|
||||
label="Require delivery OTP for this client (off by default)"
|
||||
value={requiredeliveryotp}
|
||||
onChange={setRequiredeliveryotp}
|
||||
/>
|
||||
|
||||
<HStack justify="end">
|
||||
<Button label="Create" variant="primary" onClick={createprofile} isLoading={createTenantMutation.isPending} />
|
||||
</HStack>
|
||||
</VStack>
|
||||
</Card>
|
||||
<HStack justify="end">
|
||||
<Button label="Create" variant="primary" onClick={createprofile} isLoading={createTenantMutation.isPending} />
|
||||
</HStack>
|
||||
</VStack>
|
||||
</Card>
|
||||
</PageShell>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user