finshing architecture for project now we have all layers to build profitionl project app,components ,hooks ,lib,services,styel ,types

This commit is contained in:
m7amedez5511
2026-06-08 23:05:19 +03:00
parent 70853958f5
commit 53c03e9867
45 changed files with 1408 additions and 78 deletions

View File

@@ -4,10 +4,10 @@
// نقطة الدخول — تحقق من الجلسة وتوجيه المستخدم
// ─────────────────────────────────────────────
import { useState, useEffect, useCallback } from "react";
import { loadSession, type ClientSession } from "@/src/utils/helperFun";
import RegisterStep from "../../src/Components/Client/client";
import DashboardStep from "../../src/Components/Order/order";
import Logo from "@/src/utils/logo";
import { loadSession, type ClientSession } from "@/utils/helperFun";
import RegisterStep from "../../Components/Client/client";
import DashboardStep from "../../Components/Order/order";
import Logo from "@/utils/logo";
type Step = "bootstrap" | "register" | "dashboard";

View File

@@ -1,4 +1,4 @@
import Logo from "@/src/utils/logo";
import Logo from "@/utils/logo";
import Link from "next/link";

View File

@@ -4,7 +4,7 @@
import Link from "next/link";
// FIX: Import getStoredUser so the sidebar reads the authenticated user's
// name and role from localStorage instead of showing hardcoded placeholders.
import { getStoredUser } from "../../../src/lib/auth";
import { getStoredUser } from "../../../lib/auth";
const navItems = [
{ href: "/dashboard", label: "Dashboard", permission: "read-dashboard" },

View File

@@ -5,7 +5,7 @@ import Link from "next/link";
import { useRouter } from "next/navigation";
// FIX: Import both clearAuth and getStoredUser so the topbar can show the
// authenticated user's role and handle logout properly.
import { clearAuth, getStoredUser } from "../../../src/lib/auth";
import { clearAuth, getStoredUser } from "../../../lib/auth";
export function Topbar() {
const router = useRouter();

View File

@@ -3,8 +3,8 @@
import Link from "next/link";
import { useRouter } from "next/navigation";
import { useEffect, useMemo, useState } from "react";
import { getDashboardSummary, type DashboardSummaryResponse } from "../../src/lib/api";
import { clearAuth, getStoredToken, getStoredUser } from "../../src/lib/auth";
import { getDashboardSummary, type DashboardSummaryResponse } from "../../lib/api";
import { clearAuth, getStoredToken, getStoredUser } from "../../lib/auth";
export default function DashboardPage() {
const router = useRouter();

View File

@@ -1,44 +1,41 @@
@import url("https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700&family=IBM+Plex+Mono:wght@400;500&display=swap");
@import "../styles/tokens.css";
@import "tailwindcss";
:root {
--blue: #1A73E8;
--blue-dark: #1557B0;
--blue-light: #EBF3FF;
--green: #34A853;
--green-light: #D1FAE5;
--amber: #F59E0B;
--amber-light: #FEF3C7;
--red: #E53935;
--red-light: #FEE2E2;
--text: #111827;
--text-muted: #6B7280;
--text-hint: #9CA3AF;
--border: #E5E7EB;
--surface: #F9FAFB;
--white: #fff;
--sidebar: 230px;
--radius: 10px;
--radius-sm: 7px;
--font: 'Plus Jakarta Sans', sans-serif;
--mono: 'IBM Plex Mono', monospace;
--background: #ECEEF2;
--foreground: #111827;
/* ── Base resets ────────────────────────────────────── */
*,
*::before,
*::after {
box-sizing: border-box;
}
@theme inline {
--color-background: var(--background);
--color-foreground: var(--foreground);
--font-sans: var(--font-geist-sans);
--font-mono: var(--font-geist-mono);
html {
scroll-behavior: smooth;
font-size: 14px;
/* RTL is set per route-group layout, not globally */
}
* { box-sizing: border-box; }
html { scroll-behavior: smooth; font-size: 14px; }
body {
margin: 0;
min-height: 100vh;
background: #ECEEF2;
color: var(--foreground);
font-family: var(--font);
background-color: var(--color-surface-sunken);
color: var(--color-text-primary);
font-family: var(--font-sans);
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* ── Tailwind theme bridge ──────────────────────────── */
/* Expose CSS variables as Tailwind color utilities. */
@theme inline {
--color-background: var(--color-surface-sunken);
--color-foreground: var(--color-text-primary);
--color-brand: var(--color-brand-600);
--font-sans: var(--font-sans);
--font-mono: var(--font-mono);
}
/* ── Focus ring utility ─────────────────────────────── */
.focus-ring {
outline: none;
box-shadow: 0 0 0 2px var(--color-brand-600);
}

View File

@@ -1,33 +1,46 @@
// app/layout.tsx
// Root layout — single location for font loading and global metadata.
// No inline styles, no @import in CSS.
import type { Metadata } from "next";
import { Geist, Geist_Mono } from "next/font/google";
import { Plus_Jakarta_Sans, IBM_Plex_Mono } from "next/font/google";
import "./globals.css";
const geistSans = Geist({
variable: "--font-geist-sans",
const jakartaSans = Plus_Jakarta_Sans({
subsets: ["latin"],
weight: ["400", "500", "600", "700"],
variable: "--font-sans",
display: "swap",
});
const geistMono = Geist_Mono({
variable: "--font-geist-mono",
const ibmPlexMono = IBM_Plex_Mono({
subsets: ["latin"],
weight: ["400", "500"],
variable: "--font-mono",
display: "swap",
});
export const metadata: Metadata = {
title: "Logistics Client Portal",
description: "Modern frontend for the LogisticsApp backend with dashboard and client views.",
title: {
default: "Slash.sa — Logistics Management",
template: "%s | Slash.sa",
},
description:
"Modern logistics client portal — manage deliveries, drivers, and fleet operations.",
};
export default function RootLayout({
children,
}: Readonly<{
}: {
children: React.ReactNode;
}>) {
}) {
return (
// dir is set per route-group (ar = RTL, en = LTR) not globally
<html
lang="en"
className={`${geistSans.variable} ${geistMono.variable} h-full antialiased`}
lang="ar"
className={`${jakartaSans.variable} ${ibmPlexMono.variable} h-full antialiased`}
>
<body className="min-h-full flex flex-col">{children}</body>
</html>
);
}
}

View File

@@ -3,8 +3,9 @@
import Link from "next/link";
import { useState } from "react";
import { useRouter } from "next/navigation";
import { loginUser } from "../../src/lib/auth";
import Logo from "@/src/utils/logo";
import { loginUser } from "../../lib/auth";
import Logo from "@/utils/logo";
import { Spinner } from "@/Components/UI";
export default function LoginPage() {
const router = useRouter();
@@ -161,7 +162,7 @@ export default function LoginPage() {
disabled={loading}
className="mt-6 inline-flex h-11.5 w-full items-center justify-center rounded-[9px] bg-blue-600 text-[15px] font-semibold text-white transition hover:bg-blue-700 disabled:cursor-not-allowed disabled:opacity-70"
>
{loading ? "جاري تسجيل الدخول…" : "تسجيل الدخول"}
{loading ? <Spinner /> : "تسجيل الدخول"}
</button>
<p className="mt-4 text-center text-[13px] text-slate-500">