diff --git a/apps/edr-freight-web/backoffice/src/components/layout/FreightDashboardHeader.tsx b/apps/edr-freight-web/backoffice/src/components/layout/FreightDashboardHeader.tsx index cc8074850..e626beb58 100644 --- a/apps/edr-freight-web/backoffice/src/components/layout/FreightDashboardHeader.tsx +++ b/apps/edr-freight-web/backoffice/src/components/layout/FreightDashboardHeader.tsx @@ -87,7 +87,12 @@ const FreightDashboardHeader = ({ {pageMeta.title} @@ -120,13 +125,6 @@ const FreightDashboardHeader = ({ - - - - )} - + {hasChildren && isOpen && (
@@ -224,7 +212,16 @@ const FreightSidebar = ({ }; return ( - +
@@ -233,7 +230,11 @@ const FreightSidebar = ({ EDR Freight @@ -257,20 +258,6 @@ const FreightSidebar = ({
))} - -
-
- - - - All systems operational - - - EDR Platform · v1.0 - - -
-
); }; diff --git a/apps/edr-freight-web/backoffice/src/pages/auth/LoginPage.tsx b/apps/edr-freight-web/backoffice/src/pages/auth/LoginPage.tsx index 23f05f3af..e689ef9f8 100644 --- a/apps/edr-freight-web/backoffice/src/pages/auth/LoginPage.tsx +++ b/apps/edr-freight-web/backoffice/src/pages/auth/LoginPage.tsx @@ -1,6 +1,15 @@ import { type FormEvent, useState } from "react"; import { parsePhoneNumberFromString } from "libphonenumber-js"; -import { Eye, EyeOff, Mail, Smartphone, UserRound, ArrowUpRight, Globe, ChevronDown } from "lucide-react"; +import { + Eye, + EyeOff, + Mail, + Smartphone, + UserRound, + ArrowUpRight, + Globe, + ChevronDown, +} from "lucide-react"; import { useNavigate } from "react-router-dom"; import { useAuth } from "@/auth/useAuth"; @@ -13,10 +22,25 @@ const loginModes: Array<{ icon: typeof Mail; placeholder: string; }> = [ - { value: "email", label: "Email", icon: Mail, placeholder: "name@company.com" }, - { value: "phone", label: "Phone", icon: Smartphone, placeholder: "09XXXXXXXX" }, - { value: "username", label: "Username", icon: UserRound, placeholder: "username" }, -]; + { + value: "email", + label: "Email", + icon: Mail, + placeholder: "name@company.com", + }, + { + value: "phone", + label: "Phone", + icon: Smartphone, + placeholder: "09XXXXXXXX", + }, + { + value: "username", + label: "Username", + icon: UserRound, + placeholder: "username", + }, + ]; const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; const usernamePattern = /^[a-zA-Z0-9._-]{3,32}$/; @@ -43,7 +67,9 @@ const normalizeIdentifier = (mode: LoginMode, value: string) => { } if (!usernamePattern.test(trimmed)) { - throw new Error("Username must be 3-32 characters and use letters, numbers, ., _, or -."); + throw new Error( + "Username must be 3-32 characters and use letters, numbers, ., _, or -.", + ); } return trimmed; @@ -59,14 +85,24 @@ const primaryButtonClass = "h-11 w-full rounded-full bg-primary text-sm font-semibold text-primary-foreground shadow-[0_8px_20px_-6px_rgba(16,94,52,0.5)] transition-all duration-200 hover:bg-primary/90 hover:shadow-[0_10px_24px_-6px_rgba(16,94,52,0.55)] active:scale-[0.99] disabled:cursor-not-allowed disabled:opacity-60 disabled:shadow-none"; const LeftPanelDecor = () => ( -
+
{[0, 1, 2, 3, 4, 5].map((ring) => ( - + ))}
@@ -74,12 +110,23 @@ const LeftPanelDecor = () => ( ); const RightPanelDecor = () => ( -
+
@@ -138,13 +189,22 @@ const FormFooter = () => (
© 2026 EDR Freight @@ -176,7 +236,7 @@ const LoginPage = () => { setNormalizedIdentifier(normalized); const result = await login({ email: normalized, password }); - console.log(result) + console.log(result); if (result.mfaRequired) { setNeedsMfa(true); return; @@ -212,15 +272,20 @@ const LoginPage = () => {
-

Get Started

+

+ Get Started +

- Log in to access the freight backoffice & explore all logistics resources. + Log in to access the freight backoffice & explore all logistics + resources.

- +
- - I agree to EDR Freight{" "} - - Terms & Conditions - - . - - - {error ? (
{error}
) : null} - @@ -318,8 +377,10 @@ const LoginPage = () => {

We sent a verification code to{" "} - {normalizedIdentifier}. Enter it below - to complete sign in. + + {normalizedIdentifier} + + . Enter it below to complete sign in.

@@ -354,7 +415,11 @@ const LoginPage = () => { > Back -
diff --git a/apps/edr-freight-web/backoffice/src/theme/freight-brand.ts b/apps/edr-freight-web/backoffice/src/theme/freight-brand.ts index 32192dd36..6c1efd3f3 100644 --- a/apps/edr-freight-web/backoffice/src/theme/freight-brand.ts +++ b/apps/edr-freight-web/backoffice/src/theme/freight-brand.ts @@ -1,4 +1,8 @@ -import { createTheme, type MantineColorsTuple } from "@mantine/core"; +import { + colorsTuple, + createTheme, + type MantineColorsTuple, +} from "@mantine/core"; /** EDR Freight primary brand green */ export const FREIGHT_BRAND = "#1B9E7A"; @@ -17,24 +21,155 @@ export const freightBrand = { mutedBorder: "#B7EBDC", } as const; -/** Mantine green scale with #1B9E7A at index 6 (filled buttons, nav active). */ -const freightGreen: MantineColorsTuple = [ - "#E7F8F2", - "#C5EFE1", - "#9CE4CD", - "#6BD6B5", - "#41C8A0", - "#25B58C", - FREIGHT_BRAND, - FREIGHT_BRAND_DARK, - "#105F47", - "#0A3D2E", +const edrGreen: MantineColorsTuple = [ + "#ecfdf5", + "#d1fae5", + "#a7f3d0", + "#6ee7b7", + "#34d399", + "#0EA371", + "#0A8A5F", + "#0A6F4D", + "#065f46", + "#064e3b", +]; + +const neutral: MantineColorsTuple = [ + "#F4F7FA", + "#eef2f7", + "#E6ECF2", + "#d0dae6", + "#b0bfce", + "#8fa0b2", + "#6B7C8E", + "#4b5a6a", + "#10202F", + "#0C1A2B", ]; export const freightMantineTheme = createTheme({ - primaryColor: "green", colors: { - green: freightGreen, + "edr-green": edrGreen, + gray: neutral, + + // Brand surface + text tokens (single-value semantic colors). + // Each generates --mantine-color-{name}-{0..9} CSS variables. + "edr-bg": colorsTuple("#F7FAFC"), + "edr-card": colorsTuple("#FFFFFF"), + "edr-border": colorsTuple("#E6ECF2"), + "edr-divider": colorsTuple("#EEF1F5"), + "edr-text": colorsTuple("#10202F"), + "edr-muted": colorsTuple("#6B7C8E"), + "edr-soft": colorsTuple("#ECF6F1"), + "edr-ink": colorsTuple("#0C1A2B"), + "edr-accent": colorsTuple("#F2A516"), + + // Semantic status shades (from the design system). + "edr-amber-soft": colorsTuple("#FDF3E0"), + "edr-amber-text": colorsTuple("#9A5B00"), + "edr-blue": colorsTuple("#2E5B96"), + "edr-blue-soft": colorsTuple("#E9F0F8"), + "edr-blue-dot": colorsTuple("#3B6FB0"), + "edr-red": colorsTuple("#C0392B"), + "edr-red-soft": colorsTuple("#FBEAE7"), + "edr-slate": colorsTuple("#475569"), + "edr-slate-soft": colorsTuple("#F1F4F7"), + "edr-slate-soft2": colorsTuple("#EEF2F6"), + "edr-step": colorsTuple("#94A3B8"), + "edr-step-idle": colorsTuple("#D5DBE2"), + "edr-conn-idle": colorsTuple("#E6EAEF"), + }, + primaryColor: "edr-green", + primaryShade: { light: 5, dark: 4 }, + + white: "#ffffff", + black: "#10202F", + + fontFamily: + '"Inter", ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif', + + defaultRadius: "md", + + radius: { + xs: "4px", + sm: "6px", + md: "8px", + lg: "12px", + xl: "18px", + }, + + spacing: { + xs: "8px", + sm: "12px", + md: "16px", + lg: "24px", + xl: "32px", + }, + + fontSizes: { + xs: "12px", + sm: "14px", + md: "16px", + lg: "20px", + xl: "24px", + }, + + lineHeights: { + xs: "1.4", + sm: "1.45", + md: "1.55", + lg: "1.55", + xl: "1.5", + }, + + headings: { + fontFamily: '"Inter", var(--mantine-font-family)', + fontWeight: "700", + sizes: { + h1: { fontSize: "36px", lineHeight: "1.1", fontWeight: "800" }, + h2: { fontSize: "28px", lineHeight: "1.2", fontWeight: "700" }, + h3: { fontSize: "22px", lineHeight: "1.3", fontWeight: "600" }, + h4: { fontSize: "18px", lineHeight: "1.4", fontWeight: "600" }, + h5: { fontSize: "15px", lineHeight: "1.45", fontWeight: "600" }, + h6: { fontSize: "13px", lineHeight: "1.45", fontWeight: "600" }, + }, + }, + + shadows: { + xs: "0 1px 2px rgba(16, 24, 40, 0.04)", + sm: "0 1px 3px rgba(16, 24, 40, 0.06)", + md: "0 4px 12px rgba(16, 24, 40, 0.06)", + }, + + components: { + Card: { + defaultProps: { + radius: "xl", + withBorder: true, + shadow: "none", + padding: "lg", + }, + styles: { + root: { borderColor: "#E6ECF2" }, + }, + }, + Button: { + defaultProps: { radius: "md" }, + styles: { root: { fontWeight: 600 } }, + }, + Badge: { + defaultProps: { radius: "xl", variant: "light" }, + styles: { root: { fontWeight: 600, textTransform: "none" } }, + }, + Paper: { + defaultProps: { radius: "xl", shadow: "none", withBorder: true }, + styles: { root: { borderColor: "#E6ECF2" } }, + }, + Table: { + defaultProps: { verticalSpacing: "sm", horizontalSpacing: "md" }, + }, + Title: { + styles: { root: { letterSpacing: "-0.01em" } }, + }, }, - fontFamily: "'Outfit', var(--font-sans)", });