updates on the rider and the rider substitution page regarding the crud operations and more change outthere
This commit is contained in:
@@ -45,11 +45,15 @@ const STATUS_META = {
|
||||
};
|
||||
|
||||
export default function RiderSubstitution({
|
||||
appId,
|
||||
rows,
|
||||
allRidersList,
|
||||
substituteRidersList,
|
||||
substituteAssignments,
|
||||
handleAssignSubstitute,
|
||||
onFinalizeSuccess,
|
||||
selectedDate,
|
||||
setSelectedDate,
|
||||
DT,
|
||||
BRAND,
|
||||
edge,
|
||||
@@ -58,7 +62,6 @@ export default function RiderSubstitution({
|
||||
}) {
|
||||
const theme = useTheme();
|
||||
const isMobile = useMediaQuery(theme.breakpoints.down('md'));
|
||||
const [selectedDate, setSelectedDate] = useState(dayjs());
|
||||
const [selectedBatch, setSelectedBatch] = useState('all');
|
||||
const [isFinalizing, setIsFinalizing] = useState(false);
|
||||
|
||||
@@ -118,9 +121,8 @@ export default function RiderSubstitution({
|
||||
}, [selectedDate]);
|
||||
|
||||
const filteredRows = React.useMemo(() => {
|
||||
if (selectedBatch === 'all') return rows;
|
||||
return rows?.filter((row) => getBatchForTime(row.starttime) === selectedBatch);
|
||||
}, [rows, selectedBatch, getBatchForTime]);
|
||||
return rows;
|
||||
}, [rows]);
|
||||
|
||||
const hasAssignments = Object.values(substituteAssignments || {}).some(
|
||||
(val) => val !== null && val !== undefined
|
||||
@@ -129,8 +131,37 @@ export default function RiderSubstitution({
|
||||
const handleFinalize = async () => {
|
||||
setIsFinalizing(true);
|
||||
try {
|
||||
const rawTenantId = localStorage.getItem('tenantid');
|
||||
const tenantId = (rawTenantId && rawTenantId !== 'undefined' && rawTenantId !== 'null') ? parseInt(rawTenantId, 10) : 44;
|
||||
let partnerId = '';
|
||||
try {
|
||||
const rawLocs = localStorage.getItem('applocations');
|
||||
if (rawLocs) {
|
||||
const locs = JSON.parse(rawLocs);
|
||||
const currentLoc = locs.find((l) => l.applocationid === appId);
|
||||
if (currentLoc && currentLoc.partnerid) {
|
||||
partnerId = currentLoc.partnerid;
|
||||
} else {
|
||||
const firstValidLoc = locs.find((l) => l.partnerid);
|
||||
if (firstValidLoc && firstValidLoc.partnerid) {
|
||||
partnerId = firstValidLoc.partnerid;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Error parsing applocations', e);
|
||||
}
|
||||
|
||||
if (!partnerId) {
|
||||
const savedPartnerId = localStorage.getItem('partnerid');
|
||||
if (savedPartnerId && savedPartnerId !== 'undefined' && savedPartnerId !== 'null') {
|
||||
partnerId = savedPartnerId;
|
||||
}
|
||||
}
|
||||
|
||||
if (!partnerId || partnerId === '0' || partnerId === 0) {
|
||||
partnerId = 44;
|
||||
}
|
||||
|
||||
const tenantId = parseInt(partnerId, 10);
|
||||
|
||||
const substitutions = Object.entries(substituteAssignments || {})
|
||||
.filter((entry) => entry[1] !== null && entry[1] !== undefined)
|
||||
@@ -143,7 +174,8 @@ export default function RiderSubstitution({
|
||||
absent_rider_name: absentRider?.username || absentRider?.fullname || `Rider #${absentRiderId}`,
|
||||
sub_rider_id: parseInt(subRider.userid, 10),
|
||||
sub_rider_name: subRider.username || subRider.fullname || `Rider #${subRider.userid}`,
|
||||
reason: "Scheduled"
|
||||
reason: "Scheduled",
|
||||
batch: selectedBatch
|
||||
};
|
||||
});
|
||||
|
||||
@@ -315,6 +347,8 @@ export default function RiderSubstitution({
|
||||
filteredRows?.map((row, index) => {
|
||||
const statusMeta = getRowStatusMeta(row);
|
||||
const StatusIcon = statusMeta.icon;
|
||||
const riderProfile = allRidersList?.find((r) => r.userid === row.userid);
|
||||
const starttime = riderProfile?.starttime || row.starttime;
|
||||
return (
|
||||
<MobileCard
|
||||
key={row.userid ?? index}
|
||||
@@ -398,7 +432,7 @@ export default function RiderSubstitution({
|
||||
<MobileField label="Substitute" full>
|
||||
<Autocomplete
|
||||
size="small"
|
||||
disabled={isBatchDisabled(getBatchForTime(row.starttime))}
|
||||
disabled={isBatchDisabled(getBatchForTime(starttime))}
|
||||
options={substituteRidersList || []}
|
||||
isOptionEqualToValue={(option, value) => option?.userid === value?.userid}
|
||||
getOptionLabel={(option) => `${option.username || option.fullname || ''} (#${option.userid})`}
|
||||
@@ -471,6 +505,8 @@ export default function RiderSubstitution({
|
||||
filteredRows?.map((row, index) => {
|
||||
const statusMeta = getRowStatusMeta(row);
|
||||
const StatusIcon = statusMeta.icon;
|
||||
const riderProfile = allRidersList?.find((r) => r.userid === row.userid);
|
||||
const starttime = riderProfile?.starttime || row.starttime;
|
||||
return (
|
||||
<TableRow
|
||||
key={row.userid ?? index}
|
||||
@@ -545,7 +581,7 @@ export default function RiderSubstitution({
|
||||
<TableCell sx={{ minWidth: 220 }}>
|
||||
<Autocomplete
|
||||
size="small"
|
||||
disabled={isBatchDisabled(getBatchForTime(row.starttime))}
|
||||
disabled={isBatchDisabled(getBatchForTime(starttime))}
|
||||
options={substituteRidersList || []}
|
||||
isOptionEqualToValue={(option, value) => option?.userid === value?.userid}
|
||||
getOptionLabel={(option) => `${option.username || option.fullname || ''} (#${option.userid})`}
|
||||
|
||||
@@ -23,7 +23,14 @@ import {
|
||||
Skeleton,
|
||||
useMediaQuery,
|
||||
ToggleButtonGroup,
|
||||
ToggleButton
|
||||
ToggleButton,
|
||||
Dialog,
|
||||
DialogTitle,
|
||||
DialogContent,
|
||||
DialogActions,
|
||||
Button,
|
||||
Autocomplete,
|
||||
TextField
|
||||
} from '@mui/material';
|
||||
import { useTheme } from '@mui/material/styles';
|
||||
var utc = require('dayjs/plugin/utc');
|
||||
@@ -51,7 +58,8 @@ import {
|
||||
MdAccessTime,
|
||||
MdInventory2,
|
||||
MdTwoWheeler,
|
||||
MdArrowForward
|
||||
MdArrowForward,
|
||||
MdDelete
|
||||
} from 'react-icons/md';
|
||||
import LocationAutocomplete from 'components/nearle_components/LocationAutocomplete';
|
||||
import PageHeader from 'components/nearle_components/PageHeader';
|
||||
@@ -164,9 +172,101 @@ const Riders = () => {
|
||||
const totalCols = roleid == 1 ? 11 : 10;
|
||||
const [logsRow, setLogsRow] = useState(null);
|
||||
const [riderLogsdata, setRiderLogsdata] = useState(null);
|
||||
const [historyFromDate, setHistoryFromDate] = useState(dayjs().startOf('month'));
|
||||
const [historyToDate, setHistoryToDate] = useState(dayjs().endOf('month'));
|
||||
const [historyDate, setHistoryDate] = useState(dayjs());
|
||||
const [historyStatus, setHistoryStatus] = useState('all');
|
||||
const [selectedDate, setSelectedDate] = useState(dayjs());
|
||||
const [editingSub, setEditingSub] = useState(null);
|
||||
const [newSubRider, setNewSubRider] = useState(null);
|
||||
|
||||
const getResolvedPartnerId = () => {
|
||||
let partnerId = '';
|
||||
try {
|
||||
const rawLocs = localStorage.getItem('applocations');
|
||||
if (rawLocs) {
|
||||
const locs = JSON.parse(rawLocs);
|
||||
const currentLoc = locs.find((l) => l.applocationid === appId);
|
||||
if (currentLoc && currentLoc.partnerid) {
|
||||
partnerId = currentLoc.partnerid;
|
||||
} else {
|
||||
const firstValidLoc = locs.find((l) => l.partnerid);
|
||||
if (firstValidLoc && firstValidLoc.partnerid) {
|
||||
partnerId = firstValidLoc.partnerid;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Error parsing applocations', e);
|
||||
}
|
||||
|
||||
if (!partnerId) {
|
||||
const savedPartnerId = localStorage.getItem('partnerid');
|
||||
if (savedPartnerId && savedPartnerId !== 'undefined' && savedPartnerId !== 'null') {
|
||||
partnerId = savedPartnerId;
|
||||
}
|
||||
}
|
||||
|
||||
if (!partnerId || partnerId === '0' || partnerId === 0) {
|
||||
partnerId = 44;
|
||||
}
|
||||
return partnerId;
|
||||
};
|
||||
|
||||
const getHistoryStatusColor = (status) => {
|
||||
const s = (status || '').toLowerCase();
|
||||
if (s === 'cancelled' || s === 'deleted' || s === 'inactive') return '#ef4444'; // Red
|
||||
if (s === 'scheduled') return '#0ea5e9'; // Blue
|
||||
if (s === 'active' || s === 'completed') return '#10b981'; // Green
|
||||
return '#64748b'; // Gray
|
||||
};
|
||||
|
||||
const handleDeleteSubstitution = async (row) => {
|
||||
if (window.confirm(`Are you sure you want to delete the substitution for ${row.absent_rider_name}?`)) {
|
||||
try {
|
||||
const resolvedTenantId = row.tenant_id || row.tenantid || getResolvedPartnerId();
|
||||
const url = `${process.env.REACT_APP_URL}/substitutions/${row.id}?tenant_id=${resolvedTenantId}`;
|
||||
const res = await axios.delete(url);
|
||||
if (res.data && res.data.status) {
|
||||
OpenToast('Substitution deleted successfully!', 'success', 2000);
|
||||
} else {
|
||||
OpenToast(res.data?.message || 'Failed to delete substitution.', 'error', 2000);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
OpenToast(err.response?.data?.message || err.message || 'Failed to delete substitution.', 'error', 2000);
|
||||
} finally {
|
||||
queryClient.invalidateQueries({ queryKey: ['substitutionsHistory'] });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handleUpdateSubstitutionSubmit = async () => {
|
||||
if (!newSubRider) {
|
||||
OpenToast('Please select a substitute rider', 'error', 2000);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const resolvedTenantId = editingSub.tenant_id || editingSub.tenantid || getResolvedPartnerId();
|
||||
const url = `${process.env.REACT_APP_URL}/substitutions/${editingSub.id}`;
|
||||
const payload = {
|
||||
tenant_id: parseInt(resolvedTenantId, 10),
|
||||
sub_rider_id: parseInt(newSubRider.userid, 10),
|
||||
sub_rider_name: newSubRider.username || newSubRider.fullname || `Rider #${newSubRider.userid}`
|
||||
};
|
||||
const res = await axios.put(url, payload);
|
||||
if (res.data && res.data.status) {
|
||||
OpenToast('Substitution updated successfully!', 'success', 2000);
|
||||
} else {
|
||||
OpenToast(res.data?.message || 'Failed to update substitution.', 'error', 2000);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
OpenToast(err.response?.data?.message || err.message || 'Failed to update substitution.', 'error', 2000);
|
||||
} finally {
|
||||
setEditingSub(null);
|
||||
setNewSubRider(null);
|
||||
queryClient.invalidateQueries({ queryKey: ['substitutionsHistory'] });
|
||||
}
|
||||
};
|
||||
|
||||
const [substituteAssignments, setSubstituteAssignments] = useState(() => {
|
||||
try {
|
||||
@@ -229,15 +329,18 @@ const Riders = () => {
|
||||
}
|
||||
}
|
||||
|
||||
if (!partnerId) {
|
||||
if (!partnerId || partnerId === '0' || partnerId === 0) {
|
||||
partnerId = 44; // final fallback
|
||||
}
|
||||
|
||||
const url = `${process.env.REACT_APP_URL}/partners/getallriders/?applocationid=${appId}&partnerid=${partnerId}`;
|
||||
const url = `${process.env.REACT_APP_URL}/partners/getallriders/?applocationid=0&partnerid=${partnerId}&pagesize=1000&pageno=1&status=`;
|
||||
const res = await axios.get(url);
|
||||
const allRiders = res.data.details || [];
|
||||
console.log('Substitute query - all riders returned from API:', allRiders.map(r => ({ userid: r.userid, username: r.username, partnerid: r.partnerid })));
|
||||
const allowedIds = [1121, 772, 1116];
|
||||
return allRiders.filter((rider) => allowedIds.includes(parseInt(rider.userid)));
|
||||
const filtered = allRiders.filter((rider) => allowedIds.includes(parseInt(rider.userid)));
|
||||
console.log('Substitute query - filtered allowed riders:', filtered);
|
||||
return filtered;
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
return [];
|
||||
@@ -246,10 +349,10 @@ const Riders = () => {
|
||||
});
|
||||
|
||||
const { data: subRidersLogsData, isLoading: subRidersLogsLoading } = useQuery({
|
||||
queryKey: ['subRidersLogs', appId, debouncedSearch],
|
||||
queryKey: ['subRidersLogs', appId, debouncedSearch, selectedDate.format('YYYY-MM-DD')],
|
||||
queryFn: async () => {
|
||||
try {
|
||||
const todayStr = dayjs().format('YYYY-MM-DD');
|
||||
const dateStr = selectedDate.format('YYYY-MM-DD');
|
||||
|
||||
// Resolve partner ID dynamically
|
||||
let partnerId = '';
|
||||
@@ -278,11 +381,11 @@ const Riders = () => {
|
||||
}
|
||||
}
|
||||
|
||||
if (!partnerId) {
|
||||
if (!partnerId || partnerId === '0' || partnerId === 0) {
|
||||
partnerId = 44;
|
||||
}
|
||||
|
||||
const url = `${process.env.REACT_APP_URL2}/partners/getriderlogs/?applocationid=${appId}&partnerid=${partnerId}&fromdate=${todayStr}&todate=${todayStr}&keyword=${debouncedSearch}`;
|
||||
const url = `${process.env.REACT_APP_URL2}/partners/getriderlogs/?applocationid=${appId}&partnerid=${partnerId}&fromdate=${dateStr}&todate=${dateStr}&keyword=${debouncedSearch}`;
|
||||
const res = await axios.get(url);
|
||||
return res.data.details || [];
|
||||
} catch (err) {
|
||||
@@ -293,7 +396,7 @@ const Riders = () => {
|
||||
});
|
||||
|
||||
const { data: subHistoryData, isLoading: subHistoryLoading } = useQuery({
|
||||
queryKey: ['substitutionsHistory', appId, historyFromDate, historyToDate, historyStatus],
|
||||
queryKey: ['substitutionsHistory', appId, historyDate, historyStatus],
|
||||
queryFn: async () => {
|
||||
try {
|
||||
let partnerId = '';
|
||||
@@ -322,11 +425,12 @@ const Riders = () => {
|
||||
}
|
||||
}
|
||||
|
||||
if (!partnerId) {
|
||||
if (!partnerId || partnerId === '0' || partnerId === 0) {
|
||||
partnerId = 44;
|
||||
}
|
||||
|
||||
let url = `${process.env.REACT_APP_URL}/substitutions?tenant_id=${partnerId}&from_date=${historyFromDate.format('YYYY-MM-DD')}&to_date=${historyToDate.format('YYYY-MM-DD')}`;
|
||||
const dateStr = historyDate.format('YYYY-MM-DD');
|
||||
let url = `${process.env.REACT_APP_URL}/substitutions?tenant_id=${partnerId}&from_date=${dateStr}&to_date=${dateStr}`;
|
||||
if (historyStatus !== 'all') {
|
||||
url += `&status=${historyStatus}`;
|
||||
}
|
||||
@@ -672,33 +776,14 @@ const Riders = () => {
|
||||
<Stack direction="row" spacing={1.5} alignItems="center">
|
||||
<LocalizationProvider dateAdapter={AdapterDayjs}>
|
||||
<DatePicker
|
||||
label="From Date"
|
||||
value={historyFromDate}
|
||||
onChange={(newValue) => newValue && setHistoryFromDate(newValue)}
|
||||
label="Select Date"
|
||||
value={historyDate}
|
||||
onChange={(newValue) => newValue && setHistoryDate(newValue)}
|
||||
slotProps={{
|
||||
textField: {
|
||||
size: 'small',
|
||||
sx: {
|
||||
width: 150,
|
||||
'& .MuiOutlinedInput-root': {
|
||||
borderRadius: '20px',
|
||||
'& fieldset': { borderColor: DT.borderSubtle },
|
||||
'&:hover fieldset': { borderColor: BRAND },
|
||||
'&.Mui-focused fieldset': { borderColor: BRAND }
|
||||
}
|
||||
}
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<DatePicker
|
||||
label="To Date"
|
||||
value={historyToDate}
|
||||
onChange={(newValue) => newValue && setHistoryToDate(newValue)}
|
||||
slotProps={{
|
||||
textField: {
|
||||
size: 'small',
|
||||
sx: {
|
||||
width: 150,
|
||||
width: 180,
|
||||
'& .MuiOutlinedInput-root': {
|
||||
borderRadius: '20px',
|
||||
'& fieldset': { borderColor: DT.borderSubtle },
|
||||
@@ -757,9 +842,9 @@ const Riders = () => {
|
||||
px: 1,
|
||||
py: 0.25,
|
||||
borderRadius: 999,
|
||||
bgcolor: tint('#10b981'),
|
||||
border: `1px solid ${edge('#10b981')}`,
|
||||
color: '#10b981',
|
||||
bgcolor: tint(getHistoryStatusColor(row.status)),
|
||||
border: `1px solid ${edge(getHistoryStatusColor(row.status))}`,
|
||||
color: getHistoryStatusColor(row.status),
|
||||
fontWeight: 800,
|
||||
fontSize: 10
|
||||
}}
|
||||
@@ -841,6 +926,7 @@ const Riders = () => {
|
||||
<TableCell>Substitute Rider</TableCell>
|
||||
<TableCell>Reason</TableCell>
|
||||
<TableCell align="center">Status</TableCell>
|
||||
<TableCell align="right">Action</TableCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
@@ -908,9 +994,9 @@ const Riders = () => {
|
||||
px: 1.5,
|
||||
py: 0.5,
|
||||
borderRadius: 999,
|
||||
bgcolor: tint('#10b981'),
|
||||
border: `1px solid ${edge('#10b981')}`,
|
||||
color: '#10b981',
|
||||
bgcolor: tint(getHistoryStatusColor(row.status)),
|
||||
border: `1px solid ${edge(getHistoryStatusColor(row.status))}`,
|
||||
color: getHistoryStatusColor(row.status),
|
||||
fontWeight: 800,
|
||||
fontSize: 11,
|
||||
textTransform: 'capitalize'
|
||||
@@ -919,6 +1005,43 @@ const Riders = () => {
|
||||
{row.status || 'scheduled'}
|
||||
</Box>
|
||||
</TableCell>
|
||||
<TableCell align="right">
|
||||
<Stack direction="row" spacing={0.75} justifyContent="flex-end">
|
||||
<Tooltip title="Update substitution" placement="top">
|
||||
<IconButton
|
||||
size="small"
|
||||
sx={{
|
||||
bgcolor: soft(BRAND),
|
||||
color: BRAND,
|
||||
border: `1px solid ${edge(BRAND)}`,
|
||||
'&:hover': { bgcolor: BRAND, color: '#fff' }
|
||||
}}
|
||||
onClick={() => {
|
||||
setEditingSub(row);
|
||||
setNewSubRider(null);
|
||||
}}
|
||||
>
|
||||
<MdEdit size={14} />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
<Tooltip title="Delete substitution" placement="top">
|
||||
<IconButton
|
||||
size="small"
|
||||
sx={{
|
||||
bgcolor: soft('#ef4444'),
|
||||
color: '#ef4444',
|
||||
border: `1px solid ${edge('#ef4444')}`,
|
||||
'&:hover': { bgcolor: '#ef4444', color: '#fff' }
|
||||
}}
|
||||
onClick={() => {
|
||||
handleDeleteSubstitution(row);
|
||||
}}
|
||||
>
|
||||
<MdDelete size={14} />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
</Stack>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
@@ -930,10 +1053,13 @@ const Riders = () => {
|
||||
<RiderSubstitution
|
||||
appId={appId}
|
||||
rows={subRidersLogsData || []}
|
||||
allRidersList={rows}
|
||||
substituteRidersList={substituteRidersList}
|
||||
substituteAssignments={substituteAssignments}
|
||||
handleAssignSubstitute={handleAssignSubstitute}
|
||||
onFinalizeSuccess={handleFinalizeSuccess}
|
||||
selectedDate={selectedDate}
|
||||
setSelectedDate={setSelectedDate}
|
||||
DT={DT}
|
||||
BRAND={BRAND}
|
||||
edge={edge}
|
||||
@@ -1670,6 +1796,79 @@ const Riders = () => {
|
||||
</TableContainer>
|
||||
</Paper>
|
||||
)}
|
||||
|
||||
<Dialog
|
||||
open={Boolean(editingSub)}
|
||||
onClose={() => setEditingSub(null)}
|
||||
maxWidth="xs"
|
||||
fullWidth
|
||||
PaperProps={{
|
||||
sx: {
|
||||
borderRadius: `${DT.radiusCard / 8}px`,
|
||||
p: 1
|
||||
}
|
||||
}}
|
||||
>
|
||||
<DialogTitle sx={{ fontWeight: 700, pb: 1 }}>Update Substitution</DialogTitle>
|
||||
<DialogContent>
|
||||
<Stack spacing={2} sx={{ mt: 1 }}>
|
||||
<Typography variant="body2" sx={{ color: DT.textSecondary }}>
|
||||
Choose a new substitute rider for <strong>{editingSub?.absent_rider_name}</strong>.
|
||||
</Typography>
|
||||
<Autocomplete
|
||||
size="small"
|
||||
options={substituteRidersList || []}
|
||||
isOptionEqualToValue={(option, value) => option?.userid === value?.userid}
|
||||
getOptionLabel={(option) => `${option.username || option.fullname || ''} (#${option.userid})`}
|
||||
value={newSubRider}
|
||||
onChange={(event, newValue) => setNewSubRider(newValue)}
|
||||
renderInput={(params) => (
|
||||
<TextField
|
||||
{...params}
|
||||
placeholder="Select Substitute Rider"
|
||||
sx={{
|
||||
'& .MuiOutlinedInput-root': {
|
||||
borderRadius: '8px',
|
||||
bgcolor: '#f8fafc',
|
||||
'& fieldset': { borderColor: DT.borderSubtle }
|
||||
}
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</Stack>
|
||||
</DialogContent>
|
||||
<DialogActions sx={{ px: 3, pb: 2 }}>
|
||||
<Button
|
||||
variant="outlined"
|
||||
onClick={() => setEditingSub(null)}
|
||||
sx={{
|
||||
borderRadius: '8px',
|
||||
textTransform: 'none',
|
||||
fontWeight: 600,
|
||||
borderColor: DT.borderSubtle,
|
||||
color: DT.textSecondary
|
||||
}}
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
variant="contained"
|
||||
onClick={handleUpdateSubstitutionSubmit}
|
||||
disabled={!newSubRider}
|
||||
sx={{
|
||||
borderRadius: '8px',
|
||||
textTransform: 'none',
|
||||
fontWeight: 600,
|
||||
bgcolor: BRAND,
|
||||
color: '#fff',
|
||||
'&:hover': { bgcolor: '#4D1C61' }
|
||||
}}
|
||||
>
|
||||
Save Changes
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user