Initial commit: WaMarket MVP
Marketplace inversée (Next.js 16 App Router + Supabase Cloud) : auth, schéma + RLS, publication de besoins avec upload d'images, feed avec filtres, offres, acceptation via RPC, messagerie temps réel, dashboards, et Dockerfile pour déploiement Coolify.
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import Image from "next/image";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { Input } from "@/components/ui/input";
|
||||
|
||||
export function ImageUploader({
|
||||
name,
|
||||
maxFiles = 5,
|
||||
}: {
|
||||
name: string;
|
||||
maxFiles?: number;
|
||||
}) {
|
||||
const [previews, setPreviews] = useState<string[]>([]);
|
||||
|
||||
function handleChange(e: React.ChangeEvent<HTMLInputElement>) {
|
||||
const files = Array.from(e.target.files ?? []).slice(0, maxFiles);
|
||||
setPreviews((old) => {
|
||||
old.forEach((url) => URL.revokeObjectURL(url));
|
||||
return files.map((file) => URL.createObjectURL(file));
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-2">
|
||||
<Label htmlFor={name}>Photos (optionnel, {maxFiles} max)</Label>
|
||||
<Input
|
||||
id={name}
|
||||
name={name}
|
||||
type="file"
|
||||
accept="image/*"
|
||||
multiple
|
||||
onChange={handleChange}
|
||||
/>
|
||||
{previews.length > 0 && (
|
||||
<div className="mt-2 flex flex-wrap gap-2">
|
||||
{previews.map((src, i) => (
|
||||
<div
|
||||
key={src}
|
||||
className="relative h-20 w-20 overflow-hidden rounded-md border"
|
||||
>
|
||||
<Image
|
||||
src={src}
|
||||
alt={`Aperçu ${i + 1}`}
|
||||
fill
|
||||
className="object-cover"
|
||||
unoptimized
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user