Files
periodic-table/frontend/src/context/ProjectContext.tsx
2025-12-01 11:01:13 -03:00

121 lines
3.4 KiB
TypeScript

import {
createContext,
useState,
useEffect,
useCallback,
type ReactNode,
} from 'react'
import { projectService, type Project } from '@/services'
import { useAuth } from '@/hooks'
export interface ProjectContextType {
projects: Project[]
currentProject: Project | null
isLoading: boolean
error: string | null
setCurrentProject: (project: Project | null) => void
refreshProjects: () => Promise<void>
createProject: (name: string, description?: string) => Promise<Project>
}
export const ProjectContext = createContext<ProjectContextType | undefined>(undefined)
const STORAGE_KEY = 'selectedProjectId'
interface ProjectProviderProps {
children: ReactNode
}
export function ProjectProvider({ children }: ProjectProviderProps) {
const { isAuthenticated, isLoading: authLoading } = useAuth()
const [projects, setProjects] = useState<Project[]>([])
const [currentProject, setCurrentProjectState] = useState<Project | null>(null)
const [isLoading, setIsLoading] = useState(true)
const [error, setError] = useState<string | null>(null)
const setCurrentProject = useCallback((project: Project | null) => {
setCurrentProjectState(project)
if (project) {
localStorage.setItem(STORAGE_KEY, project.id.toString())
} else {
localStorage.removeItem(STORAGE_KEY)
}
}, [])
const refreshProjects = useCallback(async () => {
if (!isAuthenticated) {
setProjects([])
setCurrentProjectState(null)
setIsLoading(false)
return
}
try {
setIsLoading(true)
setError(null)
const fetchedProjects = await projectService.getMyProjects()
setProjects(fetchedProjects)
// Restore selected project from localStorage or select first available
const savedProjectId = localStorage.getItem(STORAGE_KEY)
if (savedProjectId) {
const savedProject = fetchedProjects.find(
(p) => p.id === parseInt(savedProjectId, 10)
)
if (savedProject) {
setCurrentProjectState(savedProject)
} else if (fetchedProjects.length > 0) {
// Saved project no longer available, select first one
setCurrentProject(fetchedProjects[0])
}
} else if (fetchedProjects.length > 0) {
// No saved project, select first one
setCurrentProject(fetchedProjects[0])
}
} catch (err) {
console.error('Failed to fetch projects:', err)
setError('Failed to load projects')
} finally {
setIsLoading(false)
}
}, [isAuthenticated, setCurrentProject])
const createProject = useCallback(async (name: string, description?: string): Promise<Project> => {
const newProject = await projectService.createProject({
project_name: name,
project_desc: description,
})
// Add to projects list
setProjects((prev: Project[]) => [newProject, ...prev])
// If no current project, set this as current
if (!currentProject) {
setCurrentProject(newProject)
}
return newProject
}, [currentProject, setCurrentProject])
// Fetch projects when authentication status changes
useEffect(() => {
if (!authLoading) {
refreshProjects()
}
}, [authLoading, isAuthenticated, refreshProjects])
const value: ProjectContextType = {
projects,
currentProject,
isLoading,
error,
setCurrentProject,
refreshProjects,
createProject,
}
return (
<ProjectContext.Provider value={value}>{children}</ProjectContext.Provider>
)
}