First Commit - Portfolio Page
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
import { useState, useCallback } from 'react';
|
||||
import { handleError } from '../utils/errorHandling';
|
||||
|
||||
interface AsyncState<T> {
|
||||
data: T | null;
|
||||
error: Error | null;
|
||||
loading: boolean;
|
||||
}
|
||||
|
||||
export function useAsync<T>() {
|
||||
const [state, setState] = useState<AsyncState<T>>({
|
||||
data: null,
|
||||
error: null,
|
||||
loading: false,
|
||||
});
|
||||
|
||||
const execute = useCallback(async (asyncFunction: () => Promise<T>) => {
|
||||
setState({ data: null, error: null, loading: true });
|
||||
|
||||
try {
|
||||
const data = await asyncFunction();
|
||||
setState({ data, error: null, loading: false });
|
||||
return data;
|
||||
} catch (error) {
|
||||
const handledError = handleError(error, 'Async Operation');
|
||||
setState({ data: null, error: handledError, loading: false });
|
||||
throw handledError;
|
||||
}
|
||||
}, []);
|
||||
|
||||
return { ...state, execute };
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import { RefObject, useEffect } from 'react';
|
||||
|
||||
export function useOnClickOutside(ref: RefObject<HTMLElement>, handler: (event: MouseEvent | TouchEvent) => void) {
|
||||
useEffect(() => {
|
||||
const listener = (event: MouseEvent | TouchEvent) => {
|
||||
if (!ref.current || ref.current.contains(event.target as Node)) {
|
||||
return;
|
||||
}
|
||||
handler(event);
|
||||
};
|
||||
|
||||
document.addEventListener('mousedown', listener);
|
||||
document.addEventListener('touchstart', listener);
|
||||
|
||||
return () => {
|
||||
document.removeEventListener('mousedown', listener);
|
||||
document.removeEventListener('touchstart', listener);
|
||||
};
|
||||
}, [ref, handler]);
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// src/hooks/useProjectData.ts
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useState, useEffect } from 'react';
|
||||
|
||||
export const useProjectData = <T = unknown>(projectId: string): T | null => {
|
||||
const { i18n } = useTranslation();
|
||||
const [projectData, setProjectData] = useState<T | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const loadProjectData = async () => {
|
||||
try {
|
||||
const projectModule = await import(
|
||||
`../i18n/locales/${i18n.language}/portfolio/projects/${projectId}`
|
||||
);
|
||||
setProjectData(projectModule[projectId] as T);
|
||||
} catch (error) {
|
||||
console.error(`Failed to load project data for ${projectId}:`, error);
|
||||
setProjectData(null);
|
||||
}
|
||||
};
|
||||
|
||||
loadProjectData();
|
||||
}, [projectId, i18n.language]);
|
||||
|
||||
return projectData;
|
||||
};
|
||||
Reference in New Issue
Block a user