updated the ui
This commit is contained in:
@@ -28,12 +28,14 @@ var utc = require('dayjs/plugin/utc');
|
||||
import dayjs from 'dayjs';
|
||||
dayjs.extend(utc);
|
||||
import {
|
||||
MdDirectionsBike,
|
||||
MdMyLocation,
|
||||
MdPersonPin,
|
||||
MdCheckCircle,
|
||||
MdCancel,
|
||||
MdGroups,
|
||||
MdOutlineGroups,
|
||||
MdOutlineCheckCircle,
|
||||
MdOutlineCancel,
|
||||
MdEdit,
|
||||
MdKeyboardArrowDown,
|
||||
MdKeyboardArrowUp,
|
||||
@@ -47,6 +49,8 @@ import {
|
||||
MdTwoWheeler
|
||||
} from 'react-icons/md';
|
||||
import LocationAutocomplete from 'components/nearle_components/LocationAutocomplete';
|
||||
import PageHeader from 'components/nearle_components/PageHeader';
|
||||
import StatCard from 'components/nearle_components/StatCard';
|
||||
import { MobileCard, MobileCardList, MobileField, MobileFieldGrid } from 'components/nearle_components/MobileCard';
|
||||
import DebounceSearchBar from 'components/nearle_components/DebounceSearchBar';
|
||||
import CircularLoader from 'components/CircularLoader';
|
||||
@@ -65,10 +69,10 @@ import axios from 'axios';
|
||||
// ============================================================================
|
||||
const DT = {
|
||||
radiusPill: 999,
|
||||
radiusCard: 16,
|
||||
shadowSoft: '0 14px 40px rgba(15, 23, 42, 0.10)',
|
||||
shadowMd: '0 8px 24px rgba(15, 23, 42, 0.08)',
|
||||
shadowPop: '0 18px 50px rgba(15, 23, 42, 0.18)',
|
||||
radiusCard: 14,
|
||||
shadowSoft: '0 1px 2px rgba(15, 23, 42, 0.04), 0 8px 24px rgba(15, 23, 42, 0.05)',
|
||||
shadowMd: '0 1px 3px rgba(15, 23, 42, 0.06)',
|
||||
shadowPop: '0 12px 32px rgba(15, 23, 42, 0.12)',
|
||||
textPrimary: '#0f172a',
|
||||
textSecondary: '#64748b',
|
||||
textMuted: '#94a3b8',
|
||||
@@ -84,7 +88,6 @@ const ring = (c) => a(c, '26');
|
||||
const edge = (c) => a(c, '55');
|
||||
|
||||
const BRAND = '#662582';
|
||||
const BRAND_LIGHT = '#9255AB';
|
||||
|
||||
const SoftPaper = (props) => (
|
||||
<Paper
|
||||
@@ -133,9 +136,9 @@ const TAB_META = [
|
||||
];
|
||||
|
||||
const KPI_META = (summary) => [
|
||||
{ key: 'total', label: 'Total Riders', color: BRAND, icon: MdGroups, value: summary?.total ?? 0 },
|
||||
{ key: 'active', label: 'Active Riders', color: '#10b981', icon: MdCheckCircle, value: summary?.active ?? 0 },
|
||||
{ key: 'inactive', label: 'Inactive Riders', color: '#ef4444', icon: MdCancel, value: summary?.inactive ?? 0 }
|
||||
{ key: 'total', label: 'Total Riders', color: BRAND, icon: MdOutlineGroups, value: summary?.total ?? 0 },
|
||||
{ key: 'active', label: 'Active Riders', color: '#10b981', icon: MdOutlineCheckCircle, value: summary?.active ?? 0 },
|
||||
{ key: 'inactive', label: 'Inactive Riders', color: '#ef4444', icon: MdOutlineCancel, value: summary?.inactive ?? 0 }
|
||||
];
|
||||
|
||||
const Riders = () => {
|
||||
@@ -205,7 +208,7 @@ const Riders = () => {
|
||||
getNextPageParam: (lastPage, pages) => (lastPage.details?.length ? pages.length + 1 : undefined)
|
||||
});
|
||||
|
||||
const rows = allRidersData?.pages.flatMap((page) => page.details) || [];
|
||||
const rows = (allRidersData?.pages.flatMap((page) => page.details || []) || []).filter(Boolean);
|
||||
|
||||
useEffect(() => {
|
||||
if (!hasNextPage) return;
|
||||
@@ -247,10 +250,10 @@ const Riders = () => {
|
||||
// isn't in the palette (e.g. brand-new status string from the backend).
|
||||
const getRowStatusMeta = (row) => {
|
||||
if (tabvalue == 0) {
|
||||
const key = (row.status || '').toLowerCase() === 'active' ? 'active' : 'inactive';
|
||||
return STATUS_META[key];
|
||||
const key = (row?.status || '').toLowerCase() === 'active' ? 'active' : 'inactive';
|
||||
return STATUS_META[key] || STATUS_META.unknown;
|
||||
}
|
||||
const state = ridersStatus?.find((s) => s.userid === row.userid);
|
||||
const state = ridersStatus?.find((s) => s.userid === row?.userid);
|
||||
const key = (state?.status || 'unknown').toLowerCase();
|
||||
return STATUS_META[key] || STATUS_META.unknown;
|
||||
};
|
||||
@@ -265,64 +268,11 @@ const Riders = () => {
|
||||
</Backdrop>
|
||||
|
||||
{/* ============================================= || Header | ============================================= */}
|
||||
<Paper
|
||||
elevation={0}
|
||||
sx={{
|
||||
mb: { xs: 1.5, md: 2 },
|
||||
p: { xs: 1.5, sm: 2, md: 2.5 },
|
||||
borderRadius: DT.radiusCard / 8,
|
||||
border: '1px solid',
|
||||
borderColor: DT.borderSubtle,
|
||||
background: `linear-gradient(135deg, ${tint(BRAND)} 0%, ${tint(BRAND_LIGHT)} 100%)`,
|
||||
boxShadow: DT.shadowMd
|
||||
}}
|
||||
>
|
||||
<Stack
|
||||
direction={{ xs: 'column', sm: 'row' }}
|
||||
alignItems={{ xs: 'flex-start', sm: 'center' }}
|
||||
justifyContent="space-between"
|
||||
spacing={{ xs: 1.5, sm: 2 }}
|
||||
>
|
||||
<Stack direction="row" alignItems="center" spacing={{ xs: 1.25, sm: 1.75 }}>
|
||||
<Avatar
|
||||
sx={{
|
||||
width: { xs: 40, sm: 48 },
|
||||
height: { xs: 40, sm: 48 },
|
||||
bgcolor: BRAND,
|
||||
color: '#fff',
|
||||
boxShadow: `0 6px 18px ${ring(BRAND)}`
|
||||
}}
|
||||
>
|
||||
<MdDirectionsBike size={22} />
|
||||
</Avatar>
|
||||
<Stack>
|
||||
<Typography
|
||||
variant="h3"
|
||||
sx={{
|
||||
fontWeight: 800,
|
||||
color: DT.textPrimary,
|
||||
lineHeight: 1.1,
|
||||
fontSize: { xs: '1.25rem', sm: '1.5rem', md: '1.75rem' }
|
||||
}}
|
||||
>
|
||||
Riders
|
||||
</Typography>
|
||||
<Stack direction="row" alignItems="center" spacing={0.75} sx={{ mt: 0.5 }}>
|
||||
<Box
|
||||
sx={{
|
||||
width: 8,
|
||||
height: 8,
|
||||
borderRadius: '50%',
|
||||
bgcolor: '#10b981',
|
||||
boxShadow: '0 0 0 4px rgba(16,185,129,0.18)'
|
||||
}}
|
||||
/>
|
||||
<Typography variant="caption" sx={{ color: DT.textSecondary, fontWeight: 600 }}>
|
||||
Live · {locaName || 'All Zones'}
|
||||
</Typography>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Stack>
|
||||
<PageHeader
|
||||
title="Riders"
|
||||
subtitle={`Live · ${locaName || 'All Zones'}`}
|
||||
live
|
||||
action={
|
||||
<LocationAutocomplete
|
||||
locaName={locaName}
|
||||
setAppId={setAppId}
|
||||
@@ -334,89 +284,22 @@ const Riders = () => {
|
||||
paperComponent={SoftPaper}
|
||||
sx={{ width: { xs: '100%', sm: 280 }, zIndex: 100 }}
|
||||
/>
|
||||
</Stack>
|
||||
</Paper>
|
||||
}
|
||||
/>
|
||||
|
||||
{/* ============================================= || KPI Cards | ============================================= */}
|
||||
<Grid container spacing={{ xs: 1.25, sm: 1.5, md: 2 }} sx={{ mt: '1px' }}>
|
||||
<Grid container spacing={{ xs: 2, md: 2.5 }} sx={{ mb: { xs: 1.5, md: 2 } }}>
|
||||
{KPI_META(allRidersSummary).map((item) => {
|
||||
const Icon = item.icon;
|
||||
return (
|
||||
<Grid item key={item.key} xs={12} sm={4}>
|
||||
<Paper
|
||||
elevation={0}
|
||||
sx={{
|
||||
position: 'relative',
|
||||
overflow: 'hidden',
|
||||
p: { xs: 1.25, sm: 1.75, md: 2.25 },
|
||||
borderRadius: DT.radiusCard / 8,
|
||||
border: '1px solid',
|
||||
borderColor: DT.borderSubtle,
|
||||
background: '#fff',
|
||||
transition: 'transform 0.2s, box-shadow 0.2s, border-color 0.2s',
|
||||
'&:hover': {
|
||||
transform: 'translateY(-3px)',
|
||||
boxShadow: DT.shadowMd,
|
||||
borderColor: edge(item.color)
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
height: 3,
|
||||
background: `linear-gradient(90deg, ${item.color} 0%, ${soft(item.color)} 100%)`
|
||||
}}
|
||||
/>
|
||||
<Stack direction="row" alignItems="flex-start" justifyContent="space-between" spacing={1}>
|
||||
<Stack spacing={0.5} sx={{ minWidth: 0, flex: 1 }}>
|
||||
<Typography
|
||||
variant="caption"
|
||||
sx={{
|
||||
color: DT.textSecondary,
|
||||
fontWeight: 700,
|
||||
letterSpacing: 0.4,
|
||||
textTransform: 'uppercase',
|
||||
fontSize: { xs: 10, sm: 11 },
|
||||
whiteSpace: 'nowrap',
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis'
|
||||
}}
|
||||
>
|
||||
{item.label}
|
||||
</Typography>
|
||||
{riderSummarysLoading ? (
|
||||
<Skeleton sx={{ width: 70, height: { xs: 28, md: 36 } }} animation="wave" />
|
||||
) : (
|
||||
<Typography
|
||||
sx={{
|
||||
fontWeight: 800,
|
||||
color: DT.textPrimary,
|
||||
lineHeight: 1.1,
|
||||
fontSize: { xs: '1.5rem', sm: '1.75rem', md: '2rem' }
|
||||
}}
|
||||
>
|
||||
{item.value}
|
||||
</Typography>
|
||||
)}
|
||||
</Stack>
|
||||
<Avatar
|
||||
sx={{
|
||||
width: { xs: 36, sm: 42, md: 48 },
|
||||
height: { xs: 36, sm: 42, md: 48 },
|
||||
bgcolor: soft(item.color),
|
||||
color: item.color,
|
||||
boxShadow: `inset 0 0 0 1px ${edge(item.color)}`,
|
||||
flexShrink: 0
|
||||
}}
|
||||
>
|
||||
<Icon size={20} />
|
||||
</Avatar>
|
||||
</Stack>
|
||||
</Paper>
|
||||
<StatCard
|
||||
title={item.label}
|
||||
value={item.value ?? 0}
|
||||
icon={<Icon size={20} />}
|
||||
color={item.color}
|
||||
loading={riderSummarysLoading}
|
||||
/>
|
||||
</Grid>
|
||||
);
|
||||
})}
|
||||
@@ -474,16 +357,16 @@ const Riders = () => {
|
||||
py: 0.5,
|
||||
flexShrink: 0,
|
||||
cursor: 'pointer',
|
||||
borderRadius: 999,
|
||||
border: `1.5px solid ${active ? t.color : edge(t.color)}`,
|
||||
bgcolor: active ? t.color : tint(t.color),
|
||||
color: active ? '#fff' : t.color,
|
||||
fontWeight: 700,
|
||||
boxShadow: active ? `0 6px 18px ${ring(t.color)}` : 'none',
|
||||
transition: 'all 0.18s',
|
||||
borderRadius: '10px',
|
||||
border: `1px solid ${active ? t.color : DT.borderSubtle}`,
|
||||
bgcolor: active ? t.color : DT.surface,
|
||||
color: active ? '#fff' : DT.textSecondary,
|
||||
fontWeight: 600,
|
||||
boxShadow: 'none',
|
||||
transition: 'background-color 0.15s, border-color 0.15s, color 0.15s',
|
||||
'&:hover': {
|
||||
borderColor: t.color,
|
||||
boxShadow: active ? `0 6px 18px ${ring(t.color)}` : `0 0 0 3px ${ring(t.color)}`
|
||||
borderColor: active ? t.color : '#cbd5e1',
|
||||
bgcolor: active ? t.color : '#f8fafc'
|
||||
}
|
||||
}}
|
||||
>
|
||||
@@ -497,7 +380,7 @@ const Riders = () => {
|
||||
>
|
||||
<Icon size={13} />
|
||||
</Avatar>
|
||||
<Typography variant="caption" sx={{ fontWeight: 800, fontSize: { xs: 11.5, md: 13 }, lineHeight: 1 }}>
|
||||
<Typography variant="caption" sx={{ fontWeight: 600, fontSize: { xs: 11.5, md: 13 }, lineHeight: 1 }}>
|
||||
{t.label}
|
||||
</Typography>
|
||||
<Box
|
||||
@@ -510,10 +393,10 @@ const Riders = () => {
|
||||
justifyContent: 'center',
|
||||
borderRadius: 999,
|
||||
fontSize: { xs: 10, md: 11 },
|
||||
fontWeight: 800,
|
||||
bgcolor: active ? 'rgba(255,255,255,0.22)' : '#fff',
|
||||
color: active ? '#fff' : t.color,
|
||||
border: active ? 'none' : `1px solid ${edge(t.color)}`
|
||||
fontWeight: 700,
|
||||
bgcolor: active ? 'rgba(255,255,255,0.22)' : '#f8fafc',
|
||||
color: active ? '#fff' : '#64748b',
|
||||
border: 'none'
|
||||
}}
|
||||
>
|
||||
{riderSummarysLoading ? <Skeleton variant="text" width={14} height={10} /> : count}
|
||||
@@ -533,10 +416,10 @@ const Riders = () => {
|
||||
m: 0,
|
||||
width: '100%',
|
||||
borderRadius: 999,
|
||||
bgcolor: tint(BRAND),
|
||||
'& fieldset': { borderColor: edge(BRAND), borderWidth: 1.5 },
|
||||
'&:hover fieldset': { borderColor: BRAND },
|
||||
'&.Mui-focused fieldset': { borderColor: BRAND, borderWidth: 2 },
|
||||
bgcolor: '#ffffff',
|
||||
'& fieldset': { borderColor: '#e2e8f0', borderWidth: 1 },
|
||||
'&:hover fieldset': { borderColor: '#cbd5e1' },
|
||||
'&.Mui-focused fieldset': { borderColor: '#662582', borderWidth: 1.5 },
|
||||
'&.Mui-focused': { boxShadow: `0 0 0 3px ${ring(BRAND)}` }
|
||||
}}
|
||||
/>
|
||||
@@ -625,7 +508,7 @@ const Riders = () => {
|
||||
px: 1,
|
||||
py: 0.375,
|
||||
borderRadius: 999,
|
||||
bgcolor: tint(BRAND),
|
||||
bgcolor: '#ffffff',
|
||||
border: `1px solid ${edge(BRAND)}`,
|
||||
color: BRAND,
|
||||
fontWeight: 800,
|
||||
@@ -794,7 +677,7 @@ const Riders = () => {
|
||||
mt: 1.5,
|
||||
p: 1.25,
|
||||
borderRadius: 2,
|
||||
bgcolor: tint(BRAND),
|
||||
bgcolor: '#ffffff',
|
||||
border: `1px solid ${edge(BRAND)}`
|
||||
}}
|
||||
>
|
||||
@@ -961,7 +844,7 @@ const Riders = () => {
|
||||
px: 1,
|
||||
py: 0.375,
|
||||
borderRadius: 999,
|
||||
bgcolor: tint(BRAND),
|
||||
bgcolor: '#ffffff',
|
||||
border: `1px solid ${edge(BRAND)}`,
|
||||
color: BRAND,
|
||||
fontWeight: 800,
|
||||
@@ -1162,7 +1045,7 @@ const Riders = () => {
|
||||
<Box
|
||||
sx={{
|
||||
p: { xs: 1.5, md: 2 },
|
||||
bgcolor: tint(BRAND),
|
||||
bgcolor: '#ffffff',
|
||||
borderTop: `1px solid ${edge(BRAND)}`
|
||||
}}
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user