updates on the astryx desing
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -1,33 +1,28 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
// material-ui
|
||||
import {
|
||||
Autocomplete,
|
||||
Avatar,
|
||||
Button,
|
||||
Grid,
|
||||
InputLabel,
|
||||
MenuItem,
|
||||
Paper,
|
||||
Select,
|
||||
Stack,
|
||||
TextField,
|
||||
Typography,
|
||||
useMediaQuery,
|
||||
useTheme
|
||||
} from '@mui/material';
|
||||
import { MdPersonAddAlt1 } from 'react-icons/md';
|
||||
import { useNavigate } from 'react-router';
|
||||
import { useMutation, useQuery } from '@tanstack/react-query';
|
||||
import { enqueueSnackbar } from 'notistack';
|
||||
import { MdPersonAddAlt1 } from 'react-icons/md';
|
||||
|
||||
import { Grid } from '@astryxdesign/core/Grid';
|
||||
import { HStack } from '@astryxdesign/core/HStack';
|
||||
import { VStack } from '@astryxdesign/core/VStack';
|
||||
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';
|
||||
|
||||
// project import
|
||||
import MainCard from 'components/MainCard';
|
||||
import { createTenantCustomer, getAdminTenants } from 'pages/api/doormileApi';
|
||||
import Loader from 'components/Loader';
|
||||
import PageHeader from 'components/nearle_components/PageHeader';
|
||||
import AddressAutocomplete from 'components/nearle_components/AddressAutocomplete';
|
||||
import LocationAutocomplete from 'components/nearle_components/LocationAutocomplete';
|
||||
import { enqueueSnackbar } from 'notistack';
|
||||
import { useNavigate } from 'react-router';
|
||||
import { DT, tint } from 'themes/dt/tokens';
|
||||
import { createTenantCustomer, getAdminTenants } 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/
|
||||
@@ -43,8 +38,6 @@ import { DT, tint } from 'themes/dt/tokens';
|
||||
// ignored server-side — unconfirmed, this endpoint isn't in the "confirmed
|
||||
// end-to-end" list.
|
||||
const Createcustomer = () => {
|
||||
const theme = useTheme();
|
||||
const isMobile = useMediaQuery(theme.breakpoints.down('md'));
|
||||
const navigate = useNavigate();
|
||||
|
||||
const loggedInTenantId = localStorage.getItem('tenantid');
|
||||
@@ -66,11 +59,12 @@ const Createcustomer = () => {
|
||||
const [appLocaLat, setAppLocaLat] = useState();
|
||||
const [appLocaLng, setAppLocaLng] = useState();
|
||||
|
||||
const { data: tenantList = [], isLoading: tenantListLoading } = useQuery({
|
||||
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
|
||||
@@ -125,13 +119,8 @@ const Createcustomer = () => {
|
||||
});
|
||||
};
|
||||
|
||||
const opentoast = (message) => {
|
||||
enqueueSnackbar(message, {
|
||||
variant: 'error',
|
||||
anchorOrigin: { vertical: 'top', horizontal: 'right' },
|
||||
autoHideDuration: 2000
|
||||
});
|
||||
};
|
||||
const opentoast = (message) =>
|
||||
enqueueSnackbar(message, { variant: 'error', anchorOrigin: { vertical: 'top', horizontal: 'right' }, autoHideDuration: 2000 });
|
||||
|
||||
const createCustomerMutation = useMutation({
|
||||
mutationFn: (payload) => createTenantCustomer(payload),
|
||||
@@ -147,9 +136,7 @@ const Createcustomer = () => {
|
||||
opentoast(res.message || 'Could not create customer');
|
||||
}
|
||||
},
|
||||
onError: (err) => {
|
||||
opentoast(err.response?.data?.message || err.message || 'Failed to create customer');
|
||||
}
|
||||
onError: (err) => opentoast(err.response?.data?.message || err.message || 'Failed to create customer')
|
||||
});
|
||||
|
||||
const createprofile = () => {
|
||||
@@ -174,238 +161,86 @@ const Createcustomer = () => {
|
||||
<>
|
||||
{createCustomerMutation.isPending && <Loader />}
|
||||
|
||||
<Grid item xs={12} sx={{ mb: 2 }}>
|
||||
<Paper
|
||||
sx={{
|
||||
p: 2.5,
|
||||
borderRadius: DT.radiusCard + 'px',
|
||||
boxShadow: DT.shadowSoft,
|
||||
border: '1px solid',
|
||||
borderColor: DT.borderSubtle,
|
||||
background: `linear-gradient(135deg, ${tint('#000000')} 0%, ${tint('#3A3A3A')} 100%)`
|
||||
}}
|
||||
>
|
||||
<Stack direction="row" spacing={1.5} alignItems="center">
|
||||
<Avatar sx={{ width: 48, height: 48, bgcolor: DT.brand }}>
|
||||
<MdPersonAddAlt1 size={22} />
|
||||
</Avatar>
|
||||
<Typography variant="h3">Create Customer</Typography>
|
||||
</Stack>
|
||||
</Paper>
|
||||
</Grid>
|
||||
<MainCard
|
||||
padding={6}
|
||||
>
|
||||
<Grid container spacing={isMobile ? 2 : 3}>
|
||||
<Grid item xs={12}>
|
||||
<MainCard height="100%" padding={5}>
|
||||
<Grid container spacing={isMobile ? 2 : 3}>
|
||||
{/* ===================================================== || Location & Client || ===================================================== */}
|
||||
<Grid item xs={12} md={6}>
|
||||
<Stack spacing={1.25}>
|
||||
<InputLabel>Location</InputLabel>
|
||||
<LocationAutocomplete locaName={locaName} setAppId={setAppId} setLocoName={setLocoName} />
|
||||
</Stack>
|
||||
</Grid>
|
||||
{isStaffLogin && (
|
||||
<Grid item xs={12} md={6}>
|
||||
<Stack spacing={1.25}>
|
||||
<InputLabel>Choose Client</InputLabel>
|
||||
<Autocomplete
|
||||
fullWidth
|
||||
loading={tenantListLoading}
|
||||
options={tenantList || []}
|
||||
getOptionLabel={(option) => option?.tenantname || ''}
|
||||
renderInput={(params) => <TextField {...params} placeholder="Choose Client" />}
|
||||
onChange={(e, val) => setTid(val ? val.tenantid : '')}
|
||||
/>
|
||||
</Stack>
|
||||
</Grid>
|
||||
)}
|
||||
<PageHeader
|
||||
title="Create Customer"
|
||||
subtitle="Add a customer record"
|
||||
action={
|
||||
<AccentAvatar color={BRAND} selected size={40}>
|
||||
<MdPersonAddAlt1 size={20} />
|
||||
</AccentAvatar>
|
||||
}
|
||||
/>
|
||||
|
||||
{/* ===================================================== || Name / Phone / Email || ===================================================== */}
|
||||
<Grid item xs={12} sm={6}>
|
||||
<Stack spacing={1.25}>
|
||||
<InputLabel htmlFor="customer-firstname">Name</InputLabel>
|
||||
<TextField
|
||||
fullWidth
|
||||
id="customer-firstname"
|
||||
placeholder="First Name"
|
||||
onChange={(e) => setFirstname(e.target.value)}
|
||||
value={firstname}
|
||||
autoComplete="off"
|
||||
/>
|
||||
</Stack>
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={6}>
|
||||
<Stack spacing={1.25}>
|
||||
<InputLabel htmlFor="customer-lastname">Last Name</InputLabel>
|
||||
<TextField
|
||||
fullWidth
|
||||
id="customer-lastname"
|
||||
placeholder="Last Name"
|
||||
onChange={(e) => setLastname(e.target.value)}
|
||||
value={lastname}
|
||||
autoComplete="off"
|
||||
/>
|
||||
</Stack>
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={6}>
|
||||
<Stack spacing={1.25}>
|
||||
<InputLabel htmlFor="customer-phone">Phone Number</InputLabel>
|
||||
<Stack direction="row" justifyContent="space-between" alignItems="center" spacing={2}>
|
||||
<Select defaultValue="+1" disabled sx={{ cursor: 'not-allowed' }}>
|
||||
<MenuItem value="+1">+91</MenuItem>
|
||||
</Select>
|
||||
<TextField
|
||||
type="number"
|
||||
id="customer-phone"
|
||||
fullWidth
|
||||
placeholder="Phone Number"
|
||||
onChange={(e) => {
|
||||
if (e.target.value.toString().length <= 10) {
|
||||
setPhone(e.target.value);
|
||||
}
|
||||
}}
|
||||
value={phone}
|
||||
autoComplete="off"
|
||||
/>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={6}>
|
||||
<Stack spacing={1.25}>
|
||||
<InputLabel htmlFor="customer-email">Email</InputLabel>
|
||||
<TextField
|
||||
type="email"
|
||||
fullWidth
|
||||
id="customer-email"
|
||||
placeholder="Email Address"
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
value={email}
|
||||
autoComplete="off"
|
||||
/>
|
||||
</Stack>
|
||||
</Grid>
|
||||
|
||||
{/* ===================================================== || Door No || ===================================================== */}
|
||||
<Grid item xs={12} sm={6}>
|
||||
<Stack spacing={1.25}>
|
||||
<InputLabel htmlFor="customer-doorno">Door No</InputLabel>
|
||||
<TextField
|
||||
fullWidth
|
||||
id="customer-doorno"
|
||||
placeholder="Door No"
|
||||
onChange={(e) => setDoorno(e.target.value)}
|
||||
value={doorno}
|
||||
autoComplete="off"
|
||||
/>
|
||||
</Stack>
|
||||
</Grid>
|
||||
|
||||
{/* ===================================================== || Address section — collected, not persisted || ===================================================== */}
|
||||
<Grid item xs={12}>
|
||||
<Typography variant="caption" sx={{ color: DT.textMuted, 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.
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<Stack spacing={1.25}>
|
||||
<InputLabel>Address</InputLabel>
|
||||
<AddressAutocomplete
|
||||
id="customer-address"
|
||||
fullWidth
|
||||
value={inputValue2}
|
||||
onChange={(text) => setInputValue2(text)}
|
||||
onPlaceSelected={handlePlaceSelected}
|
||||
bias={{ lat: appLocaLat, lng: appLocaLng }}
|
||||
/>
|
||||
</Stack>
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={6}>
|
||||
<Stack spacing={1.25}>
|
||||
<InputLabel>Location</InputLabel>
|
||||
<TextField
|
||||
fullWidth
|
||||
placeholder="Location"
|
||||
onChange={(e) => setPickCust((p) => ({ ...p, suburb: e.target.value }))}
|
||||
value={pickCust.suburb || ''}
|
||||
autoComplete="off"
|
||||
/>
|
||||
</Stack>
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={6}>
|
||||
<Stack spacing={1.25}>
|
||||
<InputLabel>City</InputLabel>
|
||||
<TextField
|
||||
fullWidth
|
||||
placeholder="City"
|
||||
onChange={(e) => setPickCust((p) => ({ ...p, city: e.target.value }))}
|
||||
value={pickCust.city || ''}
|
||||
autoComplete="off"
|
||||
/>
|
||||
</Stack>
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={6}>
|
||||
<Stack spacing={1.25}>
|
||||
<InputLabel>State</InputLabel>
|
||||
<TextField
|
||||
fullWidth
|
||||
placeholder="State"
|
||||
onChange={(e) => setPickCust((p) => ({ ...p, state: e.target.value }))}
|
||||
value={pickCust.state || ''}
|
||||
autoComplete="off"
|
||||
/>
|
||||
</Stack>
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={6}>
|
||||
<Stack spacing={1.25}>
|
||||
<InputLabel>Post Code</InputLabel>
|
||||
<TextField
|
||||
fullWidth
|
||||
type="number"
|
||||
placeholder="Postcode"
|
||||
onChange={(e) => setPickCust((p) => ({ ...p, postcode: e.target.value }))}
|
||||
value={pickCust.postcode || ''}
|
||||
autoComplete="off"
|
||||
/>
|
||||
</Stack>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<Stack spacing={1.25}>
|
||||
<InputLabel>Landmark</InputLabel>
|
||||
<TextField fullWidth placeholder="Landmark" onChange={(e) => setLandmark(e.target.value)} value={landmark} autoComplete="off" />
|
||||
</Stack>
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={6}>
|
||||
<Stack spacing={1.25}>
|
||||
<InputLabel>Latitude</InputLabel>
|
||||
<TextField fullWidth disabled value={startPoint.latitude || ''} sx={{ cursor: 'not-allowed' }} />
|
||||
</Stack>
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={6}>
|
||||
<Stack spacing={1.25}>
|
||||
<InputLabel>Longitude</InputLabel>
|
||||
<TextField fullWidth disabled value={startPoint.longitude || ''} sx={{ cursor: 'not-allowed' }} />
|
||||
</Stack>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</MainCard>
|
||||
<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
|
||||
/>
|
||||
)}
|
||||
<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>
|
||||
<Grid item xs={12}>
|
||||
<Stack
|
||||
direction={{ xs: 'column', sm: 'row' }}
|
||||
justifyContent="flex-end"
|
||||
alignItems={{ xs: 'stretch', sm: 'center' }}
|
||||
spacing={2}
|
||||
>
|
||||
<Button variant="contained" onClick={createprofile} fullWidth={isMobile}>
|
||||
Create
|
||||
</Button>
|
||||
</Stack>
|
||||
|
||||
<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 }}
|
||||
/>
|
||||
|
||||
<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>
|
||||
</Grid>
|
||||
</MainCard>
|
||||
|
||||
<HStack justify="end">
|
||||
<Button label="Create" variant="primary" onClick={createprofile} isLoading={createCustomerMutation.isPending} />
|
||||
</HStack>
|
||||
</VStack>
|
||||
</Card>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,36 +1,31 @@
|
||||
import { useState } from 'react';
|
||||
|
||||
// material-ui
|
||||
import {
|
||||
Avatar,
|
||||
Button,
|
||||
FormControlLabel,
|
||||
Grid,
|
||||
InputLabel,
|
||||
MenuItem,
|
||||
Paper,
|
||||
Select,
|
||||
Stack,
|
||||
Switch,
|
||||
TextField,
|
||||
Typography,
|
||||
useMediaQuery,
|
||||
useTheme
|
||||
} from '@mui/material';
|
||||
import { MdPersonAddAlt1 } from 'react-icons/md';
|
||||
import { useMutation } from '@tanstack/react-query';
|
||||
|
||||
// project import
|
||||
import MainCard from 'components/MainCard';
|
||||
import { createAdminTenant } from 'pages/api/doormileApi';
|
||||
import Loader from 'components/Loader';
|
||||
import { enqueueSnackbar } from 'notistack';
|
||||
import { useNavigate } from 'react-router';
|
||||
import { DT, tint } from 'themes/dt/tokens';
|
||||
import { useMutation } from '@tanstack/react-query';
|
||||
import { enqueueSnackbar } from 'notistack';
|
||||
import { MdPersonAddAlt1 } from 'react-icons/md';
|
||||
|
||||
import { Grid } from '@astryxdesign/core/Grid';
|
||||
import { HStack } from '@astryxdesign/core/HStack';
|
||||
import { VStack } from '@astryxdesign/core/VStack';
|
||||
import { Card } from '@astryxdesign/core/Card';
|
||||
import { Button } from '@astryxdesign/core/Button';
|
||||
import { TextInput } from '@astryxdesign/core/TextInput';
|
||||
import { Selector } from '@astryxdesign/core/Selector';
|
||||
import { Switch } from '@astryxdesign/core/Switch';
|
||||
|
||||
import Loader from 'components/Loader';
|
||||
import PageHeader from 'components/nearle_components/PageHeader';
|
||||
import { createAdminTenant } from 'pages/api/doormileApi';
|
||||
import { DT } from 'themes/dt/tokens';
|
||||
import { AccentAvatar } from 'themes/dt/primitives';
|
||||
|
||||
const BRAND = DT.brand;
|
||||
const STATUS_OPTIONS = [
|
||||
{ value: 'Active', label: 'Active' },
|
||||
{ value: 'Inactive', label: 'Inactive' }
|
||||
];
|
||||
|
||||
const Createclient = () => {
|
||||
const theme = useTheme();
|
||||
const isMobile = useMediaQuery(theme.breakpoints.down('md'));
|
||||
const navigate = useNavigate();
|
||||
|
||||
const [tenantname, setTenantname] = useState('');
|
||||
@@ -43,13 +38,8 @@ const Createclient = () => {
|
||||
const [status, setStatus] = useState('Active');
|
||||
const [requiredeliveryotp, setRequiredeliveryotp] = useState(false);
|
||||
|
||||
const opentoast = (message) => {
|
||||
enqueueSnackbar(message, {
|
||||
variant: 'error',
|
||||
anchorOrigin: { vertical: 'top', horizontal: 'right' },
|
||||
autoHideDuration: 2000
|
||||
});
|
||||
};
|
||||
const opentoast = (message) =>
|
||||
enqueueSnackbar(message, { variant: 'error', anchorOrigin: { vertical: 'top', horizontal: 'right' }, autoHideDuration: 2000 });
|
||||
|
||||
const createTenantMutation = useMutation({
|
||||
mutationFn: (payload) => createAdminTenant(payload),
|
||||
@@ -65,9 +55,7 @@ const Createclient = () => {
|
||||
opentoast(res.message || 'Client already exists');
|
||||
}
|
||||
},
|
||||
onError: (err) => {
|
||||
opentoast(err.response?.data?.message || err.message || 'Failed to create client');
|
||||
}
|
||||
onError: (err) => opentoast(err.response?.data?.message || err.message || 'Failed to create client')
|
||||
});
|
||||
|
||||
const createprofile = () => {
|
||||
@@ -97,114 +85,45 @@ const Createclient = () => {
|
||||
<>
|
||||
{createTenantMutation.isPending && <Loader />}
|
||||
|
||||
<Grid item xs={12} sx={{ mb: 2 }}>
|
||||
<Paper
|
||||
sx={{
|
||||
p: 2.5,
|
||||
borderRadius: DT.radiusCard + 'px',
|
||||
boxShadow: DT.shadowSoft,
|
||||
border: '1px solid',
|
||||
borderColor: DT.borderSubtle,
|
||||
background: `linear-gradient(135deg, ${tint('#000000')} 0%, ${tint('#3A3A3A')} 100%)`
|
||||
}}
|
||||
>
|
||||
<Stack direction="row" spacing={1.5} alignItems="center">
|
||||
<Avatar sx={{ width: 48, height: 48, bgcolor: DT.brand }}>
|
||||
<MdPersonAddAlt1 size={22} />
|
||||
</Avatar>
|
||||
<Typography variant="h3">Create Client</Typography>
|
||||
</Stack>
|
||||
</Paper>
|
||||
</Grid>
|
||||
<MainCard
|
||||
padding={6}
|
||||
>
|
||||
<Grid container spacing={isMobile ? 2 : 3}>
|
||||
<Grid item xs={12}>
|
||||
<MainCard height="100%" padding={5}>
|
||||
<Grid container spacing={isMobile ? 2 : 3}>
|
||||
<Grid item xs={12} sm={6}>
|
||||
<Stack spacing={1.25}>
|
||||
<InputLabel htmlFor="tenant-name">Client / Business Name</InputLabel>
|
||||
<TextField
|
||||
fullWidth
|
||||
id="tenant-name"
|
||||
placeholder="e.g. DailyGrubs"
|
||||
onChange={(e) => setTenantname(e.target.value)}
|
||||
value={tenantname}
|
||||
autoComplete="off"
|
||||
/>
|
||||
</Stack>
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={6}>
|
||||
<Stack spacing={1.25}>
|
||||
<InputLabel htmlFor="tenant-status">Status</InputLabel>
|
||||
<Select id="tenant-status" fullWidth value={status} onChange={(e) => setStatus(e.target.value)}>
|
||||
<MenuItem value="Active">Active</MenuItem>
|
||||
<MenuItem value="Inactive">Inactive</MenuItem>
|
||||
</Select>
|
||||
</Stack>
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={6}>
|
||||
<Stack spacing={1.25}>
|
||||
<InputLabel htmlFor="tenant-contact">Primary Contact Number</InputLabel>
|
||||
<Stack direction="row" justifyContent="space-between" alignItems="center" spacing={2}>
|
||||
<Select defaultValue="+1" disabled sx={{ cursor: 'not-allowed' }}>
|
||||
<MenuItem value="+1">+91</MenuItem>
|
||||
</Select>
|
||||
<TextField
|
||||
type="number"
|
||||
id="tenant-contact"
|
||||
fullWidth
|
||||
placeholder="Contact Number"
|
||||
onChange={(e) => {
|
||||
if (e.target.value.toString().length <= 10) {
|
||||
setPrimarycontact(e.target.value);
|
||||
}
|
||||
}}
|
||||
value={primarycontact}
|
||||
autoComplete="off"
|
||||
/>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={6}>
|
||||
<Stack spacing={1.25}>
|
||||
<InputLabel htmlFor="tenant-email">Primary Email</InputLabel>
|
||||
<TextField
|
||||
type="email"
|
||||
fullWidth
|
||||
id="tenant-email"
|
||||
placeholder="Primary Email Address"
|
||||
onChange={(e) => setPrimaryemail(e.target.value)}
|
||||
value={primaryemail}
|
||||
autoComplete="off"
|
||||
/>
|
||||
</Stack>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<FormControlLabel
|
||||
control={<Switch checked={requiredeliveryotp} onChange={(e) => setRequiredeliveryotp(e.target.checked)} />}
|
||||
label="Require delivery OTP for this client (off by default)"
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</MainCard>
|
||||
<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
|
||||
/>
|
||||
<TextInput label="Primary Email" type="email" placeholder="Primary Email Address" value={primaryemail} onChange={setPrimaryemail} isRequired />
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<Stack
|
||||
direction={{ xs: 'column', sm: 'row' }}
|
||||
justifyContent="flex-end"
|
||||
alignItems={{ xs: 'stretch', sm: 'center' }}
|
||||
spacing={2}
|
||||
>
|
||||
<Button variant="contained" onClick={createprofile} fullWidth={isMobile}>
|
||||
Create
|
||||
</Button>
|
||||
</Stack>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</MainCard>
|
||||
|
||||
<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>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user