diff --git a/src/components/DashboardLayout.tsx b/src/components/DashboardLayout.tsx new file mode 100644 index 0000000..6838387 --- /dev/null +++ b/src/components/DashboardLayout.tsx @@ -0,0 +1,66 @@ +import { type ParentProps, createMemo } from "solid-js"; +import { useLocation, useNavigate } from "@solidjs/router"; +import DashboardShell from "~/components/DashboardShell"; + +const SIDEBAR_ITEMS = [ + "My Dashboard", + "Leads", + "My Requests", + "Credits", + "Settings", + "Logout", +]; + +const ROUTE_BY_LABEL: Record = { + "my dashboard": "/dashboard", + leads: "/dashboard/leads", + "my requests": "/dashboard/requests", + credits: "/dashboard/credits", + settings: "/dashboard/settings", + logout: "/dashboard/logout", +}; + +function readUserName() { + if (typeof window === "undefined") return "User"; + try { + const raw = + localStorage.getItem("nxtgauge_auth_user") || + localStorage.getItem("nxtgauge_user"); + if (!raw) return "User"; + const parsed = JSON.parse(raw); + return parsed?.full_name || parsed?.name || parsed?.email || "User"; + } catch { + return "User"; + } +} + +export default function DashboardLayout(props: ParentProps) { + const location = useLocation(); + const navigate = useNavigate(); + + const activeSidebar = createMemo(() => { + const path = location.pathname || ""; + if (path.startsWith("/dashboard/requests")) return "My Requests"; + if (path.startsWith("/dashboard/leads")) return "Leads"; + if (path.startsWith("/dashboard/credits")) return "Credits"; + if (path.startsWith("/dashboard/settings")) return "Settings"; + return "My Dashboard"; + }); + + const handleSidebarSelect = (item: string) => { + const target = ROUTE_BY_LABEL[item.toLowerCase()]; + if (target) navigate(target); + }; + + return ( + + {props.children} + + ); +} diff --git a/src/lib/api.ts b/src/lib/api.ts index 0fc8134..df8e6fb 100644 --- a/src/lib/api.ts +++ b/src/lib/api.ts @@ -24,6 +24,51 @@ async function apiFetch(path: string, options?: RequestInit): Promise { return res.json(); } +type ApiResponse = { + data: T; + status: number; + headers: Headers; +}; + +async function request( + path: string, + options?: { method?: string; body?: unknown; headers?: HeadersInit } +): Promise> { + const mergedHeaders: HeadersInit = { + ...getAuthHeaders(), + ...(options?.headers || {}), + }; + const init: RequestInit = { + method: options?.method || "GET", + headers: mergedHeaders, + credentials: "include", + }; + if (options?.body !== undefined) { + init.body = JSON.stringify(options.body); + } + const res = await fetch(`${API}${path}`, init); + const raw = await res.text(); + const data = raw ? JSON.parse(raw) : null; + if (!res.ok) { + const message = (data && (data.message || data.error)) || `API error ${res.status}`; + throw new Error(message); + } + return { data: data as T, status: res.status, headers: res.headers }; +} + +export const api = { + get: (path: string, headers?: HeadersInit) => + request(path, { method: "GET", headers }), + post: (path: string, body?: unknown, headers?: HeadersInit) => + request(path, { method: "POST", body, headers }), + put: (path: string, body?: unknown, headers?: HeadersInit) => + request(path, { method: "PUT", body, headers }), + patch: (path: string, body?: unknown, headers?: HeadersInit) => + request(path, { method: "PATCH", body, headers }), + delete: (path: string, headers?: HeadersInit) => + request(path, { method: "DELETE", headers }), +}; + export async function fetchProfile(rolePrefix: string): Promise { return apiFetch(`/api/${rolePrefix}/profile/me`); }