2025-10-01 15:34:19 -04:00
|
|
|
import React, { useEffect } from "react";
|
2025-09-28 05:58:29 -04:00
|
|
|
import { BrowserRouter as Router, Routes, Route, Navigate } from "react-router";
|
|
|
|
|
import { QueryClientProvider } from "@tanstack/react-query";
|
2025-09-27 03:38:42 -04:00
|
|
|
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
|
|
|
|
|
import { Toaster } from "@/components/ui/sonner";
|
|
|
|
|
|
2025-09-27 23:19:51 -04:00
|
|
|
import { ThemeProvider } from "@/components/theme-provider";
|
2025-09-27 03:38:42 -04:00
|
|
|
import AppLayout from "@/components/layout/AppLayout";
|
|
|
|
|
import LoginPage from "@/pages/LoginPage";
|
|
|
|
|
import ChatPage from "@/pages/ChatPage";
|
|
|
|
|
import SettingsPage from "@/pages/SettingsPage";
|
|
|
|
|
import NotFoundPage from "@/pages/NotFoundPage";
|
2025-09-28 10:05:11 -04:00
|
|
|
import { useVoiceStore } from "@/stores/voiceStore";
|
2025-09-27 03:38:42 -04:00
|
|
|
|
2025-09-28 05:58:29 -04:00
|
|
|
import { queryClient } from "@/lib/api-client";
|
|
|
|
|
import { useAuthStore } from "@/stores/authStore";
|
2025-09-27 03:38:42 -04:00
|
|
|
import ErrorBoundary from "@/components/common/ErrorBoundary";
|
2025-09-27 23:19:51 -04:00
|
|
|
import { Home } from "lucide-react";
|
2025-09-28 10:05:11 -04:00
|
|
|
import { Socket } from "socket.io-client";
|
2025-09-27 03:38:42 -04:00
|
|
|
|
|
|
|
|
// Protected Route wrapper
|
|
|
|
|
const ProtectedRoute: React.FC<{ children: React.ReactNode }> = ({
|
|
|
|
|
children,
|
|
|
|
|
}) => {
|
2025-09-28 05:58:29 -04:00
|
|
|
const { isAuthenticated } = useAuthStore();
|
|
|
|
|
|
|
|
|
|
// Enable this when you want to enforce authentication
|
|
|
|
|
if (!isAuthenticated) {
|
|
|
|
|
return <Navigate to="/login" replace />;
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-27 03:38:42 -04:00
|
|
|
return <>{children}</>;
|
|
|
|
|
};
|
|
|
|
|
|
2025-09-27 23:19:51 -04:00
|
|
|
// Home page component - shows server selection
|
|
|
|
|
const HomePage: React.FC = () => {
|
|
|
|
|
return (
|
|
|
|
|
<div className="flex-1 flex items-center justify-center bg-concord-primary">
|
|
|
|
|
<div className="text-center text-concord-secondary max-w-md">
|
|
|
|
|
<div className="w-16 h-16 mx-auto mb-4 bg-concord-secondary rounded-full flex items-center justify-center">
|
|
|
|
|
<Home />
|
|
|
|
|
</div>
|
|
|
|
|
<h2 className="text-xl font-semibold mb-2 text-concord-primary">
|
|
|
|
|
Welcome to Concord
|
|
|
|
|
</h2>
|
|
|
|
|
<p className="text-sm mb-4">
|
|
|
|
|
Select a server from the sidebar to start chatting, or create a new
|
|
|
|
|
server
|
|
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
};
|
2025-09-27 03:38:42 -04:00
|
|
|
|
2025-09-28 10:05:11 -04:00
|
|
|
function App(props: { socket: Socket }) {
|
|
|
|
|
const initVoiceStore = useVoiceStore((state) => state.init);
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
initVoiceStore(props.socket);
|
|
|
|
|
return () => {
|
|
|
|
|
useVoiceStore.getState().cleanup();
|
|
|
|
|
};
|
|
|
|
|
}, [props.socket, initVoiceStore]);
|
|
|
|
|
|
2025-09-27 03:38:42 -04:00
|
|
|
return (
|
|
|
|
|
<ErrorBoundary>
|
|
|
|
|
<QueryClientProvider client={queryClient}>
|
2025-10-01 16:30:44 -04:00
|
|
|
<ThemeProvider defaultTheme="system" storageKey="concord-theme">
|
2025-09-27 23:19:51 -04:00
|
|
|
<Router>
|
|
|
|
|
<div className="h-screen w-screen overflow-hidden bg-background text-foreground">
|
|
|
|
|
<Routes>
|
|
|
|
|
{/* Auth routes */}
|
|
|
|
|
<Route path="/login" element={<LoginPage />} />
|
|
|
|
|
|
|
|
|
|
{/* Protected routes with layout */}
|
2025-09-27 03:38:42 -04:00
|
|
|
<Route
|
2025-09-27 23:19:51 -04:00
|
|
|
path="/"
|
|
|
|
|
element={
|
|
|
|
|
<ProtectedRoute>
|
|
|
|
|
<AppLayout />
|
|
|
|
|
</ProtectedRoute>
|
|
|
|
|
}
|
|
|
|
|
>
|
|
|
|
|
{/* Default redirect to home */}
|
|
|
|
|
<Route index element={<HomePage />} />
|
|
|
|
|
|
|
|
|
|
{/* Server and channel routes */}
|
|
|
|
|
<Route path="channels/:instanceId" element={<ChatPage />} />
|
|
|
|
|
<Route
|
|
|
|
|
path="channels/:instanceId/:channelId"
|
|
|
|
|
element={<ChatPage />}
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
{/* Settings */}
|
|
|
|
|
<Route path="settings" element={<SettingsPage />} />
|
|
|
|
|
<Route path="settings/:section" element={<SettingsPage />} />
|
|
|
|
|
</Route>
|
|
|
|
|
|
|
|
|
|
{/* 404 */}
|
|
|
|
|
<Route path="*" element={<NotFoundPage />} />
|
|
|
|
|
</Routes>
|
|
|
|
|
</div>
|
|
|
|
|
</Router>
|
|
|
|
|
|
|
|
|
|
{import.meta.env.DEV === true && <ReactQueryDevtools />}
|
|
|
|
|
{/* Toast notifications */}
|
|
|
|
|
<Toaster />
|
|
|
|
|
</ThemeProvider>
|
2025-09-27 03:38:42 -04:00
|
|
|
</QueryClientProvider>
|
|
|
|
|
</ErrorBoundary>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default App;
|