initialization

This commit is contained in:
2026-07-07 11:16:41 +05:30
parent d716bed6a5
commit e468861709
77 changed files with 508 additions and 5306 deletions

View File

@@ -5,4 +5,8 @@ REACT_APP_STAFF_TOKEN=
REACT_APP_GOOGLE_MAPS_API_KEY=AIzaSyCF4KatYCI3vqz1_H3kiHeyS3yCMfYToh8 REACT_APP_GOOGLE_MAPS_API_KEY=AIzaSyCF4KatYCI3vqz1_H3kiHeyS3yCMfYToh8
REACT_APP_RIDER_ACCESS_ID=AAAAILMpCEU:APA91bEavuOllBI6sFgYtxXAgNmAVwNA-MnCMHLGlR4_t7UqpLajAkdn3T0CZr_zaLBknLyim9ytFLMZgbeXmKqTad_PKCbqlYjHpaizVrLXtecxqyEy4UktIacK2UvHVUATHL-7VQQk REACT_APP_RIDER_ACCESS_ID=AAAAILMpCEU:APA91bEavuOllBI6sFgYtxXAgNmAVwNA-MnCMHLGlR4_t7UqpLajAkdn3T0CZr_zaLBknLyim9ytFLMZgbeXmKqTad_PKCbqlYjHpaizVrLXtecxqyEy4UktIacK2UvHVUATHL-7VQQk
GENERATE_SOURCEMAP=false
DISABLE_ESLINT_PLUGIN=true

View File

@@ -1,3 +1,6 @@
REACT_APP_URL=https://jupiter.nearle.app/live/api/v1 REACT_APP_URL=https://jupiter.nearle.app/live/api/v1
REACT_APP_URL2= REACT_APP_URL2=
REACT_APP_STAFF_TOKEN= REACT_APP_STAFF_TOKEN=
GENERATE_SOURCEMAP=false
DISABLE_ESLINT_PLUGIN=true

View File

@@ -174,43 +174,43 @@ const AccentAvatar = ({ color, selected, size = 24, children }) => (
### Page anatomy (every operator page should follow this order) ### Page anatomy (every operator page should follow this order)
> **Use brand purple `#662582` (with light variant `#9255AB`) for every brand surface below.** Don't use indigo `#6366f1` — that's reserved for the "Accepted" status badge only. > **Use brand red `#C01227` (with light variant `#D35968`) for every brand surface below.** Don't use indigo `#6366f1` — that's reserved for the "Accepted" status badge only.
1. **Gradient header `<Paper>`**`linear-gradient(135deg, ${tint('#662582')} 0%, ${tint('#9255AB')} 100%)`, 48px filled `#662582` avatar with a page icon, `Typography variant="h3"` title, "Live · {zone}" sub-line with an 8px green pulsing dot, and a pill `LocationAutocomplete` on the right (`pill accentColor="#662582" paperComponent={SoftPaper}`). 1. **Gradient header `<Paper>`**`linear-gradient(135deg, ${tint('#C01227')} 0%, ${tint('#D35968')} 100%)`, 48px filled `#C01227` avatar with a page icon, `Typography variant="h3"` title, "Live · {zone}" sub-line with an 8px green pulsing dot, and a pill `LocationAutocomplete` on the right (`pill accentColor="#C01227" paperComponent={SoftPaper}`).
2. **KPI tiles row**`Grid` of 34 `Paper` cards, each with a 3px top stripe gradient, uppercase eyebrow label, large bold number, and a soft-tinted avatar holding an icon. The "primary" tile uses brand purple `#662582`; other tiles use semantic status colours. 2. **KPI tiles row**`Grid` of 34 `Paper` cards, each with a 3px top stripe gradient, uppercase eyebrow label, large bold number, and a soft-tinted avatar holding an icon. The "primary" tile uses brand red `#C01227`; other tiles use semantic status colours.
3. **Filter bar `<Paper>`** (optional) — pill-style `Autocomplete`s using `pillFieldSx(color)` + `SoftPaper`, each with an `AccentAvatar` start-adornment. 3. **Filter bar `<Paper>`** (optional) — pill-style `Autocomplete`s using `pillFieldSx(color)` + `SoftPaper`, each with an `AccentAvatar` start-adornment.
4. **Pill status tabs + pill search** — tabs as clickable `<Box>` pills (active = filled accent + glow ring, inactive = `tint` bg + `edge` border), each with an avatar icon and a count badge. Tab accents use the **semantic status colour** for each tab (pending → amber, delivered → emerald, etc.). Search via `DebounceSearchBar` styled with brand purple `#662582` (tint bg, edge border, focus ring). 4. **Pill status tabs + pill search** — tabs as clickable `<Box>` pills (active = filled accent + glow ring, inactive = `tint` bg + `edge` border), each with an avatar icon and a count badge. Tab accents use the **semantic status colour** for each tab (pending → amber, delivered → emerald, etc.). Search via `DebounceSearchBar` styled with brand red `#C01227` (tint bg, edge border, focus ring).
5. **Table `<Paper>`** with `<TableContainer>` + sticky `<TableHead>` — uppercase muted headers on `DT.surfaceAlt`, rows with `borderBottom: 1px solid ${DT.divider}` and `:hover` row tint. Scrollbar thumb uses brand purple `edge('#662582')`. 5. **Table `<Paper>`** with `<TableContainer>` + sticky `<TableHead>` — uppercase muted headers on `DT.surfaceAlt`, rows with `borderBottom: 1px solid ${DT.divider}` and `:hover` row tint. Scrollbar thumb uses brand red `edge('#C01227')`.
6. **Status badges in cells**`Stack` with `AccentAvatar` + label inside a soft pill (tint bg, edge border). Status colours come from a per-page `STATUS_META` map keyed by lowercase status string — these are **semantic**, not brand. 6. **Status badges in cells**`Stack` with `AccentAvatar` + label inside a soft pill (tint bg, edge border). Status colours come from a per-page `STATUS_META` map keyed by lowercase status string — these are **semantic**, not brand.
7. **Edit / action icon buttons** — soft-pill `IconButton` using brand purple `#662582` (NOT `#8b5cf6` — that overlaps with the "Picked" status badge and confuses operators). 7. **Edit / action icon buttons** — soft-pill `IconButton` using brand red `#C01227` (NOT `#8b5cf6` — that overlaps with the "Picked" status badge and confuses operators).
8. **Empty state** — centered 64px avatar (soft grey), bold "No X to show" line, and a muted helper sentence. Do not use antd `<Empty />` for new code. 8. **Empty state** — centered 64px avatar (soft grey), bold "No X to show" line, and a muted helper sentence. Do not use antd `<Empty />` for new code.
### Universal brand colour ### Universal brand colour
**`#662582` — NearlExpress brand purple.** This is the canonical primary colour for this app, defined in `src/themes/theme/default.js` as `primary.main`. It drives the sidebar, the logo, and is what every new surface (page headers, KPI primary tile, search bars, edit-action buttons, dialog/popup headers, scrollbars) must use as the brand accent. **`#C01227` — NearlExpress brand red.** This is the canonical primary colour for this app, defined in `src/themes/theme/default.js` as `primary.main`. It drives the sidebar, the logo, and is what every new surface (page headers, KPI primary tile, search bars, edit-action buttons, dialog/popup headers, scrollbars) must use as the brand accent.
Variants (also from `theme/default.js`): Variants (also from `theme/default.js`):
| Token | Hex | Use | | Token | Hex | Use |
|---|---|---| |---|---|---|
| `primary.lighter` | `#E8D9EF` | Very subtle wash bg | | `primary.lighter` | `#F6DBDF` | Very subtle wash bg |
| `primary.light` / `primary.400` | `#9255AB` | Gradient pair with main | | `primary.light` / `primary.400` | `#D35968` | Gradient pair with main |
| `primary.main` | `#662582` | Brand primary — default for all brand surfaces | | `primary.main` | `#C01227` | Brand primary — default for all brand surfaces |
| `primary.dark` | `#4D1C61` | Hover / pressed states | | `primary.dark` | `#900E1D` | Hover / pressed states |
| `primary.darker` | `#260E30` | Deep contrast text on light bg | | `primary.darker` | `#47070E` | Deep contrast text on light bg |
**Page header / dialog header gradient:** `linear-gradient(135deg, ${tint('#662582')} 0%, ${tint('#9255AB')} 100%)` (subtle wash) or `linear-gradient(135deg, #662582 0%, #9255AB 100%)` (solid, for dialog titles). **Page header / dialog header gradient:** `linear-gradient(135deg, ${tint('#C01227')} 0%, ${tint('#D35968')} 100%)` (subtle wash) or `linear-gradient(135deg, #C01227 0%, #D35968 100%)` (solid, for dialog titles).
> **Migration note:** `deliveries.js`, `Tenants.js`, and `clientPricing.js` currently use `#6366f1` (indigo) as their brand accent — a holdover from the first design pass before brand purple was canonicalised. They are scheduled to migrate to `#662582`. `customers.js` and the createorder1 Saved-Address dialog have already been migrated. > **Migration note:** `deliveries.js`, `Tenants.js`, and `clientPricing.js` currently use `#6366f1` (indigo) as their brand accent — a holdover from the first design pass before brand red was canonicalised. They are scheduled to migrate to `#C01227`. `customers.js` and the createorder1 Saved-Address dialog have already been migrated.
### Status palette (semantic — distinct from brand) ### Status palette (semantic — distinct from brand)
These colour-code lifecycle states. Do **not** swap them for brand purple — operators rely on the colour to identify status at a glance. These colour-code lifecycle states. Do **not** swap them for brand red — operators rely on the colour to identify status at a glance.
| Meaning | Colour | | Meaning | Colour |
|--------------------------|-----------| |--------------------------|-----------|
| Pending / waiting | `#f59e0b` (amber) | | Pending / waiting | `#f59e0b` (amber) |
| Accepted / assigned | `#6366f1` (indigo — semantically distinct from brand purple) | | Accepted / assigned | `#6366f1` (indigo — semantically distinct from brand red) |
| Arrived | `#06b6d4` (cyan) | | Arrived | `#06b6d4` (cyan) |
| Picked up | `#8b5cf6` (light purple — distinct from brand) | | Picked up | `#8b5cf6` (light purple — distinct from brand) |
| Active / in-transit | `#14b8a6` (teal) | | Active / in-transit | `#14b8a6` (teal) |

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 69 KiB

View File

@@ -4,8 +4,8 @@
<meta charset="utf-8" /> <meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.png" /> <link rel="icon" href="%PUBLIC_URL%/favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" /> <meta name="theme-color" content="#C01227" />
<meta name="description" content="Nearle Neighbourhood commerce" /> <meta name="description" content="Doormile — corporate logistics & last-mile delivery admin console" />
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" /> <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<link <link
rel="stylesheet" rel="stylesheet"
@@ -28,7 +28,7 @@
work correctly both with client-side routing and a non-root public URL. work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`. Learn how to configure a non-root public URL by running `npm run build`.
--> -->
<title>Nearle Console</title> <title>Doormile Console</title>
<link rel="preconnect" href="https://fonts.gstatic.com" /> <link rel="preconnect" href="https://fonts.gstatic.com" />
<link <link

BIN
public/logo192.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

View File

@@ -1,6 +1,6 @@
import { styled } from '@mui/material/styles'; import { styled } from '@mui/material/styles';
import CircularProgress from '@mui/material/CircularProgress'; import CircularProgress from '@mui/material/CircularProgress';
import nelogo from '../assets/images/logo-sm.png'; import nelogo from '../assets/images/doormile-mark.png';
// Styled Loader Wrapper // Styled Loader Wrapper
const LoaderWrapper = styled('div')(() => ({ const LoaderWrapper = styled('div')(() => ({

View File

@@ -26,13 +26,13 @@ The `DT` design tokens (palette, alpha helpers, `pillFieldSx`, `SoftPaper`, `Acc
**Hard rules when editing components here:** **Hard rules when editing components here:**
- **Universal brand colour is `#662582`** (NearlExpress purple — from `themes/theme/default.js` `primary.main`). Every brand surface (page header, dialog header, KPI primary tile, search bars, edit-action buttons, scrollbars) uses this. Gradient pair: `#662582 → #9255AB`. - **Universal brand colour is `#C01227`** (Doormile red — from `themes/theme/default.js` `primary.main`). Every brand surface (page header, dialog header, KPI primary tile, search bars, edit-action buttons, scrollbars) uses this. Gradient pair: `#C01227 → #D35968`.
- **Semantic status palette is distinct** from the brand. Use these for lifecycle indicators only: sky `#0ea5e9`, emerald `#10b981`, amber `#f59e0b`, red `#ef4444`, status-purple `#8b5cf6` (lighter than brand), cyan `#06b6d4`, teal `#14b8a6`, orange `#f97316`, muted `#94a3b8`, indigo `#6366f1` (Accepted status). Don't replace these with brand purple — operators colour-code on them. - **Semantic status palette is distinct** from the brand. Use these for lifecycle indicators only: sky `#0ea5e9`, emerald `#10b981`, amber `#f59e0b`, red `#ef4444`, status-purple `#8b5cf6` (lighter than brand), cyan `#06b6d4`, teal `#14b8a6`, orange `#f97316`, muted `#94a3b8`, indigo `#6366f1` (Accepted status). Don't replace these with brand red — operators colour-code on them.
- Don't introduce a colour from `theme.palette` for new surfaces — those are Mantis defaults and don't match the DT system. Use the hex values above directly. - Don't introduce a colour from `theme.palette` for new surfaces — those are Mantis defaults and don't match the DT system. Use the hex values above directly.
- Border radii: `12` (inner), `16` (card), `999` (pill). No other values. - Border radii: `12` (inner), `16` (card), `999` (pill). No other values.
- Shadows: `DT.shadowSoft` / `DT.shadowMd` / `DT.shadowPop`. No raw `box-shadow` strings. - Shadows: `DT.shadowSoft` / `DT.shadowMd` / `DT.shadowPop`. No raw `box-shadow` strings.
> Some existing redesigned pages (`deliveries.js`, `Tenants.js`, `clientPricing.js`) still use `#6366f1` as the brand accent — this is a legacy from the first design pass. `customers.js` and the `createorder1` Saved-Address dialog are already on `#662582`. When you next edit one of the legacy pages, migrate it to brand purple in the same PR. > Some existing redesigned pages (`deliveries.js`, `Tenants.js`, `clientPricing.js`) still use `#6366f1` as the brand accent — this is a legacy from the first design pass. `customers.js` and the `createorder1` Saved-Address dialog are already on `#C01227`. When you next edit one of the legacy pages, migrate it to brand red in the same PR.
--- ---

View File

@@ -1,7 +1,7 @@
// LoaderWithImage.jsx // LoaderWithImage.jsx
import React from 'react'; import React from 'react';
import { Box, CircularProgress } from '@mui/material'; import { Box, CircularProgress } from '@mui/material';
import nelogo from '../../assets/images/logo-sm.png'; import nelogo from '../../assets/images/doormile-mark.png';
export default function LoaderWithImage({ size = 70, imgSize = 40, alt = 'loader' }) { export default function LoaderWithImage({ size = 70, imgSize = 40, alt = 'loader' }) {
return ( return (

View File

@@ -42,7 +42,7 @@ MobileCardList.propTypes = {
// Card shell — coloured accent rail on the left, a header slot (status badge / // Card shell — coloured accent rail on the left, a header slot (status badge /
// title / action buttons), then any field grid / collapse content as children. // title / action buttons), then any field grid / collapse content as children.
export const MobileCard = ({ accent = '#662582', header, footer, selected = false, onClick, children, sx }) => ( export const MobileCard = ({ accent = '#C01227', header, footer, selected = false, onClick, children, sx }) => (
<Paper <Paper
elevation={0} elevation={0}
onClick={onClick} onClick={onClick}

View File

@@ -10,7 +10,7 @@ import { Avatar, Box, Card, CardContent, Skeleton, Stack, Typography } from '@mu
// `color` is a hex accent (defaults to brand purple); `caption` is the small // `color` is a hex accent (defaults to brand purple); `caption` is the small
// muted line under the value (e.g. "96% of total"). // muted line under the value (e.g. "96% of total").
export default function StatCard({ title, value, icon, color = '#662582', caption, loading = false }) { export default function StatCard({ title, value, icon, color = '#C01227', caption, loading = false }) {
return ( return (
<Card sx={{ height: '100%' }}> <Card sx={{ height: '100%' }}>
<CardContent sx={{ p: { xs: 1.75, md: 2 }, '&:last-child': { pb: { xs: 1.75, md: 2 } } }}> <CardContent sx={{ p: { xs: 1.75, md: 2 }, '&:last-child': { pb: { xs: 1.75, md: 2 } } }}>

View File

@@ -234,13 +234,27 @@ const NavCollapse = ({ menu, level, parentId, setSelectedItems, selectedItems, s
...(drawerOpen && { ...(drawerOpen && {
'&:hover': { '&:hover': {
// bgcolor: theme.palette.mode === ThemeMode.DARK ? 'divider' : 'primary.lighter' bgcolor: '#fff',
bgcolor: '#7b1fa2' '& .MuiTypography-root': {
color: '#C01227 !important'
},
'& svg, & .anticon': {
color: '#C01227 !important'
}
}, },
'&.Mui-selected': { '&.Mui-selected': {
bgcolor: 'transparent', bgcolor: 'transparent',
color: iconSelectedColor, color: iconSelectedColor,
'&:hover': { color: iconSelectedColor, bgcolor: theme.palette.mode === ThemeMode.DARK ? 'divider' : 'transparent' } '&:hover': {
bgcolor: '#fff',
color: '#C01227',
'& .MuiTypography-root': {
color: '#C01227 !important'
},
'& svg, & .anticon': {
color: '#C01227 !important'
}
}
} }
}), }),
...(!drawerOpen && { ...(!drawerOpen && {
@@ -273,20 +287,23 @@ const NavCollapse = ({ menu, level, parentId, setSelectedItems, selectedItems, s
alignItems: 'center', alignItems: 'center',
justifyContent: 'center', justifyContent: 'center',
'&:hover': { '&:hover': {
// bgcolor: theme.palette.mode === ThemeMode.DARK ? 'secondary.light' : 'secondary.lighter' bgcolor: '#fff',
bgcolor: '#7b1fa2', '& svg': {
color: 'white' color: '#C01227 !important'
}
} }
}), }),
...(!drawerOpen && ...(!drawerOpen &&
selected === menu.id && { selected === menu.id && {
bgcolor: 'primary.light', bgcolor: 'primary.light',
color: 'primary.main', color: 'primary.main',
'&:hover': { '&:hover': {
bgcolor: '#7b1fa2', bgcolor: '#fff',
color: 'primary.main' '& svg': {
color: '#C01227 !important'
} }
}) }
})
}} }}
> >
{menuIcon} {menuIcon}

View File

@@ -1,5 +1,5 @@
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { forwardRef, useEffect, useState } from 'react'; import { forwardRef, useEffect } from 'react';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { useDispatch, useSelector } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
@@ -41,7 +41,7 @@ const NavItem = ({ item, level }) => {
const isSelected = openItem.findIndex((id) => id === item.id) > -1; const isSelected = openItem.findIndex((id) => id === item.id) > -1;
const itemIcon = item.icon ? ( const itemIcon = item.icon ? (
<Icon style={{ fontSize: drawerOpen ? '1rem' : '1.25rem', color: isSelected ? '#662582' : '#fff' }} /> <Icon style={{ fontSize: drawerOpen ? '1rem' : '1.25rem', color: isSelected ? '#C01227' : '#fff' }} />
) : ( ) : (
false false
); );
@@ -97,87 +97,96 @@ const NavItem = ({ item, level }) => {
onClick={() => { onClick={() => {
// dispatch(setSelectedMenu(item)); // dispatch(setSelectedMenu(item));
}} }}
sx={{ sx={{
zIndex: 1201, zIndex: 1201,
pl: drawerOpen ? `${level * 28}px` : 1.5, pl: drawerOpen ? `${level * 28}px` : 1.5,
py: !drawerOpen && level === 1 ? 1.25 : 1, py: !drawerOpen && level === 1 ? 1.25 : 1,
...(drawerOpen && { ...(drawerOpen && {
'&:hover': {
bgcolor: '#7b1fa2'
},
'&.Mui-selected': {
bgcolor: theme.palette.mode === ThemeMode.DARK ? 'divider' : 'primary.lighter',
borderRight: `2px solid ${theme.palette.primary.main}`,
color: iconSelectedColor,
'&:hover': { '&:hover': {
color: iconSelectedColor, bgcolor: '#fff',
bgcolor: theme.palette.mode === ThemeMode.DARK ? 'divider' : 'primary.lighter' '& .MuiTypography-root': {
} color: '#C01227 !important'
} },
}), '& svg, & .anticon': {
...(!drawerOpen && { color: '#C01227 !important'
bgcolor: '#662582',
'&:hover': {
bgcolor: '#662582'
},
'&.Mui-selected': {
'&:hover': {
bgcolor: 'transparent'
},
bgcolor: 'transparent'
}
})
}}
{...(downLG && {
onClick: () => {
dispatch(openDrawer(false));
}
})}
>
{itemIcon && (
<ListItemIcon
sx={{
minWidth: 28,
...(!drawerOpen && {
borderRadius: 1.5,
width: 36,
height: 36,
alignItems: 'center',
justifyContent: 'center',
'&:hover': {
bgcolor: '#7b1fa2'
} }
}), },
...(!drawerOpen && '&.Mui-selected': {
isSelected && { bgcolor: theme.palette.mode === ThemeMode.DARK ? 'divider' : 'primary.lighter',
borderRight: `2px solid ${theme.palette.primary.main}`,
color: iconSelectedColor,
'&:hover': {
color: iconSelectedColor,
bgcolor: theme.palette.mode === ThemeMode.DARK ? 'divider' : 'primary.lighter'
}
}
}),
...(!drawerOpen && {
bgcolor: '#C01227',
'&:hover': {
bgcolor: '#C01227'
},
'&.Mui-selected': {
'&:hover': {
bgcolor: 'transparent'
},
bgcolor: 'transparent'
}
})
}}
{...(downLG && {
onClick: () => {
dispatch(openDrawer(false));
}
})}
>
{itemIcon && (
<ListItemIcon
sx={{
minWidth: 28,
...(!drawerOpen && {
borderRadius: 1.5,
width: 36,
height: 36,
alignItems: 'center',
justifyContent: 'center',
'&:hover': {
bgcolor: '#fff',
'& svg, & .anticon': {
color: '#C01227 !important'
}
}
}),
...(!drawerOpen &&
isSelected && {
bgcolor: theme.palette.mode === ThemeMode.DARK ? 'primary.900' : 'primary.lighter', bgcolor: theme.palette.mode === ThemeMode.DARK ? 'primary.900' : 'primary.lighter',
'&:hover': { '&:hover': {
bgcolor: theme.palette.mode === ThemeMode.DARK ? 'primary.darker' : 'primary.lighter' bgcolor: theme.palette.mode === ThemeMode.DARK ? 'primary.darker' : 'primary.lighter'
} }
}) })
}} }}
> >
{itemIcon} {itemIcon}
</ListItemIcon> </ListItemIcon>
)} )}
{(drawerOpen || (!drawerOpen && level !== 1)) && ( {(drawerOpen || (!drawerOpen && level !== 1)) && (
<ListItemText <ListItemText
primary={ primary={
<Typography variant="h6" sx={{ color: isSelected ? iconSelectedColor : textColor, whiteSpace: 'nowrap' }}> <Typography variant="h6" sx={{ color: isSelected ? iconSelectedColor : textColor, whiteSpace: 'nowrap' }}>
{item.title} {item.title}
</Typography> </Typography>
} }
/> />
)} )}
{(drawerOpen || (!drawerOpen && level !== 1)) && item.chip && ( {(drawerOpen || (!drawerOpen && level !== 1)) && item.chip && (
<Chip <Chip
color={item.chip.color} color={item.chip.color}
variant={item.chip.variant} variant={item.chip.variant}
size={item.chip.size} size={item.chip.size}
label={item.chip.label} label={item.chip.label}
avatar={item.chip.avatar && <Avatar>{item.chip.avatar}</Avatar>} avatar={item.chip.avatar && <Avatar>{item.chip.avatar}</Avatar>}
/> />
)} )}
</ListItemButton> </ListItemButton>
</Tooltip> </Tooltip>
) : ( ) : (
@@ -229,11 +238,11 @@ const NavItem = ({ item, level }) => {
}), }),
...(!drawerOpen && ...(!drawerOpen &&
isSelected && { isSelected && {
bgcolor: 'transparent', bgcolor: 'transparent',
'&:hover': { '&:hover': {
bgcolor: 'transparent' bgcolor: 'transparent'
} }
}) })
}} }}
> >
{itemIcon} {itemIcon}
@@ -254,11 +263,11 @@ const NavItem = ({ item, level }) => {
}), }),
...(!drawerOpen && ...(!drawerOpen &&
isSelected && { isSelected && {
bgcolor: 'transparent', bgcolor: 'transparent',
'&:hover': { '&:hover': {
bgcolor: 'transparent' bgcolor: 'transparent'
} }
}) })
}} }}
> >
<Dot size={4} color={isSelected ? 'primary' : 'secondary'} /> <Dot size={4} color={isSelected ? 'primary' : 'secondary'} />

