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}
|
||||
|
||||
Reference in New Issue
Block a user