- Added `media-library.php` configuration file for managing media uploads and conversions. - Updated `filesystems.php` to set default visibility for AWS S3 storage. - Implemented `FileUpload` component for handling file uploads with preview and error handling. - Created `ImagePreviewModal` component for displaying image previews in a modal. - Introduced `Attachment` UI components for better file attachment handling. - Added `useFileUpload` hook to manage file upload state and logic. - Implemented utility functions for uploading files to S3 with presigned URLs. - Created API route for generating presigned URLs for file uploads.
60 lines
1.7 KiB
TypeScript
60 lines
1.7 KiB
TypeScript
import { useCallback, useState } from 'react';
|
|
import { uploadFile, UploadError } from '@/lib/upload';
|
|
|
|
type UploadState = {
|
|
uploading: boolean;
|
|
progress: number;
|
|
error: string | null;
|
|
key: string | null;
|
|
preview: string | null;
|
|
};
|
|
|
|
export function useFileUpload() {
|
|
const [state, setState] = useState<UploadState>({
|
|
uploading: false,
|
|
progress: 0,
|
|
error: null,
|
|
key: null,
|
|
preview: null,
|
|
});
|
|
|
|
const upload = useCallback(async (file: File, folder?: string): Promise<string | null> => {
|
|
setState({ uploading: true, progress: 0, error: null, key: null, preview: null });
|
|
|
|
try {
|
|
const preview = URL.createObjectURL(file);
|
|
setState((prev) => ({ ...prev, preview, progress: 30 }));
|
|
|
|
const key = await uploadFile(file, folder);
|
|
setState((prev) => ({ ...prev, key, uploading: false, progress: 100 }));
|
|
|
|
return key;
|
|
} catch (err) {
|
|
const message = err instanceof UploadError ? err.message : 'Terjadi kesalahan saat mengunggah file.';
|
|
setState((prev) => ({ ...prev, error: message, uploading: false }));
|
|
|
|
return null;
|
|
}
|
|
}, []);
|
|
|
|
const reset = useCallback(() => {
|
|
setState({ uploading: false, progress: 0, error: null, key: null, preview: null });
|
|
}, []);
|
|
|
|
const setKey = useCallback((key: string | null) => {
|
|
setState((prev) => ({ ...prev, key }));
|
|
}, []);
|
|
|
|
const setPreview = useCallback((preview: string | null) => {
|
|
setState((prev) => ({ ...prev, preview }));
|
|
}, []);
|
|
|
|
return {
|
|
...state,
|
|
upload,
|
|
reset,
|
|
setKey,
|
|
setPreview,
|
|
};
|
|
}
|