133 lines
3.5 KiB
JavaScript
133 lines
3.5 KiB
JavaScript
import { createContext, useContext, useState, useEffect, useCallback } from 'react';
|
|
import { fetchCV as apiFetchCV, updateCV as apiUpdateCV, exportCV as apiExportCV, importCV as apiImportCV } from '../../lib/api';
|
|
import { DEFAULT_DATA, validateCV } from '../../lib/cv-data';
|
|
|
|
const CVContext = createContext(null);
|
|
|
|
export function CVProvider({ children }) {
|
|
const [data, setData] = useState(DEFAULT_DATA);
|
|
const [loading, setLoading] = useState(true);
|
|
const [error, setError] = useState(null);
|
|
|
|
useEffect(() => {
|
|
apiFetchCV()
|
|
.then(data => {
|
|
setData(data);
|
|
setLoading(false);
|
|
})
|
|
.catch(err => {
|
|
console.error('Failed to fetch CV:', err);
|
|
setError(err.message);
|
|
setLoading(false);
|
|
});
|
|
}, []);
|
|
|
|
const updatePersonal = useCallback(async (personal) => {
|
|
const newData = { ...data, personal };
|
|
setData(newData);
|
|
await apiUpdateCV(newData);
|
|
}, [data]);
|
|
|
|
const updateExperience = useCallback(async (experience) => {
|
|
const newData = { ...data, experience };
|
|
setData(newData);
|
|
await apiUpdateCV(newData);
|
|
}, [data]);
|
|
|
|
const updateSkills = useCallback(async (skills) => {
|
|
const newData = { ...data, skills };
|
|
setData(newData);
|
|
await apiUpdateCV(newData);
|
|
}, [data]);
|
|
|
|
const updateEducation = useCallback(async (education) => {
|
|
const newData = { ...data, education };
|
|
setData(newData);
|
|
await apiUpdateCV(newData);
|
|
}, [data]);
|
|
|
|
const updateProjects = useCallback(async (projects) => {
|
|
const newData = { ...data, projects };
|
|
setData(newData);
|
|
await apiUpdateCV(newData);
|
|
}, [data]);
|
|
|
|
const exportJSON = useCallback(async () => {
|
|
const validation = validateCV(data);
|
|
if (!validation.valid) {
|
|
console.warn('Exporting CV with validation warnings:', validation.errors);
|
|
}
|
|
|
|
const blob = await apiExportCV();
|
|
const url = URL.createObjectURL(blob);
|
|
const a = document.createElement('a');
|
|
a.href = url;
|
|
a.download = 'cv.json';
|
|
document.body.appendChild(a);
|
|
a.click();
|
|
document.body.removeChild(a);
|
|
URL.revokeObjectURL(url);
|
|
}, [data]);
|
|
|
|
const importJSON = useCallback(async (jsonString) => {
|
|
try {
|
|
const parsed = JSON.parse(jsonString);
|
|
const validation = validateCV(parsed);
|
|
if (!validation.valid) {
|
|
return { success: false, errors: validation.errors };
|
|
}
|
|
await apiImportCV(parsed);
|
|
setData(parsed);
|
|
return { success: true };
|
|
} catch (e) {
|
|
return { success: false, errors: [`JSON parse error: ${e.message}`] };
|
|
}
|
|
}, []);
|
|
|
|
const resetToDefault = useCallback(async () => {
|
|
await apiUpdateCV(DEFAULT_DATA);
|
|
setData(DEFAULT_DATA);
|
|
}, []);
|
|
|
|
const refresh = useCallback(async () => {
|
|
setLoading(true);
|
|
try {
|
|
const data = await apiFetchCV();
|
|
setData(data);
|
|
setError(null);
|
|
} catch (err) {
|
|
setError(err.message);
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
}, []);
|
|
|
|
return (
|
|
<CVContext.Provider value={{
|
|
data,
|
|
loading,
|
|
error,
|
|
updatePersonal,
|
|
updateExperience,
|
|
updateSkills,
|
|
updateEducation,
|
|
updateProjects,
|
|
exportJSON,
|
|
importJSON,
|
|
resetToDefault,
|
|
refresh
|
|
}}>
|
|
{children}
|
|
</CVContext.Provider>
|
|
);
|
|
}
|
|
|
|
// eslint-disable-next-line react-refresh/only-export-components
|
|
export function useCVData() {
|
|
const context = useContext(CVContext);
|
|
if (!context) {
|
|
throw new Error('useCVData must be used within a CVProvider');
|
|
}
|
|
return context;
|
|
}
|