initialisation on the doormile express console with astryx
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# CLAUDE.md — `src/components/nearle_components/`
|
||||
|
||||
Rules for editing the shared NearlExpress UI primitives.
|
||||
Rules for editing the shared Doormile Express UI primitives.
|
||||
|
||||
These components are imported across every page. Changes here have **fan-out impact** — measure twice, cut once.
|
||||
|
||||
@@ -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 Express 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 → #D25463`.
|
||||
- **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`, 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`) 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.
|
||||
|
||||
---
|
||||
|
||||
|
||||
90
src/components/nearle_components/DateRangePicker.js
Normal file
90
src/components/nearle_components/DateRangePicker.js
Normal file
@@ -0,0 +1,90 @@
|
||||
import { useState } from 'react';
|
||||
import { Box, Button, Divider, Stack, Typography } from '@mui/material';
|
||||
import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
|
||||
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
|
||||
import { DatePicker } from '@mui/x-date-pickers/DatePicker';
|
||||
import { DT, soft, edge } from 'themes/dt/tokens';
|
||||
|
||||
// Drop-in replacement for the unmaintained `mui-daterange-picker` package
|
||||
// (pinned to React 17, never updated — see the React 19 upgrade plan).
|
||||
// Matches its public shape: `onChange({ startDate, endDate, label })` fires
|
||||
// on every selection (preset or custom), `definedRanges` renders the quick
|
||||
// picks. `open`/`toggle` are accepted for API compatibility but unused —
|
||||
// visibility is already gated by the parent Dialog.
|
||||
export const DateRangePicker = ({ onChange, definedRanges = [] }) => {
|
||||
const [customStart, setCustomStart] = useState(null);
|
||||
const [customEnd, setCustomEnd] = useState(null);
|
||||
|
||||
const pickPreset = (range) => {
|
||||
onChange({ startDate: range.startDate, endDate: range.endDate, label: range.label });
|
||||
};
|
||||
|
||||
const pickCustom = (nextStart, nextEnd) => {
|
||||
if (nextStart && nextEnd) {
|
||||
onChange({ startDate: nextStart.toDate(), endDate: nextEnd.toDate(), label: undefined });
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Stack spacing={2.5} sx={{ width: '100%', pb: 1 }}>
|
||||
<Stack direction="row" flexWrap="wrap" gap={1}>
|
||||
{definedRanges.map((range) => (
|
||||
<Button
|
||||
key={range.label}
|
||||
onClick={() => pickPreset(range)}
|
||||
sx={{
|
||||
borderRadius: DT.radiusPill + 'px',
|
||||
px: 2,
|
||||
py: 0.75,
|
||||
fontWeight: 700,
|
||||
fontSize: 13,
|
||||
textTransform: 'none',
|
||||
color: DT.textPrimary,
|
||||
bgcolor: soft('#f59e0b'),
|
||||
border: '1px solid',
|
||||
borderColor: edge('#f59e0b'),
|
||||
'&:hover': { bgcolor: soft('#f59e0b'), borderColor: '#f59e0b' }
|
||||
}}
|
||||
>
|
||||
{range.label}
|
||||
</Button>
|
||||
))}
|
||||
</Stack>
|
||||
|
||||
<Divider sx={{ borderColor: DT.divider }} />
|
||||
|
||||
<Box>
|
||||
<Typography variant="caption" sx={{ color: DT.textSecondary, fontWeight: 700, textTransform: 'uppercase' }}>
|
||||
Custom range
|
||||
</Typography>
|
||||
<LocalizationProvider dateAdapter={AdapterDayjs}>
|
||||
<Stack direction={{ xs: 'column', sm: 'row' }} spacing={1.5} sx={{ mt: 1 }}>
|
||||
<DatePicker
|
||||
label="Start date"
|
||||
value={customStart}
|
||||
onChange={(v) => {
|
||||
setCustomStart(v);
|
||||
pickCustom(v, customEnd);
|
||||
}}
|
||||
format="DD-MM-YYYY"
|
||||
slotProps={{ textField: { size: 'small', fullWidth: true } }}
|
||||
/>
|
||||
<DatePicker
|
||||
label="End date"
|
||||
value={customEnd}
|
||||
minDate={customStart || undefined}
|
||||
onChange={(v) => {
|
||||
setCustomEnd(v);
|
||||
pickCustom(customStart, v);
|
||||
}}
|
||||
format="DD-MM-YYYY"
|
||||
slotProps={{ textField: { size: 'small', fullWidth: true } }}
|
||||
/>
|
||||
</Stack>
|
||||
</LocalizationProvider>
|
||||
</Box>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
export default DateRangePicker;
|
||||
@@ -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 (
|
||||
@@ -25,7 +25,8 @@ export default function LoaderWithImage({ size = 70, imgSize = 40, alt = 'loader
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
borderRadius: '50%',
|
||||
objectFit: 'contain'
|
||||
objectFit: 'cover',
|
||||
transform: 'scale(1.4)'
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
|
||||
@@ -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 } } }}>
|
||||
|
||||
Reference in New Issue
Block a user