feat: implementa sistema de logotipo dinâmico
- Adiciona campo 'logo' ao modelo Settings no Prisma - Atualiza API /api/settings para lidar com upload de logo - Cria aba Logotipo funcional no admin com upload de imagem - Atualiza Header para exibir logo dinâmico (fallback para ícone) - Atualiza Footer para exibir logo dinâmico - Atualiza Admin Layout para exibir logo dinâmico - Logo é atualizado em tempo real via evento settings:refresh
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
|
||||
import { useState, useEffect, useRef, useCallback } from 'react';
|
||||
import Link from 'next/link';
|
||||
import Image from 'next/image';
|
||||
import { usePathname, useRouter } from 'next/navigation';
|
||||
import { useToast } from '@/contexts/ToastContext';
|
||||
import { useConfirm } from '@/contexts/ConfirmContext';
|
||||
@@ -20,6 +21,7 @@ export default function AdminLayout({
|
||||
}) {
|
||||
const [isSidebarOpen, setIsSidebarOpen] = useState(true);
|
||||
const [user, setUser] = useState<{ name: string; email: string; avatar?: string | null } | null>(null);
|
||||
const [logo, setLogo] = useState<string | null>(null);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [showAvatarModal, setShowAvatarModal] = useState(false);
|
||||
const [isUploading, setIsUploading] = useState(false);
|
||||
@@ -104,6 +106,27 @@ export default function AdminLayout({
|
||||
}
|
||||
};
|
||||
fetchUser();
|
||||
|
||||
// Buscar logo das configurações
|
||||
const fetchLogo = async () => {
|
||||
try {
|
||||
const response = await fetch('/api/settings');
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
if (data.logo) {
|
||||
setLogo(data.logo);
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Erro ao buscar logo:', err);
|
||||
}
|
||||
};
|
||||
fetchLogo();
|
||||
|
||||
// Listener para atualização em tempo real
|
||||
const handleSettingsRefresh = () => fetchLogo();
|
||||
window.addEventListener('settings:refresh', handleSettingsRefresh);
|
||||
return () => window.removeEventListener('settings:refresh', handleSettingsRefresh);
|
||||
}, [router]);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -239,7 +262,18 @@ export default function AdminLayout({
|
||||
<aside className={`fixed inset-y-0 left-0 z-50 bg-white dark:bg-secondary border-r border-gray-200 dark:border-white/10 transition-all duration-300 ${isSidebarOpen ? 'w-64' : 'w-20'} hidden md:flex flex-col`}>
|
||||
<div className="h-20 flex items-center justify-center border-b border-gray-200 dark:border-white/10">
|
||||
<Link href="/admin" className="flex items-center gap-3">
|
||||
<i className="ri-building-2-fill text-3xl text-primary"></i>
|
||||
{logo ? (
|
||||
<Image
|
||||
src={logo}
|
||||
alt="Logo"
|
||||
width={32}
|
||||
height={32}
|
||||
className="object-contain"
|
||||
unoptimized
|
||||
/>
|
||||
) : (
|
||||
<i className="ri-building-2-fill text-3xl text-primary"></i>
|
||||
)}
|
||||
{isSidebarOpen && (
|
||||
<div className="flex items-center gap-2 animate-in fade-in duration-300">
|
||||
<span className="text-xl font-bold text-secondary dark:text-white font-headline leading-none">OCCTO</span>
|
||||
|
||||
Reference in New Issue
Block a user