144 lines
3.8 KiB
TypeScript
144 lines
3.8 KiB
TypeScript
import * as React from "react";
|
|
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
|
import { AuthProvider, useAuth, AuthPage } from "../auth/src";
|
|
import { UploadProvider } from "./providers/UploadProvider";
|
|
import AdminLayout from "./components/AdminLayout";
|
|
import ResourceView from "./components/ResourceView";
|
|
import { getAppConfig } from "./config";
|
|
import { initializeApiClients } from "./api/client";
|
|
import { AppConfig } from "./types/config";
|
|
import { Box, Typography, Paper, CircularProgress } from "@mui/material";
|
|
import AppTheme from "../src/shared-theme/AppTheme";
|
|
|
|
const queryClient = new QueryClient();
|
|
|
|
// Create a context for the app config
|
|
export const ConfigContext = React.createContext<AppConfig | null>(null);
|
|
|
|
function Dashboard() {
|
|
const config = React.useContext(ConfigContext);
|
|
return (
|
|
<Box>
|
|
<Typography variant="h4" gutterBottom>
|
|
Welcome to the Admin Panel
|
|
</Typography>
|
|
<Typography variant="body1">
|
|
Select a resource from the sidebar to manage data.
|
|
</Typography>
|
|
|
|
<Box
|
|
sx={{
|
|
display: "grid",
|
|
gridTemplateColumns: "repeat(auto-fill, minmax(200px, 1fr))",
|
|
gap: 3,
|
|
mt: 4,
|
|
}}
|
|
>
|
|
{config?.resources.map((res) => (
|
|
<Paper key={res.name} sx={{ p: 3, textAlign: "center" }}>
|
|
<Typography variant="h6">{res.pluralLabel}</Typography>
|
|
</Paper>
|
|
))}
|
|
</Box>
|
|
</Box>
|
|
);
|
|
}
|
|
|
|
function AdminApp() {
|
|
const { currentUser, login, logout, loading, error } = useAuth();
|
|
const config = React.useContext(ConfigContext);
|
|
const [selectedResourceName, setSelectedResourceName] = React.useState<
|
|
string | null
|
|
>(null);
|
|
const [selectedItemId, setSelectedItemId] = React.useState<string | null>(null);
|
|
|
|
const handleNavigateToResource = (resourceName: string, id: string) => {
|
|
setSelectedResourceName(resourceName);
|
|
setSelectedItemId(id);
|
|
};
|
|
|
|
if (!currentUser) {
|
|
return (
|
|
<AuthPage
|
|
mode="login"
|
|
login={login}
|
|
register={async () => {}} // Disable registration for Admin
|
|
loading={loading}
|
|
error={error}
|
|
onSwitchMode={() => {}}
|
|
onBack={() => {}}
|
|
currentUser={null}
|
|
/>
|
|
);
|
|
}
|
|
|
|
const selectedResource = config?.resources.find(
|
|
(r) => r.name === selectedResourceName
|
|
);
|
|
|
|
return (
|
|
<AdminLayout
|
|
username={currentUser.username}
|
|
onLogout={logout}
|
|
selectedResourceName={selectedResourceName}
|
|
onSelectResource={(name) => {
|
|
setSelectedResourceName(name);
|
|
setSelectedItemId(null);
|
|
}}
|
|
resources={config?.resources || []}
|
|
>
|
|
{selectedResource ? (
|
|
<ResourceView
|
|
key={`${selectedResource.name}-${selectedItemId}`}
|
|
config={selectedResource}
|
|
onNavigateToResource={handleNavigateToResource}
|
|
/>
|
|
) : (
|
|
<Dashboard />
|
|
)}
|
|
</AdminLayout>
|
|
);
|
|
}
|
|
|
|
export default function App() {
|
|
const [config, setConfig] = React.useState<AppConfig | null>(null);
|
|
|
|
React.useEffect(() => {
|
|
getAppConfig().then((cfg) => {
|
|
initializeApiClients(cfg.baseUrl, cfg.authBaseUrl);
|
|
setConfig(cfg);
|
|
});
|
|
}, []);
|
|
|
|
if (!config) {
|
|
return (
|
|
<AppTheme>
|
|
<Box
|
|
sx={{
|
|
display: "flex",
|
|
justifyContent: "center",
|
|
alignItems: "center",
|
|
height: "100vh",
|
|
}}
|
|
>
|
|
<CircularProgress />
|
|
</Box>
|
|
</AppTheme>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<AppTheme>
|
|
<QueryClientProvider client={queryClient}>
|
|
<ConfigContext.Provider value={config}>
|
|
<AuthProvider authBaseUrl={config.authBaseUrl}>
|
|
<UploadProvider>
|
|
<AdminApp />
|
|
</UploadProvider>
|
|
</AuthProvider>
|
|
</ConfigContext.Provider>
|
|
</QueryClientProvider>
|
|
</AppTheme>
|
|
);
|
|
}
|