Skip to content

Commit 5826208

Browse files
author
Boopathi
committed
Update authentication components and add main view component
1 parent de100b9 commit 5826208

File tree

4 files changed

+373
-360
lines changed

4 files changed

+373
-360
lines changed

src/app/page.tsx

Lines changed: 2 additions & 354 deletions
Original file line numberDiff line numberDiff line change
@@ -1,357 +1,5 @@
1-
2-
"use client";
3-
4-
import { useState, useEffect, useCallback } from "react";
5-
import dynamic from 'next/dynamic';
6-
import { useRouter, useSearchParams } from 'next/navigation';
7-
import Header from "@/components/layout/header";
8-
import Footer from "@/components/layout/footer";
9-
import HomeView from "@/components/views/home";
10-
import type { View, UserRole } from "@/app/types";
11-
import { useToast } from "@/hooks/use-toast";
12-
import { format } from "date-fns";
13-
import { Dialog, DialogContent } from "@/components/ui/dialog";
14-
import { Loader2 } from "lucide-react";
15-
import { signOut } from "firebase/auth";
16-
import { useFirebaseAuth } from "@/hooks/use-firebase-auth";
17-
import { API_BASE_URL } from "@/lib/api";
18-
19-
// A more obvious loading animation to show while dynamic components are being downloaded.
20-
const ModalSkeleton = () => (
21-
<Dialog open={true}>
22-
<DialogContent className="flex items-center justify-center h-64 bg-transparent border-none shadow-none">
23-
<Loader2 className="h-16 w-16 animate-spin text-primary" />
24-
</DialogContent>
25-
</Dialog>
26-
);
27-
28-
// Dynamically import all modal views. Their code will only be loaded when they're first opened.
29-
const BlogView = dynamic(() => import('@/components/views/blog'), { loading: () => <ModalSkeleton /> });
30-
const MentorsView = dynamic(() => import('@/components/views/mentors'), { loading: () => <ModalSkeleton /> });
31-
const IncubatorsView = dynamic(() => import('@/components/views/incubators'), { loading: () => <ModalSkeleton /> });
32-
const PricingView = dynamic(() => import('@/components/views/pricing'), { loading: () => <ModalSkeleton /> });
33-
const MsmesView = dynamic(() => import('@/components/views/msmes'), { loading: () => <ModalSkeleton /> });
34-
const DashboardView = dynamic(() => import('@/components/views/dashboard'), { loading: () => <ModalSkeleton /> });
35-
const MentorDashboardView = dynamic(() => import('@/components/views/mentor-dashboard'), { loading: () => <ModalSkeleton /> });
36-
const IncubatorDashboardView = dynamic(() => import('@/components/views/incubator-dashboard'), { loading: () => <ModalSkeleton /> });
37-
const MsmeDashboardView = dynamic(() => import('@/components/views/msme-dashboard'), { loading: () => <ModalSkeleton /> });
38-
const LoginModal = dynamic(() => import('@/components/auth/login-modal'), { loading: () => <ModalSkeleton /> });
39-
const SignupModal = dynamic(() => import('@/components/auth/signup-modal'), { loading: () => <ModalSkeleton /> });
40-
const EducationView = dynamic(() => import('@/components/views/education'), { loading: () => <ModalSkeleton /> });
41-
const ContactView = dynamic(() => import('@/components/views/contact'), { loading: () => <ModalSkeleton /> });
42-
43-
type User = {
44-
name: string;
45-
email: string;
46-
}
47-
type AuthProvider = 'local' | 'google' | 'linkedin';
1+
import MainView from "@/components/views/main-view";
482