View File

@@ -10,8 +10,12 @@ import DrawerHeaderStyled from './DrawerHeaderStyled';
import { MenuOrientation } from 'config'; import { MenuOrientation } from 'config';
import useConfig from 'hooks/useConfig'; import useConfig from 'hooks/useConfig';
import logo from 'assets/images/logo-nearle9.png' import logo from 'assets/images/doormile-logo.png'
import logo1 from 'assets/images/logo-sm1.png' import logo1 from 'assets/images/doormile-mark.png'
// doormile-logo.png is a white asset; this recolours it to brand red (#C01227) for the light sidebar background.
const DOORMILE_RED_FILTER = 'brightness(0) saturate(100%) invert(14%) sepia(85%) saturate(4649%) hue-rotate(345deg) brightness(97%) contrast(92%)';
// ==============================|| DRAWER HEADER ||============================== // // ==============================|| DRAWER HEADER ||============================== //
const DrawerHeader = ({ open }) => { const DrawerHeader = ({ open }) => {
@@ -37,15 +41,13 @@ const DrawerHeader = ({ open }) => {
{(open) && {(open) &&
<img src={logo} <img src={logo}
// width='160px' style={{ height: '29px', width: 'auto' }}
// height='45px' alt='Doormile'/>
// width='170px'
alt='logo'/>
} }
{(!open) && {(!open) &&
<img src={logo1} <img src={logo1}
width='40px' width='50px'
alt='logo'/> alt='Doormile'/>
} }
</DrawerHeaderStyled> </DrawerHeaderStyled>
); );

View File

@@ -15,7 +15,7 @@ const openedMixin = (theme) => ({
}), }),
overflowX: 'hidden', overflowX: 'hidden',
boxShadow: theme.palette.mode === ThemeMode.DARK ? theme.customShadows.z1 : 'none', boxShadow: theme.palette.mode === ThemeMode.DARK ? theme.customShadows.z1 : 'none',
backgroundColor:'#662582', backgroundColor:'#C01227',
}); });
const closedMixin = (theme) => ({ const closedMixin = (theme) => ({
@@ -27,7 +27,7 @@ const closedMixin = (theme) => ({
width: theme.spacing(7.5), width: theme.spacing(7.5),
borderRight: 'none', borderRight: 'none',
boxShadow: theme.customShadows.z1, boxShadow: theme.customShadows.z1,
backgroundColor:'#662582', backgroundColor:'#C01227',
}); });
// ==============================|| DRAWER - MINI STYLED ||============================== // // ==============================|| DRAWER - MINI STYLED ||============================== //

View File

@@ -55,7 +55,7 @@ const MainDrawer = ({ window }) => {
borderRight: `1px solid ${theme.palette.divider}`, borderRight: `1px solid ${theme.palette.divider}`,
backgroundImage: 'none', backgroundImage: 'none',
boxShadow: 'inherit', boxShadow: 'inherit',
bgcolor:'#662582' bgcolor:'#C01227'
} }
}} }}
> >

View File

@@ -8,7 +8,6 @@ import { AppBar, Box, ClickAwayListener, Paper, Popper, Toolbar } from '@mui/mat
import Profile from './Profile'; import Profile from './Profile';
import IconButton from 'components/@extended/IconButton'; import IconButton from 'components/@extended/IconButton';
import Transitions from 'components/@extended/Transitions'; import Transitions from 'components/@extended/Transitions';
import { ThemeMode } from 'config';
// assets // assets
import { MoreOutlined } from '@ant-design/icons'; import { MoreOutlined } from '@ant-design/icons';

View File

