demo / frontend /src /App.tsx
Pierre Andrews
Initial commit
f52d137
raw
history blame
4.68 kB
import { Alert, CssBaseline, Snackbar, ThemeProvider } from "@mui/material";
import { useCallback, useEffect, useState } from "react";
// Local imports
import { DemoView } from "./components/DemoView";
import { InitialForm } from "./components/InitialForm";
import { CustomThemeProvider, useThemeMode } from "./contexts/ThemeContext";
import { FormData, SnackbarState, UserInfo } from "./types";
import { preloadDefaultMcp } from "./utils/api";
import { useStartDemo } from "./hooks/useStartDemo";
const AppContent = () => {
const { theme } = useThemeMode();
// Authentication state
const [userInfo, setUserInfo] = useState<UserInfo | null>(null);
const [accessToken, setAccessToken] = useState<string | null>(null);
const [loginLabel, setLoginLabel] = useState<string>(
"Login with Hugging Face",
);
// Form state
const [formData, setFormData] = useState<FormData>({
model: "",
provider: "",
mcpFile: null,
});
// UI state
const [snackbar, setSnackbar] = useState<SnackbarState>({
open: false,
message: "",
severity: "info",
});
const [defaultMcpFile, setDefaultMcpFile] = useState<File | null>(null);
// Demo management hook
const {
isStarting,
iframeUrl,
iframeLoading,
healthCheckProgress,
startDemoSession,
resetDemo,
setIframeLoaded,
} = useStartDemo();
// Determine if we're in demo mode (iframe is loaded)
const isDemoActive = Boolean(iframeUrl);
// Utility functions
const showSnackbar = useCallback(
(message: string, severity: "success" | "error" | "info" = "info") => {
setSnackbar({ open: true, message, severity });
},
[],
);
const handleSnackbarClose = () => {
setSnackbar((prev: SnackbarState) => ({ ...prev, open: false }));
};
const handleIframeLoad = () => {
setIframeLoaded();
};
// Authentication handlers
const handleLoginStateChange = useCallback(
(
newUserInfo: UserInfo | null,
newAccessToken: string | null,
newLoginLabel: string,
) => {
setUserInfo(newUserInfo);
setAccessToken(newAccessToken);
setLoginLabel(newLoginLabel);
},
[],
);
// Form handlers
const handleFormChange = (newFormData: FormData) => {
setFormData(newFormData);
};
const handleFormSubmit = async () => {
await startDemoSession(formData, loginLabel, accessToken, {
logPrefix: "Initial startup",
onError: (error) => {
showSnackbar(error.message, "error");
},
});
};
const handleRestart = () => {
resetDemo();
};
const handleSettingsRestart = async () => {
await startDemoSession(formData, loginLabel, accessToken, {
logPrefix: "Settings restart",
onError: (error) => {
showSnackbar(error.message, "error");
},
});
};
// Initialize default MCP file on mount
useEffect(() => {
const loadDefaultMcp = async () => {
const mcpFile = await preloadDefaultMcp();
if (mcpFile) {
setFormData((prev: FormData) => ({ ...prev, mcpFile: mcpFile }));
setDefaultMcpFile(mcpFile);
}
};
loadDefaultMcp();
}, []);
return (
<ThemeProvider theme={theme}>
<CssBaseline />
{/* Conditional rendering based on demo state */}
{isDemoActive ? (
<DemoView
iframeUrl={iframeUrl}
iframeLoading={iframeLoading}
healthCheckProgress={healthCheckProgress}
formData={formData}
onIframeLoad={handleIframeLoad}
onRestart={handleRestart}
onFormChange={handleFormChange}
onSettingsRestart={handleSettingsRestart}
defaultMcpFile={defaultMcpFile}
/>
) : (
<InitialForm
formData={formData}
userInfo={userInfo}
accessToken={accessToken}
loginLabel={loginLabel}
isStarting={isStarting}
onFormChange={handleFormChange}
onSubmit={handleFormSubmit}
onLoginStateChange={handleLoginStateChange}
defaultMcpFile={defaultMcpFile}
/>
)}
{/* Snackbar for notifications */}
<Snackbar
open={snackbar.open}
autoHideDuration={4000}
onClose={handleSnackbarClose}
anchorOrigin={{ vertical: "bottom", horizontal: "center" }}
>
<Alert
onClose={handleSnackbarClose}
severity={snackbar.severity}
sx={{ width: "100%" }}
>
{snackbar.message}
</Alert>
</Snackbar>
</ThemeProvider>
);
};
function App() {
return (
<CustomThemeProvider>
<AppContent />
</CustomThemeProvider>
);
}
export default App;