feat: WhatsApp dinâmico do CMS - Criada API /api/contact-info que busca número do CMS - Header e botão flutuante agora puxam número dinamicamente - Número padrão: (35) 9882-9445

This commit is contained in:
Erik
2025-11-27 20:01:11 -03:00
parent 1fa574881c
commit d5183e0a0d
3 changed files with 104 additions and 7 deletions

View File

@@ -0,0 +1,68 @@
import { NextResponse } from 'next/server';
import prisma from '@/lib/prisma';
// Cache em memória para evitar muitas consultas ao banco
let cachedContactInfo: { whatsapp: string; whatsappLink: string } | null = null;
let cacheTime = 0;
const CACHE_TTL = 60 * 1000; // 1 minuto
export async function GET() {
try {
// Verifica se cache é válido
if (cachedContactInfo && Date.now() - cacheTime < CACHE_TTL) {
return NextResponse.json(cachedContactInfo);
}
// Busca dados da página de contato
const pageContent = await prisma.pageContent.findUnique({
where: {
slug_locale: {
slug: 'contato',
locale: 'pt'
}
}
});
if (!pageContent || !pageContent.content) {
// Retorna valores padrão
return NextResponse.json({
whatsapp: '(35) 9882-9445',
whatsappLink: 'https://wa.me/5535988229445'
});
}
const content = pageContent.content as {
info?: {
items?: Array<{
icon?: string;
link?: string;
linkText?: string;
}>;
};
};
// Encontra o item de WhatsApp
const whatsappItem = content.info?.items?.find(
item => item.icon === 'ri-whatsapp-line' || item.link?.includes('wa.me')
);
const result = {
whatsapp: whatsappItem?.linkText || '(35) 9882-9445',
whatsappLink: whatsappItem?.link || 'https://wa.me/5535988229445'
};
// Atualiza cache
cachedContactInfo = result;
cacheTime = Date.now();
return NextResponse.json(result);
} catch (error) {
console.error('Erro ao buscar informações de contato:', error);
// Retorna valores padrão em caso de erro
return NextResponse.json({
whatsapp: '(35) 9882-9445',
whatsappLink: 'https://wa.me/5535988229445'
});
}
}

View File

@@ -12,12 +12,23 @@ export default function Header() {
const { theme, setTheme } = useTheme(); const { theme, setTheme } = useTheme();
const { locale, setLocale, t } = useLocale(); const { locale, setLocale, t } = useLocale();
const [mounted, setMounted] = useState(false); const [mounted, setMounted] = useState(false);
const [whatsappLink, setWhatsappLink] = useState('https://wa.me/5535988229445');
// Prefixo para links baseado no locale // Prefixo para links baseado no locale
const prefix = locale === 'pt' ? '' : `/${locale}`; const prefix = locale === 'pt' ? '' : `/${locale}`;
useEffect(() => { useEffect(() => {
setMounted(true); setMounted(true);
// Busca o número do WhatsApp do CMS
fetch('/api/contact-info')
.then(res => res.json())
.then(data => {
if (data.whatsappLink) {
setWhatsappLink(data.whatsappLink);
}
})
.catch(console.error);
}, []); }, []);
// Prevent scrolling when mobile menu is open // Prevent scrolling when mobile menu is open
@@ -86,13 +97,15 @@ export default function Header() {
</nav> </nav>
<div className="shrink-0 ml-2"> <div className="shrink-0 ml-2">
<Link <a
href={`${prefix}/contato`} href={whatsappLink}
target="_blank"
rel="noopener noreferrer"
className="px-6 py-2.5 bg-primary text-white rounded-lg font-bold hover-primary transition-colors flex items-center gap-2" className="px-6 py-2.5 bg-primary text-white rounded-lg font-bold hover-primary transition-colors flex items-center gap-2"
> >
<i className="ri-whatsapp-line"></i> <i className="ri-whatsapp-line"></i>
<span className="hidden xl:inline">{t('nav.contactUs')}</span> <span className="hidden xl:inline">{t('nav.contactUs')}</span>
</Link> </a>
</div> </div>
<div className="flex items-center gap-2 pl-4 border-l border-gray-200 dark:border-white/10"> <div className="flex items-center gap-2 pl-4 border-l border-gray-200 dark:border-white/10">
@@ -186,14 +199,16 @@ export default function Header() {
</nav> </nav>
<div className="mt-6 flex flex-col gap-4 pb-8 shrink-0"> <div className="mt-6 flex flex-col gap-4 pb-8 shrink-0">
<Link <a
href={`${prefix}/contato`} href={whatsappLink}
target="_blank"
rel="noopener noreferrer"
onClick={() => setIsMobileMenuOpen(false)} onClick={() => setIsMobileMenuOpen(false)}
className="w-full py-4 bg-primary text-white rounded-xl font-bold text-center flex items-center justify-center gap-2 shadow-lg shadow-primary/20" className="w-full py-4 bg-primary text-white rounded-xl font-bold text-center flex items-center justify-center gap-2 shadow-lg shadow-primary/20"
> >
<i className="ri-whatsapp-line text-xl"></i> <i className="ri-whatsapp-line text-xl"></i>
{t('nav.contactUs')} {t('nav.contactUs')}
</Link> </a>
<div <div
className="flex items-center justify-between p-4 bg-gray-50 dark:bg-white/5 rounded-xl cursor-pointer hover:bg-gray-100 dark:hover:bg-white/10 transition-colors" className="flex items-center justify-between p-4 bg-gray-50 dark:bg-white/5 rounded-xl cursor-pointer hover:bg-gray-100 dark:hover:bg-white/10 transition-colors"

View File

@@ -2,13 +2,27 @@
import Link from 'next/link'; import Link from 'next/link';
import { useLanguage } from '@/contexts/LanguageContext'; import { useLanguage } from '@/contexts/LanguageContext';
import { useState, useEffect } from 'react';
export default function WhatsAppButton() { export default function WhatsAppButton() {
const { t } = useLanguage(); const { t } = useLanguage();
const [whatsappLink, setWhatsappLink] = useState('https://wa.me/5535988229445');
useEffect(() => {
// Busca o número do WhatsApp do CMS
fetch('/api/contact-info')
.then(res => res.json())
.then(data => {
if (data.whatsappLink) {
setWhatsappLink(data.whatsappLink);
}
})
.catch(console.error);
}, []);
return ( return (
<Link <Link
href="https://wa.me/5511999999999" // Substitua pelo número real href={whatsappLink}
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
className="fixed bottom-6 right-6 z-40 flex flex-row-reverse items-center justify-center bg-[#25D366] text-white w-14 h-14 rounded-full shadow-lg hover:bg-[#20bd5a] transition-all hover:scale-110 group animate-in slide-in-from-bottom-4 duration-700 delay-1000 hover:w-auto hover:px-6" className="fixed bottom-6 right-6 z-40 flex flex-row-reverse items-center justify-center bg-[#25D366] text-white w-14 h-14 rounded-full shadow-lg hover:bg-[#20bd5a] transition-all hover:scale-110 group animate-in slide-in-from-bottom-4 duration-700 delay-1000 hover:w-auto hover:px-6"