Spaces:
Sleeping
Sleeping
| import React, { useState, useEffect } from 'react'; | |
| import { useParams, useNavigate, useLocation } from 'react-router-dom'; | |
| import { EmployeeProjectDetail } from '../types'; | |
| import { Button } from '../components/ui/button'; | |
| import { | |
| getEmployeeProjectDetailsByEmployeeId, | |
| createEmployeeProjectDetail, | |
| updateEmployeeProjectDetail | |
| } from '../services/employeeProjectDetailApi'; | |
| import { getEmployeeById } from '../services/employeeApi'; | |
| import EmployeeProjectList from '../components/employee-projects/EmployeeProjectList'; | |
| import { ArrowLeft, User } from 'lucide-react'; | |
| import { toast } from 'sonner'; | |
| import Header from '@/components/layout/header'; | |
| import Sidebar from '@/components/layout/sidebar'; | |
| import { useIsMobile } from '@/hooks/use-mobile'; | |
| const EmployeeProjects: React.FC = () => { | |
| const { id } = useParams<{ id: string }>(); | |
| const employeeId = parseInt(id || '0'); | |
| const navigate = useNavigate(); | |
| const location = useLocation(); | |
| const isMobile = useIsMobile(); | |
| const [isSidebarOpen, setIsSidebarOpen] = useState(!isMobile); | |
| const [loading, setLoading] = useState(true); | |
| const [error, setError] = useState<string | null>(null); | |
| const [projects, setProjects] = useState<EmployeeProjectDetail[]>([]); | |
| const [employeeName, setEmployeeName] = useState<string>(''); | |
| // Close sidebar on mobile when route changes | |
| useEffect(() => { | |
| if (isMobile) { | |
| setIsSidebarOpen(false); | |
| } | |
| }, [location, isMobile]); | |
| // Update sidebar state when screen size changes | |
| useEffect(() => { | |
| setIsSidebarOpen(!isMobile); | |
| }, [isMobile]); | |
| const toggleSidebar = () => { | |
| setIsSidebarOpen(!isSidebarOpen); | |
| }; | |
| const fetchProjects = async () => { | |
| setLoading(true); | |
| setError(null); | |
| try { | |
| if (employeeId) { | |
| const fetchedProjects = await getEmployeeProjectDetailsByEmployeeId(employeeId); | |
| setProjects(fetchedProjects); | |
| // Fetch employee details to display name | |
| console.log(`Fetching employee details for ID: ${employeeId}`); | |
| const employeeResponse = await getEmployeeById(employeeId); | |
| console.log('Employee response:', employeeResponse); | |
| if (employeeResponse.success && employeeResponse.data) { | |
| const name = `${employeeResponse.data.firstName} ${employeeResponse.data.lastName}`; | |
| console.log(`Setting employee name to: ${name}`); | |
| setEmployeeName(name); | |
| } else { | |
| console.log('Employee data not available or response not successful'); | |
| } | |
| } | |
| } catch (err) { | |
| console.error('Error fetching employee projects:', err); | |
| setError('Failed to load projects. Please try again.'); | |
| toast.error('Failed to load projects'); | |
| } finally { | |
| setLoading(false); | |
| } | |
| }; | |
| useEffect(() => { | |
| if (employeeId) { | |
| fetchProjects(); | |
| } else { | |
| setError('Invalid employee ID'); | |
| setLoading(false); | |
| } | |
| }, [employeeId]); | |
| const handleAddProject = async (data: Partial<EmployeeProjectDetail>) => { | |
| try { | |
| await createEmployeeProjectDetail({ | |
| ...data, | |
| employeeId | |
| }); | |
| toast.success('Project added successfully'); | |
| fetchProjects(); // Refresh the list after adding | |
| return Promise.resolve(); | |
| } catch (error) { | |
| console.error('Error adding project:', error); | |
| toast.error('Failed to add project'); | |
| return Promise.reject(error); | |
| } | |
| }; | |
| const handleEditProject = async (projectId: number, data: Partial<EmployeeProjectDetail>) => { | |
| try { | |
| await updateEmployeeProjectDetail(projectId, { | |
| ...data, | |
| employeeId | |
| }); | |
| toast.success('Project updated successfully'); | |
| fetchProjects(); // Refresh the list after editing | |
| return Promise.resolve(); | |
| } catch (error) { | |
| console.error('Error updating project:', error); | |
| toast.error('Failed to update project'); | |
| return Promise.reject(error); | |
| } | |
| }; | |
| return ( | |
| <div className="flex min-h-screen flex-col"> | |
| <Header toggleSidebar={toggleSidebar} isSidebarOpen={isSidebarOpen} /> | |
| <Sidebar isOpen={isSidebarOpen} setIsOpen={setIsSidebarOpen} /> | |
| <main className={`flex-1 bg-muted/40 p-6 pt-20 md:p-10 md:pt-24 ${isSidebarOpen ? "md:ml-64" : ""} transition-all duration-300`}> | |
| <div className="mx-auto max-w-6xl"> | |
| <div className="flex items-center justify-between mb-6"> | |
| <div className="flex items-center"> | |
| <Button | |
| variant="ghost" | |
| size="icon" | |
| className="mr-2" | |
| onClick={() => navigate(-1)} | |
| > | |
| <ArrowLeft className="h-5 w-5" /> | |
| </Button> | |
| <div> | |
| <h1 className="text-2xl font-bold">Projects History</h1> | |
| {employeeName && ( | |
| <div className="flex items-center text-muted-foreground"> | |
| <User className="h-4 w-4 mr-1" /> | |
| <span>{employeeName}</span> | |
| </div> | |
| )} | |
| </div> | |
| </div> | |
| </div> | |
| {loading ? ( | |
| <div className="flex justify-center items-center h-64"> | |
| <div className="animate-spin rounded-full h-8 w-8 border-b-2 border-primary"></div> | |
| </div> | |
| ) : error ? ( | |
| <div className="bg-destructive/10 text-destructive p-4 rounded-md"> | |
| {error} | |
| </div> | |
| ) : ( | |
| // Log to confirm employee name is available before rendering component | |
| ((logValue) => { | |
| console.log('About to render EmployeeProjectList with employeeName:', logValue); | |
| return ( | |
| <EmployeeProjectList | |
| projects={projects} | |
| employeeId={employeeId} | |
| employeeName={employeeName} | |
| onAdd={handleAddProject} | |
| onEdit={handleEditProject} | |
| onRefresh={fetchProjects} | |
| /> | |
| ); | |
| })(employeeName) | |
| )} | |
| </div> | |
| </main> | |
| </div> | |
| ); | |
| }; | |
| export default EmployeeProjects; |