Files
auditly/App.tsx

295 lines
10 KiB
TypeScript

import React from 'react';
import { HashRouter, Routes, Route, Navigate, useParams } from 'react-router-dom';
import { ThemeProvider } from './contexts/ThemeContext';
import { AuthProvider, useAuth } from './contexts/AuthContext';
import { UserOrganizationsProvider, useUserOrganizations } from './contexts/UserOrganizationsContext';
import { OrgProvider, useOrg } from './contexts/OrgContext';
import { Layout } from './components/UiKit';
import CompanyWiki from './pages/CompanyWiki';
import EmployeeData from './pages/EmployeeData';
import Chat from './pages/Chat';
import ChatNew from './pages/ChatNew';
import HelpNew from './pages/HelpNew';
import SettingsNew from './pages/SettingsNew';
import HelpAndSettings from './pages/HelpAndSettings';
import ModernLogin from './pages/Login';
import OrgSelection from './pages/OrgSelection';
import Onboarding from './pages/Onboarding';
import EmployeeQuestionnaire from './pages/EmployeeQuestionnaire';
import EmployeeQuestionnaireSteps from './pages/EmployeeQuestionnaireSteps';
import QuestionTypesDemo from './pages/QuestionTypesDemo';
import FormsDashboard from './pages/FormsDashboard';
import DebugEmployee from './pages/DebugEmployee';
import QuestionnaireComplete from './pages/QuestionnaireComplete';
import SubscriptionSetup from './pages/SubscriptionSetup';
const RequireAuth: React.FC<{ children: React.ReactNode }> = ({ children }) => {
const { user, loading } = useAuth();
if (loading) return <div className="p-8">Loading...</div>;
if (!user) return <Navigate to="/login" replace />;
return <>{children}</>;
};
const RequireOrgSelection: React.FC<{ children: React.ReactNode }> = ({ children }) => {
const { selectedOrgId, loading } = useUserOrganizations();
if (loading) return <div className="p-8">Loading your organizations...</div>;
if (!selectedOrgId) return <Navigate to="/org-selection" replace />;
return <>{children}</>;
};
const RequireOnboarding: React.FC<{ children: React.ReactNode }> = ({ children }) => {
const { org } = useOrg();
const { user } = useAuth();
const { organizations, selectedOrgId } = useUserOrganizations();
if (!org) return <div className="p-8">Loading organization...</div>;
const userOrgRelation = organizations.find(o => o.orgId === selectedOrgId);
const isOrgOwner = userOrgRelation?.role === 'owner';
const onboardingCompleted = org.onboardingCompleted === true;
console.log('RequireOnboarding check:', {
orgId: selectedOrgId,
orgOnboardingCompleted: org.onboardingCompleted,
userRole: userOrgRelation?.role,
finalDecision: onboardingCompleted
});
if (!onboardingCompleted) {
if (isOrgOwner) {
console.log('Redirecting owner to onboarding');
return <Navigate to="/onboarding" replace />;
} else {
// Non-owners should see a waiting message
return (
<div className="p-8 text-center">
<h2 className="text-xl font-semibold mb-4">Organization Setup In Progress</h2>
<p className="text-gray-600">
Your organization is currently being set up by the administrator.
Please check back later or contact your administrator for more information.
</p>
</div>
);
}
}
return <>{children}</>;
};
// Wrapper component that provides selected org to OrgProvider
const OrgProviderWrapper: React.FC<{ children: React.ReactNode }> = ({ children }) => {
const { selectedOrgId } = useUserOrganizations();
if (!selectedOrgId) {
return <div className="p-8">No organization selected</div>;
}
return (
<OrgProvider selectedOrgId={selectedOrgId}>
{children}
</OrgProvider>
);
};
// Redirect invite URLs directly to employee questionnaire (no auth needed)
const InviteRedirect: React.FC = () => {
const { inviteCode } = useParams<{ inviteCode: string }>();
return <Navigate to={`/employee-form/${inviteCode}`} replace />;
};
function App() {
return (
<ThemeProvider>
<AuthProvider>
<UserOrganizationsProvider>
<HashRouter>
<Routes>
<Route path="/login" element={<ModernLogin />} />
<Route path="/login/:inviteCode" element={<ModernLogin />} />
<Route path="/invite/:inviteCode" element={<InviteRedirect />} />
{/* Employee questionnaire - no auth needed, uses invite code */}
<Route path="/employee-form/:inviteCode" element={<EmployeeQuestionnaire />} />
<Route path="/questionnaire/:inviteCode" element={<EmployeeQuestionnaire />} />
{/* Organization Selection - after auth, before entering app */}
<Route
path="/org-selection"
element={
<RequireAuth>
<OrgSelection />
</RequireAuth>
}
/>
{/* Subscription Setup - after organization creation */}
<Route
path="/subscription-setup"
element={
<RequireAuth>
<SubscriptionSetup />
</RequireAuth>
}
/>
{/* Routes that require both auth and org selection */}
<Route
path="/employee-questionnaire"
element={
<RequireAuth>
<RequireOrgSelection>
<OrgProviderWrapper>
<EmployeeQuestionnaire />
</OrgProviderWrapper>
</RequireOrgSelection>
</RequireAuth>
}
/>
<Route
path="/employee-questionnaire-steps"
element={
<RequireAuth>
<RequireOrgSelection>
<OrgProviderWrapper>
<EmployeeQuestionnaireSteps />
</OrgProviderWrapper>
</RequireOrgSelection>
</RequireAuth>
}
/>
<Route
path="/onboarding"
element={
<RequireAuth>
<RequireOrgSelection>
<OrgProviderWrapper>
<Onboarding />
</OrgProviderWrapper>
</RequireOrgSelection>
</RequireAuth>
}
/>
<Route path="/questionnaire-complete" element={<QuestionnaireComplete />} />
{/* New Figma Chat Implementation - Standalone route */}
<Route
path="/chat-new"
element={
<RequireAuth>
<RequireOrgSelection>
<OrgProviderWrapper>
<RequireOnboarding>
<ChatNew />
</RequireOnboarding>
</OrgProviderWrapper>
</RequireOrgSelection>
</RequireAuth>
}
/>
{/* New Figma Help Implementation - Standalone route */}
<Route
path="/help-new"
element={
<RequireAuth>
<RequireOrgSelection>
<OrgProviderWrapper>
<RequireOnboarding>
<HelpNew />
</RequireOnboarding>
</OrgProviderWrapper>
</RequireOrgSelection>
</RequireAuth>
}
/>
{/* New Figma Settings Implementation - Standalone route */}
<Route
path="/settings-new"
element={
<RequireAuth>
<RequireOrgSelection>
<OrgProviderWrapper>
<RequireOnboarding>
<SettingsNew />
</RequireOnboarding>
</OrgProviderWrapper>
</RequireOrgSelection>
</RequireAuth>
}
/>
{/* Main app routes - require auth, org selection, and completed onboarding */}
<Route
element={
<RequireAuth>
<RequireOrgSelection>
<OrgProviderWrapper>
<RequireOnboarding>
<Layout />
</RequireOnboarding>
</OrgProviderWrapper>
</RequireOrgSelection>
</RequireAuth>
}
>
<Route path="/" element={<Navigate to="/reports" replace />} />
<Route path="/company-wiki" element={<CompanyWiki />} />
<Route path="/submissions" element={<EmployeeData mode="submissions" />} />
<Route path="/reports" element={<EmployeeData mode="reports" />} />
<Route path="/chat" element={<Chat />} />
<Route path="/help" element={<HelpAndSettings />} />
<Route path="/settings" element={<HelpAndSettings />} />
</Route>
{/* Debug routes */}
<Route
path="/question-types-demo"
element={
<RequireAuth>
<RequireOrgSelection>
<OrgProviderWrapper>
<QuestionTypesDemo />
</OrgProviderWrapper>
</RequireOrgSelection>
</RequireAuth>
}
/>
<Route
path="/forms-dashboard"
element={
<RequireAuth>
<RequireOrgSelection>
<OrgProviderWrapper>
<FormsDashboard />
</OrgProviderWrapper>
</RequireOrgSelection>
</RequireAuth>
}
/>
<Route
path="/debug-employee"
element={
<RequireAuth>
<RequireOrgSelection>
<OrgProviderWrapper>
<DebugEmployee />
</OrgProviderWrapper>
</RequireOrgSelection>
</RequireAuth>
}
/>
</Routes>
</HashRouter>
</UserOrganizationsProvider>
</AuthProvider>
</ThemeProvider>
);
}
export default App;