493
export default function Home() {
50-
const [theme, setTheme] = useState<'light' | 'dark' | null>(null);
51-
const [activeView, setActiveView] = useState<View>("home");
52-
const [isLoggedIn, setLoggedIn] = useState(false);
53-
const [userRole, setUserRole] = useState<UserRole | null>(null);
54-
const [user, setUser] = useState<User | null>(null);
55-
const [authProvider, setAuthProvider] = useState<AuthProvider | null>(null);
56-
const [hasSubscription, setHasSubscription] = useState(false);
57-
const [hasUsedFreeSession, setHasUsedFreeSession] = useState(false);
58-
const [appliedPrograms, setAppliedPrograms] = useState<Record<string, string>>({});
59-
const { toast } = useToast();
60-
const [isLoading, setIsLoading] = useState(true);
61-
const router = useRouter();
62-
const searchParams = useSearchParams();
63-
const { auth } = useFirebaseAuth();
64-
65-
// This effect runs once on mount to set initial state from localStorage
66-
useEffect(() => {
67-
const savedTheme = localStorage.getItem('theme') as 'light' | 'dark' | null;
68-
const initialTheme = savedTheme || (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
69-
setTheme(initialTheme);
70-
71-
const savedIsLoggedIn = localStorage.getItem('isLoggedIn');
72-
const savedUserRole = localStorage.getItem('userRole') as UserRole | null;
73-
const savedUser = localStorage.getItem('user');
74-
const savedSubscription = localStorage.getItem('hasSubscription');
75-
const savedAppliedPrograms = localStorage.getItem('appliedPrograms');
76-
const savedAuthProvider = localStorage.getItem('authProvider') as AuthProvider | null;
77-
78-
if (savedIsLoggedIn === 'true' && savedUserRole && savedUser) {
79-
setLoggedIn(true);
80-
setUserRole(savedUserRole);
81-
setUser(JSON.parse(savedUser));
82-
setHasSubscription(savedSubscription === 'true');
83-
setHasUsedFreeSession(false);
84-
if (savedAppliedPrograms) {
85-
setAppliedPrograms(JSON.parse(savedAppliedPrograms));
86-
}
87-
if (savedAuthProvider) {
88-
setAuthProvider(savedAuthProvider);
89-
}
90-
}
91-
setIsLoading(false);
92-
}, []);
93-
94-
// This effect handles URL-based actions like post-OAuth flow or errors
95-
useEffect(() => {
96-
const error = searchParams.get('error');
97-
const status = searchParams.get('status');
98-
99-
if (status === 'pending_approval') {
100-
toast({
101-
title: "Registration Submitted",
102-
description: "Your account is pending admin approval. You'll be notified via email once it's active.",
103-
});
104-
router.replace('/');
105-
}
106-
107-
if (error) {
108-
let title = "Sign-in Failed";
109-
let description = "Could not sign in with provider. Please try again or use email.";
110-
111-
if (error === 'account_suspended') {
112-
title = "Account Suspended";
113-
description = "This account has been suspended.";
114-
} else if (error === 'email_not_provided') {
115-
title = "Email Missing";
116-
description = "Your provider did not share your email. Please try another method.";
117-
}
118-
toast({ variant: "destructive", title, description });
119-
router.replace('/');
120-
}
121-
}, [searchParams, router, toast]);
122-
123-
// This effect runs whenever the theme changes to update the DOM and localStorage
124-
useEffect(() => {
125-
if (theme) {
126-
if (theme === 'dark') {
127-
document.documentElement.classList.add('dark');
128-
} else {
129-
document.documentElement.classList.remove('dark');
130-
}
131-
localStorage.setItem('theme', theme);
132-
}
133-
}, [theme]);
134-
135-
const handleModalOpenChange = (view: View) => (isOpen: boolean) => {
136-
if (!isOpen) {
137-
setActiveView("home");
138-
} else {
139-
setActiveView(view);
140-
}
141-
};
142-
143-
const handleLoginSuccess = (data: { role: UserRole, token: string, hasSubscription: boolean, name: string, email: string, authProvider: AuthProvider }) => {
144-
const { role, token, hasSubscription, name, email, authProvider } = data;
145-
const userData = { name, email };
146-
setLoggedIn(true);
147-
setUserRole(role);
148-
setUser(userData);
149-
setHasSubscription(hasSubscription);
150-
setAuthProvider(authProvider);
151-
152-
localStorage.setItem('isLoggedIn', 'true');
153-
localStorage.setItem('userRole', role || '');
154-
localStorage.setItem('user', JSON.stringify(userData));
155-
localStorage.setItem('hasSubscription', String(hasSubscription));
156-
localStorage.setItem('token', token);
157-
localStorage.setItem('authProvider', authProvider);
158-
159-
setHasUsedFreeSession(false); // Reset for prototype testing
160-
setActiveView('dashboard');
161-
};
162-
163-
const handleLogout = async () => {
164-
try {
165-
await signOut(auth);
166-
setLoggedIn(false);
167-
setUserRole(null);
168-
setUser(null);
169-
setHasSubscription(false);
170-
setAppliedPrograms({});
171-
setAuthProvider(null);
172-
// Clear all auth-related items
173-
localStorage.removeItem('isLoggedIn');
174-
localStorage.removeItem('userRole');
175-
localStorage.removeItem('user');
176-
localStorage.removeItem('hasSubscription');
177-
localStorage.removeItem('appliedPrograms');
178-
localStorage.removeItem('token');
179-
localStorage.removeItem('authProvider');
180-
setActiveView('home');
181-
router.push('/');
182-
toast({ title: "Logged Out", description: "You have been successfully logged out." });
183-
} catch (error) {
184-
console.error("Logout failed:", error);
185-
toast({ variant: "destructive", title: "Logout Failed", description: "Could not log out. Please try again." });
186-
}
187-
};
188-
189-
const handleBookingSuccess = (mentorName: string, date: Date, time: string) => {
190-
if (!hasUsedFreeSession) {
191-
setHasUsedFreeSession(true);
192-
}
193-
toast({
194-
title: "Booking Confirmed!",
195-
description: `Your session with ${mentorName} on ${format(date, 'PPP')} at ${time} is booked.`,
196-
});
197-
};
198-
199-
const handleGetStartedOnPricing = () => {
200-
if (isLoggedIn) {
201-
setHasSubscription(true);
202-
localStorage.setItem('hasSubscription', 'true');
203-
toast({
204-
title: "Subscription Activated!",
205-
description: "You now have full access to all premium features.",
206-
});
207-
setActiveView('home');
208-
} else {
209-
setActiveView('signup');
210-
}
211-
};
212-
213-
const handleEducationApplicationSuccess = (programTitle: string, session: { language: string, date: string, time: string }) => {
214-
const newAppliedPrograms = {
215-
...appliedPrograms,
216-
[programTitle]: `${session.date}, ${session.time}`
217-
};
218-
setAppliedPrograms(newAppliedPrograms);
219-
localStorage.setItem('appliedPrograms', JSON.stringify(newAppliedPrograms));
220-
221-
toast({
222-
title: "Application Successful!",
223-
description: `You've applied for ${programTitle} on ${session.date} at ${session.time}. A calendar invite has been sent to your email.`,
224-
});
225-
};
226-
227-
const renderDashboard = () => {
228-
if (!isLoggedIn || activeView !== 'dashboard' || !userRole || !user || !authProvider) {
229-
return null;
230-
}
231-
232-
switch(userRole) {
233-
case 'mentor':
234-
return (
235-
<MentorDashboardView
236-
isOpen={true}
237-
onOpenChange={handleModalOpenChange('dashboard')}
238-
setActiveView={setActiveView}
239-
user={user}
240-
authProvider={authProvider}
241-
/>
242-
);
243-
case 'incubator':
244-
return (
245-
<IncubatorDashboardView
246-
isOpen={true}
247-
onOpenChange={handleModalOpenChange('dashboard')}
248-
user={user}
249-
authProvider={authProvider}
250-
/>
251-
);
252-
case 'msme':
253-
return (
254-
<MsmeDashboardView
255-
isOpen={true}
256-
onOpenChange={handleModalOpenChange('dashboard')}
257-
user={user}
258-
authProvider={authProvider}
259-
/>
260-
);
261-
case 'founder':
262-
case 'admin':
263-
return (
264-
<DashboardView
265-
isOpen={true}
266-
onOpenChange={handleModalOpenChange('dashboard')}
267-
user={user}
268-
userRole={userRole}
269-
authProvider={authProvider}
270-
hasSubscription={hasSubscription}
271-
setActiveView={setActiveView}
272-
/>
273-
);
274-
default:
275-
return null;
276-
}
277-
}
278-
279-
return (
280-
<>
281-
<Header
282-
activeView={activeView}
283-
setActiveView={setActiveView}
284-
isLoggedIn={isLoggedIn}
285-
onLogout={handleLogout}
286-
theme={theme}
287-
setTheme={setTheme}
288-
isLoading={isLoading}
289-
/>
290-
<main className="flex-grow">
291-
<HomeView setActiveView={setActiveView} theme={theme} isLoggedIn={isLoggedIn} />
292-
</main>
293-
<Footer />
294-
295-
{activeView === 'blog' && <BlogView isOpen={true} onOpenChange={handleModalOpenChange('blog')} />}
296-
297-
{activeView === 'mentors' && <MentorsView
298-
isOpen={true}
299-
onOpenChange={handleModalOpenChange('mentors')}
300-
isLoggedIn={isLoggedIn}
301-
hasSubscription={hasSubscription}
302-
hasUsedFreeSession={hasUsedFreeSession}
303-
onBookingSuccess={handleBookingSuccess}
304-
setActiveView={setActiveView}
305-
/>}
306-
307-
{activeView === 'incubators' && <IncubatorsView
308-
isOpen={true}
309-
onOpenChange={handleModalOpenChange('incubators')}
310-
isLoggedIn={isLoggedIn}
311-
hasSubscription={hasSubscription}
312-
setActiveView={setActiveView}
313-
/>}
314-
315-
{activeView === 'pricing' && <PricingView
316-
isOpen={true}
317-
onOpenChange={handleModalOpenChange('pricing')}
318-
onGetStartedClick={handleGetStartedOnPricing}
319-
/>}
320-
321-
{activeView === 'msmes' && <MsmesView
322-
isOpen={true}
323-
onOpenChange={handleModalOpenChange('msmes')}
324-
isLoggedIn={isLoggedIn}
325-
hasSubscription={hasSubscription}
326-
setActiveView={setActiveView}
327-
/>}
328-
329-
{activeView === 'education' && <EducationView
330-
isOpen={true}
331-
onOpenChange={handleModalOpenChange('education')}
332-
onApplicationSuccess={handleEducationApplicationSuccess}
333-
isLoggedIn={isLoggedIn}
334-
setActiveView={setActiveView}
335-
appliedPrograms={appliedPrograms}
336-
/>}
337-
338-
{renderDashboard()}
339-
340-
{activeView === 'login' && <LoginModal
341-
isOpen={true}
342-
setIsOpen={handleModalOpenChange('login')}
343-
onLoginSuccess={handleLoginSuccess}
344-
/>}
345-
346-
{activeView === 'signup' && <SignupModal
347-
isOpen={true}
348-
setIsOpen={handleModalOpenChange('signup')}
349-
/>}
350-
351-
{activeView === 'contact' && <ContactView
352-
isOpen={true}
353-
onOpenChange={handleModalOpenChange('contact')}
354-
/>}
355-
</>
356-
);
4+
return <MainView />;
3575
}

0 commit comments

Comments
 (0)