Initial commit: CMS completo com gerenciamento de leads e personalização de tema

This commit is contained in:
Erik
2025-11-26 14:09:21 -03:00
commit aaa1709e41
106 changed files with 26268 additions and 0 deletions

View File

@@ -0,0 +1,110 @@
"use client";
import Link from 'next/link';
import { useState, useEffect } from 'react';
import { useToast } from '@/contexts/ToastContext';
interface PageContent {
id: string;
slug: string;
content: any;
updatedAt: string;
}
export default function PagesList() {
const [pages, setPages] = useState<PageContent[]>([]);
const [loading, setLoading] = useState(true);
const { error: showError } = useToast();
const pageDefinitions = [
{
title: 'Página Inicial',
slug: 'home',
desc: 'Banner principal, textos de destaque e chamadas.',
icon: 'ri-home-4-line'
},
{
title: 'Sobre Nós',
slug: 'sobre',
desc: 'História da empresa, missão, visão e valores.',
icon: 'ri-team-line'
},
{
title: 'Contato',
slug: 'contato',
desc: 'Endereço, telefones, emails e horário de funcionamento.',
icon: 'ri-contacts-book-line'
},
];
useEffect(() => {
fetchPages();
}, []);
const fetchPages = async () => {
try {
const response = await fetch('/api/pages');
if (!response.ok) throw new Error('Erro ao carregar páginas');
const data = await response.json();
setPages(data);
} catch (err) {
showError('Erro ao carregar páginas');
} finally {
setLoading(false);
}
};
if (loading) {
return (
<div className="flex items-center justify-center h-64">
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-primary"></div>
</div>
);
}
return (
<div>
<div className="mb-8">
<h1 className="text-3xl font-bold font-headline text-secondary dark:text-white mb-2">Gerenciar Páginas</h1>
<p className="text-gray-500 dark:text-gray-400">Edite o conteúdo estático das páginas do site.</p>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{pageDefinitions.map((pageDef) => {
const pageData = pages.find(p => p.slug === pageDef.slug);
const lastUpdate = pageData
? new Date(pageData.updatedAt).toLocaleDateString('pt-BR')
: 'Não configurado';
return (
<div key={pageDef.slug} className="bg-white dark:bg-secondary rounded-2xl border border-gray-200 dark:border-white/10 p-6 shadow-sm hover:shadow-md transition-all group">
<div className="flex items-start justify-between mb-4">
<div className="w-12 h-12 rounded-xl bg-primary/10 text-primary flex items-center justify-center text-2xl group-hover:scale-110 transition-transform">
<i className={pageDef.icon}></i>
</div>
<span className={`text-xs font-medium px-2 py-1 rounded-lg ${
pageData
? 'text-green-600 bg-green-100 dark:bg-green-900/30'
: 'text-orange-600 bg-orange-100 dark:bg-orange-900/30'
}`}>
{pageData ? `Atualizado ${lastUpdate}` : 'Não configurado'}
</span>
</div>
<h3 className="text-xl font-bold text-secondary dark:text-white mb-2">{pageDef.title}</h3>
<p className="text-gray-500 dark:text-gray-400 text-sm mb-6 h-10">{pageDef.desc}</p>
<Link
href={`/admin/paginas/${pageDef.slug}`}
className="block w-full py-3 text-center rounded-xl border border-gray-200 dark:border-white/10 font-bold text-gray-600 dark:text-gray-300 hover:bg-primary hover:text-white hover:border-primary transition-all"
>
Editar Conteúdo
</Link>
</div>
);
})}
</div>
</div>
);
}