Skip to content

Commit 0693885

Browse files
committed
feat: Refactor authentication and CV management components, integrate new Dashboard layout and ViewCV functionality
1 parent 3929a2d commit 0693885

File tree

10 files changed

+493
-252
lines changed

10 files changed

+493
-252
lines changed

frontend/src/App.jsx

Lines changed: 2 additions & 199 deletions
Original file line numberDiff line numberDiff line change
@@ -1,209 +1,12 @@
1-
import { useState, useEffect } from 'react'
21
import './App.css'
3-
import Header from './components/Dashboard/Header'
4-
import Footer from './components/Dashboard/Footer'
5-
import Sidebar from './components/Dashboard/Sidebar'
6-
import CVBuilder from './components/Dashboard/CVBuilder/CVBuilder'
7-
import SystematicReviews from './components/Dashboard/SystematicReview/SystematicReviews'
8-
import CaseReports from './components/Dashboard/CaseReports/CaseReports'
9-
import Conferences from './components/Dashboard/Conferences/Conferences'
10-
import Existingcv from './components/Dashboard/ExistingCV/Existingcv'
11-
import Login from './components/Login/Login'
12-
import Register from './components/Register/Register'
2+
import AuthManager from './components/AuthManager/AuthManager';
133
import { ToastContainer } from 'react-toastify';
144
import 'react-toastify/dist/ReactToastify.css';
15-
import api from './utils/api';
165

