feat(admin-parity): approval management, submission viewer, role builder offline fallback
- Rebuilt approval.tsx: reject with reason prompt, request changes with field
keys, request more documents flow, RoleTypeBadge per role type, parsed
requestReason (ONBOARDING_SUBMISSION prefix), management page routing for
approved items, inline ApprovalDetailPanel with remarks timeline
- Rebuilt approval/[id].tsx: full onboarding submission viewer loading from
GET /api/admin/approvals/submission/{user_id}?roleKey=X, flattenFields
recursive flattener, detectKind image/pdf/document/url/text classifier,
image lightbox, PDF iframe modal, approve/reject per role type routing
- Added src/lib/admin-modules.ts: STATIC_PERMISSIONS fallback (39 modules x4
actions) for Internal Role Builder when backend is offline
- roles/create.tsx + roles/[id]/edit.tsx: use STATIC_PERMISSIONS when API
returns empty or fails, builder now works offline
- AdminShell + AdminSidebar: alignment/style fixes from parity review
- ExternalRoleForm: extended fields for external runtime role management
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 00:34:38 +01:00
|
|
|
import { A, useLocation, useNavigate, useSearchParams } from '@solidjs/router';
|
2026-03-24 02:36:40 +01:00
|
|
|
import { For, createEffect, createMemo, createSignal, onCleanup, onMount, type JSX } from 'solid-js';
|
2026-03-16 23:20:54 +01:00
|
|
|
import AdminSidebar from './AdminSidebar';
|
2026-03-20 22:37:17 +01:00
|
|
|
import { isExternalIdentity } from '~/lib/admin-auth';
|
feat(admin-parity): approval management, submission viewer, role builder offline fallback
- Rebuilt approval.tsx: reject with reason prompt, request changes with field
keys, request more documents flow, RoleTypeBadge per role type, parsed
requestReason (ONBOARDING_SUBMISSION prefix), management page routing for
approved items, inline ApprovalDetailPanel with remarks timeline
- Rebuilt approval/[id].tsx: full onboarding submission viewer loading from
GET /api/admin/approvals/submission/{user_id}?roleKey=X, flattenFields
recursive flattener, detectKind image/pdf/document/url/text classifier,
image lightbox, PDF iframe modal, approve/reject per role type routing
- Added src/lib/admin-modules.ts: STATIC_PERMISSIONS fallback (39 modules x4
actions) for Internal Role Builder when backend is offline
- roles/create.tsx + roles/[id]/edit.tsx: use STATIC_PERMISSIONS when API
returns empty or fails, builder now works offline
- AdminShell + AdminSidebar: alignment/style fixes from parity review
- ExternalRoleForm: extended fields for external runtime role management
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 00:34:38 +01:00
|
|
|
import { clearAdminSession, hasAdminSession, setAdminSession } from '~/lib/admin-session';
|
feat(admin): build complete admin panel with UI parity and search/filter
- Implement all admin management pages (employees, users, jobs, leads, orders, companies, customers, candidates, approval, invoices, reviews, support, KB, pricing, coupons, credits, discounts, tax, reports, ledger)
- Implement 9 professional vertical pages (developers, designers, tutors, video editors, photographers, makeup artists, graphic designers, social media managers, fitness trainers)
- Implement internal/external dashboard and role management with builder UI
- Fix tab styling: replace inline border-bottom styles with admin-tab CSS class across 8+ pages
- Add search/filter functionality to invoice and review pages
- Add toggle status (activate/deactivate) to employees page with PATCH /api/admin/employees/{id}
- Align UI styling with NextJS admin panel for visual parity
- Add stat cards to approval page showing counts by status
- Implement graceful empty states for all list views
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-03-19 13:04:10 +01:00
|
|
|
|
|
|
|
|
type Tab = { href: string; label: string; exact?: boolean };
|
|
|
|
|
|
|
|
|
|
const TAB_SETS: Array<{ prefixes: string[]; tabs: Tab[] }> = [
|
|
|
|
|
{
|
|
|
|
|
prefixes: ['/admin/roles'],
|
|
|
|
|
tabs: [
|
2026-03-24 02:36:40 +01:00
|
|
|
{ href: '/admin/roles', label: 'Roles', exact: true },
|
feat(admin): build complete admin panel with UI parity and search/filter
- Implement all admin management pages (employees, users, jobs, leads, orders, companies, customers, candidates, approval, invoices, reviews, support, KB, pricing, coupons, credits, discounts, tax, reports, ledger)
- Implement 9 professional vertical pages (developers, designers, tutors, video editors, photographers, makeup artists, graphic designers, social media managers, fitness trainers)
- Implement internal/external dashboard and role management with builder UI
- Fix tab styling: replace inline border-bottom styles with admin-tab CSS class across 8+ pages
- Add search/filter functionality to invoice and review pages
- Add toggle status (activate/deactivate) to employees page with PATCH /api/admin/employees/{id}
- Align UI styling with NextJS admin panel for visual parity
- Add stat cards to approval page showing counts by status
- Implement graceful empty states for all list views
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-03-19 13:04:10 +01:00
|
|
|
{ href: '/admin/roles/create', label: 'Create Role' },
|
2026-03-24 02:36:40 +01:00
|
|
|
{ href: '/admin/roles/templates', label: 'View Roles' },
|
feat(admin): build complete admin panel with UI parity and search/filter
- Implement all admin management pages (employees, users, jobs, leads, orders, companies, customers, candidates, approval, invoices, reviews, support, KB, pricing, coupons, credits, discounts, tax, reports, ledger)
- Implement 9 professional vertical pages (developers, designers, tutors, video editors, photographers, makeup artists, graphic designers, social media managers, fitness trainers)
- Implement internal/external dashboard and role management with builder UI
- Fix tab styling: replace inline border-bottom styles with admin-tab CSS class across 8+ pages
- Add search/filter functionality to invoice and review pages
- Add toggle status (activate/deactivate) to employees page with PATCH /api/admin/employees/{id}
- Align UI styling with NextJS admin panel for visual parity
- Add stat cards to approval page showing counts by status
- Implement graceful empty states for all list views
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-03-19 13:04:10 +01:00
|
|
|
],
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
prefixes: ['/admin/runtime-roles'],
|
|
|
|
|
tabs: [
|
2026-03-24 02:36:40 +01:00
|
|
|
{ href: '/admin/runtime-roles', label: 'Roles', exact: true },
|
|
|
|
|
{ href: '/admin/runtime-roles/new', label: 'Create Role' },
|
|
|
|
|
{ href: '/admin/role-ui-configs', label: 'View Roles' },
|
feat(admin): build complete admin panel with UI parity and search/filter
- Implement all admin management pages (employees, users, jobs, leads, orders, companies, customers, candidates, approval, invoices, reviews, support, KB, pricing, coupons, credits, discounts, tax, reports, ledger)
- Implement 9 professional vertical pages (developers, designers, tutors, video editors, photographers, makeup artists, graphic designers, social media managers, fitness trainers)
- Implement internal/external dashboard and role management with builder UI
- Fix tab styling: replace inline border-bottom styles with admin-tab CSS class across 8+ pages
- Add search/filter functionality to invoice and review pages
- Add toggle status (activate/deactivate) to employees page with PATCH /api/admin/employees/{id}
- Align UI styling with NextJS admin panel for visual parity
- Add stat cards to approval page showing counts by status
- Implement graceful empty states for all list views
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-03-19 13:04:10 +01:00
|
|
|
],
|
|
|
|
|
},
|
|
|
|
|
];
|
2026-03-16 23:20:54 +01:00
|
|
|
|
2026-03-24 02:36:40 +01:00
|
|
|
function IconBell() {
|
|
|
|
|
return (
|
|
|
|
|
<svg class="h-5 w-5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9">
|
|
|
|
|
<path d="M18 8a6 6 0 0 0-12 0c0 7-3 9-3 9h18s-3-2-3-9" />
|
|
|
|
|
<path d="M13.73 21a2 2 0 0 1-3.46 0" />
|
|
|
|
|
</svg>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function IconSearch() {
|
|
|
|
|
return (
|
|
|
|
|
<svg class="h-5 w-5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8">
|
|
|
|
|
<circle cx="11" cy="11" r="7.5" />
|
|
|
|
|
<path d="m20 20-3.8-3.8" />
|
|
|
|
|
</svg>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function IconHelp() {
|
|
|
|
|
return (
|
|
|
|
|
<svg class="h-5 w-5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
|
|
|
<circle cx="12" cy="12" r="9" />
|
|
|
|
|
<path d="M9.3 9a2.8 2.8 0 1 1 4.9 2c-.8.9-1.7 1.4-1.7 2.5" />
|
|
|
|
|
<path d="M12 17h.01" />
|
|
|
|
|
</svg>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function IconCog() {
|
|
|
|
|
return (
|
|
|
|
|
<svg class="h-5 w-5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
|
|
|
<path d="M12 15.5A3.5 3.5 0 1 0 12 8.5a3.5 3.5 0 0 0 0 7Z" />
|
|
|
|
|
<path d="M19.4 15a1.6 1.6 0 0 0 .3 1.7l.1.1a2 2 0 0 1-2.8 2.8l-.1-.1a1.6 1.6 0 0 0-1.7-.3 1.6 1.6 0 0 0-1 1.5V21a2 2 0 0 1-4 0v-.2a1.6 1.6 0 0 0-1-1.5 1.6 1.6 0 0 0-1.7.3l-.1.1a2 2 0 0 1-2.8-2.8l.1-.1a1.6 1.6 0 0 0 .3-1.7 1.6 1.6 0 0 0-1.5-1H3a2 2 0 0 1 0-4h.2a1.6 1.6 0 0 0 1.5-1 1.6 1.6 0 0 0-.3-1.7l-.1-.1a2 2 0 0 1 2.8-2.8l.1.1a1.6 1.6 0 0 0 1.7.3h.1a1.6 1.6 0 0 0 .9-1.5V3a2 2 0 1 1 4 0v.2a1.6 1.6 0 0 0 .9 1.5h.1a1.6 1.6 0 0 0 1.7-.3l.1-.1a2 2 0 1 1 2.8 2.8l-.1.1a1.6 1.6 0 0 0-.3 1.7v.1a1.6 1.6 0 0 0 1.5.9H21a2 2 0 0 1 0 4h-.2a1.6 1.6 0 0 0-1.5 1Z" />
|
|
|
|
|
</svg>
|
|
|
|
|
);
|
|
|
|
|
}
|
2026-03-19 13:50:20 +01:00
|
|
|
|
2026-03-16 23:20:54 +01:00
|
|
|
export default function AdminShell(props: { children: JSX.Element }) {
|
2026-03-19 03:36:46 +01:00
|
|
|
const location = useLocation();
|
|
|
|
|
const navigate = useNavigate();
|
feat(admin-parity): approval management, submission viewer, role builder offline fallback
- Rebuilt approval.tsx: reject with reason prompt, request changes with field
keys, request more documents flow, RoleTypeBadge per role type, parsed
requestReason (ONBOARDING_SUBMISSION prefix), management page routing for
approved items, inline ApprovalDetailPanel with remarks timeline
- Rebuilt approval/[id].tsx: full onboarding submission viewer loading from
GET /api/admin/approvals/submission/{user_id}?roleKey=X, flattenFields
recursive flattener, detectKind image/pdf/document/url/text classifier,
image lightbox, PDF iframe modal, approve/reject per role type routing
- Added src/lib/admin-modules.ts: STATIC_PERMISSIONS fallback (39 modules x4
actions) for Internal Role Builder when backend is offline
- roles/create.tsx + roles/[id]/edit.tsx: use STATIC_PERMISSIONS when API
returns empty or fails, builder now works offline
- AdminShell + AdminSidebar: alignment/style fixes from parity review
- ExternalRoleForm: extended fields for external runtime role management
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 00:34:38 +01:00
|
|
|
const [searchParams] = useSearchParams();
|
2026-03-19 03:36:46 +01:00
|
|
|
const [checkedSession, setCheckedSession] = createSignal(false);
|
feat(admin): Phase 0 — Tailwind v4 foundation, shell rewrite, modern dashboard
- Install Tailwind CSS v4 via @tailwindcss/vite; configure vite.config.ts
- Rewrite app.css: Tailwind base, Exo 2 font, brand tokens (orange #fd6216, navy #050026), scrollbar utility; fix @import order
- Rewrite AdminShell.tsx: fixed header, fixed inset body grid (sidebar + main), session check, sub-tab system, logout, admin avatar/name/role
- Rewrite AdminSidebar.tsx: collapsible w-64/w-20, orange active rail + badge/dot, CSS filter for SVG icon tinting, min-h-0 flex fix
- Replace 84 route stub CSS classes (page-title, card, btn, table-wrap, etc.) with Tailwind equivalents via safe class-attr-only regex script
- Rewrite admin dashboard: Lucide icons in colored chip backgrounds, 4-col KPI grid, Control Plane 6-module grid, hover lift animations
- Disable SSR (ssr: false) to fix Vinxi dev manifest error; clear stale .vinxi cache
- Add lucide-solid icon library
- Add scripts/cleanup-css.mjs for class migration
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 23:00:21 +01:00
|
|
|
const [adminName, setAdminName] = createSignal('Admin');
|
2026-03-24 02:36:40 +01:00
|
|
|
const [sidebarOpen, setSidebarOpen] = createSignal(false);
|
|
|
|
|
const [tabsTrackEl, setTabsTrackEl] = createSignal<HTMLDivElement>();
|
|
|
|
|
const [tabRefs, setTabRefs] = createSignal<Record<string, HTMLAnchorElement>>({});
|
|
|
|
|
const [tabIndicator, setTabIndicator] = createSignal({ left: 0, width: 0, ready: false });
|
2026-03-19 03:36:46 +01:00
|
|
|
|
feat(admin): build complete admin panel with UI parity and search/filter
- Implement all admin management pages (employees, users, jobs, leads, orders, companies, customers, candidates, approval, invoices, reviews, support, KB, pricing, coupons, credits, discounts, tax, reports, ledger)
- Implement 9 professional vertical pages (developers, designers, tutors, video editors, photographers, makeup artists, graphic designers, social media managers, fitness trainers)
- Implement internal/external dashboard and role management with builder UI
- Fix tab styling: replace inline border-bottom styles with admin-tab CSS class across 8+ pages
- Add search/filter functionality to invoice and review pages
- Add toggle status (activate/deactivate) to employees page with PATCH /api/admin/employees/{id}
- Align UI styling with NextJS admin panel for visual parity
- Add stat cards to approval page showing counts by status
- Implement graceful empty states for all list views
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-03-19 13:04:10 +01:00
|
|
|
const tabs = createMemo<Tab[]>(() => {
|
|
|
|
|
const path = location.pathname;
|
|
|
|
|
for (const set of TAB_SETS) {
|
2026-03-24 02:36:40 +01:00
|
|
|
if (set.prefixes.some((p) => path === p || path.startsWith(`${p}/`))) return set.tabs;
|
2026-03-19 03:36:46 +01:00
|
|
|
}
|
feat(admin): build complete admin panel with UI parity and search/filter
- Implement all admin management pages (employees, users, jobs, leads, orders, companies, customers, candidates, approval, invoices, reviews, support, KB, pricing, coupons, credits, discounts, tax, reports, ledger)
- Implement 9 professional vertical pages (developers, designers, tutors, video editors, photographers, makeup artists, graphic designers, social media managers, fitness trainers)
- Implement internal/external dashboard and role management with builder UI
- Fix tab styling: replace inline border-bottom styles with admin-tab CSS class across 8+ pages
- Add search/filter functionality to invoice and review pages
- Add toggle status (activate/deactivate) to employees page with PATCH /api/admin/employees/{id}
- Align UI styling with NextJS admin panel for visual parity
- Add stat cards to approval page showing counts by status
- Implement graceful empty states for all list views
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-03-19 13:04:10 +01:00
|
|
|
return [];
|
|
|
|
|
});
|
|
|
|
|
|
2026-03-24 02:36:40 +01:00
|
|
|
const isTabActive = (tab: Tab) => (tab.exact ? location.pathname === tab.href : location.pathname === tab.href || location.pathname.startsWith(`${tab.href}/`));
|
2026-03-19 03:36:46 +01:00
|
|
|
|
2026-03-24 02:36:40 +01:00
|
|
|
const refreshTabIndicator = () => {
|
|
|
|
|
const activeTab = tabs().find((tab) => isTabActive(tab));
|
|
|
|
|
const track = tabsTrackEl();
|
|
|
|
|
if (!activeTab || !track) {
|
|
|
|
|
setTabIndicator((prev) => ({ ...prev, ready: false }));
|
|
|
|
|
return;
|
2026-03-19 13:50:20 +01:00
|
|
|
}
|
2026-03-24 02:36:40 +01:00
|
|
|
const el = tabRefs()[activeTab.href];
|
|
|
|
|
if (!el) return;
|
|
|
|
|
setTabIndicator({ left: el.offsetLeft, width: el.offsetWidth, ready: true });
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
createEffect(() => {
|
|
|
|
|
tabs();
|
|
|
|
|
location.pathname;
|
|
|
|
|
requestAnimationFrame(refreshTabIndicator);
|
2026-03-19 13:50:20 +01:00
|
|
|
});
|
|
|
|
|
|
2026-03-19 03:36:46 +01:00
|
|
|
onMount(() => {
|
2026-03-24 02:36:40 +01:00
|
|
|
const onResize = () => refreshTabIndicator();
|
|
|
|
|
window.addEventListener('resize', onResize);
|
|
|
|
|
onCleanup(() => window.removeEventListener('resize', onResize));
|
|
|
|
|
|
2026-03-23 21:13:42 +01:00
|
|
|
const isLocalDev =
|
2026-03-24 02:36:40 +01:00
|
|
|
typeof window !== 'undefined' && (window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1');
|
feat(admin-parity): approval management, submission viewer, role builder offline fallback
- Rebuilt approval.tsx: reject with reason prompt, request changes with field
keys, request more documents flow, RoleTypeBadge per role type, parsed
requestReason (ONBOARDING_SUBMISSION prefix), management page routing for
approved items, inline ApprovalDetailPanel with remarks timeline
- Rebuilt approval/[id].tsx: full onboarding submission viewer loading from
GET /api/admin/approvals/submission/{user_id}?roleKey=X, flattenFields
recursive flattener, detectKind image/pdf/document/url/text classifier,
image lightbox, PDF iframe modal, approve/reject per role type routing
- Added src/lib/admin-modules.ts: STATIC_PERMISSIONS fallback (39 modules x4
actions) for Internal Role Builder when backend is offline
- roles/create.tsx + roles/[id]/edit.tsx: use STATIC_PERMISSIONS when API
returns empty or fails, builder now works offline
- AdminShell + AdminSidebar: alignment/style fixes from parity review
- ExternalRoleForm: extended fields for external runtime role management
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 00:34:38 +01:00
|
|
|
const isPreview =
|
|
|
|
|
searchParams._preview === '1' ||
|
|
|
|
|
(typeof sessionStorage !== 'undefined' && sessionStorage.getItem('nxtgauge_admin_preview') === '1');
|
|
|
|
|
|
2026-03-23 21:13:42 +01:00
|
|
|
if (isPreview || isLocalDev) {
|
feat(admin-parity): approval management, submission viewer, role builder offline fallback
- Rebuilt approval.tsx: reject with reason prompt, request changes with field
keys, request more documents flow, RoleTypeBadge per role type, parsed
requestReason (ONBOARDING_SUBMISSION prefix), management page routing for
approved items, inline ApprovalDetailPanel with remarks timeline
- Rebuilt approval/[id].tsx: full onboarding submission viewer loading from
GET /api/admin/approvals/submission/{user_id}?roleKey=X, flattenFields
recursive flattener, detectKind image/pdf/document/url/text classifier,
image lightbox, PDF iframe modal, approve/reject per role type routing
- Added src/lib/admin-modules.ts: STATIC_PERMISSIONS fallback (39 modules x4
actions) for Internal Role Builder when backend is offline
- roles/create.tsx + roles/[id]/edit.tsx: use STATIC_PERMISSIONS when API
returns empty or fails, builder now works offline
- AdminShell + AdminSidebar: alignment/style fixes from parity review
- ExternalRoleForm: extended fields for external runtime role management
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 00:34:38 +01:00
|
|
|
if (typeof sessionStorage !== 'undefined') sessionStorage.setItem('nxtgauge_admin_preview', '1');
|
|
|
|
|
setAdminSession();
|
|
|
|
|
setCheckedSession(true);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-20 22:37:17 +01:00
|
|
|
const verify = async () => {
|
|
|
|
|
if (!hasAdminSession()) {
|
|
|
|
|
const from = encodeURIComponent(location.pathname + location.search);
|
|
|
|
|
navigate(`/login?from=${from}`, { replace: true });
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
try {
|
2026-03-24 02:36:40 +01:00
|
|
|
const accessToken = typeof sessionStorage !== 'undefined' ? sessionStorage.getItem('nxtgauge_admin_access_token') || '' : '';
|
2026-03-20 22:37:17 +01:00
|
|
|
const response = await fetch('/api/gateway/users/auth/me', {
|
|
|
|
|
method: 'GET',
|
|
|
|
|
headers: {
|
|
|
|
|
Accept: 'application/json',
|
|
|
|
|
'x-portal-target': 'admin',
|
2026-03-23 21:13:42 +01:00
|
|
|
...(accessToken ? { Authorization: `Bearer ${accessToken}` } : {}),
|
2026-03-20 22:37:17 +01:00
|
|
|
},
|
|
|
|
|
credentials: 'include',
|
|
|
|
|
});
|
|
|
|
|
const payload = await response.json().catch(() => ({}));
|
feat(admin): Phase 0 — Tailwind v4 foundation, shell rewrite, modern dashboard
- Install Tailwind CSS v4 via @tailwindcss/vite; configure vite.config.ts
- Rewrite app.css: Tailwind base, Exo 2 font, brand tokens (orange #fd6216, navy #050026), scrollbar utility; fix @import order
- Rewrite AdminShell.tsx: fixed header, fixed inset body grid (sidebar + main), session check, sub-tab system, logout, admin avatar/name/role
- Rewrite AdminSidebar.tsx: collapsible w-64/w-20, orange active rail + badge/dot, CSS filter for SVG icon tinting, min-h-0 flex fix
- Replace 84 route stub CSS classes (page-title, card, btn, table-wrap, etc.) with Tailwind equivalents via safe class-attr-only regex script
- Rewrite admin dashboard: Lucide icons in colored chip backgrounds, 4-col KPI grid, Control Plane 6-module grid, hover lift animations
- Disable SSR (ssr: false) to fix Vinxi dev manifest error; clear stale .vinxi cache
- Add lucide-solid icon library
- Add scripts/cleanup-css.mjs for class migration
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 23:00:21 +01:00
|
|
|
if (!response.ok || isExternalIdentity(payload)) throw new Error('Unauthorized');
|
|
|
|
|
if (payload?.full_name) setAdminName(payload.full_name);
|
2026-03-20 22:37:17 +01:00
|
|
|
setCheckedSession(true);
|
|
|
|
|
} catch {
|
|
|
|
|
clearAdminSession();
|
|
|
|
|
const from = encodeURIComponent(location.pathname + location.search);
|
|
|
|
|
navigate(`/login?from=${from}`, { replace: true });
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
void verify();
|
2026-03-19 03:36:46 +01:00
|
|
|
});
|
|
|
|
|
|
2026-03-20 22:37:17 +01:00
|
|
|
const onLogout = async () => {
|
|
|
|
|
await fetch('/api/gateway/users/auth/logout', {
|
|
|
|
|
method: 'POST',
|
feat(admin): Phase 0 — Tailwind v4 foundation, shell rewrite, modern dashboard
- Install Tailwind CSS v4 via @tailwindcss/vite; configure vite.config.ts
- Rewrite app.css: Tailwind base, Exo 2 font, brand tokens (orange #fd6216, navy #050026), scrollbar utility; fix @import order
- Rewrite AdminShell.tsx: fixed header, fixed inset body grid (sidebar + main), session check, sub-tab system, logout, admin avatar/name/role
- Rewrite AdminSidebar.tsx: collapsible w-64/w-20, orange active rail + badge/dot, CSS filter for SVG icon tinting, min-h-0 flex fix
- Replace 84 route stub CSS classes (page-title, card, btn, table-wrap, etc.) with Tailwind equivalents via safe class-attr-only regex script
- Rewrite admin dashboard: Lucide icons in colored chip backgrounds, 4-col KPI grid, Control Plane 6-module grid, hover lift animations
- Disable SSR (ssr: false) to fix Vinxi dev manifest error; clear stale .vinxi cache
- Add lucide-solid icon library
- Add scripts/cleanup-css.mjs for class migration
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 23:00:21 +01:00
|
|
|
headers: { Accept: 'application/json', 'x-portal-target': 'admin' },
|
2026-03-20 22:37:17 +01:00
|
|
|
credentials: 'include',
|
|
|
|
|
}).catch(() => {});
|
2026-03-19 03:36:46 +01:00
|
|
|
clearAdminSession();
|
2026-03-23 21:13:42 +01:00
|
|
|
if (typeof sessionStorage !== 'undefined') {
|
|
|
|
|
sessionStorage.removeItem('nxtgauge_admin_access_token');
|
feat(admin): Phase 0 — Tailwind v4 foundation, shell rewrite, modern dashboard
- Install Tailwind CSS v4 via @tailwindcss/vite; configure vite.config.ts
- Rewrite app.css: Tailwind base, Exo 2 font, brand tokens (orange #fd6216, navy #050026), scrollbar utility; fix @import order
- Rewrite AdminShell.tsx: fixed header, fixed inset body grid (sidebar + main), session check, sub-tab system, logout, admin avatar/name/role
- Rewrite AdminSidebar.tsx: collapsible w-64/w-20, orange active rail + badge/dot, CSS filter for SVG icon tinting, min-h-0 flex fix
- Replace 84 route stub CSS classes (page-title, card, btn, table-wrap, etc.) with Tailwind equivalents via safe class-attr-only regex script
- Rewrite admin dashboard: Lucide icons in colored chip backgrounds, 4-col KPI grid, Control Plane 6-module grid, hover lift animations
- Disable SSR (ssr: false) to fix Vinxi dev manifest error; clear stale .vinxi cache
- Add lucide-solid icon library
- Add scripts/cleanup-css.mjs for class migration
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 23:00:21 +01:00
|
|
|
sessionStorage.removeItem('nxtgauge_admin_preview');
|
2026-03-23 21:13:42 +01:00
|
|
|
}
|
2026-03-19 03:36:46 +01:00
|
|
|
navigate('/login', { replace: true });
|
|
|
|
|
};
|
|
|
|
|
|
2026-03-24 02:36:40 +01:00
|
|
|
const adminInitials = createMemo(() => {
|
|
|
|
|
const parts = adminName().split(' ').map((s) => s.trim()).filter(Boolean);
|
|
|
|
|
if (parts.length === 0) return 'AD';
|
|
|
|
|
if (parts.length === 1) return parts[0].slice(0, 2).toUpperCase();
|
|
|
|
|
return `${parts[0][0] || ''}${parts[1][0] || ''}`.toUpperCase();
|
|
|
|
|
});
|
feat(admin): Phase 0 — Tailwind v4 foundation, shell rewrite, modern dashboard
- Install Tailwind CSS v4 via @tailwindcss/vite; configure vite.config.ts
- Rewrite app.css: Tailwind base, Exo 2 font, brand tokens (orange #fd6216, navy #050026), scrollbar utility; fix @import order
- Rewrite AdminShell.tsx: fixed header, fixed inset body grid (sidebar + main), session check, sub-tab system, logout, admin avatar/name/role
- Rewrite AdminSidebar.tsx: collapsible w-64/w-20, orange active rail + badge/dot, CSS filter for SVG icon tinting, min-h-0 flex fix
- Replace 84 route stub CSS classes (page-title, card, btn, table-wrap, etc.) with Tailwind equivalents via safe class-attr-only regex script
- Rewrite admin dashboard: Lucide icons in colored chip backgrounds, 4-col KPI grid, Control Plane 6-module grid, hover lift animations
- Disable SSR (ssr: false) to fix Vinxi dev manifest error; clear stale .vinxi cache
- Add lucide-solid icon library
- Add scripts/cleanup-css.mjs for class migration
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 23:00:21 +01:00
|
|
|
|
2026-03-16 23:20:54 +01:00
|
|
|
return (
|
2026-03-24 02:36:40 +01:00
|
|
|
<div class="min-h-screen bg-[#f0f1f6]">
|
ui: match stitch design system — navy accents, tighter rounding, sidebar groups
- AdminSidebar: group labels (Management/Organisation/Service Providers/Operations),
navy active state (bg-[#e8edf5] + [#0a1d37] left bar + navy icon), width 268px,
13.5px font, 40px item height, lucide-solid icons only (no img fallback), min-w-0
truncation fix, tighter py spacing
- AdminShell: header height 64px (was 86px), compact search bar 40px/rounded-lg,
navy avatar square (was orange gradient), tab indicator navy (was orange), sidebar
width 268px, main bg #f3f4f8
- Dashboard: rounded-xl→rounded-lg cards, rounded-2xl→rounded-xl sections, navy
accent bars on KPI cards, tabular-nums on values, navy pipeline progress bars
- app.css: table thead now navy (#0a1d37) with white text matching reference screenshot,
focus rings navy, admin-segment/admin-link-tabs active state navy, reduced border
radii on segmented controls and list items
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 02:49:09 +01:00
|
|
|
<header class="fixed inset-x-0 top-0 z-50 border-b border-[#d8dbe3] bg-white">
|
|
|
|
|
<div class="flex h-[64px] items-center justify-between px-6">
|
2026-03-24 02:36:40 +01:00
|
|
|
<div class="flex min-w-0 items-center gap-6">
|
|
|
|
|
<button
|
|
|
|
|
type="button"
|
|
|
|
|
class="inline-flex h-10 w-10 items-center justify-center rounded-lg border border-slate-200 text-slate-600 hover:bg-slate-50 lg:hidden"
|
|
|
|
|
onClick={() => setSidebarOpen((v) => !v)}
|
|
|
|
|
aria-label="Toggle sidebar"
|
|
|
|
|
>
|
|
|
|
|
<svg class="h-4 w-4" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
|
|
|
|
<path stroke-linecap="round" d="M4 7h16M4 12h16M4 17h16" />
|
|
|
|
|
</svg>
|
|
|
|
|
</button>
|
|
|
|
|
<A href="/admin" class="flex shrink-0 items-center">
|
|
|
|
|
<img src="/nxtgauge-logo.png" alt="NXTGAUGE" class="h-12 w-auto object-contain" />
|
|
|
|
|
</A>
|
|
|
|
|
</div>
|
feat(admin): Phase 0 — Tailwind v4 foundation, shell rewrite, modern dashboard
- Install Tailwind CSS v4 via @tailwindcss/vite; configure vite.config.ts
- Rewrite app.css: Tailwind base, Exo 2 font, brand tokens (orange #fd6216, navy #050026), scrollbar utility; fix @import order
- Rewrite AdminShell.tsx: fixed header, fixed inset body grid (sidebar + main), session check, sub-tab system, logout, admin avatar/name/role
- Rewrite AdminSidebar.tsx: collapsible w-64/w-20, orange active rail + badge/dot, CSS filter for SVG icon tinting, min-h-0 flex fix
- Replace 84 route stub CSS classes (page-title, card, btn, table-wrap, etc.) with Tailwind equivalents via safe class-attr-only regex script
- Rewrite admin dashboard: Lucide icons in colored chip backgrounds, 4-col KPI grid, Control Plane 6-module grid, hover lift animations
- Disable SSR (ssr: false) to fix Vinxi dev manifest error; clear stale .vinxi cache
- Add lucide-solid icon library
- Add scripts/cleanup-css.mjs for class migration
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 23:00:21 +01:00
|
|
|
|
2026-03-24 02:36:40 +01:00
|
|
|
<div class="flex items-center gap-4">
|
ui: match stitch design system — navy accents, tighter rounding, sidebar groups
- AdminSidebar: group labels (Management/Organisation/Service Providers/Operations),
navy active state (bg-[#e8edf5] + [#0a1d37] left bar + navy icon), width 268px,
13.5px font, 40px item height, lucide-solid icons only (no img fallback), min-w-0
truncation fix, tighter py spacing
- AdminShell: header height 64px (was 86px), compact search bar 40px/rounded-lg,
navy avatar square (was orange gradient), tab indicator navy (was orange), sidebar
width 268px, main bg #f3f4f8
- Dashboard: rounded-xl→rounded-lg cards, rounded-2xl→rounded-xl sections, navy
accent bars on KPI cards, tabular-nums on values, navy pipeline progress bars
- app.css: table thead now navy (#0a1d37) with white text matching reference screenshot,
focus rings navy, admin-segment/admin-link-tabs active state navy, reduced border
radii on segmented controls and list items
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 02:49:09 +01:00
|
|
|
<div class="hidden h-[40px] w-[560px] items-center gap-3 rounded-lg border border-[#daddE8] bg-[#f3f4f8] px-4 text-[13px] text-[#6a7285] lg:flex">
|
2026-03-24 02:36:40 +01:00
|
|
|
<IconSearch />
|
|
|
|
|
<span>Search system operations...</span>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="hidden h-10 w-px bg-[#d9dde7] lg:block" />
|
|
|
|
|
<button type="button" aria-label="Notifications" class="relative inline-flex h-10 w-10 items-center justify-center rounded-full text-[#3e4559] hover:bg-white">
|
|
|
|
|
<span class="absolute right-2 top-2 h-1.5 w-1.5 rounded-full bg-[#fd6216]" />
|
|
|
|
|
<IconBell />
|
|
|
|
|
</button>
|
|
|
|
|
<button type="button" aria-label="Help" class="hidden h-10 w-10 items-center justify-center rounded-full text-[#3e4559] hover:bg-white lg:inline-flex">
|
|
|
|
|
<IconHelp />
|
|
|
|
|
</button>
|
|
|
|
|
<button type="button" aria-label="Settings" class="hidden h-10 w-10 items-center justify-center rounded-full text-[#3e4559] hover:bg-white lg:inline-flex">
|
|
|
|
|
<IconCog />
|
|
|
|
|
</button>
|
|
|
|
|
<div class="hidden h-10 w-px bg-[#d9dde7] lg:block" />
|
ui: match stitch design system — navy accents, tighter rounding, sidebar groups
- AdminSidebar: group labels (Management/Organisation/Service Providers/Operations),
navy active state (bg-[#e8edf5] + [#0a1d37] left bar + navy icon), width 268px,
13.5px font, 40px item height, lucide-solid icons only (no img fallback), min-w-0
truncation fix, tighter py spacing
- AdminShell: header height 64px (was 86px), compact search bar 40px/rounded-lg,
navy avatar square (was orange gradient), tab indicator navy (was orange), sidebar
width 268px, main bg #f3f4f8
- Dashboard: rounded-xl→rounded-lg cards, rounded-2xl→rounded-xl sections, navy
accent bars on KPI cards, tabular-nums on values, navy pipeline progress bars
- app.css: table thead now navy (#0a1d37) with white text matching reference screenshot,
focus rings navy, admin-segment/admin-link-tabs active state navy, reduced border
radii on segmented controls and list items
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 02:49:09 +01:00
|
|
|
<div class="hidden items-center gap-2.5 lg:flex">
|
2026-03-24 02:36:40 +01:00
|
|
|
<div class="text-right leading-tight">
|
ui: match stitch design system — navy accents, tighter rounding, sidebar groups
- AdminSidebar: group labels (Management/Organisation/Service Providers/Operations),
navy active state (bg-[#e8edf5] + [#0a1d37] left bar + navy icon), width 268px,
13.5px font, 40px item height, lucide-solid icons only (no img fallback), min-w-0
truncation fix, tighter py spacing
- AdminShell: header height 64px (was 86px), compact search bar 40px/rounded-lg,
navy avatar square (was orange gradient), tab indicator navy (was orange), sidebar
width 268px, main bg #f3f4f8
- Dashboard: rounded-xl→rounded-lg cards, rounded-2xl→rounded-xl sections, navy
accent bars on KPI cards, tabular-nums on values, navy pipeline progress bars
- app.css: table thead now navy (#0a1d37) with white text matching reference screenshot,
focus rings navy, admin-segment/admin-link-tabs active state navy, reduced border
radii on segmented controls and list items
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 02:49:09 +01:00
|
|
|
<p class="text-[14px] font-semibold text-[#0a1d37]">{adminName()}</p>
|
|
|
|
|
<p class="text-[11px] text-[#6b7280]">Administrator</p>
|
2026-03-24 02:36:40 +01:00
|
|
|
</div>
|
ui: match stitch design system — navy accents, tighter rounding, sidebar groups
- AdminSidebar: group labels (Management/Organisation/Service Providers/Operations),
navy active state (bg-[#e8edf5] + [#0a1d37] left bar + navy icon), width 268px,
13.5px font, 40px item height, lucide-solid icons only (no img fallback), min-w-0
truncation fix, tighter py spacing
- AdminShell: header height 64px (was 86px), compact search bar 40px/rounded-lg,
navy avatar square (was orange gradient), tab indicator navy (was orange), sidebar
width 268px, main bg #f3f4f8
- Dashboard: rounded-xl→rounded-lg cards, rounded-2xl→rounded-xl sections, navy
accent bars on KPI cards, tabular-nums on values, navy pipeline progress bars
- app.css: table thead now navy (#0a1d37) with white text matching reference screenshot,
focus rings navy, admin-segment/admin-link-tabs active state navy, reduced border
radii on segmented controls and list items
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 02:49:09 +01:00
|
|
|
<div class="flex h-9 w-9 items-center justify-center overflow-hidden rounded-lg border border-[#d9dce7] bg-[#0a1d37] text-[13px] font-bold text-white">
|
2026-03-24 02:36:40 +01:00
|
|
|
{adminInitials()}
|
|
|
|
|
</div>
|
feat(ui): apply stitch design system — left-accent KPI cards, Intelligence Hub, glassmorphism header
- app.css: Exo 2 font, #0a1d37 navy + #fd6216 orange tokens, #f9f9fd background
- AdminShell: backdrop-blur-xl glassmorphism header, centered search bar, settings icon,
name + bordered avatar, ambient shadow-[0_4px_24px_rgba(10,29,55,0.04)]
- AdminSidebar: white bg, left orange 4px pill accent on active (before: pseudo),
bg-slate-50 active state, MANAGEMENT/FINANCE/PLATFORM group labels, user card at bottom
- Dashboard: KPI cards with absolute left-0 accent bar + ambient shadows, big font-black numbers,
System Activity bar chart, Intelligence Hub dark navy panel with quick-action buttons,
Pipeline Status cards with progress bars, Control Plane 3-col grid
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 23:34:33 +01:00
|
|
|
</div>
|
feat(admin): Phase 0 — Tailwind v4 foundation, shell rewrite, modern dashboard
- Install Tailwind CSS v4 via @tailwindcss/vite; configure vite.config.ts
- Rewrite app.css: Tailwind base, Exo 2 font, brand tokens (orange #fd6216, navy #050026), scrollbar utility; fix @import order
- Rewrite AdminShell.tsx: fixed header, fixed inset body grid (sidebar + main), session check, sub-tab system, logout, admin avatar/name/role
- Rewrite AdminSidebar.tsx: collapsible w-64/w-20, orange active rail + badge/dot, CSS filter for SVG icon tinting, min-h-0 flex fix
- Replace 84 route stub CSS classes (page-title, card, btn, table-wrap, etc.) with Tailwind equivalents via safe class-attr-only regex script
- Rewrite admin dashboard: Lucide icons in colored chip backgrounds, 4-col KPI grid, Control Plane 6-module grid, hover lift animations
- Disable SSR (ssr: false) to fix Vinxi dev manifest error; clear stale .vinxi cache
- Add lucide-solid icon library
- Add scripts/cleanup-css.mjs for class migration
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 23:00:21 +01:00
|
|
|
</div>
|
2026-03-19 03:36:46 +01:00
|
|
|
</div>
|
|
|
|
|
</header>
|
|
|
|
|
|
|
|
|
|
{checkedSession() ? (
|
ui: match stitch design system — navy accents, tighter rounding, sidebar groups
- AdminSidebar: group labels (Management/Organisation/Service Providers/Operations),
navy active state (bg-[#e8edf5] + [#0a1d37] left bar + navy icon), width 268px,
13.5px font, 40px item height, lucide-solid icons only (no img fallback), min-w-0
truncation fix, tighter py spacing
- AdminShell: header height 64px (was 86px), compact search bar 40px/rounded-lg,
navy avatar square (was orange gradient), tab indicator navy (was orange), sidebar
width 268px, main bg #f3f4f8
- Dashboard: rounded-xl→rounded-lg cards, rounded-2xl→rounded-xl sections, navy
accent bars on KPI cards, tabular-nums on values, navy pipeline progress bars
- app.css: table thead now navy (#0a1d37) with white text matching reference screenshot,
focus rings navy, admin-segment/admin-link-tabs active state navy, reduced border
radii on segmented controls and list items
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 02:49:09 +01:00
|
|
|
<div class="fixed inset-0 top-[64px] flex">
|
2026-03-24 02:36:40 +01:00
|
|
|
<div
|
|
|
|
|
class={`absolute inset-0 z-20 bg-[#0a1d37]/35 transition-opacity lg:hidden ${sidebarOpen() ? 'pointer-events-auto opacity-100' : 'pointer-events-none opacity-0'}`}
|
|
|
|
|
onClick={() => setSidebarOpen(false)}
|
|
|
|
|
/>
|
feat(admin): Phase 0 — Tailwind v4 foundation, shell rewrite, modern dashboard
- Install Tailwind CSS v4 via @tailwindcss/vite; configure vite.config.ts
- Rewrite app.css: Tailwind base, Exo 2 font, brand tokens (orange #fd6216, navy #050026), scrollbar utility; fix @import order
- Rewrite AdminShell.tsx: fixed header, fixed inset body grid (sidebar + main), session check, sub-tab system, logout, admin avatar/name/role
- Rewrite AdminSidebar.tsx: collapsible w-64/w-20, orange active rail + badge/dot, CSS filter for SVG icon tinting, min-h-0 flex fix
- Replace 84 route stub CSS classes (page-title, card, btn, table-wrap, etc.) with Tailwind equivalents via safe class-attr-only regex script
- Rewrite admin dashboard: Lucide icons in colored chip backgrounds, 4-col KPI grid, Control Plane 6-module grid, hover lift animations
- Disable SSR (ssr: false) to fix Vinxi dev manifest error; clear stale .vinxi cache
- Add lucide-solid icon library
- Add scripts/cleanup-css.mjs for class migration
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 23:00:21 +01:00
|
|
|
|
ui: match stitch design system — navy accents, tighter rounding, sidebar groups
- AdminSidebar: group labels (Management/Organisation/Service Providers/Operations),
navy active state (bg-[#e8edf5] + [#0a1d37] left bar + navy icon), width 268px,
13.5px font, 40px item height, lucide-solid icons only (no img fallback), min-w-0
truncation fix, tighter py spacing
- AdminShell: header height 64px (was 86px), compact search bar 40px/rounded-lg,
navy avatar square (was orange gradient), tab indicator navy (was orange), sidebar
width 268px, main bg #f3f4f8
- Dashboard: rounded-xl→rounded-lg cards, rounded-2xl→rounded-xl sections, navy
accent bars on KPI cards, tabular-nums on values, navy pipeline progress bars
- app.css: table thead now navy (#0a1d37) with white text matching reference screenshot,
focus rings navy, admin-segment/admin-link-tabs active state navy, reduced border
radii on segmented controls and list items
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 02:49:09 +01:00
|
|
|
<div class={`absolute inset-y-0 left-0 z-30 w-[268px] -translate-x-full transition-transform duration-200 lg:static lg:translate-x-0 ${sidebarOpen() ? 'translate-x-0' : ''}`}>
|
2026-03-24 02:36:40 +01:00
|
|
|
<AdminSidebar onNavigate={() => setSidebarOpen(false)} onLogout={onLogout} />
|
|
|
|
|
</div>
|
|
|
|
|
|
ui: match stitch design system — navy accents, tighter rounding, sidebar groups
- AdminSidebar: group labels (Management/Organisation/Service Providers/Operations),
navy active state (bg-[#e8edf5] + [#0a1d37] left bar + navy icon), width 268px,
13.5px font, 40px item height, lucide-solid icons only (no img fallback), min-w-0
truncation fix, tighter py spacing
- AdminShell: header height 64px (was 86px), compact search bar 40px/rounded-lg,
navy avatar square (was orange gradient), tab indicator navy (was orange), sidebar
width 268px, main bg #f3f4f8
- Dashboard: rounded-xl→rounded-lg cards, rounded-2xl→rounded-xl sections, navy
accent bars on KPI cards, tabular-nums on values, navy pipeline progress bars
- app.css: table thead now navy (#0a1d37) with white text matching reference screenshot,
focus rings navy, admin-segment/admin-link-tabs active state navy, reduced border
radii on segmented controls and list items
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 02:49:09 +01:00
|
|
|
<main class="scrollbar min-w-0 flex-1 overflow-y-auto bg-[#f3f4f8] px-7 pb-8 pt-7">
|
2026-03-24 02:36:40 +01:00
|
|
|
<ShowTabs
|
|
|
|
|
tabs={tabs()}
|
|
|
|
|
isTabActive={isTabActive}
|
|
|
|
|
setTabsTrackEl={setTabsTrackEl}
|
|
|
|
|
setTabRefs={setTabRefs}
|
|
|
|
|
tabIndicator={tabIndicator}
|
|
|
|
|
/>
|
feat(admin): Phase 0 — Tailwind v4 foundation, shell rewrite, modern dashboard
- Install Tailwind CSS v4 via @tailwindcss/vite; configure vite.config.ts
- Rewrite app.css: Tailwind base, Exo 2 font, brand tokens (orange #fd6216, navy #050026), scrollbar utility; fix @import order
- Rewrite AdminShell.tsx: fixed header, fixed inset body grid (sidebar + main), session check, sub-tab system, logout, admin avatar/name/role
- Rewrite AdminSidebar.tsx: collapsible w-64/w-20, orange active rail + badge/dot, CSS filter for SVG icon tinting, min-h-0 flex fix
- Replace 84 route stub CSS classes (page-title, card, btn, table-wrap, etc.) with Tailwind equivalents via safe class-attr-only regex script
- Rewrite admin dashboard: Lucide icons in colored chip backgrounds, 4-col KPI grid, Control Plane 6-module grid, hover lift animations
- Disable SSR (ssr: false) to fix Vinxi dev manifest error; clear stale .vinxi cache
- Add lucide-solid icon library
- Add scripts/cleanup-css.mjs for class migration
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 23:00:21 +01:00
|
|
|
{props.children}
|
2026-03-19 03:36:46 +01:00
|
|
|
</main>
|
|
|
|
|
</div>
|
|
|
|
|
) : (
|
ui: match stitch design system — navy accents, tighter rounding, sidebar groups
- AdminSidebar: group labels (Management/Organisation/Service Providers/Operations),
navy active state (bg-[#e8edf5] + [#0a1d37] left bar + navy icon), width 268px,
13.5px font, 40px item height, lucide-solid icons only (no img fallback), min-w-0
truncation fix, tighter py spacing
- AdminShell: header height 64px (was 86px), compact search bar 40px/rounded-lg,
navy avatar square (was orange gradient), tab indicator navy (was orange), sidebar
width 268px, main bg #f3f4f8
- Dashboard: rounded-xl→rounded-lg cards, rounded-2xl→rounded-xl sections, navy
accent bars on KPI cards, tabular-nums on values, navy pipeline progress bars
- app.css: table thead now navy (#0a1d37) with white text matching reference screenshot,
focus rings navy, admin-segment/admin-link-tabs active state navy, reduced border
radii on segmented controls and list items
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 02:49:09 +01:00
|
|
|
<div class="fixed inset-0 top-[64px] flex">
|
|
|
|
|
<div class="hidden w-[268px] border-r border-[#d7d8df] bg-white lg:block" />
|
|
|
|
|
<main class="flex flex-1 items-center justify-center bg-[#f3f4f8]">
|
2026-03-24 02:36:40 +01:00
|
|
|
<p class="text-sm text-gray-500">Checking session...</p>
|
2026-03-19 03:36:46 +01:00
|
|
|
</main>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
2026-03-16 23:20:54 +01:00
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
2026-03-24 02:36:40 +01:00
|
|
|
|
|
|
|
|
function ShowTabs(props: {
|
|
|
|
|
tabs: Tab[];
|
|
|
|
|
isTabActive: (tab: Tab) => boolean;
|
|
|
|
|
setTabsTrackEl: (el: HTMLDivElement) => void;
|
|
|
|
|
setTabRefs: (fn: (prev: Record<string, HTMLAnchorElement>) => Record<string, HTMLAnchorElement>) => void;
|
|
|
|
|
tabIndicator: () => { left: number; width: number; ready: boolean };
|
|
|
|
|
}) {
|
|
|
|
|
if (props.tabs.length === 0) return null;
|
|
|
|
|
|
|
|
|
|
return (
|
ui: match stitch design system — navy accents, tighter rounding, sidebar groups
- AdminSidebar: group labels (Management/Organisation/Service Providers/Operations),
navy active state (bg-[#e8edf5] + [#0a1d37] left bar + navy icon), width 268px,
13.5px font, 40px item height, lucide-solid icons only (no img fallback), min-w-0
truncation fix, tighter py spacing
- AdminShell: header height 64px (was 86px), compact search bar 40px/rounded-lg,
navy avatar square (was orange gradient), tab indicator navy (was orange), sidebar
width 268px, main bg #f3f4f8
- Dashboard: rounded-xl→rounded-lg cards, rounded-2xl→rounded-xl sections, navy
accent bars on KPI cards, tabular-nums on values, navy pipeline progress bars
- app.css: table thead now navy (#0a1d37) with white text matching reference screenshot,
focus rings navy, admin-segment/admin-link-tabs active state navy, reduced border
radii on segmented controls and list items
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 02:49:09 +01:00
|
|
|
<div ref={props.setTabsTrackEl} class="relative mb-6 flex items-center gap-1 border-b border-[#d8dbe3]">
|
2026-03-24 02:36:40 +01:00
|
|
|
<For each={props.tabs}>
|
|
|
|
|
{(tab) => (
|
|
|
|
|
<A
|
|
|
|
|
href={tab.href}
|
|
|
|
|
ref={(el) => props.setTabRefs((prev) => ({ ...prev, [tab.href]: el }))}
|
|
|
|
|
aria-current={props.isTabActive(tab) ? 'page' : undefined}
|
ui: match stitch design system — navy accents, tighter rounding, sidebar groups
- AdminSidebar: group labels (Management/Organisation/Service Providers/Operations),
navy active state (bg-[#e8edf5] + [#0a1d37] left bar + navy icon), width 268px,
13.5px font, 40px item height, lucide-solid icons only (no img fallback), min-w-0
truncation fix, tighter py spacing
- AdminShell: header height 64px (was 86px), compact search bar 40px/rounded-lg,
navy avatar square (was orange gradient), tab indicator navy (was orange), sidebar
width 268px, main bg #f3f4f8
- Dashboard: rounded-xl→rounded-lg cards, rounded-2xl→rounded-xl sections, navy
accent bars on KPI cards, tabular-nums on values, navy pipeline progress bars
- app.css: table thead now navy (#0a1d37) with white text matching reference screenshot,
focus rings navy, admin-segment/admin-link-tabs active state navy, reduced border
radii on segmented controls and list items
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 02:49:09 +01:00
|
|
|
class={`relative px-4 pb-3 pt-3 text-[13.5px] font-semibold transition-colors ${
|
|
|
|
|
props.isTabActive(tab) ? 'text-[#0a1d37]' : 'text-[#636b7f] hover:text-[#0a1d37]'
|
2026-03-24 02:36:40 +01:00
|
|
|
}`}
|
|
|
|
|
>
|
|
|
|
|
{tab.label}
|
|
|
|
|
</A>
|
|
|
|
|
)}
|
|
|
|
|
</For>
|
|
|
|
|
<div
|
ui: match stitch design system — navy accents, tighter rounding, sidebar groups
- AdminSidebar: group labels (Management/Organisation/Service Providers/Operations),
navy active state (bg-[#e8edf5] + [#0a1d37] left bar + navy icon), width 268px,
13.5px font, 40px item height, lucide-solid icons only (no img fallback), min-w-0
truncation fix, tighter py spacing
- AdminShell: header height 64px (was 86px), compact search bar 40px/rounded-lg,
navy avatar square (was orange gradient), tab indicator navy (was orange), sidebar
width 268px, main bg #f3f4f8
- Dashboard: rounded-xl→rounded-lg cards, rounded-2xl→rounded-xl sections, navy
accent bars on KPI cards, tabular-nums on values, navy pipeline progress bars
- app.css: table thead now navy (#0a1d37) with white text matching reference screenshot,
focus rings navy, admin-segment/admin-link-tabs active state navy, reduced border
radii on segmented controls and list items
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 02:49:09 +01:00
|
|
|
class={`absolute bottom-0 h-[2px] bg-[#0a1d37] transition-all duration-300 ease-out ${props.tabIndicator().ready ? 'opacity-100' : 'opacity-0'}`}
|
2026-03-24 02:36:40 +01:00
|
|
|
style={{ left: `${props.tabIndicator().left}px`, width: `${props.tabIndicator().width}px` }}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|