@@ -24,7 +24,6 @@ import {
import MainCard from 'components/MainCard'; import MainCard from 'components/MainCard';
import IconButton from 'components/@extended/IconButton'; import IconButton from 'components/@extended/IconButton';
import Transitions from 'components/@extended/Transitions'; import Transitions from 'components/@extended/Transitions';
import { ThemeMode } from 'config';
// assets // assets
import { BellOutlined, CheckCircleOutlined, GiftOutlined, MessageOutlined, SettingOutlined } from '@ant-design/icons'; import { BellOutlined, CheckCircleOutlined, GiftOutlined, MessageOutlined, SettingOutlined } from '@ant-design/icons';
@@ -90,7 +89,7 @@ const Notification = () => {
// color="primary" // color="primary"
sx={{ sx={{
"& .MuiBadge-badge": { "& .MuiBadge-badge": {
color: "#662582", color: "#C01227",
backgroundColor: "white" backgroundColor: "white"
} }
}} }}

View File

@@ -13,8 +13,6 @@ import Avatar from 'components/@extended/Avatar';
import MainCard from 'components/MainCard'; import MainCard from 'components/MainCard';
import Transitions from 'components/@extended/Transitions'; import Transitions from 'components/@extended/Transitions';
import IconButton from 'components/@extended/IconButton'; import IconButton from 'components/@extended/IconButton';
import { ThemeMode } from 'config';
// import useAuth from 'hooks/useAuth'; // import useAuth from 'hooks/useAuth';
// assets // assets
@@ -83,13 +81,7 @@ const Profile = () => {
<ButtonBase <ButtonBase
sx={{ sx={{
p: 0.25, p: 0.25,
// bgcolor: open ? iconBackColorOpen : 'transparent',
borderRadius: 1 borderRadius: 1
// '&:hover': { bgcolor: theme.palette.mode === ThemeMode.DARK ? 'secondary.light' : 'secondary.lighter' },
// '&:focus-visible': {
// outline: `2px solid ${theme.palette.secondary.dark}`,
// outlineOffset: 2
// }
}} }}
aria-label="open profile" aria-label="open profile"
ref={anchorRef} ref={anchorRef}

View File

@@ -1,4 +1,4 @@
import { useMemo, useState } from 'react'; import { useState } from 'react';
// material-ui // material-ui
import { import {

View File

@@ -9,7 +9,7 @@ import AppBarStyled from './AppBarStyled';
import HeaderContent from './HeaderContent'; import HeaderContent from './HeaderContent';
import IconButton from 'components/@extended/IconButton'; import IconButton from 'components/@extended/IconButton';
import { MenuOrientation, ThemeMode } from 'config'; import { MenuOrientation } from 'config';
import useConfig from 'hooks/useConfig'; import useConfig from 'hooks/useConfig';
import { dispatch, useSelector } from 'store'; import { dispatch, useSelector } from 'store';
import { openDrawer } from 'store/reducers/menu'; import { openDrawer } from 'store/reducers/menu';
@@ -66,7 +66,7 @@ const Header = () => {
zIndex: 1200, zIndex: 1200,
width: isHorizontal ? '100%' : drawerOpen ? 'calc(100% - 260px)' : { xs: '100%', lg: 'calc(100% - 60px)' }, width: isHorizontal ? '100%' : drawerOpen ? 'calc(100% - 260px)' : { xs: '100%', lg: 'calc(100% - 60px)' },
// boxShadow: theme.customShadows.z1 // boxShadow: theme.customShadows.z1
bgcolor:'#662582' bgcolor:'#C01227'
} }
}; };

View File

@@ -59,7 +59,7 @@ const icons = {
const nearle = { const nearle = {
id: 'nearle_Pages', id: 'nearle_Pages',
title: <FormattedMessage id="Nearle" />, title: <FormattedMessage id="Doormile" />,
icon: icons.FileDoneOutlined, icon: icons.FileDoneOutlined,
type: 'group', type: 'group',
children: [ children: [

View File

@@ -1,57 +0,0 @@
import { Link } from 'react-router-dom';
// material-ui
import { useTheme } from '@mui/material/styles';
import { Box, Button, Grid, Divider, Typography, useMediaQuery } from '@mui/material';
// project import
import useAuth from 'hooks/useAuth';
import AnimateButton from 'components/@extended/AnimateButton';
import AuthWrapper from 'sections/auth/AuthWrapper';
// ================================|| CHECK MAIL ||================================ //
const CheckMail = () => {
const theme = useTheme();
const matchDownSM = useMediaQuery(theme.breakpoints.down('sm'));
const { isLoggedIn } = useAuth();
return (
<AuthWrapper>
<Grid container spacing={3}>
<Grid item xs={12}>
<Box sx={{ mb: { xs: -0.5, sm: 0.5 } }}>
<Typography variant="h3">Hi, Check Your Mail</Typography>
<Typography color="secondary" sx={{ mb: 0.5, mt: 1.25 }}>
We have sent a password recover instructions to your email.
</Typography>
</Box>
</Grid>
<Grid item xs={12}>
<AnimateButton>
<Button
component={Link}
to={isLoggedIn ? '/auth/login' : '/login'}
disableElevation
fullWidth
size="large"
type="submit"
variant="contained"
color="primary"
>
Sign in
</Button>
</AnimateButton>
</Grid>
<Grid item xs={12}>
<Divider>
<Typography variant={matchDownSM ? 'subtitle1' : 'h5'}>Sign up with</Typography>
</Divider>
</Grid>
</Grid>
</AuthWrapper>
);
};
export default CheckMail;

View File

@@ -1,29 +0,0 @@
// material-ui
import { Grid, Stack, Typography } from '@mui/material';
// project import
import AuthWrapper from 'sections/auth/AuthWrapper';
import AuthCodeVerification from 'sections/auth/auth-forms/AuthCodeVerification';
// ================================|| CODE VERIFICATION ||================================ //
const CodeVerification = () => (
<AuthWrapper>
<Grid container spacing={3}>
<Grid item xs={12}>
<Stack spacing={1}>
<Typography variant="h3">Enter Verification Code</Typography>
<Typography color="secondary">We send you on mail.</Typography>
</Stack>
</Grid>
<Grid item xs={12}>
<Typography>We`ve send you code on jone. ****@company.com</Typography>
</Grid>
<Grid item xs={12}>
<AuthCodeVerification />
</Grid>
</Grid>
</AuthWrapper>
);
export default CodeVerification;

View File

@@ -1,41 +0,0 @@
import { Link } from 'react-router-dom';
// material-ui
import { Grid, Stack, Typography } from '@mui/material';
// project import
import useAuth from 'hooks/useAuth';
import AuthWrapper from 'sections/auth/AuthWrapper';
import AuthForgotPassword from 'sections/auth/auth-forms/AuthForgotPassword';
// ================================|| FORGOT PASSWORD ||================================ //
const ForgotPassword = () => {
const { isLoggedIn } = useAuth();
return (
<AuthWrapper>
<Grid container spacing={3}>
<Grid item xs={12}>
<Stack direction="row" justifyContent="space-between" alignItems="baseline" sx={{ mb: { xs: -0.5, sm: 0.5 } }}>
<Typography variant="h3">Forgot Password</Typography>
<Typography
component={Link}
to={isLoggedIn ? '/auth/login' : '/login'}
variant="body1"
sx={{ textDecoration: 'none' }}
color="primary"
>
Back to Login
</Typography>
</Stack>
</Grid>
<Grid item xs={12}>
<AuthForgotPassword />
</Grid>
</Grid>
</AuthWrapper>
);
};
export default ForgotPassword;

View File

@@ -1,41 +0,0 @@
import { Link } from 'react-router-dom';
// material-ui
import { Grid, Stack, Typography } from '@mui/material';
// project import
import useAuth from 'hooks/useAuth';
import AuthWrapper from 'sections/auth/AuthWrapper';
import AuthLogin from 'sections/auth/auth-forms/AuthLogin';
// ================================|| LOGIN ||================================ //
const Login = () => {
const { isLoggedIn } = useAuth();
return (
<AuthWrapper>
<Grid container spacing={3}>
<Grid item xs={12}>
<Stack direction="row" justifyContent="space-between" alignItems="baseline" sx={{ mb: { xs: -0.5, sm: 0.5 } }}>
<Typography variant="h3">Login</Typography>
<Typography
component={Link}
to={isLoggedIn ? '/auth/register' : '/register'}
variant="body1"
sx={{ textDecoration: 'none' }}
color="primary"
>
Don&apos;t have an account?
</Typography>
</Stack>
</Grid>
<Grid item xs={12}>
<AuthLogin />
</Grid>
</Grid>
</AuthWrapper>
);
};
export default Login;

View File

@@ -1,41 +0,0 @@
import { Link } from 'react-router-dom';
// material-ui
import { Grid, Stack, Typography } from '@mui/material';
// project import
import useAuth from 'hooks/useAuth';
import AuthWrapper from 'sections/auth/AuthWrapper';
import FirebaseRegister from 'sections/auth/auth-forms/AuthRegister';
// ================================|| REGISTER ||================================ //
const Register = () => {
const { isLoggedIn } = useAuth();
return (
<AuthWrapper>
<Grid container spacing={3}>
<Grid item xs={12}>
<Stack direction="row" justifyContent="space-between" alignItems="baseline" sx={{ mb: { xs: -0.5, sm: 0.5 } }}>
<Typography variant="h3">Sign up</Typography>
<Typography
component={Link}
to={isLoggedIn ? '/auth/login' : '/login'}
variant="body1"
sx={{ textDecoration: 'none' }}
color="primary"
>
Already have an account?
</Typography>
</Stack>
</Grid>
<Grid item xs={12}>
<FirebaseRegister />
</Grid>
</Grid>
</AuthWrapper>
);
};
export default Register;

View File

@@ -1,26 +0,0 @@
// material-ui
import { Grid, Stack, Typography } from '@mui/material';
// project import
import AuthWrapper from 'sections/auth/AuthWrapper';
import AuthResetPassword from 'sections/auth/auth-forms/AuthResetPassword';
// ================================|| RESET PASSWORD ||================================ //
const ResetPassword = () => (
<AuthWrapper>
<Grid container spacing={3}>
<Grid item xs={12}>
<Stack sx={{ mb: { xs: -0.5, sm: 0.5 } }} spacing={1}>
<Typography variant="h3">Reset Password</Typography>
<Typography color="secondary">Please choose your new password</Typography>
</Stack>
</Grid>
<Grid item xs={12}>
<AuthResetPassword />
</Grid>
</Grid>
</AuthWrapper>
);
export default ResetPassword;

View File

@@ -1,24 +0,0 @@
import React, { useRef, useEffect } from 'react';
const CtrlK = () => {
useEffect(() => {
const handleKeyPress = (event) => {
if (event.key === 'k' && (event.metaKey || event.ctrlKey)) {
event.preventDefault();
textFieldRef.current.focus();
}
if (event.key === 'Escape' && document.activeElement === textFieldRef.current) {
textFieldRef.current.blur();
}
};
document.addEventListener('keydown', handleKeyPress);
return () => {
document.removeEventListener('keydown', handleKeyPress);
};
}, [textFieldRef]);
};
export default CtrlK;

View File

@@ -1,20 +0,0 @@
// material-ui
import { Typography } from '@mui/material';
// project import
import MainCard from 'components/MainCard';
// ==============================|| SAMPLE PAGE ||============================== //
const SamplePage = () => (
<MainCard title="Sample Card">
<Typography variant="body2">
Lorem ipsum dolor sit amen, consenter nipissing eli, sed do elusion tempos incident ut laborers et doolie magna alissa. Ut enif ad
minim venice, quin nostrum exercitation illampu laborings nisi ut liquid ex ea commons construal. Duos aube grue dolor in reprehended
in voltage veil esse colum doolie eu fujian bulla parian. Exceptive sin ocean cuspidate non president, sunk in culpa qui officiate
descent molls anim id est labours.
</Typography>
</MainCard>
);
export default SamplePage;

View File

@@ -1,45 +0,0 @@
import { Grid, useMediaQuery, useTheme } from '@mui/material';
import { useQuery } from '@tanstack/react-query';
import CircularLoader from 'components/CircularLoader';
import Loader from 'components/Loader';
import MainCard from 'components/MainCard';
import { getusers } from 'pages/api/api';
const ViewProfile = () => {
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down('md'));
const {
data: userdata,
isLoading,
isError,
error
} = useQuery({
queryKey: ['getuser'],
queryFn: getusers
});
return (
<>
{isLoading && (
<>
<Loader />
<CircularLoader />
</>
)}
<MainCard sx={{ p: { xs: 1.5, md: 3 } }}>
<Grid container spacing={isMobile ? 2 : 3}>
<Grid item xs={12} sm={6} md={4}>
{userdata?.firstname}
</Grid>
<Grid item xs={12} sm={6} md={4}>
{' '}
</Grid>
<Grid item xs={12} sm={6} md={4}>
{' '}
</Grid>
</Grid>
</MainCard>
</>
);
};
export default ViewProfile;

View File

@@ -61,7 +61,7 @@ const DT = {
divider: '#f1f5f9', divider: '#f1f5f9',
surface: '#ffffff', surface: '#ffffff',
surfaceAlt: '#f8fafc', surfaceAlt: '#f8fafc',
brand: '#662582' brand: '#C01227'
}; };
const a = (c, suffix) => `${c}${suffix}`; const a = (c, suffix) => `${c}${suffix}`;
const tint = (c) => a(c, '08'); const tint = (c) => a(c, '08');
@@ -69,7 +69,7 @@ const soft = (c) => a(c, '18');
const ring = (c) => a(c, '26'); const ring = (c) => a(c, '26');
const edge = (c) => a(c, '55'); const edge = (c) => a(c, '55');
const BRAND = '#662582'; const BRAND = '#C01227';
const SoftPaper = (props) => ( const SoftPaper = (props) => (
<Paper <Paper

View File

@@ -119,7 +119,7 @@ const pillFieldSx = (color) => ({
'& fieldset': { borderColor: '#e2e8f0', borderWidth: 1 }, '& fieldset': { borderColor: '#e2e8f0', borderWidth: 1 },
'&:hover fieldset': { borderColor: '#cbd5e1' }, '&:hover fieldset': { borderColor: '#cbd5e1' },
'&.Mui-focused': { boxShadow: `0 0 0 3px ${ring(color)}` }, '&.Mui-focused': { boxShadow: `0 0 0 3px ${ring(color)}` },
'&.Mui-focused fieldset': { borderColor: '#662582', borderWidth: 1.5 } '&.Mui-focused fieldset': { borderColor: '#C01227', borderWidth: 1.5 }
}, },
'& .MuiAutocomplete-endAdornment .MuiSvgIcon-root': { color: color } '& .MuiAutocomplete-endAdornment .MuiSvgIcon-root': { color: color }
}); });
@@ -596,7 +596,7 @@ const Clients1 = () => {
setLocoName={setLocoName} setLocoName={setLocoName}
setPage={setPage} setPage={setPage}
pill pill
accentColor="#662582" accentColor="#C01227"
icon={<MdMyLocation size={14} />} icon={<MdMyLocation size={14} />}
placeholder="Select Zone" placeholder="Select Zone"
paperComponent={SoftPaper} paperComponent={SoftPaper}
@@ -622,7 +622,7 @@ const Clients1 = () => {
title={item.label} title={item.label}
value={value ?? 0} value={value ?? 0}
icon={<Icon size={20} />} icon={<Icon size={20} />}
color={idx === 0 ? '#662582' : item.color} color={idx === 0 ? '#C01227' : item.color}
loading={summaryDataIsLoading} loading={summaryDataIsLoading}
/> />
</Box> </Box>
@@ -749,11 +749,11 @@ const Clients1 = () => {
m: 0, m: 0,
width: '100%', width: '100%',
borderRadius: 999, borderRadius: 999,
bgcolor: tint('#662582'), bgcolor: tint('#C01227'),
'& fieldset': { borderColor: edge('#662582'), borderWidth: 1.5 }, '& fieldset': { borderColor: edge('#C01227'), borderWidth: 1.5 },
'&:hover fieldset': { borderColor: '#662582' }, '&:hover fieldset': { borderColor: '#C01227' },
'&.Mui-focused fieldset': { borderColor: '#662582', borderWidth: 2 }, '&.Mui-focused fieldset': { borderColor: '#C01227', borderWidth: 2 },
'&.Mui-focused': { boxShadow: `0 0 0 3px ${ring('#662582')}` } '&.Mui-focused': { boxShadow: `0 0 0 3px ${ring('#C01227')}` }
}} }}
/> />
</Box> </Box>
@@ -780,9 +780,9 @@ const Clients1 = () => {
maxHeight: { xs: 'calc(100vh - 220px)', md: 'calc(100vh - 190px)' }, maxHeight: { xs: 'calc(100vh - 220px)', md: 'calc(100vh - 190px)' },
'&::-webkit-scrollbar': { width: '10px', height: '10px' }, '&::-webkit-scrollbar': { width: '10px', height: '10px' },
'&::-webkit-scrollbar-thumb': { '&::-webkit-scrollbar-thumb': {
backgroundColor: edge('#662582'), backgroundColor: edge('#C01227'),
borderRadius: '8px', borderRadius: '8px',
'&:hover': { backgroundColor: '#662582' } '&:hover': { backgroundColor: '#C01227' }
}, },
'&::-webkit-scrollbar-track': { backgroundColor: DT.surfaceAlt } '&::-webkit-scrollbar-track': { backgroundColor: DT.surfaceAlt }
}} }}
@@ -883,7 +883,7 @@ const Clients1 = () => {
</TableCell> </TableCell>
<TableCell> <TableCell>
<Stack direction="row" alignItems="center" spacing={1}> <Stack direction="row" alignItems="center" spacing={1}>
<AccentAvatar color="#662582" size={32}> <AccentAvatar color="#C01227" size={32}>
<MdPersonPin size={16} /> <MdPersonPin size={16} />
</AccentAvatar> </AccentAvatar>
<Stack> <Stack>
@@ -996,10 +996,10 @@ const Clients1 = () => {
<IconButton <IconButton
size="small" size="small"
sx={{ sx={{
bgcolor: openRowIndex1 === index ? '#662582' : soft('#662582'), bgcolor: openRowIndex1 === index ? '#C01227' : soft('#C01227'),
color: openRowIndex1 === index ? '#fff' : '#662582', color: openRowIndex1 === index ? '#fff' : '#C01227',
border: `1px solid ${edge('#662582')}`, border: `1px solid ${edge('#C01227')}`,
'&:hover': { bgcolor: '#662582', color: '#fff' } '&:hover': { bgcolor: '#C01227', color: '#fff' }
}} }}
onClick={() => { onClick={() => {
setSelectedCustomer(row); setSelectedCustomer(row);
@@ -1913,7 +1913,7 @@ const Clients1 = () => {
header={ header={
<Stack direction="row" alignItems="flex-start" justifyContent="space-between" spacing={1}> <Stack direction="row" alignItems="flex-start" justifyContent="space-between" spacing={1}>
<Stack direction="row" alignItems="center" spacing={1} sx={{ minWidth: 0 }}> <Stack direction="row" alignItems="center" spacing={1} sx={{ minWidth: 0 }}>
<AccentAvatar color="#662582" size={36}> <AccentAvatar color="#C01227" size={36}>
<MdPersonPin size={18} /> <MdPersonPin size={18} />
</AccentAvatar> </AccentAvatar>
<Stack sx={{ minWidth: 0 }}> <Stack sx={{ minWidth: 0 }}>
@@ -2012,10 +2012,10 @@ const Clients1 = () => {
<IconButton <IconButton
size="small" size="small"
sx={{ sx={{
bgcolor: expanded ? '#662582' : soft('#662582'), bgcolor: expanded ? '#C01227' : soft('#C01227'),
color: expanded ? '#fff' : '#662582', color: expanded ? '#fff' : '#C01227',
border: `1px solid ${edge('#662582')}`, border: `1px solid ${edge('#C01227')}`,
'&:hover': { bgcolor: '#662582', color: '#fff' } '&:hover': { bgcolor: '#C01227', color: '#fff' }
}} }}
onClick={() => { onClick={() => {
setSelectedCustomer(row); setSelectedCustomer(row);
@@ -2108,7 +2108,7 @@ const Clients1 = () => {
> >
<DialogTitle <DialogTitle
sx={{ sx={{
bgcolor: '#662582', bgcolor: '#C01227',
color: '#fff', color: '#fff',
fontSize: '20px' fontSize: '20px'
}} }}

View File

@@ -396,7 +396,7 @@ export default function Customers() {
} }
}; };
const KPI_META = [ const KPI_META = [
{ key: 'total', label: 'Total Customers', color: '#662582', icon: MdOutlineGroups, value: pageCount?.Total ?? 0 }, { key: 'total', label: 'Total Customers', color: '#C01227', icon: MdOutlineGroups, value: pageCount?.Total ?? 0 },
{ key: 'loaded', label: 'Loaded in View', color: '#0ea5e9', icon: MdOutlineHowToReg, value: rows.length }, { key: 'loaded', label: 'Loaded in View', color: '#0ea5e9', icon: MdOutlineHowToReg, value: rows.length },
{ key: 'zone', label: 'Active Zone', color: '#10b981', icon: MdOutlinePlace, value: locaName || 'All Zones' } { key: 'zone', label: 'Active Zone', color: '#10b981', icon: MdOutlinePlace, value: locaName || 'All Zones' }
]; ];
@@ -416,7 +416,7 @@ export default function Customers() {
setAppId={setAppId} setAppId={setAppId}
setLocoName={setLocoName} setLocoName={setLocoName}
pill pill
accentColor="#662582" accentColor="#C01227"
icon={<MdMyLocation size={14} />} icon={<MdMyLocation size={14} />}
placeholder="Select Zone" placeholder="Select Zone"
paperComponent={SoftPaper} paperComponent={SoftPaper}
@@ -466,7 +466,7 @@ export default function Customers() {
spacing={1.25} spacing={1.25}
> >
<Stack direction="row" alignItems="center" spacing={1.25}> <Stack direction="row" alignItems="center" spacing={1.25}>
<AccentAvatar color="#662582" size={32}> <AccentAvatar color="#C01227" size={32}>
<MdGroups size={18} /> <MdGroups size={18} />
</AccentAvatar> </AccentAvatar>
<Stack> <Stack>
@@ -491,11 +491,11 @@ export default function Customers() {
m: 0, m: 0,
width: '100%', width: '100%',
borderRadius: 999, borderRadius: 999,
bgcolor: tint('#662582'), bgcolor: tint('#C01227'),
'& fieldset': { borderColor: edge('#662582'), borderWidth: 1.5 }, '& fieldset': { borderColor: edge('#C01227'), borderWidth: 1.5 },
'&:hover fieldset': { borderColor: '#662582' }, '&:hover fieldset': { borderColor: '#C01227' },
'&.Mui-focused fieldset': { borderColor: '#662582', borderWidth: 2 }, '&.Mui-focused fieldset': { borderColor: '#C01227', borderWidth: 2 },
'&.Mui-focused': { boxShadow: `0 0 0 3px ${ring('#662582')}` } '&.Mui-focused': { boxShadow: `0 0 0 3px ${ring('#C01227')}` }
}} }}
/> />
</Box> </Box>
@@ -535,11 +535,11 @@ export default function Customers() {
rows?.map((row, index) => ( rows?.map((row, index) => (
<MobileCard <MobileCard
key={row.customerid || `${row.firstname}-${index}`} key={row.customerid || `${row.firstname}-${index}`}
accent="#662582" accent="#C01227"
header={ header={
<Stack direction="row" alignItems="center" justifyContent="space-between" spacing={1}> <Stack direction="row" alignItems="center" justifyContent="space-between" spacing={1}>
<Stack direction="row" alignItems="center" spacing={1} sx={{ minWidth: 0 }}> <Stack direction="row" alignItems="center" spacing={1} sx={{ minWidth: 0 }}>
<AccentAvatar color="#662582" size={36}> <AccentAvatar color="#C01227" size={36}>
<MdPersonPin size={18} /> <MdPersonPin size={18} />
</AccentAvatar> </AccentAvatar>
<Stack sx={{ minWidth: 0 }}> <Stack sx={{ minWidth: 0 }}>
@@ -626,9 +626,9 @@ export default function Customers() {
maxHeight: { xs: 'calc(100vh - 220px)', md: 'calc(100vh - 190px)' }, maxHeight: { xs: 'calc(100vh - 220px)', md: 'calc(100vh - 190px)' },
'&::-webkit-scrollbar': { width: 10, height: 10 }, '&::-webkit-scrollbar': { width: 10, height: 10 },
'&::-webkit-scrollbar-thumb': { '&::-webkit-scrollbar-thumb': {
backgroundColor: edge('#662582'), backgroundColor: edge('#C01227'),
borderRadius: 8, borderRadius: 8,
'&:hover': { backgroundColor: '#662582' } '&:hover': { backgroundColor: '#C01227' }
}, },
'&::-webkit-scrollbar-track': { backgroundColor: DT.surfaceAlt } '&::-webkit-scrollbar-track': { backgroundColor: DT.surfaceAlt }
}} }}
@@ -700,7 +700,7 @@ export default function Customers() {
</TableCell> </TableCell>
<TableCell> <TableCell>
<Stack direction="row" alignItems="center" spacing={1}> <Stack direction="row" alignItems="center" spacing={1}>
<AccentAvatar color="#662582" size={36}> <AccentAvatar color="#C01227" size={36}>
<MdPersonPin size={18} /> <MdPersonPin size={18} />
</AccentAvatar> </AccentAvatar>
<Stack> <Stack>
@@ -829,7 +829,7 @@ export default function Customers() {
<DialogTitle <DialogTitle
id="alert-dialog-title" id="alert-dialog-title"
sx={{ sx={{
background: `linear-gradient(135deg, #662582 0%, #9255AB 100%)`, background: `linear-gradient(135deg, #C01227 0%, #D35968 100%)`,
color: '#fff', color: '#fff',
py: 2 py: 2
}} }}

View File

@@ -1,9 +0,0 @@
const Dashboard = () => {
return (
<>
<h1>Dashboard</h1>
</>
);
};
export default Dashboard;

View File

@@ -126,7 +126,7 @@ const DT = {
divider: '#f1f5f9', divider: '#f1f5f9',
surface: '#ffffff', surface: '#ffffff',
surfaceAlt: '#f8fafc', surfaceAlt: '#f8fafc',
brand: '#662582' brand: '#C01227'
}; };
// Quick alpha helpers (hex + percentage suffix). Mirrors the batch-dropdown // Quick alpha helpers (hex + percentage suffix). Mirrors the batch-dropdown
@@ -912,7 +912,7 @@ const Deliveries = () => {
setLocoName={setLocoName} setLocoName={setLocoName}
setPage={setPage} setPage={setPage}
pill pill
accentColor="#662582" accentColor="#C01227"
icon={<MdMyLocation size={14} />} icon={<MdMyLocation size={14} />}
placeholder="Select Zone" placeholder="Select Zone"
paperComponent={SoftPaper} paperComponent={SoftPaper}
@@ -962,7 +962,7 @@ const Deliveries = () => {
}} }}
> >
<Stack direction="row" alignItems="center" spacing={1} sx={{ mb: { xs: 1, md: 1.5 }, color: DT.textSecondary }}> <Stack direction="row" alignItems="center" spacing={1} sx={{ mb: { xs: 1, md: 1.5 }, color: DT.textSecondary }}>
<Avatar sx={{ width: 28, height: 28, bgcolor: soft('#662582'), color: '#662582' }}> <Avatar sx={{ width: 28, height: 28, bgcolor: soft('#C01227'), color: '#C01227' }}>
<MdTune size={16} /> <MdTune size={16} />
</Avatar> </Avatar>
<Typography variant="caption" sx={{ fontWeight: 800, letterSpacing: 0.6, textTransform: 'uppercase', color: DT.textSecondary }}> <Typography variant="caption" sx={{ fontWeight: 800, letterSpacing: 0.6, textTransform: 'uppercase', color: DT.textSecondary }}>
@@ -1125,8 +1125,8 @@ const Deliveries = () => {
transition: 'border-color 0.15s, box-shadow 0.15s', transition: 'border-color 0.15s, box-shadow 0.15s',
'& fieldset': { borderColor: '#e2e8f0', borderWidth: 1 }, '& fieldset': { borderColor: '#e2e8f0', borderWidth: 1 },
'&:hover fieldset': { borderColor: '#cbd5e1' }, '&:hover fieldset': { borderColor: '#cbd5e1' },
'&.Mui-focused': { boxShadow: `0 0 0 3px ${ring('#662582')}` }, '&.Mui-focused': { boxShadow: `0 0 0 3px ${ring('#C01227')}` },
'&.Mui-focused fieldset': { borderColor: '#662582', borderWidth: 1.5 } '&.Mui-focused fieldset': { borderColor: '#C01227', borderWidth: 1.5 }
}, },
'& .MuiAutocomplete-endAdornment .MuiSvgIcon-root': { color: '#94a3b8' } '& .MuiAutocomplete-endAdornment .MuiSvgIcon-root': { color: '#94a3b8' }
}} }}
@@ -1442,10 +1442,10 @@ const Deliveries = () => {
overflowX: 'auto', overflowX: 'auto',
'&::-webkit-scrollbar': { width: '10px', height: '10px', cursor: 'pointer' }, '&::-webkit-scrollbar': { width: '10px', height: '10px', cursor: 'pointer' },
'&::-webkit-scrollbar-thumb': { '&::-webkit-scrollbar-thumb': {
backgroundColor: edge('#662582'), backgroundColor: edge('#C01227'),
borderRadius: '8px', borderRadius: '8px',
cursor: 'pointer', cursor: 'pointer',
'&:hover': { backgroundColor: '#662582' } '&:hover': { backgroundColor: '#C01227' }
}, },
'&::-webkit-scrollbar-track': { backgroundColor: DT.surfaceAlt } '&::-webkit-scrollbar-track': { backgroundColor: DT.surfaceAlt }
}} }}
@@ -1562,7 +1562,7 @@ const Deliveries = () => {
<IconButton <IconButton
size="small" size="small"
onClick={(e) => handleMenuOpen(e, row)} onClick={(e) => handleMenuOpen(e, row)}
sx={{ borderRadius: 999, bgcolor: tint('#662582'), color: '#662582', border: `1px solid ${edge('#662582')}`, '&:hover': { bgcolor: soft('#662582') } }} sx={{ borderRadius: 999, bgcolor: tint('#C01227'), color: '#C01227', border: `1px solid ${edge('#C01227')}`, '&:hover': { bgcolor: soft('#C01227') } }}
> >
<EditOutlined /> <EditOutlined />
</IconButton> </IconButton>
@@ -1650,7 +1650,7 @@ const Deliveries = () => {
</MobileField> </MobileField>
<MobileField label="Step"> <MobileField label="Step">
{row.step ? ( {row.step ? (
<Box sx={{ ...chipSx('#662582'), minWidth: 30, fontWeight: 800 }}>{row.step}</Box> <Box sx={{ ...chipSx('#C01227'), minWidth: 30, fontWeight: 800 }}>{row.step}</Box>
) : ( ) : (
<Typography variant="caption" sx={{ color: DT.textMuted }}></Typography> <Typography variant="caption" sx={{ color: DT.textMuted }}></Typography>
)} )}
@@ -1664,8 +1664,8 @@ const Deliveries = () => {
{isOpen && ( {isOpen && (
<Box sx={{ mt: 1.5, p: 1.25, borderRadius: 2, bgcolor: DT.surfaceAlt, border: `1px solid ${DT.divider}` }}> <Box sx={{ mt: 1.5, p: 1.25, borderRadius: 2, bgcolor: DT.surfaceAlt, border: `1px solid ${DT.divider}` }}>
<Stack direction="row" alignItems="center" spacing={1} sx={{ mb: 1 }}> <Stack direction="row" alignItems="center" spacing={1} sx={{ mb: 1 }}>
<AccentAvatar color="#662582" size={22}><MdInventory2 size={12} /></AccentAvatar> <AccentAvatar color="#C01227" size={22}><MdInventory2 size={12} /></AccentAvatar>
<Typography variant="caption" sx={{ fontWeight: 800, letterSpacing: 0.5, textTransform: 'uppercase', color: '#662582' }}> <Typography variant="caption" sx={{ fontWeight: 800, letterSpacing: 0.5, textTransform: 'uppercase', color: '#C01227' }}>
Product Details Product Details
</Typography> </Typography>
</Stack> </Stack>
@@ -2065,9 +2065,9 @@ const Deliveries = () => {
height: 24, height: 24,
px: 0.875, px: 0.875,
borderRadius: 999, borderRadius: 999,
bgcolor: tint('#662582'), bgcolor: tint('#C01227'),
border: `1px solid ${edge('#662582')}`, border: `1px solid ${edge('#C01227')}`,
color: '#662582', color: '#C01227',
fontWeight: 800, fontWeight: 800,
fontSize: 11 fontSize: 11
}} }}
@@ -2133,10 +2133,10 @@ const Deliveries = () => {
onClick={(e) => handleMenuOpen(e, row)} onClick={(e) => handleMenuOpen(e, row)}
sx={{ sx={{
borderRadius: 999, borderRadius: 999,
bgcolor: tint('#662582'), bgcolor: tint('#C01227'),
color: '#662582', color: '#C01227',
border: `1px solid ${edge('#662582')}`, border: `1px solid ${edge('#C01227')}`,
'&:hover': { bgcolor: soft('#662582') } '&:hover': { bgcolor: soft('#C01227') }
}} }}
> >
<EditOutlined /> <EditOutlined />
@@ -2168,9 +2168,9 @@ const Deliveries = () => {
background: '#fff' background: '#fff'
}} }}
> >
<Stack direction="row" alignItems="center" spacing={1} sx={{ px: 2, py: 1.25, borderBottom: `1px solid ${DT.divider}`, bgcolor: tint('#662582') }}> <Stack direction="row" alignItems="center" spacing={1} sx={{ px: 2, py: 1.25, borderBottom: `1px solid ${DT.divider}`, bgcolor: tint('#C01227') }}>
<AccentAvatar color="#662582"><MdInventory2 size={14} /></AccentAvatar> <AccentAvatar color="#C01227"><MdInventory2 size={14} /></AccentAvatar>
<Typography variant="caption" sx={{ fontWeight: 800, letterSpacing: 0.5, textTransform: 'uppercase', color: '#662582' }}> <Typography variant="caption" sx={{ fontWeight: 800, letterSpacing: 0.5, textTransform: 'uppercase', color: '#C01227' }}>
Product Details Product Details
</Typography> </Typography>
</Stack> </Stack>
@@ -2778,14 +2778,14 @@ const Deliveries = () => {
borderRadius: 2, borderRadius: 2,
bgcolor: '#fff', bgcolor: '#fff',
'& fieldset': { borderColor: DT.borderSubtle }, '& fieldset': { borderColor: DT.borderSubtle },
'&:hover fieldset': { borderColor: '#662582' }, '&:hover fieldset': { borderColor: '#C01227' },
'&.Mui-focused fieldset': { borderColor: '#662582', borderWidth: 2 }, '&.Mui-focused fieldset': { borderColor: '#C01227', borderWidth: 2 },
'&.Mui-focused': { boxShadow: `0 0 0 3px ${ring('#662582')}` } '&.Mui-focused': { boxShadow: `0 0 0 3px ${ring('#C01227')}` }
} }
}} }}
> >
{['pending','accepted','started','arrived','delivered','cancelled'].map((s) => { {['pending','accepted','started','arrived','delivered','cancelled'].map((s) => {
const m = STATUS_META[s] || { label: s, color: '#662582', icon: MdHistoryToggleOff }; const m = STATUS_META[s] || { label: s, color: '#C01227', icon: MdHistoryToggleOff };
const Ic = m.icon; const Ic = m.icon;
return ( return (
<MenuItem key={s} value={s} sx={{ gap: 1 }}> <MenuItem key={s} value={s} sx={{ gap: 1 }}>
@@ -2812,9 +2812,9 @@ const Deliveries = () => {
borderRadius: 2, borderRadius: 2,
bgcolor: '#fff', bgcolor: '#fff',
'& fieldset': { borderColor: DT.borderSubtle }, '& fieldset': { borderColor: DT.borderSubtle },
'&:hover fieldset': { borderColor: '#662582' }, '&:hover fieldset': { borderColor: '#C01227' },
'&.Mui-focused fieldset': { borderColor: '#662582', borderWidth: 2 }, '&.Mui-focused fieldset': { borderColor: '#C01227', borderWidth: 2 },
'&.Mui-focused': { boxShadow: `0 0 0 3px ${ring('#662582')}` } '&.Mui-focused': { boxShadow: `0 0 0 3px ${ring('#C01227')}` }
} }
}} }}
/> />

File diff suppressed because it is too large Load Diff

View File

@@ -80,7 +80,7 @@ import logger from '../../../utils/logger';
// emerald for the actual GPS trail (signals "live / real" data). Per-step // emerald for the actual GPS trail (signals "live / real" data). Per-step
// distinction in Combined view is carried by the numbered drop pins, which // distinction in Combined view is carried by the numbered drop pins, which
// keep STEP_PALETTE so the timeline link to a specific delivery survives. // keep STEP_PALETTE so the timeline link to a specific delivery survives.
const COMBINED_PLANNED_COLOR = '#662582'; const COMBINED_PLANNED_COLOR = '#C01227';
const COMBINED_ACTUAL_COLOR = '#10b981'; const COMBINED_ACTUAL_COLOR = '#10b981';
const toNum = (v) => { const toNum = (v) => {
@@ -5729,7 +5729,7 @@ const Dispatch = ({
style={{ style={{
boxShadow: 'var(--shadow-lg)', boxShadow: 'var(--shadow-lg)',
background: compareOpen background: compareOpen
? 'linear-gradient(135deg, #662582, #9255AB)' ? 'linear-gradient(135deg, #C01227, #D35968)'
: '#fff', : '#fff',
marginLeft: 8, marginLeft: 8,
color: compareOpen ? '#fff' : undefined color: compareOpen ? '#fff' : undefined
@@ -6328,7 +6328,7 @@ const Dispatch = ({
<div className="da-section"> <div className="da-section">
<div className="da-hero-row"> <div className="da-hero-row">
<div className="da-hero-card"> <div className="da-hero-card">
<div className="da-hero-icon" style={{ background: '#6625821f', color: '#662582' }}> <div className="da-hero-icon" style={{ background: '#C012271f', color: '#C01227' }}>
<MdOutlineInventory2 /> <MdOutlineInventory2 />
</div> </div>
<div className="da-hero-value">{analysisFormatNum(fleet.total_orders)}</div> <div className="da-hero-value">{analysisFormatNum(fleet.total_orders)}</div>
@@ -6809,7 +6809,7 @@ const Dispatch = ({
<div className="da-pos-modal-title-wrap"> <div className="da-pos-modal-title-wrap">
<div <div
className="da-pos-modal-avatar" className="da-pos-modal-avatar"
style={{ background: `${riderPositionModal.color || '#662582'}22`, color: riderPositionModal.color || '#662582' }} style={{ background: `${riderPositionModal.color || '#C01227'}22`, color: riderPositionModal.color || '#C01227' }}
> >
<MdTwoWheeler /> <MdTwoWheeler />
</div> </div>

View File

@@ -72,7 +72,7 @@ const soft = (c) => a(c, '18');
const ring = (c) => a(c, '26'); const ring = (c) => a(c, '26');
const edge = (c) => a(c, '55'); const edge = (c) => a(c, '55');
const BRAND = '#662582'; const BRAND = '#C01227';
const AccentAvatar = ({ color, selected, size = 24, children }) => ( const AccentAvatar = ({ color, selected, size = 24, children }) => (
<Avatar <Avatar
@@ -396,7 +396,7 @@ const Invoice = () => {
bgcolor: '#ffffff', bgcolor: '#ffffff',
'& fieldset': { borderColor: '#e2e8f0', borderWidth: 1 }, '& fieldset': { borderColor: '#e2e8f0', borderWidth: 1 },
'&:hover fieldset': { borderColor: '#cbd5e1' }, '&:hover fieldset': { borderColor: '#cbd5e1' },
'&.Mui-focused fieldset': { borderColor: '#662582', borderWidth: 1.5 }, '&.Mui-focused fieldset': { borderColor: '#C01227', borderWidth: 1.5 },
'&.Mui-focused': { boxShadow: `0 0 0 3px ${ring(BRAND)}` } '&.Mui-focused': { boxShadow: `0 0 0 3px ${ring(BRAND)}` }
}} }}
/> />

View File

@@ -3,7 +3,10 @@ import { useLocation } from 'react-router-dom';
import { useTheme } from '@mui/material/styles'; import { useTheme } from '@mui/material/styles';
import useMediaQuery from '@mui/material/useMediaQuery'; import useMediaQuery from '@mui/material/useMediaQuery';
// import nearleLogo from '../../../assets/images/nearleLogo.png'; // import nearleLogo from '../../../assets/images/nearleLogo.png';
import logo_nearle1 from '../../../assets/images/logo-nearle1.png'; import logo_nearle1 from '../../../assets/images/doormile-logo.png';
// doormile-logo.png is a white asset; this recolours it to brand red (#C01227) for the light invoice background.
const DOORMILE_RED_FILTER = 'brightness(0) saturate(100%) invert(15%) sepia(93%) saturate(5437%) hue-rotate(346deg) brightness(81%) contrast(92%)';
import axios from 'axios'; import axios from 'axios';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import Loader from 'components/Loader'; import Loader from 'components/Loader';
@@ -191,7 +194,7 @@ const InvoicePreview = () => {
> >
<Box sx={{ pt: 0.5 }}> <Box sx={{ pt: 0.5 }}>
<Stack direction="row" spacing={2}> <Stack direction="row" spacing={2}>
<img src={logo_nearle1} style={{ width: '150px', height: '50px' }} />{' '} <img src={logo_nearle1} style={{ width: '150px', height: '20px', filter: DOORMILE_RED_FILTER }} />{' '}
</Stack> </Stack>
{/* <Typography {/* <Typography
sx={{ color: theme.palette.primary.main, py: 0.5 }} sx={{ color: theme.palette.primary.main, py: 0.5 }}

View File

@@ -8,8 +8,7 @@ import { useTheme } from '@mui/material/styles';
import axios from 'axios'; import axios from 'axios';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import Loader from 'components/Loader'; import Loader from 'components/Loader';
import logo from 'assets/images/logo-nearle1.png'; import doormileLogo from 'assets/images/doormile-logo.png';
import expressImage from 'assets/images/express.png';
import { useSelector, useDispatch } from 'react-redux'; import { useSelector, useDispatch } from 'react-redux';
import { OpenToast } from 'components/third-party/OpenToast'; import { OpenToast } from 'components/third-party/OpenToast';
import { closeGlobalToast, GlobalToast } from 'components/nearle_components/GlobalToast'; import { closeGlobalToast, GlobalToast } from 'components/nearle_components/GlobalToast';
@@ -18,6 +17,9 @@ import VisibilityOff from '@mui/icons-material/VisibilityOff';
import { setLoginUser } from 'store/reducers/loginUserSlice'; import { setLoginUser } from 'store/reducers/loginUserSlice';
import { markSessionStart } from 'utils/session'; import { markSessionStart } from 'utils/session';
// doormile-logo.png is a white asset; this recolours it to brand red (#C01227) for light surfaces.
const DOORMILE_RED_FILTER = 'brightness(0) saturate(100%) invert(15%) sepia(93%) saturate(5437%) hue-rotate(346deg) brightness(81%) contrast(92%)';
const Login = () => { const Login = () => {
const dispatch = useDispatch(); const dispatch = useDispatch();
const fcmtoken = useSelector((state) => state.fcm); const fcmtoken = useSelector((state) => state.fcm);
@@ -167,18 +169,18 @@ const Login = () => {
justifyContent: 'center', justifyContent: 'center',
color: '#fff', color: '#fff',
p: 6, p: 6,
background: 'linear-gradient(150deg, #4D1C61 0%, #662582 52%, #9255AB 100%)' background: 'linear-gradient(150deg, #900E1D 0%, #C01227 52%, #D35968 100%)'
}} }}
> >
{/* Logo at the top-left corner */} {/* Logo at the top-left corner */}
<img <img
src={expressImage} src={doormileLogo}
alt="Operate your dispatch" alt="Doormile"
style={{ style={{
position: 'absolute', position: 'absolute',
top: 48, top: 48,
left: 48, left: 48,
maxHeight: 60 maxHeight: 40
}} }}
/> />
@@ -213,7 +215,7 @@ const Login = () => {
end to end. end to end.
</Typography> </Typography>
<Typography sx={{ fontSize: 17.5, color: 'rgba(255,255,255,0.85)', mb: 4, lineHeight: 1.6 }}> <Typography sx={{ fontSize: 17.5, color: 'rgba(255,255,255,0.85)', mb: 4, lineHeight: 1.6 }}>
Orders, AI route optimisation, live rider tracking and billing all in the NearlExpress operator console. Orders, AI route optimisation, live rider tracking and billing all in the Doormile operator console.
</Typography> </Typography>
<Stack spacing={1.5} sx={{ display: 'inline-flex', textAlign: 'left' }}> <Stack spacing={1.5} sx={{ display: 'inline-flex', textAlign: 'left' }}>
@@ -255,7 +257,7 @@ const Login = () => {
> >
{/* Logo */} {/* Logo */}
<Stack alignItems="center" mb={2.5}> <Stack alignItems="center" mb={2.5}>
<img src={logo} alt="loginpagelogo" style={{ maxHeight: 48 }} /> <img src={doormileLogo} alt="Doormile" style={{ maxHeight: 40, filter: DOORMILE_RED_FILTER }} />
</Stack> </Stack>
{/* Title */} {/* Title */}
@@ -263,7 +265,7 @@ const Login = () => {
Welcome back Welcome back
</Typography> </Typography>
<Typography variant="body2" textAlign="center" sx={{ color: '#64748b', mb: 3 }}> <Typography variant="body2" textAlign="center" sx={{ color: '#64748b', mb: 3 }}>
Sign in to the NearlExpress console Sign in to the Doormile console
</Typography> </Typography>
<CardContent sx={{ p: 0 }}> <CardContent sx={{ p: 0 }}>
@@ -440,7 +442,7 @@ const Login = () => {
component={Link} component={Link}
href="https://nearle.in" href="https://nearle.in"
target="_blank" target="_blank"
sx={{ color: '#94a3b8', textDecoration: 'none', fontWeight: 600, '&:hover': { color: '#662582' } }} sx={{ color: '#94a3b8', textDecoration: 'none', fontWeight: 600, '&:hover': { color: '#C01227' } }}
> >
&copy; All rights reserved &copy; All rights reserved
</Typography> </Typography>
@@ -449,7 +451,7 @@ const Login = () => {
component={Link} component={Link}
href="https://nearle.in/terms" href="https://nearle.in/terms"
target="_blank" target="_blank"
sx={{ color: '#94a3b8', textDecoration: 'none', fontWeight: 600, '&:hover': { color: '#662582' } }} sx={{ color: '#94a3b8', textDecoration: 'none', fontWeight: 600, '&:hover': { color: '#C01227' } }}
> >
Terms and Conditions Terms and Conditions
</Typography> </Typography>
@@ -458,7 +460,7 @@ const Login = () => {
component={Link} component={Link}
href="https://nearle.in/privacy" href="https://nearle.in/privacy"
target="_blank" target="_blank"
sx={{ color: '#94a3b8', textDecoration: 'none', fontWeight: 600, '&:hover': { color: '#662582' } }} sx={{ color: '#94a3b8', textDecoration: 'none', fontWeight: 600, '&:hover': { color: '#C01227' } }}
> >
Privacy Policy Privacy Policy
</Typography> </Typography>

View File

@@ -22,7 +22,10 @@ import { useTheme } from '@mui/material/styles';
import useMediaQuery from '@mui/material/useMediaQuery'; import useMediaQuery from '@mui/material/useMediaQuery';
import AnimateButton from 'components/@extended/AnimateButton'; import AnimateButton from 'components/@extended/AnimateButton';
import logo from 'assets/images/logo-nearle1.png'; import logo from 'assets/images/doormile-logo.png';
// doormile-logo.png is a white asset; this recolours it to brand red (#C01227) for light surfaces.
const DOORMILE_RED_FILTER = 'brightness(0) saturate(100%) invert(15%) sepia(93%) saturate(5437%) hue-rotate(346deg) brightness(81%) contrast(92%)';
import axios from 'axios'; import axios from 'axios';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
@@ -228,7 +231,7 @@ const Login = () => {
// sx={{ ml: 3, mt: 3 }} // sx={{ ml: 3, mt: 3 }}
sx={{ ml: { xs: 0, md: 3 }, mt: { xs: 3, md: 1 }, textAlign: { xs: 'center', md: 'left' } }} sx={{ ml: { xs: 0, md: 3 }, mt: { xs: 3, md: 1 }, textAlign: { xs: 'center', md: 'left' } }}
> >
<img src={logo} alt="legendary" width={isMobile ? '160px' : '200px'} /> <img src={logo} alt="Doormile" width={isMobile ? '160px' : '200px'} style={{ filter: DOORMILE_RED_FILTER }} />
</Grid> </Grid>
<Grid item xs={12}> <Grid item xs={12}>
<Grid <Grid

View File

@@ -696,7 +696,7 @@
.weight-card-btn.active.weight-heavy { .weight-card-btn.active.weight-heavy {
background: rgba(99, 102, 241, 0.04) !important; background: rgba(99, 102, 241, 0.04) !important;
border-color: #662582 !important; border-color: #C01227 !important;
box-shadow: 0 6px 16px rgba(99, 102, 241, 0.15) !important; box-shadow: 0 6px 16px rgba(99, 102, 241, 0.15) !important;
} }
@@ -707,7 +707,7 @@
left: 0; left: 0;
right: 0; right: 0;
height: 3px; height: 3px;
background: #662582; background: #C01227;
} }
/* Premium Card Overrides */ /* Premium Card Overrides */

View File

@@ -159,9 +159,9 @@ const OrderMap = ({ startPoint, endPoint, appLocaLat, appLocaLng }) => {
{hasPick && <Marker position={pickCoords} icon={pickupIcon} />} {hasPick && <Marker position={pickCoords} icon={pickupIcon} />}
{hasDrop && <Marker position={dropCoords} icon={dropoffIcon} />} {hasDrop && <Marker position={dropCoords} icon={dropoffIcon} />}
{routePoints.length > 0 ? ( {routePoints.length > 0 ? (
<Polyline positions={routePoints} color="#662582" weight={4} /> <Polyline positions={routePoints} color="#C01227" weight={4} />
) : ( ) : (
hasPick && hasDrop && <Polyline positions={[pickCoords, dropCoords]} color="#662582" weight={4} /> hasPick && hasDrop && <Polyline positions={[pickCoords, dropCoords]} color="#C01227" weight={4} />
)} )}
<MapBoundsController startPoint={startPoint} endPoint={endPoint} /> <MapBoundsController startPoint={startPoint} endPoint={endPoint} />
</MapContainer> </MapContainer>
@@ -1388,7 +1388,7 @@ const Createorder1 = () => {
InputProps={{ InputProps={{
startAdornment: ( startAdornment: (
<InputAdornment position="start"> <InputAdornment position="start">
<SearchOutlined style={{ fontSize: 15, color: '#662582' }} /> <SearchOutlined style={{ fontSize: 15, color: '#C01227' }} />
</InputAdornment> </InputAdornment>
), ),
endAdornment: ( endAdornment: (
@@ -1424,7 +1424,7 @@ const Createorder1 = () => {
InputProps={{ InputProps={{
startAdornment: ( startAdornment: (
<InputAdornment position="start"> <InputAdornment position="start">
<FaLocationDot style={{ fontSize: 14, color: '#662582' }} /> <FaLocationDot style={{ fontSize: 14, color: '#C01227' }} />
</InputAdornment> </InputAdornment>
), ),
endAdornment: ( endAdornment: (
@@ -2166,7 +2166,7 @@ const Createorder1 = () => {
{/* Map Card */} {/* Map Card */}
<Card className="orders-card" sx={{ p: 1.5, display: 'flex', flexDirection: 'column' }}> <Card className="orders-card" sx={{ p: 1.5, display: 'flex', flexDirection: 'column' }}>
<Typography sx={{ fontWeight: 700, mb: 1.25, display: 'flex', alignItems: 'center', gap: 0.75, color: '#1e293b', fontSize: '14px', letterSpacing: '-0.01em' }}> <Typography sx={{ fontWeight: 700, mb: 1.25, display: 'flex', alignItems: 'center', gap: 0.75, color: '#1e293b', fontSize: '14px', letterSpacing: '-0.01em' }}>
<MyLocationIcon sx={{ color: '#662582', fontSize: 16 }} /> <MyLocationIcon sx={{ color: '#C01227', fontSize: 16 }} />
Live Route Preview Live Route Preview
</Typography> </Typography>
<div className="map-preview-wrapper"> <div className="map-preview-wrapper">
@@ -2345,7 +2345,7 @@ const Createorder1 = () => {
} }
}} }}
> >
<DialogTitle sx={{ background: 'linear-gradient(135deg, #662582 0%, #9255AB 100%)', color: 'white', py: 2.5 }}> <DialogTitle sx={{ background: 'linear-gradient(135deg, #C01227 0%, #D35968 100%)', color: 'white', py: 2.5 }}>
<Stack spacing={1.5}> <Stack spacing={1.5}>
<Typography variant="h4" sx={{ fontWeight: 600, color: 'white' }}> <Typography variant="h4" sx={{ fontWeight: 600, color: 'white' }}>
{`Select Saved Address (${pickordrop === 1 ? 'Pickup' : 'Drop'})`} {`Select Saved Address (${pickordrop === 1 ? 'Pickup' : 'Drop'})`}

View File

@@ -895,7 +895,7 @@ const Details = () => {
{stafflist.map((val, i) => { {stafflist.map((val, i) => {
const isSelected = staffarr.find((res) => res.userid == val.userid) ? true : false; const isSelected = staffarr.find((res) => res.userid == val.userid) ? true : false;
return ( return (
<MobileCard key={i} accent="#662582" selected={isSelected}> <MobileCard key={i} accent="#C01227" selected={isSelected}>
<Stack direction="row" justifyContent="space-between" alignItems="flex-start" spacing={1}> <Stack direction="row" justifyContent="space-between" alignItems="flex-start" spacing={1}>
<Stack direction="row" alignItems="center" spacing={1}> <Stack direction="row" alignItems="center" spacing={1}>
<Avatar alt="" src={''} sx={{ width: 32, height: 32 }} /> <Avatar alt="" src={''} sx={{ width: 32, height: 32 }} />
@@ -1549,14 +1549,14 @@ const Details = () => {
{isMobile ? ( {isMobile ? (
<MobileCardList> <MobileCardList>
{val5.orderdetails.length === 0 && ( {val5.orderdetails.length === 0 && (
<MobileCard accent="#662582"> <MobileCard accent="#C01227">
<Skeleton animation="wave" /> <Skeleton animation="wave" />
<Skeleton animation="wave" /> <Skeleton animation="wave" />
<Skeleton animation="wave" /> <Skeleton animation="wave" />
</MobileCard> </MobileCard>
)} )}
{val5.orderdetails.map((row, i) => ( {val5.orderdetails.map((row, i) => (
<MobileCard key={i + 1} accent="#662582" sx={{ opacity: row.status == 0 ? '' : '0.7' }}> <MobileCard key={i + 1} accent="#C01227" sx={{ opacity: row.status == 0 ? '' : '0.7' }}>
<Stack direction="row" justifyContent="space-between" alignItems="flex-start" spacing={1}> <Stack direction="row" justifyContent="space-between" alignItems="flex-start" spacing={1}>
<Stack direction="column"> <Stack direction="column">
<Typography sx={{ fontSize: 10, fontWeight: 800, color: '#94a3b8' }}>#{i + 1}</Typography> <Typography sx={{ fontSize: 10, fontWeight: 800, color: '#94a3b8' }}>#{i + 1}</Typography>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,741 +0,0 @@
import {
Autocomplete,
Button,
Chip,
Divider,
Grid,
Stack,
Table,
TableBody,
TableCell,
TableContainer,
TableHead,
TableRow,
TextField,
Tooltip,
Typography,
Backdrop,
IconButton,
Badge,
Accordion,
AccordionSummary,
AccordionActions,
AccordionDetails,
useMediaQuery
} from '@mui/material';
import React, { Fragment, useEffect, useMemo, useState } from 'react';
import { useTheme } from '@mui/material/styles';
import { MobileCard, MobileCardList, MobileField, MobileFieldGrid } from 'components/nearle_components/MobileCard';
import { useLocation, useNavigate } from 'react-router-dom';
import dayjs from 'dayjs';
import MainCard from 'components/MainCard';
import ArrowBackIcon from '@mui/icons-material/ArrowBack';
import { createAutomationDeliveries, fetchPaymentType, fetchRidersList, finalCreatedeliveries, notifyRider } from 'pages/api/api';
import { OpenToast } from 'components/third-party/OpenToast';
import { useMutation, useQuery } from '@tanstack/react-query';
import Loader from 'components/Loader';
import CircularLoader from 'components/CircularLoader';
import { Empty } from 'antd';
import HoverSocialCard from 'components/cards/statistics/HoverSocialCard';
import { DashboardFilled, DashboardOutlined, OpenAIFilled } from '@ant-design/icons';
import { MdDirectionsBike } from 'react-icons/md';
import { FaMapLocationDot } from 'react-icons/fa6';
import { HiOutlineArrowLeft } from 'react-icons/hi';
import { IoReload } from 'react-icons/io5';
import CheckBoxOutlineBlankIcon from '@mui/icons-material/CheckBoxOutlineBlank';
import CheckBoxIcon from '@mui/icons-material/CheckBox';
import { GiProfit } from 'react-icons/gi';
import { ArrowRightAltOutlined } from '@mui/icons-material';
import LocalShippingIcon from '@mui/icons-material/LocalShipping';
import WarningIcon from '@mui/icons-material/Warning';
import BoltIcon from '@mui/icons-material/Bolt';
import CurrencyRupeeIcon from '@mui/icons-material/CurrencyRupee';
import SavingsIcon from '@mui/icons-material/Savings';
import EnergySavingsLeafIcon from '@mui/icons-material/EnergySavingsLeaf';
import DirectionsBikeOutlinedIcon from '@mui/icons-material/DirectionsBikeOutlined';
import DownloadOutlinedIcon from '@mui/icons-material/DownloadOutlined';
import { exportToExcel } from 'components/exportToExcel';
import CSVExport from 'components/third-party/ReactTable';
var utc = require('dayjs/plugin/utc');
dayjs.extend(utc);
const OptimisedOrderPreview = () => {
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down('md'));
const navigate = useNavigate();
const location = useLocation();
console.log('location.state', location.state);
const [rider, setRider] = useState(null);
const [payment, setPayment] = useState(null);
const [finaldeliveryList, setFinalDeliveryList] = useState([]);
const [isLoading, setIsLoading] = useState(false);
const [deliverylist, setDeliverylist] = useState(location.state?.deliverylist);
const [zoneData, setZoneData] = useState(location?.state?.zoneData);
const [metaData, setMetaData] = useState(location.state?.metaData);
const riderToken = location.state?.riderToken;
const appId = location.state?.appId;
const aiMode = location.state?.aiMode;
const reassignOrders = location.state?.reassignOrders;
const [csvExportData, setCsvExportData] = useState([]);
useEffect(() => {
console.log('called');
console.log('aiMode', aiMode);
console.log('riderToken', riderToken);
console.log('zoneData', zoneData);
console.log('metaData', metaData);
console.log('reassignOrders', reassignOrders);
}, [zoneData, metaData, deliverylist]);
useEffect(() => {
const filtered = finaldeliveryList.map((item) => ({
zone_name: item.zone_name,
ordernotes: item.ordernotes,
rider: item.rider,
step: item.step,
ordertype: item.ordertype,
orderamount: item.orderamount,
riderkms: item.riderkms,
cumulativekms: item.cumulativekms,
baseprice: item.baseprice,
minkm: item.minkm,
priceperkm: item.priceperkm,
kms: item.kms,
actualkms: item.actualkms,
rider_charge: item.rider_charge,
deliveryamt: item.deliveryamt,
deliverycharges: item.deliverycharges,
profit: item.profit
}));
setCsvExportData(filtered);
console.log('csvExportData', filtered);
}, [finaldeliveryList]);
useEffect(() => {
if (!deliverylist?.length) return;
const updateDeliveryAmtList = deliverylist.map((list) => {
const cumulativeKms = Number(list.cumulativekms || 0);
const minKm = Number(list.minkm || 0);
const basePrice = Number(list.baseprice || 0);
const pricePerKm = Number(list.priceperkm || 0);
if (cumulativeKms <= minKm) {
return {
...list,
deliveryamt: basePrice
};
}
return {
...list,
deliveryamt: (cumulativeKms - minKm) * pricePerKm + basePrice
};
});
setFinalDeliveryList(updateDeliveryAmtList);
console.log('finaldeliveryList', updateDeliveryAmtList);
}, [deliverylist]);
// ==============================|| fetchPaymentType ||============================== //
const {
data: paymentModes = [],
isLoading: paymentModesLoading,
isError: paymentModesError,
error: paymentModesErrorMessage
} = useQuery({
queryKey: ['paymentmodes'],
queryFn: fetchPaymentType
});
// ==============================|| fetchRidersList ||============================== //
const {
data: ridersList = [],
isLoading: ridersListLoading,
isError: ridersListError,
error: ridersListErrorMessage,
refetch: ridersListRefetch
} = useQuery({
queryKey: ['ridersList', appId], // Unique key for caching & re-fetching
queryFn: fetchRidersList,
enabled: appId !== 0 // Ensures query runs only when appId is valid
});
const getRiderName = async (userid) => {
await ridersList.map((rider) => {
if (rider.userid == userid) {
return rider.firstname;
}
});
};
// ======================================================= || notifyRiderMutation || =======================================================
const notifyRiderMutation = useMutation({
mutationFn: notifyRider, // Using the separate function
onSuccess: () => {
OpenToast('Notification sent Successfully', 'success', 2000);
},
onError: (error) => {
OpenToast(error.message, 'error', 2000);
}
});
const createFinalDeliveryMutation = useMutation({
mutationFn: finalCreatedeliveries, // for optimised delivery create
onSuccess: (data, variables) => {
console.log('data', data);
console.log('varialbles', variables);
notifyRiderMutation.mutate(rider.userfcmtoken || riderToken); // Call notifyRider after success
if (data.status == 'accepted') {
OpenToast('Delivery Created Successfully', 'success', 2000);
}
},
onError: (error) => {
OpenToast(error.message, 'error', 4000);
},
onSettled: () => {
setTimeout(() => {
setIsLoading(false);
navigate('/nearle/deliveries');
}, 2000);
}
});
const handleFinalCreateDelivery = async () => {
// console.log('Final delivery list:', finaldeliveryList);
setIsLoading(true);
createFinalDeliveryMutation.mutate({
deliveries: finaldeliveryList
});
};
const createDeliveryMutation = useMutation({
// 0 -> manual rider assign 1 -> ai rider assign
mutationFn: createAutomationDeliveries,
onSuccess: (data, variables) => {
console.log('data', data);
console.log('varialbles', variables);
OpenToast('Orders Optimised Successfully', 'success', 2000);
// notifyRiderMutation.mutate(variables?.riderToken); // Call notifyRider after success
setZoneData(data?.zones);
setDeliverylist(data?.details);
setMetaData(data?.meta);
setIsLoading(false);
},
onError: (error) => {
OpenToast(error.message, 'error', 4000);
setIsLoading(false);
},
onSettled: () => {
setIsLoading(false);
}
});
const tuningTypes = [
{
tuneid: 1,
type: 'Rider'
},
{
tuneid: 2,
type: 'Pickup'
},
{
tuneid: 3,
type: 'Zone'
}
];
return (
<Fragment>
{
<Backdrop
sx={{
color: '#fff',
zIndex: (theme) => theme.zIndex.drawer + 1
}}
open={paymentModesLoading || ridersListLoading || isLoading} // when loader = true, backdrop covers the page
>
<CircularLoader color="inherit" />
</Backdrop>
}
{(paymentModesLoading || ridersListLoading || isLoading) && (
<>
<Loader />
<CircularLoader />
</>
)}
<Stack
direction={{ xs: 'column', md: 'row' }}
alignItems={{ xs: 'stretch', md: 'center' }}
justifyContent="space-between"
spacing={{ xs: 1.5, md: 0 }}
sx={{}}
>
<Stack direction="row" alignItems="center" spacing={1}>
<Tooltip title="Back to orders" placement="top">
<IconButton
onClick={() => navigate('/nearle/orders')}
sx={{
bgcolor: 'action.hover',
'&:hover': { bgcolor: 'action.selected' }
}}
>
<HiOutlineArrowLeft size={20} />
</IconButton>
</Tooltip>
<Typography variant="h3" fontWeight={600}>
Assign Orders
</Typography>
</Stack>
{/* <Button
variant="contained"
color="primary"
startIcon={<IoReload />}
onClick={() => {
setIsLoading(true);
createDeliveryMutation.mutate({ deliveries: reassignOrders });
}}
>
Tuning
</Button> */}
<Autocomplete
multiple
id="checkboxes-tags-demo"
options={tuningTypes}
disableCloseOnSelect
getOptionLabel={(option) => option.type}
renderOption={(props, option, { selected }) => {
const { id, ...optionProps } = props;
const SelectionIcon = selected ? CheckBoxIcon : CheckBoxOutlineBlankIcon;
return (
<li key={id} {...optionProps}>
<SelectionIcon fontSize="small" style={{ marginRight: 8, padding: 9, boxSizing: 'content-box' }} />
{option.type}
</li>
);
}}
sx={{ width: { xs: '100%', md: 400 } }}
renderInput={(params) => (
<TextField
{...params}
sx={{
'& .MuiInputBase-input': {
lineHeight: '1.5' // 👈 important
}
}}
label="Hyper Tuning"
// placeholder="Favorites"
/>
)}
/>
{/* <Button
variant="outlined"
size="small"
startIcon={<DownloadOutlinedIcon />}
onClick={() => {
exportToExcel(finaldeliveryList, 'users', 'UsersData');
}}
>
Export Report
</Button> */}
<CSVExport
data={csvExportData}
filename={`Orders_Detail_${dayjs().format('YYYY-MM-DD_HHmmss')}.csv`}
label=" CSV"
style={{ m: 1 }}
/>
</Stack>
<Stack sx={{ my: 2 }}>
<Grid container spacing={2}>
<Grid item xs={6} sm={6} md={3}>
<HoverSocialCard
secondary={metaData?.total_orders}
primary={'Orders'}
percentage={<DashboardFilled />}
color={theme.palette.success.main}
sx={{ cursor: 'pointer' }}
/>
</Grid>
<Grid item xs={6} sm={6} md={3}>
<HoverSocialCard
secondary={metaData?.utilized_riders}
primary={'Riders'}
percentage={<MdDirectionsBike />}
color={theme.palette.warning.main}
/>
</Grid>
<Grid item xs={6} sm={6} md={3}>
<HoverSocialCard
secondary={zoneData?.length}
primary={'Zones'}
percentage={<FaMapLocationDot />}
color={theme.palette.info.main}
/>
</Grid>
<Grid item xs={6} sm={6} md={3}>
<HoverSocialCard
secondary={metaData?.total_profit}
primary={'Profit'}
percentage={<GiProfit />}
color={theme.palette.error.main}
/>
</Grid>
</Grid>
</Stack>
<MainCard content={false}>
{zoneData?.map((zone, index) => {
const riders = zone?.riders.flatMap((rider) => rider);
const orders = zone?.riders?.flatMap((rider) => rider.orders);
return (
<Accordion key={index}>
<AccordionSummary>
<Stack direction="row" alignItems="center" spacing={2} sx={{ m: 2 }}>
<Typography variant="h5" fontWeight={1000}>
Zone {index + 1} :
</Typography>
<Chip label={zone.zone_name} color="primary" variant="light" size="small" sx={{ minWidth: 100 }} />
<Tooltip title={`Orders`} placement="top">
<Badge badgeContent={zone.total_orders} color="secondary">
<DashboardOutlined style={{ fontSize: 20 }} />
</Badge>
</Tooltip>
<Tooltip title={`Riders`} placement="top">
<Badge color="secondary" badgeContent={zone.active_riders_count}>
<DirectionsBikeOutlinedIcon style={{ fontSize: 20 }} />
</Badge>
</Tooltip>
</Stack>
</AccordionSummary>
<AccordionDetails sx={{ p: { xs: 0, md: 1 } }}>
{isMobile ? (
<MobileCardList>
{orders.map((val, i) => {
const typeAccent =
val.ordertype === 'Economy' ? '#10b981' : val.ordertype === 'Risky' ? '#ef4444' : '#662582';
return (
<MobileCard key={i} accent={typeAccent}>
<Stack direction="row" alignItems="center" justifyContent="space-between" spacing={1}>
<Stack direction="row" alignItems="center" spacing={1} sx={{ minWidth: 0 }}>
<Chip size="small" label={`#${i + 1}`} variant="light" color="primary" />
<Typography variant="subtitle2" noWrap sx={{ minWidth: 0 }}>
{`${val.locationname}-(${val.locationsuburb})`}
</Typography>
</Stack>
<Chip
size="small"
label={val.ordertype}
icon={
val.ordertype === 'Economy' ? (
<EnergySavingsLeafIcon />
) : val.ordertype === 'Risky' ? (
<WarningIcon />
) : (
<BoltIcon />
)
}
color={val.ordertype === 'Economy' ? 'success' : val.ordertype === 'Risky' ? 'error' : 'primary'}
variant="light"
/>
</Stack>
<MobileFieldGrid>
<MobileField label="Order Id" value={val.orderid} />
<MobileField label="Rider">
<Typography sx={{ fontSize: 13, fontWeight: 600 }} noWrap>
{val.rider}
</Typography>
<Typography variant="caption">ID : {val.userid}</Typography>
</MobileField>
<MobileField label="Pickup">
<Stack spacing={0.25} sx={{ minWidth: 0 }}>
<Typography variant="caption" noWrap>
{val.pickupcustomer}
</Typography>
<Typography variant="caption" noWrap>
{val.pickupcontactno}
</Typography>
<Tooltip title={val.pickupaddress}>
<Typography variant="caption" noWrap sx={{ cursor: 'pointer' }}>
{val.pickupsuburb || val.pickupaddress.slice(0, 20)}
</Typography>
</Tooltip>
<Chip
size="small"
label={dayjs(val.pickupslot).format('DD/MM/YYYY hh:mm A')}
variant="light"
sx={{ color: '#0a803b', bgcolor: '#c3f3c7', alignSelf: 'flex-start' }}
/>
</Stack>
</MobileField>
<MobileField label="Delivery">
<Stack spacing={0.25} sx={{ minWidth: 0 }}>
<Typography variant="caption" noWrap>
{val.deliverycustomer}
</Typography>
<Typography variant="caption" noWrap>
{val.deliverycontactno}
</Typography>
<Tooltip title={val.deliveryaddress}>
<Typography variant="caption" noWrap sx={{ cursor: 'pointer' }}>
{val.deliverysuburb || val.deliveryaddress.slice(0, 20)}
</Typography>
</Tooltip>
<Chip
size="small"
label={dayjs(val.expecteddeliverytime).format('DD/MM/YYYY hh:mm A')}
variant="light"
sx={{ color: '#DD2C00', background: '#FBE9E7', alignSelf: 'flex-start' }}
/>
</Stack>
</MobileField>
{val.ordernotes ? <MobileField full label="Notes" value={val.ordernotes} /> : null}
<MobileField label="Profit">
<Chip
size="small"
label={`${parseFloat(val?.profit).toFixed(2)}`}
variant="light"
sx={{ color: '#009688', bgcolor: '#b2dfdb' }}
/>
</MobileField>
<MobileField label="Charges">
<Chip
size="small"
label={`${val.deliverycharge.toFixed(2)} `}
variant="light"
sx={{ color: '#0074e7', bgcolor: '#cce3fa' }}
/>
</MobileField>
<MobileField label="KMS">
<Chip size="small" label={`${val.kms} km`} color="error" variant="light" />
</MobileField>
<MobileField label="Cumulative KMS">
<Chip size="small" label={`${val.cumulativekms} km`} color="success" variant="light" />
</MobileField>
</MobileFieldGrid>
</MobileCard>
);
})}
</MobileCardList>
) : (
<TableContainer sx={{ p: 0, m: 0 }}>
<Table stickyHeader>
<TableHead>
<TableRow>
<TableCell>#</TableCell>
{/* <TableCell>Tenant</TableCell> */}
<TableCell>Order Location</TableCell>
<TableCell>Pickup</TableCell>
<TableCell>Delivery</TableCell>
<TableCell>Notes</TableCell>
<TableCell>Rider</TableCell>
<TableCell align="center">Type</TableCell>
<TableCell align="center">Profit</TableCell>
<TableCell align="center">Charges</TableCell>
<TableCell align="center">KMS</TableCell>
</TableRow>
</TableHead>
<TableBody>
{orders.map((val, i) => (
<Fragment key={i}>
<TableRow sx={{}}>
<TableCell>
<Typography> {i + 1}</Typography>
</TableCell>
{/* <TableCell>
<Tooltip title={val.tenantaddress}>
<Typography variant="body1" noWrap>
{val.tenantname}
</Typography>
<Typography noWrap sx={{ fontSize: '11px' }}>
{val.tenantsuburb}
<br />
</Typography>
<Typography noWrap variant="body2">
{val.applocation}
</Typography>
</Tooltip>
</TableCell> */}
<TableCell align="left">
<Tooltip title={val.locationaddress} placement="top">
<Typography variant="body1" noWrap>
{`${val.locationname}-(${val.locationsuburb})`}
</Typography>
</Tooltip>
<Tooltip title="Order Id">
<Typography variant="body2" noWrap>
{val.orderid}
</Typography>
</Tooltip>
<Stack display={'flex'} flexDirection={'row'} gap={3} sx={{ cursor: 'pointer' }}>
<Tooltip title="Pickup Time">
<Typography noWrap sx={{ fontSize: '12px' }}>
{dayjs(val.pickupslot).format('DD/MM/YYYY')}
</Typography>
<Chip
size="small"
label={dayjs(val.pickupslot).format('hh:mm A')}
variant="light"
sx={{ color: '#0a803b', bgcolor: '#c3f3c7' }}
/>
</Tooltip>
<ArrowRightAltOutlined />
<Tooltip title="Estimated Delivery time">
<Typography noWrap sx={{ fontSize: '12px' }}>
{dayjs(val.expecteddeliverytime).format('DD/MM/YYYY')}
</Typography>
<Chip
size="small"
label={dayjs(val.expecteddeliverytime).format('hh:mm A')}
variant="light"
sx={{ color: '#DD2C00', background: '#FBE9E7' }}
/>
</Tooltip>
</Stack>
</TableCell>
<TableCell align="left">
<Stack direction={'row'} spacing={1}>
<Stack direction="column">
<Typography variant="caption">{val.pickupcustomer}</Typography>
<Typography variant="caption">{val.pickupcontactno}</Typography>
<Tooltip title={val.pickupaddress}>
<Typography sx={{ cursor: 'pointer' }} variant="caption">
{val.pickupsuburb || val.pickupaddress.slice(0, 20)}
</Typography>
</Tooltip>
</Stack>
</Stack>
</TableCell>
<TableCell align="left">
<Stack direction={'row'} spacing={1}>
<Stack direction="column">
<Typography variant="caption">{val.deliverycustomer}</Typography>
<Typography variant="caption">{val.deliverycontactno}</Typography>
<Tooltip title={val.deliveryaddress}>
<Typography sx={{ cursor: 'pointer' }} variant="caption">
{val.deliverysuburb || val.deliveryaddress.slice(0, 20)}
</Typography>
</Tooltip>
</Stack>
</Stack>
</TableCell>
<TableCell align="left">
<Typography variant="caption" sx={{ whiteSpace: 'nowrap' }}>
{val.ordernotes}
</Typography>
</TableCell>
<TableCell align="left">
<Typography variant="caption" sx={{ whiteSpace: 'nowrap' }}>
{val.rider}
</Typography>
<br />
<Typography variant="caption">ID : {val.userid}</Typography>
</TableCell>
<TableCell align="center">
<Chip
size="small"
label={val.ordertype}
icon={
val.ordertype === 'Economy' ? (
<EnergySavingsLeafIcon />
) : val.ordertype === 'Risky' ? (
<WarningIcon />
) : (
<BoltIcon />
)
}
color={val.ordertype === 'Economy' ? 'success' : val.ordertype === 'Risky' ? 'error' : 'primary'}
variant="light"
/>
</TableCell>
<TableCell align="center">
<Chip
size="small"
label={`${parseFloat(val?.profit).toFixed(2)}`}
variant="light"
sx={{ color: '#009688', bgcolor: '#b2dfdb' }}
/>
</TableCell>
<TableCell align="center">
<Stack display={'flex'} flexDirection={'column'} gap={1} sx={{ cursor: 'pointer' }}>
<Tooltip title="Charges" placement="top">
<Chip
size="small"
label={`${val.deliverycharge.toFixed(2)} `}
variant="light"
sx={{ color: '#0074e7', bgcolor: '#cce3fa' }}
/>
</Tooltip>
{/* <Tooltip title="Amount" placement="left">
<Chip size="small" label={`₹ ${val.deliveryamt.toFixed(2)} `} color="success" variant="light" />
</Tooltip> */}
</Stack>
</TableCell>
<TableCell align="center">
<Stack display={'flex'} flexDirection={'column'} gap={1} sx={{ cursor: 'pointer' }}>
<Tooltip title="KMS" placement="top">
<Chip size="small" label={`${val.kms} km`} color="error" variant="light" />
</Tooltip>
<Tooltip title="Cumulative Kms" placement="right">
<Chip size="small" label={`${val.cumulativekms} km`} color="success" variant="light" />
</Tooltip>
</Stack>
</TableCell>
</TableRow>
</Fragment>
))}
</TableBody>
</Table>
</TableContainer>
)}
</AccordionDetails>
</Accordion>
);
})}
<Divider />
<Stack
display={'flex'}
flexDirection={{ xs: 'column', sm: 'row' }}
gap={2}
alignItems={{ xs: 'stretch', sm: 'center' }}
justifyContent={'end'}
sx={{ p: 2 }}
>
<Button
sx={{ width: { xs: '100%', sm: 'auto' } }}
variant="contained"
color="secondary"
startIcon={<ArrowBackIcon />}
onClick={() => {
navigate('/nearle/orders');
}}
>
Back
</Button>
<Button
sx={{ my: { xs: 0, sm: 2 }, width: { xs: '100%', sm: 'auto' } }}
variant="contained"
disabled={aiMode === 0 && (!rider || !payment)}
onClick={handleFinalCreateDelivery}
>
Assign Orders
</Button>
</Stack>
</MainCard>
</Fragment>
);
};
export default OptimisedOrderPreview;

View File

@@ -144,7 +144,7 @@ const dtSoft = (c) => dtA(c, '18');
const dtRing = (c) => dtA(c, '26'); const dtRing = (c) => dtA(c, '26');
const dtEdge = (c) => dtA(c, '55'); const dtEdge = (c) => dtA(c, '55');
const BRAND = '#662582'; const BRAND = '#C01227';
const SoftPaper = (props) => ( const SoftPaper = (props) => (
<Paper <Paper
@@ -181,8 +181,8 @@ const pillFieldSx = () => ({
fontWeight: 600, fontWeight: 600,
'& fieldset': { borderColor: '#e2e8f0', borderWidth: 1 }, '& fieldset': { borderColor: '#e2e8f0', borderWidth: 1 },
'&:hover fieldset': { borderColor: '#cbd5e1' }, '&:hover fieldset': { borderColor: '#cbd5e1' },
'&.Mui-focused': { boxShadow: `0 0 0 3px ${dtRing('#662582')}` }, '&.Mui-focused': { boxShadow: `0 0 0 3px ${dtRing('#C01227')}` },
'&.Mui-focused fieldset': { borderColor: '#662582', borderWidth: 1.5 } '&.Mui-focused fieldset': { borderColor: '#C01227', borderWidth: 1.5 }
} }
}); });
@@ -967,7 +967,7 @@ const Orders = () => {
{/* ============================================= || KPI Cards || ============================================= */} {/* ============================================= || KPI Cards || ============================================= */}
<Grid container spacing={{ xs: 2, md: 2.5 }} sx={{ mb: { xs: 1.5, md: 2 } }}> <Grid container spacing={{ xs: 2, md: 2.5 }} sx={{ mb: { xs: 1.5, md: 2 } }}>
{[ {[
{ key: 'created', label: 'Created Orders', color: '#662582', icon: MdOutlineReceiptLong, value: percentageData?.created, percentage: percentageData?.percentage1 }, { key: 'created', label: 'Created Orders', color: '#C01227', icon: MdOutlineReceiptLong, value: percentageData?.created, percentage: percentageData?.percentage1 },
{ key: 'pending', label: 'Pending Orders', color: '#f59e0b', icon: MdOutlinePendingActions, value: percentageData?.uncoveredOrders, percentage: percentageData?.percentage2 }, { key: 'pending', label: 'Pending Orders', color: '#f59e0b', icon: MdOutlinePendingActions, value: percentageData?.uncoveredOrders, percentage: percentageData?.percentage2 },
{ key: 'delivered', label: 'Delivered Orders', color: '#10b981', icon: MdOutlineCheckCircle, value: percentageData?.coveredOrders, percentage: percentageData?.percentage3 }, { key: 'delivered', label: 'Delivered Orders', color: '#10b981', icon: MdOutlineCheckCircle, value: percentageData?.coveredOrders, percentage: percentageData?.percentage3 },
{ key: 'cancelled', label: 'Cancelled Orders', color: '#ef4444', icon: MdOutlineCancel, value: percentageData?.cancelled, percentage: percentageData?.percentage4 } { key: 'cancelled', label: 'Cancelled Orders', color: '#ef4444', icon: MdOutlineCancel, value: percentageData?.cancelled, percentage: percentageData?.percentage4 }
@@ -1279,7 +1279,7 @@ const Orders = () => {
bgcolor: dtTint(BRAND), bgcolor: dtTint(BRAND),
'& fieldset': { borderColor: dtEdge(BRAND), borderWidth: 1.5 }, '& fieldset': { borderColor: dtEdge(BRAND), borderWidth: 1.5 },
'&:hover fieldset': { borderColor: '#cbd5e1' }, '&:hover fieldset': { borderColor: '#cbd5e1' },
'&.Mui-focused fieldset': { borderColor: '#662582', borderWidth: 1.5 }, '&.Mui-focused fieldset': { borderColor: '#C01227', borderWidth: 1.5 },
'&.Mui-focused': { boxShadow: `0 0 0 3px ${dtRing(BRAND)}` } '&.Mui-focused': { boxShadow: `0 0 0 3px ${dtRing(BRAND)}` }
}} }}
/> />

View File

@@ -107,7 +107,7 @@ export default function RidersRoutes({ details, loading, riderName, dateRange, o
// brand purple to match the planned-route polyline below. // brand purple to match the planned-route polyline below.
const stepIcon = (n, isFocused) => { const stepIcon = (n, isFocused) => {
const size = isFocused ? 38 : 32; const size = isFocused ? 38 : 32;
const color = isFocused ? '#4D1C61' : '#662582'; const color = isFocused ? '#900E1D' : '#C01227';
const svg = encodeURIComponent( const svg = encodeURIComponent(
`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="${size}" height="${size}">` + `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="${size}" height="${size}">` +
`<circle cx="16" cy="16" r="14" fill="${color}" stroke="white" stroke-width="3"/>` + `<circle cx="16" cy="16" r="14" fill="${color}" stroke="white" stroke-width="3"/>` +
@@ -126,7 +126,7 @@ export default function RidersRoutes({ details, loading, riderName, dateRange, o
px: 2, px: 2,
py: 1.25, py: 1.25,
borderBottom: '1px solid rgba(15, 23, 42, 0.08)', borderBottom: '1px solid rgba(15, 23, 42, 0.08)',
background: 'linear-gradient(135deg, #662582 0%, #9255AB 100%)', background: 'linear-gradient(135deg, #C01227 0%, #D35968 100%)',
color: '#fff', color: '#fff',
flexShrink: 0 flexShrink: 0
}} }}
@@ -207,12 +207,12 @@ export default function RidersRoutes({ details, loading, riderName, dateRange, o
{/* Translucent backdrop so the route stays legible on busy tiles. */} {/* Translucent backdrop so the route stays legible on busy tiles. */}
<Polyline <Polyline
path={routePath} path={routePath}
options={{ strokeColor: '#662582', strokeOpacity: 0.25, strokeWeight: 8 }} options={{ strokeColor: '#C01227', strokeOpacity: 0.25, strokeWeight: 8 }}
/> />
{/* Road-following planned route from the Directions API. */} {/* Road-following planned route from the Directions API. */}
<Polyline <Polyline
path={routePath} path={routePath}
options={{ strokeColor: '#662582', strokeOpacity: 0.95, strokeWeight: 4 }} options={{ strokeColor: '#C01227', strokeOpacity: 0.95, strokeWeight: 4 }}
/> />
</> </>
) : ( ) : (
@@ -221,7 +221,7 @@ export default function RidersRoutes({ details, loading, riderName, dateRange, o
<Polyline <Polyline
path={dropPath} path={dropPath}
options={{ options={{
strokeColor: '#662582', strokeColor: '#C01227',
strokeOpacity: 0, strokeOpacity: 0,
strokeWeight: 0, strokeWeight: 0,
icons: [ icons: [
@@ -229,7 +229,7 @@ export default function RidersRoutes({ details, loading, riderName, dateRange, o
icon: { icon: {
path: 'M 0,-1 0,1', path: 'M 0,-1 0,1',
strokeOpacity: 0.6, strokeOpacity: 0.6,
strokeColor: '#662582', strokeColor: '#C01227',
scale: 3 scale: 3
}, },
offset: '0', offset: '0',

View File

@@ -114,8 +114,8 @@ const soft = (c) => a(c, '18');
const ring = (c) => a(c, '26'); const ring = (c) => a(c, '26');
const edge = (c) => a(c, '55'); const edge = (c) => a(c, '55');
const BRAND = '#662582'; const BRAND = '#C01227';
const BRAND_LIGHT = '#9255AB'; const BRAND_LIGHT = '#D35968';
const SoftPaper = (props) => ( const SoftPaper = (props) => (
<Paper <Paper
@@ -153,7 +153,7 @@ const pillFieldSx = (color) => ({
'& fieldset': { borderColor: '#e2e8f0', borderWidth: 1 }, '& fieldset': { borderColor: '#e2e8f0', borderWidth: 1 },
'&:hover fieldset': { borderColor: '#cbd5e1' }, '&:hover fieldset': { borderColor: '#cbd5e1' },
'&.Mui-focused': { boxShadow: `0 0 0 3px ${ring(color)}` }, '&.Mui-focused': { boxShadow: `0 0 0 3px ${ring(color)}` },
'&.Mui-focused fieldset': { borderColor: '#662582', borderWidth: 1.5 } '&.Mui-focused fieldset': { borderColor: '#C01227', borderWidth: 1.5 }
} }
}); });
@@ -1172,7 +1172,7 @@ export default function OrdersDetails() {
bgcolor: '#ffffff', bgcolor: '#ffffff',
'& fieldset': { borderColor: '#e2e8f0', borderWidth: 1 }, '& fieldset': { borderColor: '#e2e8f0', borderWidth: 1 },
'&:hover fieldset': { borderColor: '#cbd5e1' }, '&:hover fieldset': { borderColor: '#cbd5e1' },
'&.Mui-focused fieldset': { borderColor: '#662582', borderWidth: 1.5 }, '&.Mui-focused fieldset': { borderColor: '#C01227', borderWidth: 1.5 },
'&.Mui-focused': { boxShadow: `0 0 0 3px ${ring(BRAND)}` } '&.Mui-focused': { boxShadow: `0 0 0 3px ${ring(BRAND)}` }
}} }}
/> />

View File

@@ -87,8 +87,8 @@ const soft = (c) => a(c, '18');
const ring = (c) => a(c, '26'); const ring = (c) => a(c, '26');
const edge = (c) => a(c, '55'); const edge = (c) => a(c, '55');
const BRAND = '#662582'; const BRAND = '#C01227';
const BRAND_LIGHT = '#9255AB'; const BRAND_LIGHT = '#D35968';
const SoftPaper = (props) => ( const SoftPaper = (props) => (
<Paper <Paper
@@ -190,7 +190,7 @@ const pillFieldSx = (color) => ({
'& fieldset': { borderColor: '#e2e8f0', borderWidth: 1 }, '& fieldset': { borderColor: '#e2e8f0', borderWidth: 1 },
'&:hover fieldset': { borderColor: '#cbd5e1' }, '&:hover fieldset': { borderColor: '#cbd5e1' },
'&.Mui-focused': { boxShadow: `0 0 0 3px ${ring(color)}` }, '&.Mui-focused': { boxShadow: `0 0 0 3px ${ring(color)}` },
'&.Mui-focused fieldset': { borderColor: '#662582', borderWidth: 1.5 } '&.Mui-focused fieldset': { borderColor: '#C01227', borderWidth: 1.5 }
} }
}); });
@@ -588,7 +588,7 @@ export default function OrdersReport() {
bgcolor: '#ffffff', bgcolor: '#ffffff',
'& fieldset': { borderColor: '#e2e8f0', borderWidth: 1 }, '& fieldset': { borderColor: '#e2e8f0', borderWidth: 1 },
'&:hover fieldset': { borderColor: '#cbd5e1' }, '&:hover fieldset': { borderColor: '#cbd5e1' },
'&.Mui-focused fieldset': { borderColor: '#662582', borderWidth: 1.5 }, '&.Mui-focused fieldset': { borderColor: '#C01227', borderWidth: 1.5 },
'&.Mui-focused': { boxShadow: `0 0 0 3px ${ring(BRAND)}` } '&.Mui-focused': { boxShadow: `0 0 0 3px ${ring(BRAND)}` }
}} }}
/> />

View File

@@ -66,7 +66,7 @@ const tint = (c) => aColor(c, '08');
const edge = (c) => aColor(c, '55'); const edge = (c) => aColor(c, '55');
const ring = (c) => aColor(c, '26'); const ring = (c) => aColor(c, '26');
const BRAND = '#662582'; const BRAND = '#C01227';
const SoftPaper = (props) => ( const SoftPaper = (props) => (
<Paper <Paper
@@ -552,7 +552,7 @@ export default function ProfitabilityReport() {
bgcolor: '#ffffff', bgcolor: '#ffffff',
'& fieldset': { borderColor: '#e2e8f0', borderWidth: 1 }, '& fieldset': { borderColor: '#e2e8f0', borderWidth: 1 },
'&:hover fieldset': { borderColor: '#cbd5e1' }, '&:hover fieldset': { borderColor: '#cbd5e1' },
'&.Mui-focused fieldset': { borderColor: '#662582', borderWidth: 1.5 }, '&.Mui-focused fieldset': { borderColor: '#C01227', borderWidth: 1.5 },
'&.Mui-focused': { boxShadow: `0 0 0 3px ${ring(BRAND)}` } '&.Mui-focused': { boxShadow: `0 0 0 3px ${ring(BRAND)}` }
}} }}
/> />

View File

@@ -86,8 +86,8 @@ const soft = (c) => a(c, '18');
const ring = (c) => a(c, '26'); const ring = (c) => a(c, '26');
const edge = (c) => a(c, '55'); const edge = (c) => a(c, '55');
const BRAND = '#662582'; const BRAND = '#C01227';
const BRAND_LIGHT = '#9255AB'; const BRAND_LIGHT = '#D35968';
const SoftPaper = (props) => ( const SoftPaper = (props) => (
<Paper <Paper
@@ -456,7 +456,7 @@ export default function RidersSummary() {
bgcolor: '#ffffff', bgcolor: '#ffffff',
'& fieldset': { borderColor: '#e2e8f0', borderWidth: 1 }, '& fieldset': { borderColor: '#e2e8f0', borderWidth: 1 },
'&:hover fieldset': { borderColor: '#cbd5e1' }, '&:hover fieldset': { borderColor: '#cbd5e1' },
'&.Mui-focused fieldset': { borderColor: '#662582', borderWidth: 1.5 }, '&.Mui-focused fieldset': { borderColor: '#C01227', borderWidth: 1.5 },
'&.Mui-focused': { boxShadow: `0 0 0 3px ${ring(BRAND)}` } '&.Mui-focused': { boxShadow: `0 0 0 3px ${ring(BRAND)}` }
}} }}
/> />

View File

@@ -902,7 +902,7 @@ const Requests = () => {
<MobileCardList scroll> <MobileCardList scroll>
{loading && {loading &&
[0, 1, 2, 3, 4].map((item) => ( [0, 1, 2, 3, 4].map((item) => (
<MobileCard key={item} accent="#662582"> <MobileCard key={item} accent="#C01227">
<Stack direction="row" alignItems="center" spacing={1}> <Stack direction="row" alignItems="center" spacing={1}>
<Skeleton variant="circular" width={32} height={32} /> <Skeleton variant="circular" width={32} height={32} />
<Stack sx={{ flex: 1 }}> <Stack sx={{ flex: 1 }}>
@@ -923,13 +923,13 @@ const Requests = () => {
return ( return (
<MobileCard <MobileCard
key={row.sno} key={row.sno}
accent="#662582" accent="#C01227"
selected={isItemSelected} selected={isItemSelected}
onClick={(event) => handleClick(event, row.sno)} onClick={(event) => handleClick(event, row.sno)}
header={ header={
<Stack direction="row" alignItems="center" justifyContent="space-between" spacing={1}> <Stack direction="row" alignItems="center" justifyContent="space-between" spacing={1}>
<Stack direction="row" alignItems="center" spacing={1} sx={{ minWidth: 0 }}> <Stack direction="row" alignItems="center" spacing={1} sx={{ minWidth: 0 }}>
<Avatar sx={{ width: 32, height: 32, bgcolor: '#66258218', color: '#662582', fontSize: 13 }}> <Avatar sx={{ width: 32, height: 32, bgcolor: '#C0122718', color: '#C01227', fontSize: 13 }}>
{row.requestor ? String(row.requestor).charAt(0).toUpperCase() : '#'} {row.requestor ? String(row.requestor).charAt(0).toUpperCase() : '#'}
</Avatar> </Avatar>
<Stack sx={{ minWidth: 0 }}> <Stack sx={{ minWidth: 0 }}>
@@ -942,7 +942,7 @@ const Requests = () => {
</Stack> </Stack>
</Stack> </Stack>
{row.amount != null && ( {row.amount != null && (
<Chip label={row.amount} size="small" sx={{ bgcolor: '#66258218', color: '#662582', fontWeight: 700 }} /> <Chip label={row.amount} size="small" sx={{ bgcolor: '#C0122718', color: '#C01227', fontWeight: 700 }} />
)} )}
</Stack> </Stack>
} }

View File

@@ -269,7 +269,7 @@ export default function RiderSubstitution({
bgcolor: BRAND, bgcolor: BRAND,
color: '#fff', color: '#fff',
'&:hover': { '&:hover': {
bgcolor: '#4D1C61' bgcolor: '#900E1D'
} }
} }
} }
@@ -657,7 +657,7 @@ export default function RiderSubstitution({
fontWeight: 700, fontWeight: 700,
textTransform: 'none', textTransform: 'none',
'&:hover': { '&:hover': {
bgcolor: '#4D1C61' bgcolor: '#900E1D'
} }
}} }}
> >

View File

@@ -77,7 +77,7 @@ import RiderSubstitution from './RiderSubstitution';
// ============================================================================ // ============================================================================
// Design tokens — shared with the deliveries / tenants / customers pages so // Design tokens — shared with the deliveries / tenants / customers pages so
// every surface (header, KPI tiles, table, badges, dialog) speaks the same // every surface (header, KPI tiles, table, badges, dialog) speaks the same
// visual language. Brand purple `#662582` is the canonical primary; status // visual language. Brand purple `#C01227` is the canonical primary; status
// colours are semantic and distinct from the brand. // colours are semantic and distinct from the brand.
// ============================================================================ // ============================================================================
const DT = { const DT = {
@@ -100,7 +100,7 @@ const soft = (c) => a(c, '18');
const ring = (c) => a(c, '26'); const ring = (c) => a(c, '26');
const edge = (c) => a(c, '55'); const edge = (c) => a(c, '55');
const BRAND = '#662582'; const BRAND = '#C01227';
const SoftPaper = (props) => ( const SoftPaper = (props) => (
<Paper <Paper
@@ -763,7 +763,7 @@ const Riders = () => {
bgcolor: '#ffffff', bgcolor: '#ffffff',
'& fieldset': { borderColor: '#e2e8f0', borderWidth: 1 }, '& fieldset': { borderColor: '#e2e8f0', borderWidth: 1 },
'&:hover fieldset': { borderColor: '#cbd5e1' }, '&:hover fieldset': { borderColor: '#cbd5e1' },
'&.Mui-focused fieldset': { borderColor: '#662582', borderWidth: 1.5 }, '&.Mui-focused fieldset': { borderColor: '#C01227', borderWidth: 1.5 },
'&.Mui-focused': { boxShadow: `0 0 0 3px ${ring(BRAND)}` } '&.Mui-focused': { boxShadow: `0 0 0 3px ${ring(BRAND)}` }
}} }}
/> />
@@ -813,7 +813,7 @@ const Riders = () => {
bgcolor: BRAND, bgcolor: BRAND,
color: '#fff', color: '#fff',
'&:hover': { '&:hover': {
bgcolor: '#4D1C61' bgcolor: '#900E1D'
} }
} }
} }
@@ -1914,7 +1914,7 @@ const Riders = () => {
fontWeight: 600, fontWeight: 600,
bgcolor: BRAND, bgcolor: BRAND,
color: '#fff', color: '#fff',
'&:hover': { bgcolor: '#4D1C61' } '&:hover': { bgcolor: '#900E1D' }
}} }}
> >
Save Changes Save Changes

View File

@@ -31,8 +31,8 @@ const DT = {
surface: '#ffffff', surface: '#ffffff',
surfaceAlt: '#f8fafc' surfaceAlt: '#f8fafc'
}; };
const BRAND = '#662582'; const BRAND = '#C01227';
const BRAND_LIGHT = '#9255AB'; const BRAND_LIGHT = '#D35968';
const tint = (c) => `${c}08`; const tint = (c) => `${c}08`;
const soft = (c) => `${c}18`; const soft = (c) => `${c}18`;
@@ -143,7 +143,7 @@ const ViewProfile = () => {
color: '#fff', color: '#fff',
fontSize: { xs: 24, md: 28 }, fontSize: { xs: 24, md: 28 },
fontWeight: 700, fontWeight: 700,
boxShadow: '0 10px 24px rgba(102, 37, 130, 0.35)' boxShadow: '0 10px 24px rgba(192, 18, 39, 0.35)'
}} }}
> >
{initialsOf(fullname)} {initialsOf(fullname)}

View File

@@ -1,31 +0,0 @@
import React from 'react';
import { useTheme } from '@mui/material/styles';
import { CardActions, Grid, Stack, Typography } from '@mui/material';
const TitleCard = ({ title, secondary, sx }) => {
const theme = useTheme();
return (
<CardActions
sx={{
position: 'sticky',
top: '30px',
bgcolor: theme.palette.background.default,
zIndex: 10,
width: '100%',
...sx
}}
>
<Grid container>
<Grid item xs={12}>
<Stack direction="row" justifyContent="space-between" alignItems="center" gap={2} sx={{ flexWrap: 'wrap' }}>
<Typography variant="h3">{title}</Typography>
{secondary}
</Stack>
</Grid>
</Grid>
</CardActions>
);
};
export default TitleCard;

View File

@@ -121,7 +121,7 @@ export default function ThemeCustomization({ children }) {
// soft slate that tints toward brand purple on hover. // soft slate that tints toward brand purple on hover.
'*': { '*': {
scrollbarWidth: 'thin', // Firefox scrollbarWidth: 'thin', // Firefox
scrollbarColor: 'rgba(102, 37, 130, 0.28) transparent' scrollbarColor: 'rgba(192, 18, 39, 0.28) transparent'
}, },
'*::-webkit-scrollbar': { '*::-webkit-scrollbar': {
width: '10px', width: '10px',
@@ -131,13 +131,13 @@ export default function ThemeCustomization({ children }) {
backgroundColor: 'transparent' backgroundColor: 'transparent'
}, },
'*::-webkit-scrollbar-thumb': { '*::-webkit-scrollbar-thumb': {
backgroundColor: 'rgba(102, 37, 130, 0.26)', backgroundColor: 'rgba(192, 18, 39, 0.26)',
borderRadius: '8px', borderRadius: '8px',
border: '2px solid transparent', border: '2px solid transparent',
backgroundClip: 'padding-box' backgroundClip: 'padding-box'
}, },
'*::-webkit-scrollbar-thumb:hover': { '*::-webkit-scrollbar-thumb:hover': {
backgroundColor: 'rgba(102, 37, 130, 0.45)' backgroundColor: 'rgba(192, 18, 39, 0.45)'
}, },
'*::-webkit-scrollbar-corner': { '*::-webkit-scrollbar-corner': {
backgroundColor: 'transparent' backgroundColor: 'transparent'

View File

@@ -23,10 +23,10 @@ export default function Autocomplete() {
borderRadius: 8, borderRadius: 8,
margin: '1px 0', margin: '1px 0',
'&[aria-selected="true"]': { '&[aria-selected="true"]': {
backgroundColor: 'rgba(102, 37, 130, 0.08)' backgroundColor: 'rgba(192, 18, 39, 0.08)'
}, },
'&.Mui-focused': { '&.Mui-focused': {
backgroundColor: 'rgba(102, 37, 130, 0.06)' backgroundColor: 'rgba(192, 18, 39, 0.06)'
} }
} }
}, },

View File

@@ -40,16 +40,16 @@ const Default = (colors) => {
// contrastText // contrastText
// }, // },
primary: { primary: {
lighter: '#E8D9EF', lighter: '#F6DBDF',
100: '#CBA7DA', 100: '#E9ACB3',
200: '#AE76C4', 200: '#DD7F8A',
light: '#9255AB', light: '#D35968',
400: '#9255AB', 400: '#D35968',
main: '#662582', main: '#C01227',
dark: '#4D1C61', dark: '#900E1D',
700: '#3A1549', 700: '#6D0A16',
darker: '#260E30', darker: '#47070E',
900: '#17081D', 900: '#2A0409',
contrastText: '#FFFFFF' contrastText: '#FFFFFF'
}, },
secondary: { secondary: {

View File

@@ -18,5 +18,6 @@
"riderslogs": "Riders Logs", "riderslogs": "Riders Logs",
"invoice": "Invoice", "invoice": "Invoice",
"dispatch": "Dispatch", "dispatch": "Dispatch",
"profitability": "Profitability" "profitability": "Profitability",
"Doormile": "Doormile"
} }