Fix organization setup flow: redirect to onboarding for incomplete setup
This commit is contained in:
238
App.tsx
Normal file
238
App.tsx
Normal file
@@ -0,0 +1,238 @@
|
||||
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 HelpAndSettings from './pages/HelpAndSettings';
|
||||
import Login from './pages/Login';
|
||||
import ModernLogin from './pages/ModernLogin';
|
||||
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';
|
||||
import { isFirebaseConfigured } from './services/firebase';
|
||||
|
||||
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 } = useUserOrganizations();
|
||||
|
||||
if (!org) return <div className="p-8">Loading organization...</div>;
|
||||
|
||||
if (!org.onboardingCompleted) {
|
||||
// Only org owners should be redirected to onboarding
|
||||
const userOrgRelation = organizations.find(o => o.orgId === org.orgId);
|
||||
const isOrgOwner = userOrgRelation?.role === 'owner';
|
||||
|
||||
if (isOrgOwner) {
|
||||
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 />} />
|
||||
<Route path="/legacy-login" element={<Login />} />
|
||||
|
||||
{/* Employee questionnaire - no auth needed, uses invite code */}
|
||||
<Route path="/employee-form/: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 />} />
|
||||
|
||||
{/* 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;
|
||||
Reference in New Issue
Block a user