"use client"; import { useRef, useState } from 'react'; import Link from 'next/link'; import { useRouter } from 'next/navigation'; import { useToast } from '@/contexts/ToastContext'; type UploadedImage = { url: string; path: string; name: string; }; const CATEGORY_OPTIONS = [ { value: 'Engenharia Veicular', label: 'Engenharia Veicular' }, { value: 'Projetos Mecânicos', label: 'Projetos Mecânicos' }, { value: 'Laudos e Inspeções', label: 'Laudos e Inspeções' }, { value: 'Segurança do Trabalho', label: 'Segurança do Trabalho' }, ]; const STATUS_OPTIONS = [ { value: 'Concluído', label: 'Concluído' }, { value: 'Em andamento', label: 'Em andamento' }, { value: 'Rascunho', label: 'Rascunho' }, ]; export default function NewProject() { const router = useRouter(); const { success, error } = useToast(); const coverInputRef = useRef(null); const galleryInputRef = useRef(null); const [loading, setLoading] = useState(false); const [formData, setFormData] = useState({ title: '', category: '', client: '', status: 'Concluído', description: '', date: '', featured: false, }); const [coverImage, setCoverImage] = useState(null); const [galleryImages, setGalleryImages] = useState([]); const [uploadingCover, setUploadingCover] = useState(false); const [uploadingGallery, setUploadingGallery] = useState(false); const isSaving = loading || uploadingCover || uploadingGallery; const uploadFile = async (file: File): Promise => { if (file.size > 2 * 1024 * 1024) { error('Arquivo maior que 2MB. Escolha uma imagem menor.'); return null; } const supportedTypes = ['image/png', 'image/jpeg', 'image/webp']; if (!supportedTypes.includes(file.type)) { error('Formato inválido. Utilize PNG, JPG ou WEBP.'); return null; } const body = new FormData(); body.append('file', file); const response = await fetch('/api/upload', { method: 'POST', body, }); if (!response.ok) { const data = await response.json().catch(() => ({})); throw new Error(data?.error || 'Erro ao enviar imagem'); } const data = await response.json(); return { url: data.url, path: data.path, name: file.name, }; }; const handleCoverSelect = async (event: React.ChangeEvent) => { const file = event.target.files?.[0]; if (!file) return; setUploadingCover(true); try { const uploaded = await uploadFile(file); if (uploaded) { setCoverImage(uploaded); success('Imagem de capa carregada.'); } } catch (err) { console.error('Erro ao enviar imagem de capa:', err); error(err instanceof Error ? err.message : 'Falha ao enviar imagem de capa.'); } finally { setUploadingCover(false); event.target.value = ''; } }; const handleGallerySelect = async (event: React.ChangeEvent) => { const files = Array.from(event.target.files ?? []); if (files.length === 0) return; if (galleryImages.length + files.length > 8) { error('Limite de 8 imagens atingido. Remova algumas antes de adicionar novas.'); event.target.value = ''; return; } setUploadingGallery(true); try { for (const file of files) { const uploaded = await uploadFile(file); if (uploaded) { setGalleryImages((prev) => [...prev, uploaded]); } } success('Galeria atualizada.'); } catch (err) { console.error('Erro ao enviar imagem da galeria:', err); error(err instanceof Error ? err.message : 'Falha ao enviar imagem da galeria.'); } finally { setUploadingGallery(false); event.target.value = ''; } }; const handleRemoveGalleryImage = (path: string) => { setGalleryImages((prev) => prev.filter((image) => image.path !== path)); }; const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); if (!formData.title || !formData.category) { error('Informe ao menos o título e a categoria do projeto.'); return; } setLoading(true); try { const response = await fetch('/api/projects', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ title: formData.title.trim(), category: formData.category, client: formData.client?.trim() || null, status: formData.status, description: formData.description?.trim() || null, completionDate: formData.date ? new Date(formData.date).toISOString() : null, coverImage: coverImage?.url ?? null, galleryImages: galleryImages.map((image) => image.url), featured: formData.featured, }), }); const data = await response.json().catch(() => ({})); if (!response.ok) { throw new Error(data?.error || 'Erro ao salvar projeto'); } success('Projeto cadastrado com sucesso!'); router.push('/admin/projetos'); } catch (err) { console.error('Erro ao salvar projeto:', err); error(err instanceof Error ? err.message : 'Não foi possível salvar o projeto.'); } finally { setLoading(false); } }; return (

Novo Projeto

Adicione um novo projeto ao portfólio.

{/* Basic Info */}

Informações Básicas

setFormData({...formData, title: e.target.value})} className="w-full px-4 py-3 bg-gray-50 dark:bg-white/5 border border-gray-200 dark:border-white/10 rounded-xl text-gray-900 dark:text-white focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary transition-all" placeholder="Ex: Adequação de Frota Coca-Cola" required />
setFormData({...formData, client: e.target.value})} className="w-full px-4 py-3 bg-gray-50 dark:bg-white/5 border border-gray-200 dark:border-white/10 rounded-xl text-gray-900 dark:text-white focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary transition-all" placeholder="Ex: Coca-Cola FEMSA" />
setFormData({...formData, date: e.target.value})} className="w-full px-4 py-3 bg-gray-50 dark:bg-white/5 border border-gray-200 dark:border-white/10 rounded-xl text-gray-900 dark:text-white focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary transition-all" />

Projetos em destaque podem ser exibidos em seções especiais como a home.

{/* Media */}

Mídia

coverInputRef.current?.click()} className="border-2 border-dashed border-gray-300 dark:border-white/20 rounded-xl p-6 text-center hover:border-primary dark:hover:border-primary transition-colors cursor-pointer bg-gray-50 dark:bg-white/5 relative min-h-[200px] flex items-center justify-center" > {coverImage ? (
{coverImage.name}
) : (
{uploadingCover ? ( ) : ( )}

{uploadingCover ? 'Enviando imagem...' : 'Clique para fazer upload ou arraste e solte'}

PNG, JPG ou WEBP (máximo 2MB)

)}
{galleryImages.map((image) => (
{image.name}
))}

Adicione até 8 imagens para apresentar detalhes do projeto.

{/* Actions */}
Cancelar
); }