initialization
@@ -5,4 +5,8 @@ REACT_APP_STAFF_TOKEN=
|
||||
REACT_APP_GOOGLE_MAPS_API_KEY=AIzaSyCF4KatYCI3vqz1_H3kiHeyS3yCMfYToh8
|
||||
REACT_APP_RIDER_ACCESS_ID=AAAAILMpCEU:APA91bEavuOllBI6sFgYtxXAgNmAVwNA-MnCMHLGlR4_t7UqpLajAkdn3T0CZr_zaLBknLyim9ytFLMZgbeXmKqTad_PKCbqlYjHpaizVrLXtecxqyEy4UktIacK2UvHVUATHL-7VQQk
|
||||
|
||||
GENERATE_SOURCEMAP=false
|
||||
DISABLE_ESLINT_PLUGIN=true
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
REACT_APP_URL=https://jupiter.nearle.app/live/api/v1
|
||||
REACT_APP_URL2=
|
||||
REACT_APP_STAFF_TOKEN=
|
||||
|
||||
GENERATE_SOURCEMAP=false
|
||||
DISABLE_ESLINT_PLUGIN=true
|
||||
32
CLAUDE.md
@@ -174,43 +174,43 @@ const AccentAvatar = ({ color, selected, size = 24, children }) => (
|
||||
|
||||
### 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}`).
|
||||
2. **KPI tiles row** — `Grid` of 3–4 `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.
|
||||
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 3–4 `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.
|
||||
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).
|
||||
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')`.
|
||||
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 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.
|
||||
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.
|
||||
|
||||
### 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`):
|
||||
|
||||
| Token | Hex | Use |
|
||||
|---|---|---|
|
||||
| `primary.lighter` | `#E8D9EF` | Very subtle wash bg |
|
||||
| `primary.light` / `primary.400` | `#9255AB` | Gradient pair with main |
|
||||
| `primary.main` | `#662582` | Brand primary — default for all brand surfaces |
|
||||
| `primary.dark` | `#4D1C61` | Hover / pressed states |
|
||||
| `primary.darker` | `#260E30` | Deep contrast text on light bg |
|
||||
| `primary.lighter` | `#F6DBDF` | Very subtle wash bg |
|
||||
| `primary.light` / `primary.400` | `#D35968` | Gradient pair with main |
|
||||
| `primary.main` | `#C01227` | Brand primary — default for all brand surfaces |
|
||||
| `primary.dark` | `#900E1D` | Hover / pressed states |
|
||||
| `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)
|
||||
|
||||
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 |
|
||||
|--------------------------|-----------|
|
||||
| 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) |
|
||||
| Picked up | `#8b5cf6` (light purple — distinct from brand) |
|
||||
| Active / in-transit | `#14b8a6` (teal) |
|
||||
|
||||
|
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 69 KiB |
@@ -4,8 +4,8 @@
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="%PUBLIC_URL%/favicon.png" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<meta name="description" content="Nearle Neighbourhood commerce" />
|
||||
<meta name="theme-color" content="#C01227" />
|
||||
<meta name="description" content="Doormile — corporate logistics & last-mile delivery admin console" />
|
||||
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
|
||||
<link
|
||||
rel="stylesheet"
|
||||
@@ -28,7 +28,7 @@
|
||||
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`.
|
||||
-->
|
||||
<title>Nearle Console</title>
|
||||
<title>Doormile Console</title>
|
||||
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" />
|
||||
<link
|
||||
|
||||
BIN
public/logo192.png
Normal file
|
After Width: | Height: | Size: 82 KiB |
BIN
src/assets/images/doormile-logo.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
src/assets/images/doormile-mark.png
Normal file
|
After Width: | Height: | Size: 82 KiB |
|
Before Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 4.0 KiB |
|
Before Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 4.5 KiB |
@@ -1,6 +1,6 @@
|
||||
import { styled } from '@mui/material/styles';
|
||||
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
|
||||
const LoaderWrapper = styled('div')(() => ({
|
||||
|
||||
@@ -26,13 +26,13 @@ The `DT` design tokens (palette, alpha helpers, `pillFieldSx`, `SoftPaper`, `Acc
|
||||
|
||||
**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`.
|
||||
- **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.
|
||||
- **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 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.
|
||||
- Border radii: `12` (inner), `16` (card), `999` (pill). No other values.
|
||||
- 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.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// LoaderWithImage.jsx
|
||||
import React from 'react';
|
||||
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' }) {
|
||||
return (
|
||||
|
||||
@@ -42,7 +42,7 @@ MobileCardList.propTypes = {
|
||||
|
||||
// Card shell — coloured accent rail on the left, a header slot (status badge /
|
||||
// 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
|
||||
elevation={0}
|
||||
onClick={onClick}
|
||||
|
||||
@@ -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
|
||||
// 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 (
|
||||
<Card sx={{ height: '100%' }}>
|
||||
<CardContent sx={{ p: { xs: 1.75, md: 2 }, '&:last-child': { pb: { xs: 1.75, md: 2 } } }}>
|
||||
|
||||
@@ -234,13 +234,27 @@ const NavCollapse = ({ menu, level, parentId, setSelectedItems, selectedItems, s
|
||||
|
||||
...(drawerOpen && {
|
||||
'&:hover': {
|
||||
// bgcolor: theme.palette.mode === ThemeMode.DARK ? 'divider' : 'primary.lighter'
|
||||
bgcolor: '#7b1fa2'
|
||||
bgcolor: '#fff',
|
||||
'& .MuiTypography-root': {
|
||||
color: '#C01227 !important'
|
||||
},
|
||||
'& svg, & .anticon': {
|
||||
color: '#C01227 !important'
|
||||
}
|
||||
},
|
||||
'&.Mui-selected': {
|
||||
bgcolor: 'transparent',
|
||||
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 && {
|
||||
@@ -273,9 +287,10 @@ const NavCollapse = ({ menu, level, parentId, setSelectedItems, selectedItems, s
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
'&:hover': {
|
||||
// bgcolor: theme.palette.mode === ThemeMode.DARK ? 'secondary.light' : 'secondary.lighter'
|
||||
bgcolor: '#7b1fa2',
|
||||
color: 'white'
|
||||
bgcolor: '#fff',
|
||||
'& svg': {
|
||||
color: '#C01227 !important'
|
||||
}
|
||||
}
|
||||
}),
|
||||
...(!drawerOpen &&
|
||||
@@ -283,8 +298,10 @@ const NavCollapse = ({ menu, level, parentId, setSelectedItems, selectedItems, s
|
||||
bgcolor: 'primary.light',
|
||||
color: 'primary.main',
|
||||
'&:hover': {
|
||||
bgcolor: '#7b1fa2',
|
||||
color: 'primary.main'
|
||||
bgcolor: '#fff',
|
||||
'& svg': {
|
||||
color: '#C01227 !important'
|
||||
}
|
||||
}
|
||||
})
|
||||
}}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import { forwardRef, useEffect, useState } from 'react';
|
||||
import { forwardRef, useEffect } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
|
||||
@@ -41,7 +41,7 @@ const NavItem = ({ item, level }) => {
|
||||
const isSelected = openItem.findIndex((id) => id === item.id) > -1;
|
||||
|
||||
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
|
||||
);
|
||||
@@ -103,7 +103,13 @@ const NavItem = ({ item, level }) => {
|
||||
py: !drawerOpen && level === 1 ? 1.25 : 1,
|
||||
...(drawerOpen && {
|
||||
'&:hover': {
|
||||
bgcolor: '#7b1fa2'
|
||||
bgcolor: '#fff',
|
||||
'& .MuiTypography-root': {
|
||||
color: '#C01227 !important'
|
||||
},
|
||||
'& svg, & .anticon': {
|
||||
color: '#C01227 !important'
|
||||
}
|
||||
},
|
||||
'&.Mui-selected': {
|
||||
bgcolor: theme.palette.mode === ThemeMode.DARK ? 'divider' : 'primary.lighter',
|
||||
@@ -116,9 +122,9 @@ const NavItem = ({ item, level }) => {
|
||||
}
|
||||
}),
|
||||
...(!drawerOpen && {
|
||||
bgcolor: '#662582',
|
||||
bgcolor: '#C01227',
|
||||
'&:hover': {
|
||||
bgcolor: '#662582'
|
||||
bgcolor: '#C01227'
|
||||
},
|
||||
'&.Mui-selected': {
|
||||
'&:hover': {
|
||||
@@ -145,7 +151,10 @@ const NavItem = ({ item, level }) => {
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
'&:hover': {
|
||||
bgcolor: '#7b1fa2'
|
||||
bgcolor: '#fff',
|
||||
'& svg, & .anticon': {
|
||||
color: '#C01227 !important'
|
||||
}
|
||||
}
|
||||
}),
|
||||
...(!drawerOpen &&
|
||||
|
||||
@@ -10,8 +10,12 @@ import DrawerHeaderStyled from './DrawerHeaderStyled';
|
||||
import { MenuOrientation } from 'config';
|
||||
import useConfig from 'hooks/useConfig';
|
||||
|
||||
import logo from 'assets/images/logo-nearle9.png'
|
||||
import logo1 from 'assets/images/logo-sm1.png'
|
||||
import logo from 'assets/images/doormile-logo.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 ||============================== //
|
||||
|
||||
const DrawerHeader = ({ open }) => {
|
||||
@@ -37,15 +41,13 @@ const DrawerHeader = ({ open }) => {
|
||||
|
||||
{(open) &&
|
||||
<img src={logo}
|
||||
// width='160px'
|
||||
// height='45px'
|
||||
// width='170px'
|
||||
alt='logo'/>
|
||||
style={{ height: '29px', width: 'auto' }}
|
||||
alt='Doormile'/>
|
||||
}
|
||||
{(!open) &&
|
||||
<img src={logo1}
|
||||
width='40px'
|
||||
alt='logo'/>
|
||||
width='50px'
|
||||
alt='Doormile'/>
|
||||
}
|
||||
</DrawerHeaderStyled>
|
||||
);
|
||||
|
||||
@@ -15,7 +15,7 @@ const openedMixin = (theme) => ({
|
||||
}),
|
||||
overflowX: 'hidden',
|
||||
boxShadow: theme.palette.mode === ThemeMode.DARK ? theme.customShadows.z1 : 'none',
|
||||
backgroundColor:'#662582',
|
||||
backgroundColor:'#C01227',
|
||||
});
|
||||
|
||||
const closedMixin = (theme) => ({
|
||||
@@ -27,7 +27,7 @@ const closedMixin = (theme) => ({
|
||||
width: theme.spacing(7.5),
|
||||
borderRight: 'none',
|
||||
boxShadow: theme.customShadows.z1,
|
||||
backgroundColor:'#662582',
|
||||
backgroundColor:'#C01227',
|
||||
});
|
||||
|
||||
// ==============================|| DRAWER - MINI STYLED ||============================== //
|
||||
|
||||
@@ -55,7 +55,7 @@ const MainDrawer = ({ window }) => {
|
||||
borderRight: `1px solid ${theme.palette.divider}`,
|
||||
backgroundImage: 'none',
|
||||
boxShadow: 'inherit',
|
||||
bgcolor:'#662582'
|
||||
bgcolor:'#C01227'
|
||||
}
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -8,7 +8,6 @@ import { AppBar, Box, ClickAwayListener, Paper, Popper, Toolbar } from '@mui/mat
|
||||
import Profile from './Profile';
|
||||
import IconButton from 'components/@extended/IconButton';
|
||||
import Transitions from 'components/@extended/Transitions';
|
||||
import { ThemeMode } from 'config';
|
||||
|
||||
// assets
|
||||
import { MoreOutlined } from '@ant-design/icons';
|
||||
|
||||
@@ -24,7 +24,6 @@ import {
|
||||
import MainCard from 'components/MainCard';
|
||||
import IconButton from 'components/@extended/IconButton';
|
||||
import Transitions from 'components/@extended/Transitions';
|
||||
import { ThemeMode } from 'config';
|
||||
|
||||
// assets
|
||||
import { BellOutlined, CheckCircleOutlined, GiftOutlined, MessageOutlined, SettingOutlined } from '@ant-design/icons';
|
||||
@@ -90,7 +89,7 @@ const Notification = () => {
|
||||
// color="primary"
|
||||
sx={{
|
||||
"& .MuiBadge-badge": {
|
||||
color: "#662582",
|
||||
color: "#C01227",
|
||||
backgroundColor: "white"
|
||||
}
|
||||
}}
|
||||
|
||||
@@ -13,8 +13,6 @@ import Avatar from 'components/@extended/Avatar';
|
||||
import MainCard from 'components/MainCard';
|
||||
import Transitions from 'components/@extended/Transitions';
|
||||
import IconButton from 'components/@extended/IconButton';
|
||||
|
||||
import { ThemeMode } from 'config';
|
||||
// import useAuth from 'hooks/useAuth';
|
||||
|
||||
// assets
|
||||
@@ -83,13 +81,7 @@ const Profile = () => {
|
||||
<ButtonBase
|
||||
sx={{
|
||||
p: 0.25,
|
||||
// bgcolor: open ? iconBackColorOpen : 'transparent',
|
||||
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"
|
||||
ref={anchorRef}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useMemo, useState } from 'react';
|
||||
import { useState } from 'react';
|
||||
|
||||
// material-ui
|
||||
import {
|
||||
|
||||
@@ -9,7 +9,7 @@ import AppBarStyled from './AppBarStyled';
|
||||
import HeaderContent from './HeaderContent';
|
||||
import IconButton from 'components/@extended/IconButton';
|
||||
|
||||
import { MenuOrientation, ThemeMode } from 'config';
|
||||
import { MenuOrientation } from 'config';
|
||||
import useConfig from 'hooks/useConfig';
|
||||
import { dispatch, useSelector } from 'store';
|
||||
import { openDrawer } from 'store/reducers/menu';
|
||||
@@ -66,7 +66,7 @@ const Header = () => {
|
||||
zIndex: 1200,
|
||||
width: isHorizontal ? '100%' : drawerOpen ? 'calc(100% - 260px)' : { xs: '100%', lg: 'calc(100% - 60px)' },
|
||||
// boxShadow: theme.customShadows.z1
|
||||
bgcolor:'#662582'
|
||||
bgcolor:'#C01227'
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ const icons = {
|
||||
|
||||
const nearle = {
|
||||
id: 'nearle_Pages',
|
||||
title: <FormattedMessage id="Nearle" />,
|
||||
title: <FormattedMessage id="Doormile" />,
|
||||
icon: icons.FileDoneOutlined,
|
||||
type: 'group',
|
||||
children: [
|
||||
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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't have an account?
|
||||
</Typography>
|
||||
</Stack>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<AuthLogin />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</AuthWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
export default Login;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -61,7 +61,7 @@ const DT = {
|
||||
divider: '#f1f5f9',
|
||||
surface: '#ffffff',
|
||||
surfaceAlt: '#f8fafc',
|
||||
brand: '#662582'
|
||||
brand: '#C01227'
|
||||
};
|
||||
const a = (c, suffix) => `${c}${suffix}`;
|
||||
const tint = (c) => a(c, '08');
|
||||
@@ -69,7 +69,7 @@ const soft = (c) => a(c, '18');
|
||||
const ring = (c) => a(c, '26');
|
||||
const edge = (c) => a(c, '55');
|
||||
|
||||
const BRAND = '#662582';
|
||||
const BRAND = '#C01227';
|
||||
|
||||
const SoftPaper = (props) => (
|
||||
<Paper
|
||||
|
||||
@@ -119,7 +119,7 @@ const pillFieldSx = (color) => ({
|
||||
'& fieldset': { borderColor: '#e2e8f0', borderWidth: 1 },
|
||||
'&:hover fieldset': { borderColor: '#cbd5e1' },
|
||||
'&.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 }
|
||||
});
|
||||
@@ -596,7 +596,7 @@ const Clients1 = () => {
|
||||
setLocoName={setLocoName}
|
||||
setPage={setPage}
|
||||
pill
|
||||
accentColor="#662582"
|
||||
accentColor="#C01227"
|
||||
icon={<MdMyLocation size={14} />}
|
||||
placeholder="Select Zone"
|
||||
paperComponent={SoftPaper}
|
||||
@@ -622,7 +622,7 @@ const Clients1 = () => {
|
||||
title={item.label}
|
||||
value={value ?? 0}
|
||||
icon={<Icon size={20} />}
|
||||
color={idx === 0 ? '#662582' : item.color}
|
||||
color={idx === 0 ? '#C01227' : item.color}
|
||||
loading={summaryDataIsLoading}
|
||||
/>
|
||||
</Box>
|
||||
@@ -749,11 +749,11 @@ const Clients1 = () => {
|
||||
m: 0,
|
||||
width: '100%',
|
||||
borderRadius: 999,
|
||||
bgcolor: tint('#662582'),
|
||||
'& fieldset': { borderColor: edge('#662582'), borderWidth: 1.5 },
|
||||
'&:hover fieldset': { borderColor: '#662582' },
|
||||
'&.Mui-focused fieldset': { borderColor: '#662582', borderWidth: 2 },
|
||||
'&.Mui-focused': { boxShadow: `0 0 0 3px ${ring('#662582')}` }
|
||||
bgcolor: tint('#C01227'),
|
||||
'& fieldset': { borderColor: edge('#C01227'), borderWidth: 1.5 },
|
||||
'&:hover fieldset': { borderColor: '#C01227' },
|
||||
'&.Mui-focused fieldset': { borderColor: '#C01227', borderWidth: 2 },
|
||||
'&.Mui-focused': { boxShadow: `0 0 0 3px ${ring('#C01227')}` }
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
@@ -780,9 +780,9 @@ const Clients1 = () => {
|
||||
maxHeight: { xs: 'calc(100vh - 220px)', md: 'calc(100vh - 190px)' },
|
||||
'&::-webkit-scrollbar': { width: '10px', height: '10px' },
|
||||
'&::-webkit-scrollbar-thumb': {
|
||||
backgroundColor: edge('#662582'),
|
||||
backgroundColor: edge('#C01227'),
|
||||
borderRadius: '8px',
|
||||
'&:hover': { backgroundColor: '#662582' }
|
||||
'&:hover': { backgroundColor: '#C01227' }
|
||||
},
|
||||
'&::-webkit-scrollbar-track': { backgroundColor: DT.surfaceAlt }
|
||||
}}
|
||||
@@ -883,7 +883,7 @@ const Clients1 = () => {
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Stack direction="row" alignItems="center" spacing={1}>
|
||||
<AccentAvatar color="#662582" size={32}>
|
||||
<AccentAvatar color="#C01227" size={32}>
|
||||
<MdPersonPin size={16} />
|
||||
</AccentAvatar>
|
||||
<Stack>
|
||||
@@ -996,10 +996,10 @@ const Clients1 = () => {
|
||||
<IconButton
|
||||
size="small"
|
||||
sx={{
|
||||
bgcolor: openRowIndex1 === index ? '#662582' : soft('#662582'),
|
||||
color: openRowIndex1 === index ? '#fff' : '#662582',
|
||||
border: `1px solid ${edge('#662582')}`,
|
||||
'&:hover': { bgcolor: '#662582', color: '#fff' }
|
||||
bgcolor: openRowIndex1 === index ? '#C01227' : soft('#C01227'),
|
||||
color: openRowIndex1 === index ? '#fff' : '#C01227',
|
||||
border: `1px solid ${edge('#C01227')}`,
|
||||
'&:hover': { bgcolor: '#C01227', color: '#fff' }
|
||||
}}
|
||||
onClick={() => {
|
||||
setSelectedCustomer(row);
|
||||
@@ -1913,7 +1913,7 @@ const Clients1 = () => {
|
||||
header={
|
||||
<Stack direction="row" alignItems="flex-start" justifyContent="space-between" spacing={1}>
|
||||
<Stack direction="row" alignItems="center" spacing={1} sx={{ minWidth: 0 }}>
|
||||
<AccentAvatar color="#662582" size={36}>
|
||||
<AccentAvatar color="#C01227" size={36}>
|
||||
<MdPersonPin size={18} />
|
||||
</AccentAvatar>
|
||||
<Stack sx={{ minWidth: 0 }}>
|
||||
@@ -2012,10 +2012,10 @@ const Clients1 = () => {
|
||||
<IconButton
|
||||
size="small"
|
||||
sx={{
|
||||
bgcolor: expanded ? '#662582' : soft('#662582'),
|
||||
color: expanded ? '#fff' : '#662582',
|
||||
border: `1px solid ${edge('#662582')}`,
|
||||
'&:hover': { bgcolor: '#662582', color: '#fff' }
|
||||
bgcolor: expanded ? '#C01227' : soft('#C01227'),
|
||||
color: expanded ? '#fff' : '#C01227',
|
||||
border: `1px solid ${edge('#C01227')}`,
|
||||
'&:hover': { bgcolor: '#C01227', color: '#fff' }
|
||||
}}
|
||||
onClick={() => {
|
||||
setSelectedCustomer(row);
|
||||
@@ -2108,7 +2108,7 @@ const Clients1 = () => {
|
||||
>
|
||||
<DialogTitle
|
||||
sx={{
|
||||
bgcolor: '#662582',
|
||||
bgcolor: '#C01227',
|
||||
color: '#fff',
|
||||
fontSize: '20px'
|
||||
}}
|
||||
|
||||
@@ -396,7 +396,7 @@ export default function Customers() {
|
||||
}
|
||||
};
|
||||
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: 'zone', label: 'Active Zone', color: '#10b981', icon: MdOutlinePlace, value: locaName || 'All Zones' }
|
||||
];
|
||||
@@ -416,7 +416,7 @@ export default function Customers() {
|
||||
setAppId={setAppId}
|
||||
setLocoName={setLocoName}
|
||||
pill
|
||||
accentColor="#662582"
|
||||
accentColor="#C01227"
|
||||
icon={<MdMyLocation size={14} />}
|
||||
placeholder="Select Zone"
|
||||
paperComponent={SoftPaper}
|
||||
@@ -466,7 +466,7 @@ export default function Customers() {
|
||||
spacing={1.25}
|
||||
>
|
||||
<Stack direction="row" alignItems="center" spacing={1.25}>
|
||||
<AccentAvatar color="#662582" size={32}>
|
||||
<AccentAvatar color="#C01227" size={32}>
|
||||
<MdGroups size={18} />
|
||||
</AccentAvatar>
|
||||
<Stack>
|
||||
@@ -491,11 +491,11 @@ export default function Customers() {
|
||||
m: 0,
|
||||
width: '100%',
|
||||
borderRadius: 999,
|
||||
bgcolor: tint('#662582'),
|
||||
'& fieldset': { borderColor: edge('#662582'), borderWidth: 1.5 },
|
||||
'&:hover fieldset': { borderColor: '#662582' },
|
||||
'&.Mui-focused fieldset': { borderColor: '#662582', borderWidth: 2 },
|
||||
'&.Mui-focused': { boxShadow: `0 0 0 3px ${ring('#662582')}` }
|
||||
bgcolor: tint('#C01227'),
|
||||
'& fieldset': { borderColor: edge('#C01227'), borderWidth: 1.5 },
|
||||
'&:hover fieldset': { borderColor: '#C01227' },
|
||||
'&.Mui-focused fieldset': { borderColor: '#C01227', borderWidth: 2 },
|
||||
'&.Mui-focused': { boxShadow: `0 0 0 3px ${ring('#C01227')}` }
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
@@ -535,11 +535,11 @@ export default function Customers() {
|
||||
rows?.map((row, index) => (
|
||||
<MobileCard
|
||||
key={row.customerid || `${row.firstname}-${index}`}
|
||||
accent="#662582"
|
||||
accent="#C01227"
|
||||
header={
|
||||
<Stack direction="row" alignItems="center" justifyContent="space-between" spacing={1}>
|
||||
<Stack direction="row" alignItems="center" spacing={1} sx={{ minWidth: 0 }}>
|
||||
<AccentAvatar color="#662582" size={36}>
|
||||
<AccentAvatar color="#C01227" size={36}>
|
||||
<MdPersonPin size={18} />
|
||||
</AccentAvatar>
|
||||
<Stack sx={{ minWidth: 0 }}>
|
||||
@@ -626,9 +626,9 @@ export default function Customers() {
|
||||
maxHeight: { xs: 'calc(100vh - 220px)', md: 'calc(100vh - 190px)' },
|
||||
'&::-webkit-scrollbar': { width: 10, height: 10 },
|
||||
'&::-webkit-scrollbar-thumb': {
|
||||
backgroundColor: edge('#662582'),
|
||||
backgroundColor: edge('#C01227'),
|
||||
borderRadius: 8,
|
||||
'&:hover': { backgroundColor: '#662582' }
|
||||
'&:hover': { backgroundColor: '#C01227' }
|
||||
},
|
||||
'&::-webkit-scrollbar-track': { backgroundColor: DT.surfaceAlt }
|
||||
}}
|
||||
@@ -700,7 +700,7 @@ export default function Customers() {
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Stack direction="row" alignItems="center" spacing={1}>
|
||||
<AccentAvatar color="#662582" size={36}>
|
||||
<AccentAvatar color="#C01227" size={36}>
|
||||
<MdPersonPin size={18} />
|
||||
</AccentAvatar>
|
||||
<Stack>
|
||||
@@ -829,7 +829,7 @@ export default function Customers() {
|
||||
<DialogTitle
|
||||
id="alert-dialog-title"
|
||||
sx={{
|
||||
background: `linear-gradient(135deg, #662582 0%, #9255AB 100%)`,
|
||||
background: `linear-gradient(135deg, #C01227 0%, #D35968 100%)`,
|
||||
color: '#fff',
|
||||
py: 2
|
||||
}}
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
const Dashboard = () => {
|
||||
return (
|
||||
<>
|
||||
<h1>Dashboard</h1>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default Dashboard;
|
||||
@@ -126,7 +126,7 @@ const DT = {
|
||||
divider: '#f1f5f9',
|
||||
surface: '#ffffff',
|
||||
surfaceAlt: '#f8fafc',
|
||||
brand: '#662582'
|
||||
brand: '#C01227'
|
||||
};
|
||||
|
||||
// Quick alpha helpers (hex + percentage suffix). Mirrors the batch-dropdown
|
||||
@@ -912,7 +912,7 @@ const Deliveries = () => {
|
||||
setLocoName={setLocoName}
|
||||
setPage={setPage}
|
||||
pill
|
||||
accentColor="#662582"
|
||||
accentColor="#C01227"
|
||||
icon={<MdMyLocation size={14} />}
|
||||
placeholder="Select Zone"
|
||||
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 }}>
|
||||
<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} />
|
||||
</Avatar>
|
||||
<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',
|
||||
'& fieldset': { borderColor: '#e2e8f0', borderWidth: 1 },
|
||||
'&:hover fieldset': { borderColor: '#cbd5e1' },
|
||||
'&.Mui-focused': { boxShadow: `0 0 0 3px ${ring('#662582')}` },
|
||||
'&.Mui-focused fieldset': { borderColor: '#662582', borderWidth: 1.5 }
|
||||
'&.Mui-focused': { boxShadow: `0 0 0 3px ${ring('#C01227')}` },
|
||||
'&.Mui-focused fieldset': { borderColor: '#C01227', borderWidth: 1.5 }
|
||||
},
|
||||
'& .MuiAutocomplete-endAdornment .MuiSvgIcon-root': { color: '#94a3b8' }
|
||||
}}
|
||||
@@ -1442,10 +1442,10 @@ const Deliveries = () => {
|
||||
overflowX: 'auto',
|
||||
'&::-webkit-scrollbar': { width: '10px', height: '10px', cursor: 'pointer' },
|
||||
'&::-webkit-scrollbar-thumb': {
|
||||
backgroundColor: edge('#662582'),
|
||||
backgroundColor: edge('#C01227'),
|
||||
borderRadius: '8px',
|
||||
cursor: 'pointer',
|
||||
'&:hover': { backgroundColor: '#662582' }
|
||||
'&:hover': { backgroundColor: '#C01227' }
|
||||
},
|
||||
'&::-webkit-scrollbar-track': { backgroundColor: DT.surfaceAlt }
|
||||
}}
|
||||
@@ -1562,7 +1562,7 @@ const Deliveries = () => {
|
||||
<IconButton
|
||||
size="small"
|
||||
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 />
|
||||
</IconButton>
|
||||
@@ -1650,7 +1650,7 @@ const Deliveries = () => {
|
||||
</MobileField>
|
||||
<MobileField label="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>
|
||||
)}
|
||||
@@ -1664,8 +1664,8 @@ const Deliveries = () => {
|
||||
{isOpen && (
|
||||
<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 }}>
|
||||
<AccentAvatar color="#662582" size={22}><MdInventory2 size={12} /></AccentAvatar>
|
||||
<Typography variant="caption" sx={{ fontWeight: 800, letterSpacing: 0.5, textTransform: 'uppercase', color: '#662582' }}>
|
||||
<AccentAvatar color="#C01227" size={22}><MdInventory2 size={12} /></AccentAvatar>
|
||||
<Typography variant="caption" sx={{ fontWeight: 800, letterSpacing: 0.5, textTransform: 'uppercase', color: '#C01227' }}>
|
||||
Product Details
|
||||
</Typography>
|
||||
</Stack>
|
||||
@@ -2065,9 +2065,9 @@ const Deliveries = () => {
|
||||
height: 24,
|
||||
px: 0.875,
|
||||
borderRadius: 999,
|
||||
bgcolor: tint('#662582'),
|
||||
border: `1px solid ${edge('#662582')}`,
|
||||
color: '#662582',
|
||||
bgcolor: tint('#C01227'),
|
||||
border: `1px solid ${edge('#C01227')}`,
|
||||
color: '#C01227',
|
||||
fontWeight: 800,
|
||||
fontSize: 11
|
||||
}}
|
||||
@@ -2133,10 +2133,10 @@ const Deliveries = () => {
|
||||
onClick={(e) => handleMenuOpen(e, row)}
|
||||
sx={{
|
||||
borderRadius: 999,
|
||||
bgcolor: tint('#662582'),
|
||||
color: '#662582',
|
||||
border: `1px solid ${edge('#662582')}`,
|
||||
'&:hover': { bgcolor: soft('#662582') }
|
||||
bgcolor: tint('#C01227'),
|
||||
color: '#C01227',
|
||||
border: `1px solid ${edge('#C01227')}`,
|
||||
'&:hover': { bgcolor: soft('#C01227') }
|
||||
}}
|
||||
>
|
||||
<EditOutlined />
|
||||
@@ -2168,9 +2168,9 @@ const Deliveries = () => {
|
||||
background: '#fff'
|
||||
}}
|
||||
>
|
||||
<Stack direction="row" alignItems="center" spacing={1} sx={{ px: 2, py: 1.25, borderBottom: `1px solid ${DT.divider}`, bgcolor: tint('#662582') }}>
|
||||
<AccentAvatar color="#662582"><MdInventory2 size={14} /></AccentAvatar>
|
||||
<Typography variant="caption" sx={{ fontWeight: 800, letterSpacing: 0.5, textTransform: 'uppercase', color: '#662582' }}>
|
||||
<Stack direction="row" alignItems="center" spacing={1} sx={{ px: 2, py: 1.25, borderBottom: `1px solid ${DT.divider}`, bgcolor: tint('#C01227') }}>
|
||||
<AccentAvatar color="#C01227"><MdInventory2 size={14} /></AccentAvatar>
|
||||
<Typography variant="caption" sx={{ fontWeight: 800, letterSpacing: 0.5, textTransform: 'uppercase', color: '#C01227' }}>
|
||||
Product Details
|
||||
</Typography>
|
||||
</Stack>
|
||||
@@ -2778,14 +2778,14 @@ const Deliveries = () => {
|
||||
borderRadius: 2,
|
||||
bgcolor: '#fff',
|
||||
'& fieldset': { borderColor: DT.borderSubtle },
|
||||
'&:hover fieldset': { borderColor: '#662582' },
|
||||
'&.Mui-focused fieldset': { borderColor: '#662582', borderWidth: 2 },
|
||||
'&.Mui-focused': { boxShadow: `0 0 0 3px ${ring('#662582')}` }
|
||||
'&:hover fieldset': { borderColor: '#C01227' },
|
||||
'&.Mui-focused fieldset': { borderColor: '#C01227', borderWidth: 2 },
|
||||
'&.Mui-focused': { boxShadow: `0 0 0 3px ${ring('#C01227')}` }
|
||||
}
|
||||
}}
|
||||
>
|
||||
{['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;
|
||||
return (
|
||||
<MenuItem key={s} value={s} sx={{ gap: 1 }}>
|
||||
@@ -2812,9 +2812,9 @@ const Deliveries = () => {
|
||||
borderRadius: 2,
|
||||
bgcolor: '#fff',
|
||||
'& fieldset': { borderColor: DT.borderSubtle },
|
||||
'&:hover fieldset': { borderColor: '#662582' },
|
||||
'&.Mui-focused fieldset': { borderColor: '#662582', borderWidth: 2 },
|
||||
'&.Mui-focused': { boxShadow: `0 0 0 3px ${ring('#662582')}` }
|
||||
'&:hover fieldset': { borderColor: '#C01227' },
|
||||
'&.Mui-focused fieldset': { borderColor: '#C01227', borderWidth: 2 },
|
||||
'&.Mui-focused': { boxShadow: `0 0 0 3px ${ring('#C01227')}` }
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -80,7 +80,7 @@ import logger from '../../../utils/logger';
|
||||
// emerald for the actual GPS trail (signals "live / real" data). Per-step
|
||||
// distinction in Combined view is carried by the numbered drop pins, which
|
||||
// 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 toNum = (v) => {
|
||||
@@ -5729,7 +5729,7 @@ const Dispatch = ({
|
||||
style={{
|
||||
boxShadow: 'var(--shadow-lg)',
|
||||
background: compareOpen
|
||||
? 'linear-gradient(135deg, #662582, #9255AB)'
|
||||
? 'linear-gradient(135deg, #C01227, #D35968)'
|
||||
: '#fff',
|
||||
marginLeft: 8,
|
||||
color: compareOpen ? '#fff' : undefined
|
||||
@@ -6328,7 +6328,7 @@ const Dispatch = ({
|
||||
<div className="da-section">
|
||||
<div className="da-hero-row">
|
||||
<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 />
|
||||
</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-avatar"
|
||||
style={{ background: `${riderPositionModal.color || '#662582'}22`, color: riderPositionModal.color || '#662582' }}
|
||||
style={{ background: `${riderPositionModal.color || '#C01227'}22`, color: riderPositionModal.color || '#C01227' }}
|
||||
>
|
||||
<MdTwoWheeler />
|
||||
</div>
|
||||
|
||||
@@ -72,7 +72,7 @@ const soft = (c) => a(c, '18');
|
||||
const ring = (c) => a(c, '26');
|
||||
const edge = (c) => a(c, '55');
|
||||
|
||||
const BRAND = '#662582';
|
||||
const BRAND = '#C01227';
|
||||
|
||||
const AccentAvatar = ({ color, selected, size = 24, children }) => (
|
||||
<Avatar
|
||||
@@ -396,7 +396,7 @@ const Invoice = () => {
|
||||
bgcolor: '#ffffff',
|
||||
'& fieldset': { borderColor: '#e2e8f0', borderWidth: 1 },
|
||||
'&: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)}` }
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -3,7 +3,10 @@ import { useLocation } from 'react-router-dom';
|
||||
import { useTheme } from '@mui/material/styles';
|
||||
import useMediaQuery from '@mui/material/useMediaQuery';
|
||||
// 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 dayjs from 'dayjs';
|
||||
import Loader from 'components/Loader';
|
||||
@@ -191,7 +194,7 @@ const InvoicePreview = () => {
|
||||
>
|
||||
<Box sx={{ pt: 0.5 }}>
|
||||
<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>
|
||||
{/* <Typography
|
||||
sx={{ color: theme.palette.primary.main, py: 0.5 }}
|
||||
|
||||
@@ -8,8 +8,7 @@ import { useTheme } from '@mui/material/styles';
|
||||
import axios from 'axios';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import Loader from 'components/Loader';
|
||||
import logo from 'assets/images/logo-nearle1.png';
|
||||
import expressImage from 'assets/images/express.png';
|
||||
import doormileLogo from 'assets/images/doormile-logo.png';
|
||||
import { useSelector, useDispatch } from 'react-redux';
|
||||
import { OpenToast } from 'components/third-party/OpenToast';
|
||||
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 { 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 dispatch = useDispatch();
|
||||
const fcmtoken = useSelector((state) => state.fcm);
|
||||
@@ -167,18 +169,18 @@ const Login = () => {
|
||||
justifyContent: 'center',
|
||||
color: '#fff',
|
||||
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 */}
|
||||
<img
|
||||
src={expressImage}
|
||||
alt="Operate your dispatch"
|
||||
src={doormileLogo}
|
||||
alt="Doormile"
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: 48,
|
||||
left: 48,
|
||||
maxHeight: 60
|
||||
maxHeight: 40
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -213,7 +215,7 @@ const Login = () => {
|
||||
end to end.
|
||||
</Typography>
|
||||
<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>
|
||||
|
||||
<Stack spacing={1.5} sx={{ display: 'inline-flex', textAlign: 'left' }}>
|
||||
@@ -255,7 +257,7 @@ const Login = () => {
|
||||
>
|
||||
{/* Logo */}
|
||||
<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>
|
||||
|
||||
{/* Title */}
|
||||
@@ -263,7 +265,7 @@ const Login = () => {
|
||||
Welcome back
|
||||
</Typography>
|
||||
<Typography variant="body2" textAlign="center" sx={{ color: '#64748b', mb: 3 }}>
|
||||
Sign in to the NearlExpress console
|
||||
Sign in to the Doormile console
|
||||
</Typography>
|
||||
|
||||
<CardContent sx={{ p: 0 }}>
|
||||
@@ -440,7 +442,7 @@ const Login = () => {
|
||||
component={Link}
|
||||
href="https://nearle.in"
|
||||
target="_blank"
|
||||
sx={{ color: '#94a3b8', textDecoration: 'none', fontWeight: 600, '&:hover': { color: '#662582' } }}
|
||||
sx={{ color: '#94a3b8', textDecoration: 'none', fontWeight: 600, '&:hover': { color: '#C01227' } }}
|
||||
>
|
||||
© All rights reserved
|
||||
</Typography>
|
||||
@@ -449,7 +451,7 @@ const Login = () => {
|
||||
component={Link}
|
||||
href="https://nearle.in/terms"
|
||||
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
|
||||
</Typography>
|
||||
@@ -458,7 +460,7 @@ const Login = () => {
|
||||
component={Link}
|
||||
href="https://nearle.in/privacy"
|
||||
target="_blank"
|
||||
sx={{ color: '#94a3b8', textDecoration: 'none', fontWeight: 600, '&:hover': { color: '#662582' } }}
|
||||
sx={{ color: '#94a3b8', textDecoration: 'none', fontWeight: 600, '&:hover': { color: '#C01227' } }}
|
||||
>
|
||||
Privacy Policy
|
||||
</Typography>
|
||||
|
||||
@@ -22,7 +22,10 @@ import { useTheme } from '@mui/material/styles';
|
||||
import useMediaQuery from '@mui/material/useMediaQuery';
|
||||
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 { useNavigate } from 'react-router-dom';
|
||||
@@ -228,7 +231,7 @@ const Login = () => {
|
||||
// sx={{ ml: 3, mt: 3 }}
|
||||
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 item xs={12}>
|
||||
<Grid
|
||||
|
||||
@@ -696,7 +696,7 @@
|
||||
|
||||
.weight-card-btn.active.weight-heavy {
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -707,7 +707,7 @@
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 3px;
|
||||
background: #662582;
|
||||
background: #C01227;
|
||||
}
|
||||
|
||||
/* Premium Card Overrides */
|
||||
|
||||
@@ -159,9 +159,9 @@ const OrderMap = ({ startPoint, endPoint, appLocaLat, appLocaLng }) => {
|
||||
{hasPick && <Marker position={pickCoords} icon={pickupIcon} />}
|
||||
{hasDrop && <Marker position={dropCoords} icon={dropoffIcon} />}
|
||||
{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} />
|
||||
</MapContainer>
|
||||
@@ -1388,7 +1388,7 @@ const Createorder1 = () => {
|
||||
InputProps={{
|
||||
startAdornment: (
|
||||
<InputAdornment position="start">
|
||||
<SearchOutlined style={{ fontSize: 15, color: '#662582' }} />
|
||||
<SearchOutlined style={{ fontSize: 15, color: '#C01227' }} />
|
||||
</InputAdornment>
|
||||
),
|
||||
endAdornment: (
|
||||
@@ -1424,7 +1424,7 @@ const Createorder1 = () => {
|
||||
InputProps={{
|
||||
startAdornment: (
|
||||
<InputAdornment position="start">
|
||||
<FaLocationDot style={{ fontSize: 14, color: '#662582' }} />
|
||||
<FaLocationDot style={{ fontSize: 14, color: '#C01227' }} />
|
||||
</InputAdornment>
|
||||
),
|
||||
endAdornment: (
|
||||
@@ -2166,7 +2166,7 @@ const Createorder1 = () => {
|
||||
{/* Map Card */}
|
||||
<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' }}>
|
||||
<MyLocationIcon sx={{ color: '#662582', fontSize: 16 }} />
|
||||
<MyLocationIcon sx={{ color: '#C01227', fontSize: 16 }} />
|
||||
Live Route Preview
|
||||
</Typography>
|
||||
<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}>
|
||||
<Typography variant="h4" sx={{ fontWeight: 600, color: 'white' }}>
|
||||
{`Select Saved Address (${pickordrop === 1 ? 'Pickup' : 'Drop'})`}
|
||||
|
||||
@@ -895,7 +895,7 @@ const Details = () => {
|
||||
{stafflist.map((val, i) => {
|
||||
const isSelected = staffarr.find((res) => res.userid == val.userid) ? true : false;
|
||||
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" alignItems="center" spacing={1}>
|
||||
<Avatar alt="" src={''} sx={{ width: 32, height: 32 }} />
|
||||
@@ -1549,14 +1549,14 @@ const Details = () => {
|
||||
{isMobile ? (
|
||||
<MobileCardList>
|
||||
{val5.orderdetails.length === 0 && (
|
||||
<MobileCard accent="#662582">
|
||||
<MobileCard accent="#C01227">
|
||||
<Skeleton animation="wave" />
|
||||
<Skeleton animation="wave" />
|
||||
<Skeleton animation="wave" />
|
||||
</MobileCard>
|
||||
)}
|
||||
{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="column">
|
||||
<Typography sx={{ fontSize: 10, fontWeight: 800, color: '#94a3b8' }}>#{i + 1}</Typography>
|
||||
|
||||
@@ -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;
|
||||
@@ -144,7 +144,7 @@ const dtSoft = (c) => dtA(c, '18');
|
||||
const dtRing = (c) => dtA(c, '26');
|
||||
const dtEdge = (c) => dtA(c, '55');
|
||||
|
||||
const BRAND = '#662582';
|
||||
const BRAND = '#C01227';
|
||||
|
||||
const SoftPaper = (props) => (
|
||||
<Paper
|
||||
@@ -181,8 +181,8 @@ const pillFieldSx = () => ({
|
||||
fontWeight: 600,
|
||||
'& fieldset': { borderColor: '#e2e8f0', borderWidth: 1 },
|
||||
'&:hover fieldset': { borderColor: '#cbd5e1' },
|
||||
'&.Mui-focused': { boxShadow: `0 0 0 3px ${dtRing('#662582')}` },
|
||||
'&.Mui-focused fieldset': { borderColor: '#662582', borderWidth: 1.5 }
|
||||
'&.Mui-focused': { boxShadow: `0 0 0 3px ${dtRing('#C01227')}` },
|
||||
'&.Mui-focused fieldset': { borderColor: '#C01227', borderWidth: 1.5 }
|
||||
}
|
||||
});
|
||||
|
||||
@@ -967,7 +967,7 @@ const Orders = () => {
|
||||
{/* ============================================= || KPI Cards || ============================================= */}
|
||||
<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: '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 }
|
||||
@@ -1279,7 +1279,7 @@ const Orders = () => {
|
||||
bgcolor: dtTint(BRAND),
|
||||
'& fieldset': { borderColor: dtEdge(BRAND), borderWidth: 1.5 },
|
||||
'&: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)}` }
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -107,7 +107,7 @@ export default function RidersRoutes({ details, loading, riderName, dateRange, o
|
||||
// brand purple to match the planned-route polyline below.
|
||||
const stepIcon = (n, isFocused) => {
|
||||
const size = isFocused ? 38 : 32;
|
||||
const color = isFocused ? '#4D1C61' : '#662582';
|
||||
const color = isFocused ? '#900E1D' : '#C01227';
|
||||
const svg = encodeURIComponent(
|
||||
`<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"/>` +
|
||||
@@ -126,7 +126,7 @@ export default function RidersRoutes({ details, loading, riderName, dateRange, o
|
||||
px: 2,
|
||||
py: 1.25,
|
||||
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',
|
||||
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. */}
|
||||
<Polyline
|
||||
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. */}
|
||||
<Polyline
|
||||
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
|
||||
path={dropPath}
|
||||
options={{
|
||||
strokeColor: '#662582',
|
||||
strokeColor: '#C01227',
|
||||
strokeOpacity: 0,
|
||||
strokeWeight: 0,
|
||||
icons: [
|
||||
@@ -229,7 +229,7 @@ export default function RidersRoutes({ details, loading, riderName, dateRange, o
|
||||
icon: {
|
||||
path: 'M 0,-1 0,1',
|
||||
strokeOpacity: 0.6,
|
||||
strokeColor: '#662582',
|
||||
strokeColor: '#C01227',
|
||||
scale: 3
|
||||
},
|
||||
offset: '0',
|
||||
|
||||
@@ -114,8 +114,8 @@ const soft = (c) => a(c, '18');
|
||||
const ring = (c) => a(c, '26');
|
||||
const edge = (c) => a(c, '55');
|
||||
|
||||
const BRAND = '#662582';
|
||||
const BRAND_LIGHT = '#9255AB';
|
||||
const BRAND = '#C01227';
|
||||
const BRAND_LIGHT = '#D35968';
|
||||
|
||||
const SoftPaper = (props) => (
|
||||
<Paper
|
||||
@@ -153,7 +153,7 @@ const pillFieldSx = (color) => ({
|
||||
'& fieldset': { borderColor: '#e2e8f0', borderWidth: 1 },
|
||||
'&:hover fieldset': { borderColor: '#cbd5e1' },
|
||||
'&.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',
|
||||
'& fieldset': { borderColor: '#e2e8f0', borderWidth: 1 },
|
||||
'&: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)}` }
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -87,8 +87,8 @@ const soft = (c) => a(c, '18');
|
||||
const ring = (c) => a(c, '26');
|
||||
const edge = (c) => a(c, '55');
|
||||
|
||||
const BRAND = '#662582';
|
||||
const BRAND_LIGHT = '#9255AB';
|
||||
const BRAND = '#C01227';
|
||||
const BRAND_LIGHT = '#D35968';
|
||||
|
||||
const SoftPaper = (props) => (
|
||||
<Paper
|
||||
@@ -190,7 +190,7 @@ const pillFieldSx = (color) => ({
|
||||
'& fieldset': { borderColor: '#e2e8f0', borderWidth: 1 },
|
||||
'&:hover fieldset': { borderColor: '#cbd5e1' },
|
||||
'&.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',
|
||||
'& fieldset': { borderColor: '#e2e8f0', borderWidth: 1 },
|
||||
'&: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)}` }
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -66,7 +66,7 @@ const tint = (c) => aColor(c, '08');
|
||||
const edge = (c) => aColor(c, '55');
|
||||
const ring = (c) => aColor(c, '26');
|
||||
|
||||
const BRAND = '#662582';
|
||||
const BRAND = '#C01227';
|
||||
|
||||
const SoftPaper = (props) => (
|
||||
<Paper
|
||||
@@ -552,7 +552,7 @@ export default function ProfitabilityReport() {
|
||||
bgcolor: '#ffffff',
|
||||
'& fieldset': { borderColor: '#e2e8f0', borderWidth: 1 },
|
||||
'&: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)}` }
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -86,8 +86,8 @@ const soft = (c) => a(c, '18');
|
||||
const ring = (c) => a(c, '26');
|
||||
const edge = (c) => a(c, '55');
|
||||
|
||||
const BRAND = '#662582';
|
||||
const BRAND_LIGHT = '#9255AB';
|
||||
const BRAND = '#C01227';
|
||||
const BRAND_LIGHT = '#D35968';
|
||||
|
||||
const SoftPaper = (props) => (
|
||||
<Paper
|
||||
@@ -456,7 +456,7 @@ export default function RidersSummary() {
|
||||
bgcolor: '#ffffff',
|
||||
'& fieldset': { borderColor: '#e2e8f0', borderWidth: 1 },
|
||||
'&: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)}` }
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -902,7 +902,7 @@ const Requests = () => {
|
||||
<MobileCardList scroll>
|
||||
{loading &&
|
||||
[0, 1, 2, 3, 4].map((item) => (
|
||||
<MobileCard key={item} accent="#662582">
|
||||
<MobileCard key={item} accent="#C01227">
|
||||
<Stack direction="row" alignItems="center" spacing={1}>
|
||||
<Skeleton variant="circular" width={32} height={32} />
|
||||
<Stack sx={{ flex: 1 }}>
|
||||
@@ -923,13 +923,13 @@ const Requests = () => {
|
||||
return (
|
||||
<MobileCard
|
||||
key={row.sno}
|
||||
accent="#662582"
|
||||
accent="#C01227"
|
||||
selected={isItemSelected}
|
||||
onClick={(event) => handleClick(event, row.sno)}
|
||||
header={
|
||||
<Stack direction="row" alignItems="center" justifyContent="space-between" spacing={1}>
|
||||
<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() : '#'}
|
||||
</Avatar>
|
||||
<Stack sx={{ minWidth: 0 }}>
|
||||
@@ -942,7 +942,7 @@ const Requests = () => {
|
||||
</Stack>
|
||||
</Stack>
|
||||
{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>
|
||||
}
|
||||
|
||||
@@ -269,7 +269,7 @@ export default function RiderSubstitution({
|
||||
bgcolor: BRAND,
|
||||
color: '#fff',
|
||||
'&:hover': {
|
||||
bgcolor: '#4D1C61'
|
||||
bgcolor: '#900E1D'
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -657,7 +657,7 @@ export default function RiderSubstitution({
|
||||
fontWeight: 700,
|
||||
textTransform: 'none',
|
||||
'&:hover': {
|
||||
bgcolor: '#4D1C61'
|
||||
bgcolor: '#900E1D'
|
||||
}
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -77,7 +77,7 @@ import RiderSubstitution from './RiderSubstitution';
|
||||
// ============================================================================
|
||||
// Design tokens — shared with the deliveries / tenants / customers pages so
|
||||
// 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.
|
||||
// ============================================================================
|
||||
const DT = {
|
||||
@@ -100,7 +100,7 @@ const soft = (c) => a(c, '18');
|
||||
const ring = (c) => a(c, '26');
|
||||
const edge = (c) => a(c, '55');
|
||||
|
||||
const BRAND = '#662582';
|
||||
const BRAND = '#C01227';
|
||||
|
||||
const SoftPaper = (props) => (
|
||||
<Paper
|
||||
@@ -763,7 +763,7 @@ const Riders = () => {
|
||||
bgcolor: '#ffffff',
|
||||
'& fieldset': { borderColor: '#e2e8f0', borderWidth: 1 },
|
||||
'&: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)}` }
|
||||
}}
|
||||
/>
|
||||
@@ -813,7 +813,7 @@ const Riders = () => {
|
||||
bgcolor: BRAND,
|
||||
color: '#fff',
|
||||
'&:hover': {
|
||||
bgcolor: '#4D1C61'
|
||||
bgcolor: '#900E1D'
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1914,7 +1914,7 @@ const Riders = () => {
|
||||
fontWeight: 600,
|
||||
bgcolor: BRAND,
|
||||
color: '#fff',
|
||||
'&:hover': { bgcolor: '#4D1C61' }
|
||||
'&:hover': { bgcolor: '#900E1D' }
|
||||
}}
|
||||
>
|
||||
Save Changes
|
||||
|
||||
@@ -31,8 +31,8 @@ const DT = {
|
||||
surface: '#ffffff',
|
||||
surfaceAlt: '#f8fafc'
|
||||
};
|
||||
const BRAND = '#662582';
|
||||
const BRAND_LIGHT = '#9255AB';
|
||||
const BRAND = '#C01227';
|
||||
const BRAND_LIGHT = '#D35968';
|
||||
const tint = (c) => `${c}08`;
|
||||
const soft = (c) => `${c}18`;
|
||||
|
||||
@@ -143,7 +143,7 @@ const ViewProfile = () => {
|
||||
color: '#fff',
|
||||
fontSize: { xs: 24, md: 28 },
|
||||
fontWeight: 700,
|
||||
boxShadow: '0 10px 24px rgba(102, 37, 130, 0.35)'
|
||||
boxShadow: '0 10px 24px rgba(192, 18, 39, 0.35)'
|
||||
}}
|
||||
>
|
||||
{initialsOf(fullname)}
|
||||
|
||||
@@ -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;
|
||||
@@ -121,7 +121,7 @@ export default function ThemeCustomization({ children }) {
|
||||
// soft slate that tints toward brand purple on hover.
|
||||
'*': {
|
||||
scrollbarWidth: 'thin', // Firefox
|
||||
scrollbarColor: 'rgba(102, 37, 130, 0.28) transparent'
|
||||
scrollbarColor: 'rgba(192, 18, 39, 0.28) transparent'
|
||||
},
|
||||
'*::-webkit-scrollbar': {
|
||||
width: '10px',
|
||||
@@ -131,13 +131,13 @@ export default function ThemeCustomization({ children }) {
|
||||
backgroundColor: 'transparent'
|
||||
},
|
||||
'*::-webkit-scrollbar-thumb': {
|
||||
backgroundColor: 'rgba(102, 37, 130, 0.26)',
|
||||
backgroundColor: 'rgba(192, 18, 39, 0.26)',
|
||||
borderRadius: '8px',
|
||||
border: '2px solid transparent',
|
||||
backgroundClip: 'padding-box'
|
||||
},
|
||||
'*::-webkit-scrollbar-thumb:hover': {
|
||||
backgroundColor: 'rgba(102, 37, 130, 0.45)'
|
||||
backgroundColor: 'rgba(192, 18, 39, 0.45)'
|
||||
},
|
||||
'*::-webkit-scrollbar-corner': {
|
||||
backgroundColor: 'transparent'
|
||||
|
||||
@@ -23,10 +23,10 @@ export default function Autocomplete() {
|
||||
borderRadius: 8,
|
||||
margin: '1px 0',
|
||||
'&[aria-selected="true"]': {
|
||||
backgroundColor: 'rgba(102, 37, 130, 0.08)'
|
||||
backgroundColor: 'rgba(192, 18, 39, 0.08)'
|
||||
},
|
||||
'&.Mui-focused': {
|
||||
backgroundColor: 'rgba(102, 37, 130, 0.06)'
|
||||
backgroundColor: 'rgba(192, 18, 39, 0.06)'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -40,16 +40,16 @@ const Default = (colors) => {
|
||||
// contrastText
|
||||
// },
|
||||
primary: {
|
||||
lighter: '#E8D9EF',
|
||||
100: '#CBA7DA',
|
||||
200: '#AE76C4',
|
||||
light: '#9255AB',
|
||||
400: '#9255AB',
|
||||
main: '#662582',
|
||||
dark: '#4D1C61',
|
||||
700: '#3A1549',
|
||||
darker: '#260E30',
|
||||
900: '#17081D',
|
||||
lighter: '#F6DBDF',
|
||||
100: '#E9ACB3',
|
||||
200: '#DD7F8A',
|
||||
light: '#D35968',
|
||||
400: '#D35968',
|
||||
main: '#C01227',
|
||||
dark: '#900E1D',
|
||||
700: '#6D0A16',
|
||||
darker: '#47070E',
|
||||
900: '#2A0409',
|
||||
contrastText: '#FFFFFF'
|
||||
},
|
||||
secondary: {
|
||||
|
||||
@@ -18,5 +18,6 @@
|
||||
"riderslogs": "Riders Logs",
|
||||
"invoice": "Invoice",
|
||||
"dispatch": "Dispatch",
|
||||
"profitability": "Profitability"
|
||||
"profitability": "Profitability",
|
||||
"Doormile": "Doormile"
|
||||
}
|
||||
|
||||