176
function App() {
18-
const [activeSection, setActiveSection] = useState('cv-builder');
19-
const [isAuthenticated, setIsAuthenticated] = useState(false);
20-
const [showRegister, setShowRegister] = useState(false);
21-
const [user, setUser] = useState(null);
22-
const [loading, setLoading] = useState(true);
23-
const [currentCVStep, setCurrentCVStep] = useState(1);
24-
const [completedSteps, setCompletedSteps] = useState([]);
25-
26-
useEffect(() => {
27-
checkAuthStatus();
28-
}, []);
29-
30-
const checkAuthStatus = async () => {
31-
try {
32-
const response = await api.get('/users/current-user', { withCredentials: true });
33-
if (response.data.success) {
34-
setUser(response.data.data);
35-
setIsAuthenticated(true);
36-
}
37-
} catch (error) {
38-
setIsAuthenticated(false);
39-
setUser(null);
40-
} finally {
41-
setLoading(false);
42-
}
43-
};
44-
45-
const handleLogin = (userData) => {
46-
setUser(userData);
47-
setIsAuthenticated(true);
48-
setShowRegister(false);
49-
};
50-
51-
const handleRegister = (userData) => {
52-
setUser(userData);
53-
setIsAuthenticated(true);
54-
setShowRegister(false);
55-
};
56-
57-
const handleLogout = async () => {
58-
try {
59-
await api.post('/users/logout');
60-
} catch (error) {
61-
console.error('Logout error:', error);
62-
} finally {
63-
setUser(null);
64-
setIsAuthenticated(false);
65-
setActiveSection('cv-builder');
66-
// Reset CV builder states on logout
67-
setCurrentCVStep(1);
68-
setCompletedSteps([]);
69-
}
70-
};
71-
72-
const handleSectionChange = (section) => {
73-
setActiveSection(section);
74-
// Reset CV step when switching to CV builder from other sections
75-
if (section === 'cv-builder' && activeSection !== 'cv-builder') {
76-
setCurrentCVStep(1);
77-
}
78-
};
79-
80-
const handleCVStepChange = (step) => {
81-
setCurrentCVStep(step);
82-
};
83-
84-
const handleStepComplete = (step) => {
85-
if (!completedSteps.includes(step)) {
86-
setCompletedSteps(prev => [...prev, step].sort((a, b) => a - b));
87-
}
88-
};
89-
90-
const renderActiveSection = () => {
91-
switch (activeSection) {
92-
case 'cv-builder':
93-
return (
94-
<CVBuilder
95-
key={user?._id || "guest"}
96-
user={user}
97-
currentStep={currentCVStep}
98-
onStepChange={handleCVStepChange}
99-
onStepComplete={handleStepComplete}
100-
/>
101-
);
102-
103-
case 'existing-cv':
104-
return (
105-
<Existingcv onBack={() => setActiveSection('cv-builder')} />
106-
);
107-
108-
case 'systematic-reviews':
109-
return (
110-
<SystematicReviews
111-
onBack={() => setActiveSection('cv-builder')}
112-
user={user}
113-
/>
114-
);
115-
116-
case 'case-reports':
117-
return (
118-
<CaseReports
119-
onBack={() => setActiveSection('cv-builder')}
120-
user={user}
121-
/>
122-
);
123-
124-
case 'conferences':
125-
return (
126-
<Conferences
127-
onBack={() => setActiveSection('cv-builder')}
128-
user={user}
129-
/>
130-
);
131-
132-
case 'workshops':
133-
return (
134-
<Workshops
135-
onBack={() => setActiveSection('cv-builder')}
136-
user={user}
137-
/>
138-
);
139-
140-
case 'emr-training':
141-
return (
142-
<EMRTraining
143-
onBack={() => setActiveSection('cv-builder')}
144-
user={user}
145-
/>
146-
);
147-
148-
default:
149-
return (
150-
<CVBuilder
151-
key={user?._id || "guest"}
152-
user={user}
153-
currentStep={currentCVStep}
154-
onStepChange={handleCVStepChange}
155-
onStepComplete={handleStepComplete}
156-
/>
157-
);
158-
}
159-
};
160-
161-
if (loading) {
162-
return (
163-
<div className="min-h-screen bg-gray-50 flex items-center justify-center">
164-
<div className="text-xl text-[#04445E]">Loading...</div>
165-
</div>
166-
);
167-
}
168-
1697
return (
1708
<>
171-
{!isAuthenticated ? (
172-
showRegister ? (
173-
<Register
174-
onRegister={handleRegister}
175-
onNavigateToLogin={() => setShowRegister(false)}
176-
/>
177-
) : (
178-
<Login
179-
onLogin={handleLogin}
180-
onNavigateToRegister={() => setShowRegister(true)}
181-
/>
182-
)
183-
) : (
184-
<div className="min-h-screen bg-gray-50 flex flex-col">
185-
<Header user={user} onLogout={handleLogout} />
186-
187-
<div className="flex-1 max-w-full w-full px-4 sm:px-6 lg:px-8 py-8">
188-
<div className="flex gap-8 h-full">
189-
<Sidebar
190-
activeSection={activeSection}
191-
onSectionChange={handleSectionChange}
192-
user={user}
193-
// CV Builder specific props - only pass when CV Builder is active
194-
currentStep={activeSection === 'cv-builder' ? currentCVStep : null}
195-
onStepChange={activeSection === 'cv-builder' ? handleCVStepChange : null}
196-
completedSteps={activeSection === 'cv-builder' ? completedSteps : []}
197-
/>
198-
<div className="flex-1">
199-
{renderActiveSection()}
200-
</div>
201-
</div>
202-
</div>
203-
204-
<Footer />
205-
</div>
206-
)}
9+
<AuthManager />
20710

20811
<ToastContainer
20912
position="top-right"
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import React, { useState, useEffect } from 'react';
2+
import Login from '../Login/Login';
3+
import Register from '../Register/Register';
4+
import DashboardLayout from '../Dashboard/Dashboard';
5+
import api from '../../utils/api';
6+
7+
const AuthManager = () => {
8+
const [isAuthenticated, setIsAuthenticated] = useState(false);
9+
const [showRegister, setShowRegister] = useState(false);
10+
const [user, setUser] = useState(null);
11+
const [loading, setLoading] = useState(true);
12+
13+
useEffect(() => {
14+
checkAuthStatus();
15+
}, []);
16+
17+
const checkAuthStatus = async () => {
18+
try {
19+
const response = await api.get('/users/current-user', { withCredentials: true });
20+
if (response.data.success) {
21+
setUser(response.data.data);
22+
setIsAuthenticated(true);
23+
}
24+
} catch (error) {
25+
setIsAuthenticated(false);
26+
setUser(null);
27+
} finally {
28+
setLoading(false);
29+
}
30+
};
31+
32+
const handleLogin = (userData) => {
33+
setUser(userData);
34+
setIsAuthenticated(true);
35+
setShowRegister(false);
36+
};
37+
38+
const handleRegister = (userData) => {
39+
setUser(userData);
40+
setIsAuthenticated(true);
41+
setShowRegister(false);
42+
};
43+
44+
const handleLogout = async () => {
45+
try {
46+
await api.post('/users/logout');
47+
} catch (error) {
48+
console.error('Logout error:', error);
49+
} finally {
50+
setUser(null);
51+
setIsAuthenticated(false);
52+
}
53+
};
54+
55+
if (loading) {
56+
return (
57+
<div className="min-h-screen bg-gray-50 flex items-center justify-center">
58+
<div className="text-xl text-[#04445E]">Loading...</div>
59+
</div>
60+
);
61+
}
62+
63+
if (!isAuthenticated) {
64+
return showRegister ? (
65+
<Register
66+
onRegister={handleRegister}
67+
onNavigateToLogin={() => setShowRegister(false)}
68+
/>
69+
) : (
70+
<Login
71+
onLogin={handleLogin}
72+
onNavigateToRegister={() => setShowRegister(true)}
73+
/>
74+
);
75+
}
76+
77+
return <DashboardLayout user={user} onLogout={handleLogout} />;
78+
};
79+
80+
export default AuthManager;

frontend/src/components/Dashboard/CVBuilder/CVBuilder.jsx

Lines changed: 1 addition & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import NavigationControls from './NavigationControls';
55
import api from '../../../utils/api.js';
66
import { toast } from 'react-toastify';
77
import CVPreview from './CVPreview.jsx';
8-
import CVStatus from './CVStatus.jsx';
98

109
const initialCVData = {
1110
basicDetails: {
@@ -51,7 +50,6 @@ const CVBuilder = ({ onPreview, user, onStepChange, currentStep, onStepComplete
5150
const [formData, setFormData] = useState(initialCVData);
5251
const [internalCurrentStep, setInternalCurrentStep] = useState(1);
5352
const [showPreview, setShowPreview] = useState(false);
54-
const [cvExists, setCvExists] = useState(false);
5553
const [loading, setLoading] = useState(true);
5654
const [completedSteps, setCompletedSteps] = useState([]);
5755

@@ -90,13 +88,10 @@ const CVBuilder = ({ onPreview, user, onStepChange, currentStep, onStepComplete
9088
const response = await api.get(`/cv/${user._id}`);
9189
if (response.data.success) {
9290
setFormData(response.data.data);
93-
setCvExists(true);
9491
setCompletedSteps(calculateCompletedSteps(response.data.data));
95-
} else {
96-
setCvExists(false);
9792
}
9893
} catch (error) {
99-
setCvExists(false);
94+
// CV doesn't exist, keep default empty form
10095
} finally {
10196
setLoading(false);
10297
}
@@ -172,7 +167,6 @@ const CVBuilder = ({ onPreview, user, onStepChange, currentStep, onStepComplete
172167
try {
173168
await api.post('/cv/save', formData);
174169
toast.success("CV Saved Successfully");
175-
setCvExists(true);
176170
} catch (error) {
177171
const errorMessage = error.response?.data?.message || 'Failed to save CV';
178172
toast.error(errorMessage);
@@ -182,12 +176,6 @@ const CVBuilder = ({ onPreview, user, onStepChange, currentStep, onStepComplete
182176
const handlePreview = useCallback(() => setShowPreview(true), []);
183177
const handleBackFromPreview = useCallback(() => setShowPreview(false), []);
184178

185-
const handleEdit = useCallback(() => {
186-
setCvExists(false);
187-
setInternalCurrentStep(1);
188-
onStepChange?.(1);
189-
}, [onStepChange]);
190-
191179
const handleDownload = useCallback(() => {
192180
toast.info('PDF download functionality will be implemented soon');
193181
}, []);
@@ -240,18 +228,6 @@ const CVBuilder = ({ onPreview, user, onStepChange, currentStep, onStepComplete
240228
);
241229
}
242230

243-
if (cvExists) {
244-
return (
245-
<CVStatus
246-
cvData={formData}
247-
onEdit={handleEdit}
248-
onDownload={handleDownload}
249-
completedSteps={completedSteps}
250-
totalSteps={totalSteps}
251-
/>
252-
);
253-
}
254-
255231
return (
256232
<div className="bg-white rounded-xl shadow-lg p-8">
257233
{memoizedProgressBar}

frontend/src/components/Dashboard/CVBuilder/steps/EducationStep.jsx

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,6 @@ const EducationStep = ({ formData, onInputChange }) => (
77
<h2 className="text-2xl font-bold text-[#04445E] mb-6">Education Details</h2>
88

99
<FormGrid>
10-
<FormField
11-
label="Medical School Name"
12-
type="text"
13-
value={formData.education.medicalSchoolName}
14-
onChange={(value) => onInputChange('education', 'medicalSchoolName', value)}
15-
/>
1610

1711
<FormField
1812
label="Country"

0 commit comments

Comments
 (0)