feat: Implement standalone admin at /admin with custom login page and auth system

This commit is contained in:
dwindown
2025-11-04 21:28:00 +07:00
parent 549ef12802
commit e161163362
6 changed files with 486 additions and 4 deletions

View File

@@ -1,5 +1,5 @@
import React, { useEffect, useState } from 'react';
import { HashRouter, Routes, Route, NavLink, useLocation, useParams } from 'react-router-dom';
import { HashRouter, Routes, Route, NavLink, useLocation, useParams, Navigate } from 'react-router-dom';
import Dashboard from '@/routes/Dashboard';
import DashboardRevenue from '@/routes/Dashboard/Revenue';
import DashboardOrders from '@/routes/Dashboard/Orders';
@@ -19,6 +19,7 @@ import ProductAttributes from '@/routes/Products/Attributes';
import CouponsIndex from '@/routes/Coupons';
import CouponNew from '@/routes/Coupons/New';
import CustomersIndex from '@/routes/Customers';
import { Login } from '@/routes/Login';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { LayoutDashboard, ReceiptText, Package, Tag, Users, Settings as SettingsIcon, Maximize2, Minimize2, Loader2 } from 'lucide-react';
import { Toaster } from 'sonner';
@@ -394,13 +395,63 @@ function Shell() {
);
}
function AuthWrapper() {
const [isAuthenticated, setIsAuthenticated] = useState(
window.WNW_CONFIG?.isAuthenticated ?? true
);
const [isChecking, setIsChecking] = useState(window.WNW_CONFIG?.standaloneMode ?? false);
const location = useLocation();
useEffect(() => {
if (window.WNW_CONFIG?.standaloneMode) {
fetch(window.WNW_CONFIG.restUrl + '/auth/check', {
credentials: 'include',
})
.then(res => res.json())
.then(data => {
setIsAuthenticated(data.authenticated);
if (data.authenticated && data.user) {
window.WNW_CONFIG.currentUser = data.user;
}
})
.catch(() => setIsAuthenticated(false))
.finally(() => setIsChecking(false));
}
}, []);
if (isChecking) {
return (
<div className="flex items-center justify-center min-h-screen">
<Loader2 className="w-12 h-12 animate-spin text-primary" />
</div>
);
}
if (window.WNW_CONFIG?.standaloneMode && !isAuthenticated && location.pathname !== '/login') {
return <Navigate to="/login" replace />;
}
if (location.pathname === '/login' && isAuthenticated) {
return <Navigate to="/dashboard" replace />;
}
return (
<DashboardProvider>
<Shell />
</DashboardProvider>
);
}
export default function App() {
return (
<QueryClientProvider client={qc}>
<HashRouter>
<DashboardProvider>
<Shell />
</DashboardProvider>
<Routes>
{window.WNW_CONFIG?.standaloneMode && (
<Route path="/login" element={<Login />} />
)}
<Route path="/*" element={<AuthWrapper />} />
</Routes>
<Toaster
richColors
theme="light"