updates on the map configuration and the design

This commit is contained in:
2026-08-28 16:42:19 +05:30
parent 01d69e2f4f
commit 2c892b93c3
3 changed files with 172 additions and 51 deletions

View File

@@ -1,7 +1,7 @@
import { memo, useState } from 'react';
import PropTypes from 'prop-types';
import { AiOutlineCopy as CopyOutlined } from 'react-icons/ai';
import { LuChevronDown } from 'react-icons/lu';
import { LuChevronDown, LuDownload } from 'react-icons/lu';
import { HStack } from '@astryxdesign/core/HStack';
import { VStack } from '@astryxdesign/core/VStack';
@@ -112,7 +112,9 @@ const AssistantMessage = ({ message, onCopy, onSubmitForm, onCancelAction, onCho
{/* A conversational step that needs a dropdown rather than typing. */}
{message.liveStop && (
<VStack className="dai-action" gap={1} padding={0}>
<Button label="Stop" variant="secondary" size="sm" onClick={() => onStopLive(message)} />
<Button variant="secondary" size="sm" onClick={() => onStopLive(message)}>
Stop
</Button>
</VStack>
)}
@@ -195,11 +197,16 @@ const AssistantMessage = ({ message, onCopy, onSubmitForm, onCancelAction, onCho
{message.downloadRows?.length > 0 && (
<VStack className="dai-action" gap={1} padding={0}>
<Button
label={`Download the ${message.downloadRows.length} row${message.downloadRows.length === 1 ? '' : 's'} that didn’t go through`}
variant="secondary"
variant="outline"
size="sm"
className="flex items-center justify-center gap-2 text-xs font-medium text-slate-700 bg-white border border-slate-200 hover:bg-slate-50 hover:text-slate-900 rounded-lg px-3.5 py-2 w-full shadow-2xs transition-colors cursor-pointer"
onClick={() => downloadCsv('doormile-bulk-orders-unsendable.csv', failedRowsCsv(message.downloadRows))}
/>
>
<LuDownload className="w-3.5 h-3.5 text-slate-500 shrink-0" />
<span>
Download {message.downloadRows.length} unsendable row{message.downloadRows.length === 1 ? '' : 's'} (CSV)
</span>
</Button>
</VStack>
)}

View File

@@ -1,15 +1,17 @@
import { useLocation, useNavigate } from 'react-router-dom';
import { Home } from 'lucide-react';
import { Button, EmptyState, Surface } from '@/components/ds';
import React from 'react';
import { useLocation, useNavigate, Link } from 'react-router-dom';
import {
ArrowLeft,
Radio,
Package,
Bike,
BarChart3,
Home,
MapPin,
Truck
} from 'lucide-react';
import { useAuth } from '@/lib/AuthContext';
/**
* The 404 page.
*
* Signed-in operators get a second line naming the route table, because a
* missing route in a console is nearly always a link that was renamed rather
* than a page that never existed.
*/
export default function PageNotFound() {
const location = useLocation();
const navigate = useNavigate();
@@ -17,26 +19,139 @@ export default function PageNotFound() {
const path = location.pathname;
return (
<main className="flex min-h-screen items-center justify-center p-6">
<Surface radius="xl" padding="lg" className="w-full max-w-md">
<EmptyState
icon={Home}
title="Page not found"
description={`Nothing is registered at "${path}".`}
action={
<Button onClick={() => navigate(isAuthenticated ? '/doormile/dispatch' : '/login')}>
{isAuthenticated ? 'Back to Dispatch' : 'Sign in'}
</Button>
}
/>
const quickLinks = [
{
title: 'Live Dispatch',
desc: 'Real-time fleet tracking & active runs',
icon: Radio,
path: '/doormile/dispatch',
color: 'text-rose-600 bg-rose-50 border-rose-200/70 group-hover:bg-rose-100/70'
},
{
title: 'Orders Management',
desc: 'Pending, assigned, and bulk bookings',
icon: Package,
path: '/doormile/orders',
color: 'text-blue-600 bg-blue-50 border-blue-200/70 group-hover:bg-blue-100/70'
},
{
title: 'Live Deliveries',
desc: 'Active consignments & transit logs',
icon: Truck,
path: '/doormile/deliveries',
color: 'text-amber-600 bg-amber-50 border-amber-200/70 group-hover:bg-amber-100/70'
},
{
title: 'Milers Fleet',
desc: 'Rider profiles, roster & status',
icon: Bike,
path: '/doormile/milers',
color: 'text-emerald-600 bg-emerald-50 border-emerald-200/70 group-hover:bg-emerald-100/70'
},
{
title: 'Reports & Analytics',
desc: 'Daily summaries & financial KPIs',
icon: BarChart3,
path: '/doormile/reports/orderssummary',
color: 'text-purple-600 bg-purple-50 border-purple-200/70 group-hover:bg-purple-100/70'
}
];
return (
<main className="relative min-h-screen w-full bg-white text-slate-900 flex flex-col items-center justify-center p-6 selection:bg-rose-500 selection:text-white">
{/* Background subtle mesh & grid */}
<div className="absolute inset-0 bg-[radial-gradient(ellipse_80%_60%_at_50%_-10%,rgba(216,30,6,0.06),rgba(255,255,255,0))] pointer-events-none" />
<div className="absolute inset-0 bg-[linear-gradient(to_right,#0f172a08_1px,transparent_1px),linear-gradient(to_bottom,#0f172a08_1px,transparent_1px)] bg-[size:32px_32px] [mask-image:radial-gradient(ellipse_60%_50%_at_50%_40%,#000_70%,transparent_100%)] pointer-events-none" />
<div className="relative z-10 w-full max-w-2xl flex flex-col items-center text-center">
{/* Top Brand Pill */}
<div className="inline-flex items-center gap-2 px-3.5 py-1.5 rounded-full bg-white border border-slate-200/90 shadow-2xs mb-5">
<span className="w-2 h-2 rounded-full bg-rose-600 animate-pulse" />
<span className="text-xs font-semibold tracking-wider uppercase text-slate-600">
Doormile Operations Console
</span>
</div>
{/* Clean 404 Visual Graphic without any overlay icon */}
<div className="select-none my-1">
<span className="text-8xl sm:text-9xl font-black tracking-tight text-slate-900 bg-clip-text bg-gradient-to-b from-slate-900 via-slate-800 to-slate-400">
404
</span>
</div>
{/* Heading & Context */}
<h1 className="text-2xl sm:text-3xl font-bold tracking-tight text-slate-900 mb-2">
Page not found
</h1>
<p className="text-sm sm:text-base text-slate-600 max-w-lg mb-4">
The requested destination is not registered in the console or has been moved to a new route.
</p>
{/* Target Path Badge */}
<div className="inline-flex items-center gap-2 max-w-full px-3.5 py-1.5 rounded-lg bg-slate-100 border border-slate-200 font-mono text-xs text-rose-600 mb-7 shadow-2xs truncate">
<MapPin className="w-3.5 h-3.5 text-slate-500 shrink-0" />
<span className="truncate">{path}</span>
</div>
{/* Primary & Secondary Action CTAs */}
<div className="flex flex-wrap items-center justify-center gap-3 w-full max-w-md mb-9">
<button
type="button"
onClick={() => navigate(isAuthenticated ? '/doormile/dispatch' : '/login')}
className="flex-1 min-w-[160px] inline-flex items-center justify-center gap-2 px-5 py-2.5 rounded-xl font-medium text-sm text-white bg-rose-600 hover:bg-rose-700 active:scale-[0.98] shadow-sm shadow-rose-600/20 transition-all cursor-pointer"
>
<Home className="w-4 h-4" />
<span>{isAuthenticated ? 'Back to Dispatch' : 'Sign in to Console'}</span>
</button>
<button
type="button"
onClick={() => navigate(-1)}
className="flex-1 min-w-[140px] inline-flex items-center justify-center gap-2 px-5 py-2.5 rounded-xl font-medium text-sm text-slate-700 bg-white hover:bg-slate-50 border border-slate-200 active:scale-[0.98] transition-all cursor-pointer shadow-2xs"
>
<ArrowLeft className="w-4 h-4" />
<span>Go Back</span>
</button>
</div>
{/* Quick Operations Links */}
{isAuthenticated && (
<p className="mt-2 text-center text-caption text-ink-4">
If this address used to work, check the route table in <code>src/App.jsx</code>.
</p>
<div className="w-full bg-slate-50/80 border border-slate-200 rounded-2xl p-5 shadow-xs">
<div className="flex items-center justify-between mb-3 text-left">
<span className="text-xs font-semibold uppercase tracking-wider text-slate-600">
Quick Navigation
</span>
<span className="text-[11px] text-slate-500">Operational shortcuts</span>
</div>
<div className="grid grid-cols-1 sm:grid-cols-2 gap-2.5 text-left">
{quickLinks.map((item) => {
const IconComponent = item.icon;
return (
<Link
key={item.path}
to={item.path}
className="flex items-center gap-3 p-2.5 rounded-xl bg-white hover:bg-slate-50/90 border border-slate-200/90 hover:border-slate-300 shadow-2xs transition-all group"
>
<div className={`w-8 h-8 rounded-lg flex items-center justify-center shrink-0 border ${item.color} transition-transform group-hover:scale-105`}>
<IconComponent className="w-4 h-4" />
</div>
<div className="min-w-0 flex-1">
<div className="text-xs font-semibold text-slate-800 group-hover:text-slate-950 truncate">
{item.title}
</div>
<div className="text-[11px] text-slate-500 truncate">
{item.desc}
</div>
</div>
</Link>
);
})}
</div>
</div>
)}
</Surface>
</div>
</main>
);
}

View File

@@ -5237,12 +5237,12 @@
padding-right: 44px;
}
/* --- Header: purple gradient with order id + status + rider --- */
/* --- Header: red gradient with order id + status + rider --- */
.dispatch-container .dispatch-popup .pu-header {
background: var(--color-accent);
background: linear-gradient(135deg, #D81E06 0%, #C8102E 100%);
padding: 14px 16px 12px;
color: #fff;
border-radius: 5px 5px 0 0;
border-radius: 8px 8px 0 0;
}
.dispatch-container .dispatch-popup .pu-header-top {
@@ -5254,8 +5254,7 @@
}
.dispatch-container .dispatch-popup .pu-id {
/* Override the legacy pu-id styling — no separate background, sits on
the purple gradient instead. */
/* Override the legacy pu-id styling — sits on the red header instead. */
background: transparent;
border: 0;
border-radius: 0;
@@ -5374,13 +5373,13 @@
font-weight: 800;
letter-spacing: 0.08em;
text-transform: uppercase;
color: var(--color-accent);
color: #D81E06;
}
.dispatch-container .dispatch-popup .pu-header-step-value {
font-size: 15px;
font-weight: 800;
color: var(--color-accent);
color: #D81E06;
white-space: nowrap;
}
@@ -5405,8 +5404,8 @@
font-weight: 800;
letter-spacing: 0.08em;
text-transform: uppercase;
color: var(--color-accent);
border-bottom: 1px solid rgba(123, 31, 162, 0.18);
color: #D81E06;
border-bottom: 1px solid rgba(216, 30, 6, 0.15);
}
/* --- Timeline: lay events out as a 2-column grid so the 6-row vertical
@@ -5438,18 +5437,18 @@
align-items: flex-start;
gap: 8px;
padding: 8px 10px;
background: rgba(123, 31, 162, 0.05);
border: 1px solid rgba(123, 31, 162, 0.12);
border-radius: 5px;
background: rgba(216, 30, 6, 0.04);
border: 1px solid rgba(216, 30, 6, 0.1);
border-radius: 6px;
min-width: 0;
}
.dispatch-container .dispatch-popup .pu-detail-icon {
width: 26px;
height: 26px;
border-radius: 5px;
background: rgba(123, 31, 162, 0.12);
color: var(--color-accent);
border-radius: 6px;
background: rgba(216, 30, 6, 0.1);
color: #D81E06;
display: flex;
align-items: center;
justify-content: center;
@@ -5492,7 +5491,7 @@
gap: 6px;
margin-top: 8px;
padding-top: 8px;
border-top: 1px dashed rgba(123, 31, 162, 0.18);
border-top: 1px dashed rgba(216, 30, 6, 0.18);
}
.dispatch-container .dispatch-popup .pu-distance-chip {
@@ -5500,8 +5499,8 @@
align-items: center;
gap: 5px;
padding: 5px 10px;
background: linear-gradient(135deg, rgba(123, 31, 162, 0.08), rgba(156, 39, 176, 0.06));
border: 1px solid rgba(123, 31, 162, 0.2);
background: rgba(216, 30, 6, 0.05);
border: 1px solid rgba(216, 30, 6, 0.15);
border-radius: 999px;
font-size: 11px;
font-weight: 600;
@@ -5509,7 +5508,7 @@
.dispatch-container .dispatch-popup .pu-distance-icon {
display: inline-flex;
color: var(--color-accent);
color: #D81E06;
}
.dispatch-container .dispatch-popup .pu-distance-icon svg {