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:
@@ -1,6 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import Link from 'next/link';
|
||||
import Image from 'next/image';
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useTheme } from "next-themes";
|
||||
import { useLocale } from '@/contexts/LocaleContext';
|
||||
@@ -10,6 +11,7 @@ export default function Header() {
|
||||
const [isSearchOpen, setIsSearchOpen] = useState(false);
|
||||
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
|
||||
const [isLoggedIn, setIsLoggedIn] = useState(false);
|
||||
const [logo, setLogo] = useState<string | null>(null);
|
||||
const { theme, setTheme } = useTheme();
|
||||
const { locale, setLocale, t } = useLocale();
|
||||
const [mounted, setMounted] = useState(false);
|
||||
@@ -30,7 +32,20 @@ export default function Header() {
|
||||
})
|
||||
.catch(() => setIsLoggedIn(false));
|
||||
|
||||
// Busca o número do WhatsApp do CMS
|
||||
// Busca as configurações (logo e whatsapp)
|
||||
fetch('/api/settings')
|
||||
.then(res => res.json())
|
||||
.then(data => {
|
||||
if (data.logo) {
|
||||
setLogo(data.logo);
|
||||
}
|
||||
if (data.whatsapp) {
|
||||
setWhatsappLink(`https://wa.me/${data.whatsapp.replace(/\D/g, '')}`);
|
||||
}
|
||||
})
|
||||
.catch(console.error);
|
||||
|
||||
// Busca o número do WhatsApp do CMS (fallback)
|
||||
fetch('/api/contact-info')
|
||||
.then(res => res.json())
|
||||
.then(data => {
|
||||
@@ -39,6 +54,21 @@ export default function Header() {
|
||||
}
|
||||
})
|
||||
.catch(console.error);
|
||||
|
||||
// Listener para atualização em tempo real
|
||||
const handleSettingsRefresh = () => {
|
||||
fetch('/api/settings')
|
||||
.then(res => res.json())
|
||||
.then(data => {
|
||||
if (data.logo !== undefined) {
|
||||
setLogo(data.logo);
|
||||
}
|
||||
})
|
||||
.catch(console.error);
|
||||
};
|
||||
|
||||
window.addEventListener('settings:refresh', handleSettingsRefresh);
|
||||
return () => window.removeEventListener('settings:refresh', handleSettingsRefresh);
|
||||
}, []);
|
||||
|
||||
// Prevent scrolling when mobile menu is open
|
||||
@@ -81,7 +111,18 @@ export default function Header() {
|
||||
<header className={`w-full bg-white dark:bg-secondary shadow-sm sticky ${isLoggedIn ? 'top-0' : 'top-0'} z-50 transition-colors duration-300`}>
|
||||
<div className="container mx-auto px-4 h-20 flex items-center justify-between gap-4">
|
||||
<Link href={`${prefix}/`} className="flex items-center gap-3 shrink-0 group mr-auto z-50 relative">
|
||||
<i className="ri-building-2-fill text-4xl text-primary group-hover:scale-105 transition-transform"></i>
|
||||
{logo ? (
|
||||
<Image
|
||||
src={logo}
|
||||
alt="Logo"
|
||||
width={40}
|
||||
height={40}
|
||||
className="object-contain group-hover:scale-105 transition-transform"
|
||||
unoptimized
|
||||
/>
|
||||
) : (
|
||||
<i className="ri-building-2-fill text-4xl text-primary group-hover:scale-105 transition-transform"></i>
|
||||
)}
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-3xl font-bold text-secondary dark:text-white font-headline leading-none">OCCTO</span>
|
||||
<span className="text-[10px] font-bold text-primary bg-primary/10 px-2 py-1 rounded-md uppercase tracking-wider">ENG.</span>
|
||||
|
||||
Reference in New Issue
Block a user