Initial commit: CMS completo com gerenciamento de leads e personalização de tema
This commit is contained in:
200
frontend/src/app/admin/projetos/novo/page.tsx
Normal file
200
frontend/src/app/admin/projetos/novo/page.tsx
Normal file
@@ -0,0 +1,200 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from 'react';
|
||||
import Link from 'next/link';
|
||||
import { useRouter } from 'next/navigation';
|
||||
|
||||
export default function NewProject() {
|
||||
const router = useRouter();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [formData, setFormData] = useState({
|
||||
title: '',
|
||||
category: '',
|
||||
client: '',
|
||||
status: 'active',
|
||||
description: '',
|
||||
date: ''
|
||||
});
|
||||
|
||||
const handleSubmit = async (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
setLoading(true);
|
||||
|
||||
// Simulate API call
|
||||
setTimeout(() => {
|
||||
console.log('Project data:', formData);
|
||||
setLoading(false);
|
||||
router.push('/admin/projetos');
|
||||
}, 1500);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="max-w-4xl mx-auto">
|
||||
<div className="flex items-center gap-4 mb-8">
|
||||
<Link
|
||||
href="/admin/projetos"
|
||||
className="w-10 h-10 rounded-xl bg-white dark:bg-secondary border border-gray-200 dark:border-white/10 flex items-center justify-center text-gray-500 hover:text-primary hover:border-primary transition-colors shadow-sm"
|
||||
>
|
||||
<i className="ri-arrow-left-line text-xl"></i>
|
||||
</Link>
|
||||
<div>
|
||||
<h1 className="text-3xl font-bold font-headline text-secondary dark:text-white mb-1">Novo Projeto</h1>
|
||||
<p className="text-gray-500 dark:text-gray-400">Adicione um novo projeto ao portfólio.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form onSubmit={handleSubmit} className="space-y-8">
|
||||
{/* Basic Info */}
|
||||
<div className="bg-white dark:bg-secondary p-8 rounded-2xl border border-gray-200 dark:border-white/10 shadow-sm">
|
||||
<h2 className="text-xl font-bold text-secondary dark:text-white mb-6 flex items-center gap-2">
|
||||
<i className="ri-information-line text-primary"></i>
|
||||
Informações Básicas
|
||||
</h2>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<div className="md:col-span-2">
|
||||
<label className="block text-sm font-bold text-gray-700 dark:text-gray-300 mb-2">Título do Projeto</label>
|
||||
<input
|
||||
type="text"
|
||||
value={formData.title}
|
||||
onChange={(e) => 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
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-bold text-gray-700 dark:text-gray-300 mb-2">Categoria</label>
|
||||
<select
|
||||
value={formData.category}
|
||||
onChange={(e) => setFormData({...formData, category: 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 appearance-none cursor-pointer"
|
||||
required
|
||||
>
|
||||
<option value="">Selecione uma categoria</option>
|
||||
<option value="veicular">Engenharia Veicular</option>
|
||||
<option value="mecanica">Projetos Mecânicos</option>
|
||||
<option value="laudos">Laudos e Inspeções</option>
|
||||
<option value="seguranca">Segurança do Trabalho</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-bold text-gray-700 dark:text-gray-300 mb-2">Cliente</label>
|
||||
<input
|
||||
type="text"
|
||||
value={formData.client}
|
||||
onChange={(e) => 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"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-bold text-gray-700 dark:text-gray-300 mb-2">Data de Conclusão</label>
|
||||
<input
|
||||
type="date"
|
||||
value={formData.date}
|
||||
onChange={(e) => 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"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-bold text-gray-700 dark:text-gray-300 mb-2">Status</label>
|
||||
<select
|
||||
value={formData.status}
|
||||
onChange={(e) => setFormData({...formData, status: 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 appearance-none cursor-pointer"
|
||||
>
|
||||
<option value="active">Concluído</option>
|
||||
<option value="pending">Em Andamento</option>
|
||||
<option value="draft">Rascunho</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div className="md:col-span-2">
|
||||
<label className="block text-sm font-bold text-gray-700 dark:text-gray-300 mb-2">Descrição Detalhada</label>
|
||||
<textarea
|
||||
value={formData.description}
|
||||
onChange={(e) => setFormData({...formData, description: e.target.value})}
|
||||
rows={6}
|
||||
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 resize-none"
|
||||
placeholder="Descreva os detalhes técnicos, desafios e soluções do projeto..."
|
||||
></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Media */}
|
||||
<div className="bg-white dark:bg-secondary p-8 rounded-2xl border border-gray-200 dark:border-white/10 shadow-sm">
|
||||
<h2 className="text-xl font-bold text-secondary dark:text-white mb-6 flex items-center gap-2">
|
||||
<i className="ri-image-line text-primary"></i>
|
||||
Mídia
|
||||
</h2>
|
||||
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<label className="block text-sm font-bold text-gray-700 dark:text-gray-300 mb-2">Imagem de Capa</label>
|
||||
<div className="border-2 border-dashed border-gray-300 dark:border-white/20 rounded-xl p-8 text-center hover:border-primary dark:hover:border-primary transition-colors cursor-pointer bg-gray-50 dark:bg-white/5">
|
||||
<div className="w-16 h-16 bg-primary/10 rounded-full flex items-center justify-center text-primary mx-auto mb-4">
|
||||
<i className="ri-upload-cloud-2-line text-3xl"></i>
|
||||
</div>
|
||||
<p className="text-gray-600 dark:text-gray-300 font-medium mb-1">Clique para fazer upload ou arraste e solte</p>
|
||||
<p className="text-xs text-gray-400">PNG, JPG ou WEBP (Max. 2MB)</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-bold text-gray-700 dark:text-gray-300 mb-2">Galeria de Fotos</label>
|
||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
|
||||
<div className="aspect-square border-2 border-dashed border-gray-300 dark:border-white/20 rounded-xl flex flex-col items-center justify-center text-gray-400 hover:text-primary hover:border-primary transition-colors cursor-pointer bg-gray-50 dark:bg-white/5">
|
||||
<i className="ri-add-line text-3xl mb-2"></i>
|
||||
<span className="text-xs font-bold">Adicionar</span>
|
||||
</div>
|
||||
{/* Placeholders for uploaded images */}
|
||||
{[1, 2].map((i) => (
|
||||
<div key={i} className="aspect-square rounded-xl bg-gray-200 dark:bg-white/10 relative group overflow-hidden">
|
||||
<div className="absolute inset-0 bg-black/50 opacity-0 group-hover:opacity-100 transition-opacity flex items-center justify-center gap-2">
|
||||
<button type="button" className="w-8 h-8 rounded-lg bg-white/20 hover:bg-white/40 text-white flex items-center justify-center backdrop-blur-sm transition-colors">
|
||||
<i className="ri-delete-bin-line"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Actions */}
|
||||
<div className="flex items-center justify-end gap-4 pt-4">
|
||||
<Link
|
||||
href="/admin/projetos"
|
||||
className="px-8 py-3 border border-gray-200 dark:border-white/10 text-gray-600 dark:text-gray-300 rounded-xl font-bold hover:bg-gray-50 dark:hover:bg-white/5 transition-colors"
|
||||
>
|
||||
Cancelar
|
||||
</Link>
|
||||
<button
|
||||
type="submit"
|
||||
disabled={loading}
|
||||
className="px-8 py-3 bg-primary text-white rounded-xl font-bold hover:bg-orange-600 transition-colors shadow-lg shadow-primary/20 flex items-center gap-2 disabled:opacity-70 disabled:cursor-not-allowed"
|
||||
>
|
||||
{loading ? (
|
||||
<>
|
||||
<i className="ri-loader-4-line animate-spin"></i>
|
||||
Salvando...
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<i className="ri-save-line"></i>
|
||||
Salvar Projeto
|
||||
</>
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user