feat: add video upload feature with support for validation and processing
- Introduced "video" as a new content type across backend and frontend. - Updated validation schemas and MIME-type handling for video files. - Implemented file size limits for videos (10 MB max) in configuration. - Enhanced upload flow with auto-detection of file types (image, GIF, video). - Expanded media processing to handle video files and convert them to WebM format.
This commit is contained in:
@@ -42,7 +42,7 @@ import type { Category } from "@/types/content";
|
||||
|
||||
const uploadSchema = z.object({
|
||||
title: z.string().min(3, "Le titre doit faire au moins 3 caractères"),
|
||||
type: z.enum(["meme", "gif"]),
|
||||
type: z.enum(["meme", "gif", "video"]),
|
||||
categoryId: z.string().optional(),
|
||||
tags: z.string().optional(),
|
||||
});
|
||||
@@ -112,6 +112,16 @@ export default function UploadPage() {
|
||||
return;
|
||||
}
|
||||
setFile(selectedFile);
|
||||
|
||||
// Auto-détection du type
|
||||
if (selectedFile.type === "image/gif") {
|
||||
form.setValue("type", "gif");
|
||||
} else if (selectedFile.type.startsWith("video/")) {
|
||||
form.setValue("type", "video");
|
||||
} else {
|
||||
form.setValue("type", "meme");
|
||||
}
|
||||
|
||||
const reader = new FileReader();
|
||||
reader.onloadend = () => {
|
||||
setPreview(reader.result as string);
|
||||
@@ -182,7 +192,7 @@ export default function UploadPage() {
|
||||
<Form {...form}>
|
||||
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-6">
|
||||
<div className="space-y-4">
|
||||
<FormLabel>Fichier (Image ou GIF)</FormLabel>
|
||||
<FormLabel>Fichier (Image, GIF ou Vidéo)</FormLabel>
|
||||
{!preview ? (
|
||||
<button
|
||||
type="button"
|
||||
@@ -194,25 +204,29 @@ export default function UploadPage() {
|
||||
</div>
|
||||
<p className="font-medium">Cliquez pour choisir un fichier</p>
|
||||
<p className="text-xs text-muted-foreground mt-1">
|
||||
PNG, JPG ou GIF jusqu'à 10Mo
|
||||
PNG, JPG, GIF, MP4 ou MOV jusqu'à 10Mo
|
||||
</p>
|
||||
<input
|
||||
id="file-upload"
|
||||
type="file"
|
||||
className="hidden"
|
||||
accept="image/*,.gif"
|
||||
accept="image/*,video/mp4,video/webm,video/quicktime,.gif"
|
||||
onChange={handleFileChange}
|
||||
/>
|
||||
</button>
|
||||
) : (
|
||||
<div className="relative rounded-lg overflow-hidden border bg-zinc-100 dark:bg-zinc-800">
|
||||
<div className="relative h-[400px] w-full">
|
||||
<NextImage
|
||||
src={preview}
|
||||
alt="Preview"
|
||||
fill
|
||||
className="object-contain"
|
||||
/>
|
||||
<div className="relative h-[400px] w-full flex items-center justify-center">
|
||||
{file?.type.startsWith("video/") ? (
|
||||
<video src={preview} controls className="max-h-full max-w-full" />
|
||||
) : (
|
||||
<NextImage
|
||||
src={preview}
|
||||
alt="Preview"
|
||||
fill
|
||||
className="object-contain"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
<Button
|
||||
type="button"
|
||||
@@ -260,6 +274,7 @@ export default function UploadPage() {
|
||||
<SelectContent>
|
||||
<SelectItem value="meme">Image fixe</SelectItem>
|
||||
<SelectItem value="gif">GIF Animé</SelectItem>
|
||||
<SelectItem value="video">Vidéo</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<FormMessage />
|
||||
|
||||
@@ -7,7 +7,7 @@ export interface Content {
|
||||
description?: string;
|
||||
url: string;
|
||||
thumbnailUrl?: string;
|
||||
type: "meme" | "gif";
|
||||
type: "meme" | "gif" | "video";
|
||||
mimeType: string;
|
||||
size: number;
|
||||
width?: number;
|
||||
|
||||
Reference in New Issue
Block a user