Files
tfm_ainventory/frontend/hooks/usePhotoUpload.ts

93 lines
2.4 KiB
TypeScript

import { useState, useCallback } from 'react';
import { inventoryApi } from '@/lib/api';
interface Photo {
thumbnail_url: string;
full_url: string;
uploaded_at: string;
}
interface UsePhotoUploadReturn {
upload: (file: File, itemId: number) => Promise<Photo>;
isLoading: boolean;
error: string | null;
}
const ACCEPTED_MIME_TYPES = ['image/jpeg', 'image/png', 'image/webp', 'image/gif'];
const MAX_FILE_SIZE = 10 * 1024 * 1024; // 10MB
export function usePhotoUpload(): UsePhotoUploadReturn {
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const validateFile = useCallback((file: File): { valid: boolean; error?: string } => {
// Validate file size
if (file.size > MAX_FILE_SIZE) {
return {
valid: false,
error: 'File too large, max 10MB',
};
}
// Validate MIME type
if (!ACCEPTED_MIME_TYPES.includes(file.type)) {
return {
valid: false,
error: 'Invalid image format',
};
}
return { valid: true };
}, []);
const upload = useCallback(
async (file: File, itemId: number): Promise<Photo> => {
setError(null);
setIsLoading(true);
try {
// Validate file (synchronously)
const validation = validateFile(file);
if (!validation.valid) {
const errorMsg = validation.error || 'File validation failed';
setError(errorMsg);
setIsLoading(false);
throw new Error(errorMsg);
}
// Create FormData for multipart upload
const formData = new FormData();
formData.append('file', file);
// Upload to backend
const response = await inventoryApi.uploadItemPhoto(itemId, formData);
// Handle response
if (response.status === 'ok' && response.photo) {
const photo: Photo = {
thumbnail_url: response.photo.thumbnail_url,
full_url: response.photo.full_url,
uploaded_at: response.photo.uploaded_at,
};
setIsLoading(false);
return photo;
}
throw new Error('Invalid response from server');
} catch (err: any) {
const errorMsg = err.message || 'Upload failed';
setError(errorMsg);
setIsLoading(false);
throw new Error(errorMsg);
}
},
[validateFile]
);
return {
upload,
isLoading,
error,
};
}