From c17b055c2e844fde24097a3bbd54793cab057187 Mon Sep 17 00:00:00 2001 From: Wang Ng Date: Sat, 18 Jul 2026 19:31:45 -0500 Subject: [PATCH 1/3] fix(ui): modify dropdown to match component UI replace default dropdown UI from mac/windows to a custom designed one --- .../components/address/CSVUploadOverlay.tsx | 269 ++++++++++++++---- app/ui/src/app/edit/formStyles.v2.ts | 12 +- 2 files changed, 224 insertions(+), 57 deletions(-) diff --git a/app/ui/src/app/edit/components/address/CSVUploadOverlay.tsx b/app/ui/src/app/edit/components/address/CSVUploadOverlay.tsx index 519bbafc..3b5153f1 100644 --- a/app/ui/src/app/edit/components/address/CSVUploadOverlay.tsx +++ b/app/ui/src/app/edit/components/address/CSVUploadOverlay.tsx @@ -1,6 +1,14 @@ "use client"; -import { useRef, useState, useCallback, useMemo, useEffect } from "react"; +import { + useRef, + useState, + useCallback, + useMemo, + useEffect, + useLayoutEffect, + type CSSProperties, +} from "react"; import { OVERLAY_BACKDROP, OVERLAY_HEADER, @@ -10,6 +18,7 @@ import { OVERLAY_CANCEL_BTN, OVERLAY_PRIMARY_BTN, CSV_UPLOAD_OVERLAY_PANEL, + CSV_UPLOAD_OVERLAY_PANEL_TALL, CSV_UPLOAD_OVERLAY_INNER, CSV_UPLOAD_OVERLAY_CONTENT, CSV_UPLOAD_OVERLAY_TOP, @@ -26,6 +35,14 @@ import { CSV_UPLOAD_FILE_CHIP_RIGHT, CSV_UPLOAD_FILE_CHIP_SIZE, CSV_UPLOAD_FILE_CHIP_REMOVE, + OVERLAY_SELECT_WRAPPER, + OVERLAY_SELECT_VALUE, + OVERLAY_SELECT_ICON, + CSV_UPLOAD_SELECT_PLACEHOLDER, + OVERLAY_AUTOCOMPLETE_DROPDOWN, + OVERLAY_AUTOCOMPLETE_ITEM, + OVERLAY_AUTOCOMPLETE_ITEM_ACTIVE, + OVERLAY_AUTOCOMPLETE_ITEM_TEXT, } from "@/app/edit/formStyles.v2"; import ErrorOverlay from "@/app/edit/components/shared/ErrorOverlay"; import type { AddressCard } from "@/app/edit/types/delivery"; @@ -58,6 +75,22 @@ type CSVUploadOverlayProps = { initialFile?: File; }; +const CHEVRON_DOWN_ICON = ( + + + +); + const MAX_CSV_BYTES = 10 * 1024 * 1024; function formatFileSize(bytes: number): string { @@ -106,6 +139,175 @@ function buildAddressCards( }); } +// ─── Custom mapping dropdown (matches overlay design instead of native - onMappingChange(header, e.target.value as MappableField) - } - className="absolute inset-0 w-full h-full opacity-0 cursor-pointer" - > - - {( - Object.keys(FIELD_LABELS) as Exclude< - MappableField, - "" - >[] - ).map((f) => ( - - ))} - - - {mapping[header] - ? FIELD_LABELS[ - mapping[header] as Exclude - ] - : "Select"} - - - - - + onMappingChange(header, field)} + />
{previewRows.map((row, i) => { @@ -350,7 +511,7 @@ function StepRowSelector({ Review and select information to import

-
+
e.stopPropagation()} role="dialog" aria-modal="true" diff --git a/app/ui/src/app/edit/formStyles.v2.ts b/app/ui/src/app/edit/formStyles.v2.ts index c0892095..20c0ebae 100644 --- a/app/ui/src/app/edit/formStyles.v2.ts +++ b/app/ui/src/app/edit/formStyles.v2.ts @@ -792,14 +792,17 @@ export const ERROR_OVERLAY_FOOTER = "flex items-center justify-end"; export const CSV_UPLOAD_OVERLAY_PANEL = "bg-[var(--edit-bg-primary)] flex flex-col gap-[14px] items-end overflow-hidden p-4 lg:p-6 rounded-[6px] w-full lg:max-w-[800px] mx-2 lg:mx-4 shadow-lg max-h-[90dvh]"; +export const CSV_UPLOAD_OVERLAY_PANEL_TALL = + "bg-[var(--edit-bg-primary)] flex flex-col gap-[14px] items-end overflow-hidden p-4 lg:p-6 rounded-[6px] w-full lg:max-w-[800px] mx-2 lg:mx-4 shadow-lg h-[90dvh]"; + export const CSV_UPLOAD_OVERLAY_INNER = - "flex flex-col gap-[16px] items-end w-full"; + "flex flex-col gap-[16px] items-end w-full flex-1 min-h-0"; export const CSV_UPLOAD_OVERLAY_CONTENT = - "flex flex-col gap-[16px] items-center w-full"; + "flex flex-col gap-[16px] items-center w-full flex-1 min-h-0"; export const CSV_UPLOAD_OVERLAY_TOP = - "flex flex-col gap-[24px] items-start w-full"; + "flex flex-col gap-[24px] items-start w-full flex-1 min-h-0"; export const CSV_UPLOAD_DROP_ZONE = "bg-[var(--edit-stone-50)] border border-[var(--edit-stone-200)] border-dashed flex flex-col h-[200px] items-center justify-center overflow-clip pt-[24px] pb-[16px] rounded-[6px] w-full"; @@ -841,6 +844,9 @@ export const CSV_UPLOAD_FILE_CHIP_SIZE = export const CSV_UPLOAD_FILE_CHIP_REMOVE = "flex items-center justify-center size-4 text-[var(--edit-text-primary)] hover:opacity-70 transition-opacity cursor-pointer"; +export const CSV_UPLOAD_SELECT_PLACEHOLDER = + "font-normal text-[16px] leading-6 text-[var(--edit-stone-600)] pointer-events-none flex-1 truncate"; + // ── SpinnerIcon ─────────────────────────────────────────────────────────────── export const SPINNER_ICON_WRAPPER = "relative size-[33px]"; From 7a07421d856a9f1b77e055b2a9653074a50d7ffc Mon Sep 17 00:00:00 2001 From: Wang Ng Date: Sat, 18 Jul 2026 19:33:15 -0500 Subject: [PATCH 2/3] fix(ui): update 'upload file' to match updated design --- app/ui/src/app/upload-route/page.tsx | 95 ++++++++++++----------- app/ui/src/app/upload-save-point/page.tsx | 93 ++++++++++++---------- app/ui/src/app/welcome/page.tsx | 24 +++--- 3 files changed, 114 insertions(+), 98 deletions(-) diff --git a/app/ui/src/app/upload-route/page.tsx b/app/ui/src/app/upload-route/page.tsx index 42ae6195..3436f311 100644 --- a/app/ui/src/app/upload-route/page.tsx +++ b/app/ui/src/app/upload-route/page.tsx @@ -119,48 +119,64 @@ export default function UploadRoutePage() { .upload-dropzone { width: 100%; max-width: 580px; - border: 1.5px dashed #ccc; - border-radius: 12px; - padding: 52px 24px; + height: 200px; + border: 1px dashed #dcdbd8; + border-radius: 6px; + padding: 24px 24px 16px; display: flex; flex-direction: column; align-items: center; justify-content: center; - gap: 10px; - cursor: pointer; - background: #f9f9f8; + gap: 8px; + background: #f8f7f5; transition: border-color 0.15s, background 0.15s; - margin-bottom: 16px; - min-height: 160px; + margin-bottom: 8px; } .upload-dropzone.dragging { - border-color: #4a8c7a; - background: #f0f7f5; + border-color: #57ac91; + background: #f0faf6; } - .upload-dropzone-icon { color: #555; margin-bottom: 4px; } + .upload-dropzone-icon { color: #3d3d3c; margin-bottom: 4px; display: flex; } .upload-dropzone-text { - font-size: 14px; - color: #333; + font-size: 16px; + color: #272725; text-align: center; } .upload-dropzone-browse { font-size: 14px; - color: #4a8c7a; - font-weight: 500; + font-weight: 600; + color: #272725; text-align: center; + background: none; + border: none; + cursor: pointer; + font-family: inherit; + padding: 8px 16px; + border-radius: 4px; + transition: background 0.15s; + } + + .upload-dropzone-browse:hover { background: #f6f5f2; } + + .upload-dropzone-description { + width: 100%; + max-width: 580px; + font-size: 14px; + color: #464544; + margin-bottom: 24px; } .upload-file-row { width: 100%; max-width: 580px; - background: #eef5f3; - border: 1px solid #d0e5df; - border-radius: 8px; - padding: 10px 16px; + background: #d5f2e8; + border: none; + border-radius: 6px; + padding: 16px; display: flex; align-items: center; gap: 10px; @@ -306,7 +322,6 @@ export default function UploadRoutePage() { {/* Drop zone — shows spinner while file is being read */}
!isProcessing && inputRef.current?.click()} onDragEnter={handleDragEnter} onDragOver={(e) => e.preventDefault()} onDragLeave={handleDragLeave} @@ -317,36 +332,23 @@ export default function UploadRoutePage() { ) : ( <>
- - - +

Drag and drop .json files here, or

-

Browse files

+ )}
+

+ Import your route file to begin. Maximum file size of {MAX_FILE_MB}{" "} + MB. +

+ {file && !isProcessing && (
!isProcessing && inputRef.current?.click()} onDragEnter={handleDragEnter} onDragOver={(e) => e.preventDefault()} onDragLeave={handleDragLeave} @@ -315,34 +330,23 @@ export default function UploadSavePointPage() { ) : ( <>
- + - -

Drag and drop .json or .csv files here, or

-

Browse files

+ )}
+

+ Import a save point or CSV file to continue. Maximum file size of{" "} + {MAX_FILE_MB} MB. +

+ {file && !isProcessing && (
-

Resume session

+

Start new session

- Import a saved CSV file from a previous session to continue - managing and optimizing routes. + Set up vehicles, drivers, and delivery stops to create your + optimized route.

@@ -218,22 +218,22 @@ export default function WelcomePage() {
-

Start new session

+

Resume session

- Set up vehicles, drivers, and delivery stops to create your - optimized route. + Import a saved CSV file from a previous session to continue + managing and optimizing routes.

From ff614ed6d6465a9c17837a42dab5bbaff4cd85f2 Mon Sep 17 00:00:00 2001 From: Wang Ng Date: Mon, 20 Jul 2026 22:08:56 -0500 Subject: [PATCH 3/3] make csv parser box dynamic based on # of entries --- app/ui/src/app/edit/formStyles.v2.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/ui/src/app/edit/formStyles.v2.ts b/app/ui/src/app/edit/formStyles.v2.ts index 20c0ebae..7ca6c5a5 100644 --- a/app/ui/src/app/edit/formStyles.v2.ts +++ b/app/ui/src/app/edit/formStyles.v2.ts @@ -793,7 +793,7 @@ export const CSV_UPLOAD_OVERLAY_PANEL = "bg-[var(--edit-bg-primary)] flex flex-col gap-[14px] items-end overflow-hidden p-4 lg:p-6 rounded-[6px] w-full lg:max-w-[800px] mx-2 lg:mx-4 shadow-lg max-h-[90dvh]"; export const CSV_UPLOAD_OVERLAY_PANEL_TALL = - "bg-[var(--edit-bg-primary)] flex flex-col gap-[14px] items-end overflow-hidden p-4 lg:p-6 rounded-[6px] w-full lg:max-w-[800px] mx-2 lg:mx-4 shadow-lg h-[90dvh]"; + "bg-[var(--edit-bg-primary)] flex flex-col gap-[14px] items-end overflow-hidden p-4 lg:p-6 rounded-[6px] w-full lg:max-w-[800px] mx-2 lg:mx-4 shadow-lg min-h-[360px] max-h-[90dvh]"; export const CSV_UPLOAD_OVERLAY_INNER = "flex flex-col gap-[16px] items-end w-full flex-1 min-h-0";