updates on the profitability

This commit is contained in:
2026-06-15 20:51:04 +05:30
parent b35361d440
commit 7858d42f86
3 changed files with 133 additions and 113 deletions

View File

@@ -2238,7 +2238,7 @@
white-space: nowrap; white-space: nowrap;
transition: color 0.18s ease, background 0.18s ease, box-shadow 0.18s ease; transition: color 0.18s ease, background 0.18s ease, box-shadow 0.18s ease;
-webkit-appearance: none; -webkit-appearance: none;
appearance: none; appearance: none;
} }
.dispatch-container .trip-sort-pill svg { .dispatch-container .trip-sort-pill svg {
@@ -2275,13 +2275,11 @@
/* Mode-semantic accent on the active pill's icon — picks up the same /* Mode-semantic accent on the active pill's icon — picks up the same
indigo / emerald used on the Compare control + the time-rank badge indigo / emerald used on the Compare control + the time-rank badge
below, so the page reads as a coherent system. */ below, so the page reads as a coherent system. */
.dispatch-container .trip-sort-toggle[data-mode='planned'] .dispatch-container .trip-sort-toggle[data-mode='planned'] .trip-sort-pill.is-active svg {
.trip-sort-pill.is-active svg {
color: #662582; color: #662582;
} }
.dispatch-container .trip-sort-toggle[data-mode='time'] .dispatch-container .trip-sort-toggle[data-mode='time'] .trip-sort-pill.is-active svg {
.trip-sort-pill.is-active svg {
color: #10b981; color: #10b981;
} }
@@ -9598,8 +9596,17 @@
} }
@keyframes da-live-pulse { @keyframes da-live-pulse {
0%, 100% { opacity: 1; transform: scale(1); }
50% { opacity: 0.4; transform: scale(0.85); } 0%,
100% {
opacity: 1;
transform: scale(1);
}
50% {
opacity: 0.4;
transform: scale(0.85);
}
} }
.dispatch-container .da-metric-grid { .dispatch-container .da-metric-grid {
@@ -10011,8 +10018,13 @@
} }
@keyframes da-pos-fade { @keyframes da-pos-fade {
from { opacity: 0; } from {
to { opacity: 1; } opacity: 0;
}
to {
opacity: 1;
}
} }
.dispatch-container .da-pos-modal-card { .dispatch-container .da-pos-modal-card {
@@ -10030,8 +10042,15 @@
} }
@keyframes da-pos-rise { @keyframes da-pos-rise {
from { opacity: 0; transform: translateY(12px) scale(0.98); } from {
to { opacity: 1; transform: translateY(0) scale(1); } opacity: 0;
transform: translateY(12px) scale(0.98);
}
to {
opacity: 1;
transform: translateY(0) scale(1);
}
} }
.dispatch-container .da-pos-modal-head { .dispatch-container .da-pos-modal-head {
@@ -10652,11 +10671,9 @@
top: 0; top: 0;
bottom: 0; bottom: 0;
background-image: background-image:
repeating-linear-gradient( repeating-linear-gradient(135deg,
135deg,
#e2e8f0 0 6px, #e2e8f0 0 6px,
#f1f5f9 6px 12px #f1f5f9 6px 12px);
);
border-left: 1px dashed #cbd5e1; border-left: 1px dashed #cbd5e1;
} }
@@ -10900,6 +10917,7 @@
(≥ md) is untouched; every rule here is gated inside this media query. (≥ md) is untouched; every rule here is gated inside this media query.
========================================================================= */ ========================================================================= */
@media (max-width: 768px) { @media (max-width: 768px) {
/* The standalone page un-does MainCard's 24px padding via negative margin /* The standalone page un-does MainCard's 24px padding via negative margin
+ 100vw-ish sizing; keep that, just allow the inner body to grow with + 100vw-ish sizing; keep that, just allow the inner body to grow with
its stacked children instead of being clipped to a single row height. */ its stacked children instead of being clipped to a single row height. */

View File

@@ -83,7 +83,7 @@ body {
Fixed architecture: NO overflow, NO clipping, NO width:100vw Fixed architecture: NO overflow, NO clipping, NO width:100vw
════════════════════════════════════════════════════════════════════════════ */ ════════════════════════════════════════════════════════════════════════════ */
.profitability-dashboard { .dispatch-container .profitability-dashboard {
width: 100%; width: 100%;
max-width: 100%; max-width: 100%;
overflow-x: hidden; overflow-x: hidden;
@@ -126,7 +126,7 @@ body {
HEADER SECTION — Premium Top Header HEADER SECTION — Premium Top Header
════════════════════════════════════════════════════════════════════════════ */ ════════════════════════════════════════════════════════════════════════════ */
.profitability-header { .profitability-dashboard .profitability-header {
width: 100%; width: 100%;
max-width: 100%; max-width: 100%;
@@ -252,7 +252,7 @@ body {
flex-shrink: 0; flex-shrink: 0;
} }
.profitability-kpi-chip { .profitability-dashboard .profitability-kpi-chip {
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
gap: var(--space-md); gap: var(--space-md);
@@ -329,7 +329,7 @@ body {
════════════════════════════════════════════════════════════════════════════ */ ════════════════════════════════════════════════════════════════════════════ */
/* Enhanced KPI card interactions */ /* Enhanced KPI card interactions */
.profitability-summary-card { .profitability-dashboard .profitability-summary-card {
position: relative; position: relative;
min-width: 0; min-width: 0;
max-width: 100%; max-width: 100%;
@@ -404,6 +404,7 @@ body {
opacity: 0; opacity: 0;
transform: scaleY(0.95); transform: scaleY(0.95);
} }
to { to {
opacity: 1; opacity: 1;
transform: scaleY(1); transform: scaleY(1);
@@ -549,7 +550,7 @@ body {
CONTROLS BAR — Search, Filter, Sort CONTROLS BAR — Search, Filter, Sort
════════════════════════════════════════════════════════════════════════════ */ ════════════════════════════════════════════════════════════════════════════ */
.profitability-controls-bar { .profitability-dashboard .profitability-controls-bar {
width: 100%; width: 100%;
max-width: 100%; max-width: 100%;
@@ -588,7 +589,7 @@ body {
flex-shrink: 0; flex-shrink: 0;
} }
.profitability-search-input { .profitability-dashboard .profitability-search-input {
width: 100%; width: 100%;
height: 40px; height: 40px;
@@ -619,7 +620,7 @@ body {
box-shadow: 0 0 0 3px rgba(108, 76, 241, 0.1); box-shadow: 0 0 0 3px rgba(108, 76, 241, 0.1);
} }
.profitability-search-input:focus ~ .profitability-search-icon { .profitability-search-input:focus~.profitability-search-icon {
color: var(--primary); color: var(--primary);
} }
@@ -633,7 +634,7 @@ body {
border: 1px solid var(--border-light); border: 1px solid var(--border-light);
} }
.profitability-tab-btn { .profitability-dashboard .profitability-tab-btn {
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
@@ -696,7 +697,7 @@ body {
display: none; display: none;
} }
.profitability-sort-select { .profitability-dashboard .profitability-sort-select {
height: 40px; height: 40px;
padding: 0 32px 0 var(--space-md); padding: 0 32px 0 var(--space-md);
@@ -790,7 +791,7 @@ body {
RIDER CARD — Modern Enterprise SaaS Card RIDER CARD — Modern Enterprise SaaS Card
════════════════════════════════════════════════════════════════════════════ */ ════════════════════════════════════════════════════════════════════════════ */
.rider-profitability-card { .profitability-dashboard .rider-profitability-card {
width: 100%; width: 100%;
max-width: 100%; max-width: 100%;
min-width: 0; min-width: 0;
@@ -825,7 +826,7 @@ body {
box-shadow: 0 0 0 2px var(--primary-light), var(--shadow-md); box-shadow: 0 0 0 2px var(--primary-light), var(--shadow-md);
} }
.rider-card-header { .profitability-dashboard .rider-card-header {
display: flex; display: flex;
align-items: center; align-items: center;
gap: var(--space-lg); gap: var(--space-lg);
@@ -1043,13 +1044,14 @@ body {
opacity: 0; opacity: 0;
transform: translateY(-8px); transform: translateY(-8px);
} }
to { to {
opacity: 1; opacity: 1;
transform: translateY(0); transform: translateY(0);
} }
} }
.rider-detail-inner { .profitability-dashboard .rider-detail-inner {
padding: var(--space-lg); padding: var(--space-lg);
} }
@@ -1060,7 +1062,7 @@ body {
margin-bottom: var(--space-xl); margin-bottom: var(--space-xl);
} }
.cost-tile { .profitability-dashboard .cost-tile {
display: flex; display: flex;
gap: var(--space-md); gap: var(--space-md);
padding: var(--space-lg); padding: var(--space-lg);
@@ -1170,7 +1172,7 @@ body {
overflow: hidden; overflow: hidden;
} }
.revenue-breakdown-header { .profitability-dashboard .revenue-breakdown-header {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
@@ -1211,7 +1213,7 @@ body {
border-collapse: collapse; border-collapse: collapse;
} }
.orders-table thead th { .profitability-dashboard .orders-table thead th {
padding: var(--space-md) var(--space-lg); padding: var(--space-md) var(--space-lg);
text-align: left; text-align: left;
font-size: 11px; font-size: 11px;
@@ -1237,7 +1239,7 @@ body {
border-bottom: none; border-bottom: none;
} }
.orders-table tbody td { .profitability-dashboard .orders-table tbody td {
padding: var(--space-md) var(--space-lg); padding: var(--space-md) var(--space-lg);
vertical-align: middle; vertical-align: middle;
font-size: 13px; font-size: 13px;
@@ -1495,7 +1497,7 @@ body {
font-size: 12px; font-size: 12px;
} }
.profitability-kpi-chip { .profitability-dashboard .profitability-kpi-chip {
padding: var(--space-sm) var(--space-md); padding: var(--space-sm) var(--space-md);
font-size: 11px; font-size: 11px;
} }
@@ -1504,7 +1506,7 @@ body {
font-size: 14px; font-size: 14px;
} }
.profitability-summary-card { .profitability-dashboard .profitability-summary-card {
padding: var(--space-lg); padding: var(--space-lg);
} }

View File

@@ -125,94 +125,94 @@ const RidersLogs = () => {
{/* Individuals */} {/* Individuals */}
{ridersIsLoading || riderIsFetching {ridersIsLoading || riderIsFetching
? Array.from({ length: 10 }).map((_, index) => ( ? Array.from({ length: 10 }).map((_, index) => (
<Fragment key={index}> <Fragment key={index}>
<ListItem sx={{ py: 1.5, px: 2 }}> <ListItem sx={{ py: 1.5, px: 2 }}>
<ListItemAvatar>
<Skeleton variant="circular" width={24} height={24} />
</ListItemAvatar>
<ListItemText
primary={<Skeleton variant="text" width="60%" height={22} />}
secondary={<Skeleton variant="text" width="40%" height={18} />}
/>
<Stack spacing={0.5} textAlign="right">
<Skeleton variant="text" width={50} height={18} />
<Skeleton variant="text" width={80} height={16} />
</Stack>
</ListItem>
<Divider />
</Fragment>
))
: !isMobile &&
riders?.map((row) => {
return (
<Fragment key={row.userid}>
<ListItem
sx={{
cursor: 'pointer',
py: 1,
px: 2,
borderRadius: 1,
'&:hover': { bgcolor: theme.palette.secondary.lighter }
}}
secondaryAction={
<Stack textAlign="right" spacing={0.5}>
<Typography variant="body2" noWrap sx={{ color: row.status == 'active' ? 'success.main' : 'error.main' }}>
{row.userid}
</Typography>
<Typography variant="caption" color="text.secondary" noWrap>
{dayjs(row.logdate).format('DD/MM/YYYY hh:mm A')}
</Typography>
</Stack>
}
>
<ListItemAvatar> <ListItemAvatar>
<Skeleton variant="circular" width={24} height={24} /> <Checkbox
sx={{
color: row.status == 'active' ? 'green' : 'red',
'&.Mui-checked': {
color: row.status == 'active' ? 'green' : 'red'
}
}}
checked={
// INDIVIDUAL CHECKED CONDITION
selectedRiders?.length === 1 && selectedRiders[0]?.userid === row?.userid
}
onChange={(e) => {
if (e.target.checked) {
// SELECT ONE RIDER
setSelectedRiders([row]);
} else {
// UNCHECK -> SELECT ALL
setSelectedRiders(riders);
}
}}
/>
</ListItemAvatar> </ListItemAvatar>
<ListItemText <ListItemText
primary={<Skeleton variant="text" width="60%" height={22} />} primary={
secondary={<Skeleton variant="text" width="40%" height={18} />} <Typography noWrap>
/> {row.username?.slice(0, 25) || ''}
{row.username?.length > 25 && '...'}
<Stack spacing={0.5} textAlign="right"> {/* {row.status === 'active' && <TaskAltIcon fontSize="small" color="success" sx={{ ml: 1 }} />} */}
<Skeleton variant="text" width={50} height={18} /> </Typography>
<Skeleton variant="text" width={80} height={16} /> }
</Stack> secondary={
<Typography variant="caption" color="text.secondary" noWrap>
{row.contactno || '##########'}
</Typography>
}
/>
</ListItem> </ListItem>
<Divider /> <Divider />
</Fragment> </Fragment>
)) );
: !isMobile && })}
riders?.map((row) => {
return (
<Fragment key={row.userid}>
<ListItem
sx={{
cursor: 'pointer',
py: 1,
px: 2,
borderRadius: 1,
'&:hover': { bgcolor: theme.palette.secondary.lighter }
}}
secondaryAction={
<Stack textAlign="right" spacing={0.5}>
<Typography variant="body2" noWrap sx={{ color: row.status == 'active' ? 'success.main' : 'error.main' }}>
{row.userid}
</Typography>
<Typography variant="caption" color="text.secondary" noWrap>
{dayjs(row.logdate).format('DD/MM/YYYY hh:mm A')}
</Typography>
</Stack>
}
>
<ListItemAvatar>
<Checkbox
sx={{
color: row.status == 'active' ? 'green' : 'red',
'&.Mui-checked': {
color: row.status == 'active' ? 'green' : 'red'
}
}}
checked={
// INDIVIDUAL CHECKED CONDITION
selectedRiders?.length === 1 && selectedRiders[0]?.userid === row?.userid
}
onChange={(e) => {
if (e.target.checked) {
// SELECT ONE RIDER
setSelectedRiders([row]);
} else {
// UNCHECK -> SELECT ALL
setSelectedRiders(riders);
}
}}
/>
</ListItemAvatar>
<ListItemText
primary={
<Typography noWrap>
{row.username?.slice(0, 25) || ''}
{row.username?.length > 25 && '...'}
{/* {row.status === 'active' && <TaskAltIcon fontSize="small" color="success" sx={{ ml: 1 }} />} */}
</Typography>
}
secondary={
<Typography variant="caption" color="text.secondary" noWrap>
{row.contactno || '##########'}
</Typography>
}
/>
</ListItem>
<Divider />
</Fragment>
);
})}
</List> </List>
{/* Mobile: rider rows rendered as app-style cards (same selection behaviour) */} {/* Mobile: rider rows rendered as app-style cards (same selection behaviour) */}