feat: integrate S3 storage adapter and update file upload functionality

This commit is contained in:
2026-04-10 22:54:46 -03:00
parent 98515550ca
commit 4b1bd056fc
14 changed files with 319 additions and 309 deletions

View File

@@ -1,6 +1,7 @@
'use client';
import { saveArticle } from '@/lib/feature/article/article.external';
import { uploadFile } from '@/lib/storage/storage.utils';
import { FileUploadField } from '@/ui/components/internal/file-upload-field';
import { Button } from '@/ui/components/shadcn/button';
import {
@@ -60,7 +61,7 @@ export const CreateArticleForm = () => {
title: z.string().min(3).max(255),
slug: z.string().min(3),
description: z.string().min(10),
coverImageUrl: z.string().url('Cover image URL must be a valid URL'),
coverImageUrl: z.url('Cover image URL must be a valid URL'),
content: z
.string()
.min(10, 'Article content must have at least 10 characters'),
@@ -119,19 +120,27 @@ export const CreateArticleForm = () => {
);
const handleCoverImageFileChange = useCallback(
(file: File | null) => {
async (file: File | null) => {
if (coverImageUrlRef.current) {
URL.revokeObjectURL(coverImageUrlRef.current);
coverImageUrlRef.current = null;
}
setCoverImageFile(file);
if (file) {
const url = URL.createObjectURL(file);
coverImageUrlRef.current = url;
form.setValue('coverImageUrl', url);
} else {
if (!file) {
setCoverImageFile(null);
form.setValue('coverImageUrl', '');
return;
}
const fileMetadataResult = await uploadFile(file);
if (!fileMetadataResult.ok) {
setCoverImageFile(null);
form.setValue('coverImageUrl', '');
toast((fileMetadataResult.error as Error).message);
return;
}
const fileMetadata = fileMetadataResult.value;
coverImageUrlRef.current = fileMetadata.signedUrl;
form.setValue('coverImageUrl', fileMetadata.signedUrl);
},
[form]
);

View File

@@ -21,7 +21,7 @@ import React, { useCallback } from 'react';
export interface FileUploadFieldProps {
file: File | null;
onFileChange: (file: File | null) => void;
onFileChange: (file: File | null) => Promise<void>;
accept?: string;
validate?: (file: File) => string | null;
onFileReject?: (file: File, message: string) => void;
@@ -45,7 +45,8 @@ export const FileUploadField: React.FC<FileUploadFieldProps> = ({
const handleAccept = useCallback(
(files: File[]) => {
const accepted = files[0];
if (accepted) onFileChange(accepted);
if (!accepted) return;
onFileChange(accepted).then(() => {});
},
[onFileChange]
);