From 080444e29dae72d6abdba2b84e494ffb7b0f6b14 Mon Sep 17 00:00:00 2001 From: Erik Date: Sat, 29 Nov 2025 16:01:46 -0300 Subject: [PATCH] feat: Reorganize admin config tabs and sync contact info across pages --- frontend/src/app/(public)/contato/page.tsx | 122 +++++++++++++----- frontend/src/app/[locale]/contato/page.tsx | 121 ++++++++++++----- frontend/src/app/admin/configuracoes/page.tsx | 105 ++++++++++++--- 3 files changed, 262 insertions(+), 86 deletions(-) diff --git a/frontend/src/app/(public)/contato/page.tsx b/frontend/src/app/(public)/contato/page.tsx index f2f52ba..8ef2538 100644 --- a/frontend/src/app/(public)/contato/page.tsx +++ b/frontend/src/app/(public)/contato/page.tsx @@ -26,9 +26,17 @@ interface ContactContent { }; } +interface SettingsData { + address?: string | null; + phone?: string | null; + email?: string | null; + whatsapp?: string | null; +} + export default function ContatoPage() { const { success, error: showError } = useToast(); const [content, setContent] = useState(null); + const [settings, setSettings] = useState({}); const [loading, setLoading] = useState(true); const [submitting, setSubmitting] = useState(false); const [formData, setFormData] = useState({ @@ -44,6 +52,7 @@ export default function ContatoPage() { useEffect(() => { fetchContent(); + fetchSettings(); }, []); const fetchContent = async () => { @@ -62,6 +71,23 @@ export default function ContatoPage() { } }; + const fetchSettings = async () => { + try { + const response = await fetch('/api/settings'); + if (response.ok) { + const data = await response.json(); + setSettings({ + address: data.address, + phone: data.phone, + email: data.email, + whatsapp: data.whatsapp + }); + } + } catch (error) { + console.error('Erro ao carregar configurações:', error); + } + }; + const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); setSubmitting(true); @@ -103,31 +129,46 @@ export default function ContatoPage() { title: 'Informações', subtitle: 'Como nos encontrar', description: 'Estamos à disposição para atender sua empresa com a excelência técnica que seu projeto exige.', - items: [ - { - icon: 'ri-whatsapp-line', - title: 'Telefone', - description: 'Atendimento de segunda a sexta, das 8h às 18h', - link: 'https://wa.me/5527999999999', - linkText: '(27) 99999-9999' - }, - { - icon: 'ri-mail-send-line', - title: 'E-mail', - description: 'Responderemos em até 24 horas úteis', - link: 'mailto:contato@octto.com.br', - linkText: 'contato@octto.com.br' - }, - { - icon: 'ri-map-pin-line', - title: 'Endereço', - description: 'Av. Nossa Senhora da Penha, 1234\nSanta Lúcia, Vitória - ES\nCEP: 29056-000', - link: 'https://maps.google.com', - linkText: 'Ver no mapa' - } - ] + items: [] as ContactInfo[] }; + // Montar items dinamicamente baseado nas configurações + const contactItems: ContactInfo[] = []; + + if (settings.whatsapp || settings.phone) { + const phoneNumber = settings.whatsapp || settings.phone; + contactItems.push({ + icon: 'ri-whatsapp-line', + title: 'Telefone', + description: 'Atendimento de segunda a sexta, das 8h às 18h', + link: settings.whatsapp ? `https://wa.me/55${settings.whatsapp.replace(/\D/g, '')}` : `tel:${phoneNumber?.replace(/\D/g, '')}`, + linkText: phoneNumber || '' + }); + } + + if (settings.email) { + contactItems.push({ + icon: 'ri-mail-send-line', + title: 'E-mail', + description: 'Responderemos em até 24 horas úteis', + link: `mailto:${settings.email}`, + linkText: settings.email + }); + } + + if (settings.address) { + contactItems.push({ + icon: 'ri-map-pin-line', + title: 'Endereço', + description: settings.address, + link: `https://maps.google.com/maps?q=${encodeURIComponent(settings.address)}`, + linkText: 'Ver no mapa' + }); + } + + // Usar items do CMS se existir, senão usar os dinâmicos + const displayItems = info.items?.length > 0 ? info.items : contactItems; + return (
{/* Hero Section */} @@ -165,20 +206,31 @@ export default function ContatoPage() {
- {info.items.map((item, index) => ( -
-
-
- -
-
-

{item.title}

-

{item.description}

- - {item.linkText} - + {displayItems.length > 0 ? ( + displayItems.map((item, index) => ( +
+
+
+ +
+
+

{item.title}

+

{item.description}

+ + {item.linkText} + +
+ )) + ) : ( +
+ +

Informações de contato não configuradas

+
+ )} +
+
))}
diff --git a/frontend/src/app/[locale]/contato/page.tsx b/frontend/src/app/[locale]/contato/page.tsx index 40d2a5e..0a74777 100644 --- a/frontend/src/app/[locale]/contato/page.tsx +++ b/frontend/src/app/[locale]/contato/page.tsx @@ -26,10 +26,18 @@ interface ContactContent { }; } +interface SettingsData { + address?: string | null; + phone?: string | null; + email?: string | null; + whatsapp?: string | null; +} + export default function ContatoPage() { const { success, error: showError } = useToast(); const { locale, t } = useLocale(); const [content, setContent] = useState(null); + const [settings, setSettings] = useState({}); const [loading, setLoading] = useState(true); const [submitting, setSubmitting] = useState(false); const [formData, setFormData] = useState({ @@ -42,6 +50,7 @@ export default function ContatoPage() { useEffect(() => { fetchContent(); + fetchSettings(); }, [locale]); const fetchContent = async () => { @@ -61,6 +70,23 @@ export default function ContatoPage() { } }; + const fetchSettings = async () => { + try { + const response = await fetch('/api/settings'); + if (response.ok) { + const data = await response.json(); + setSettings({ + address: data.address, + phone: data.phone, + email: data.email, + whatsapp: data.whatsapp + }); + } + } catch (error) { + console.error('Erro ao carregar configurações:', error); + } + }; + const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); setSubmitting(true); @@ -102,31 +128,46 @@ export default function ContatoPage() { title: t('contact.infoTitle'), subtitle: t('contact.infoSubtitle'), description: t('contact.infoDescription'), - items: [ - { - icon: 'ri-whatsapp-line', - title: t('contact.phone'), - description: t('contact.phoneDescription'), - link: 'https://wa.me/5527999999999', - linkText: '(27) 99999-9999' - }, - { - icon: 'ri-mail-send-line', - title: t('contact.email'), - description: t('contact.emailDescription'), - link: 'mailto:contato@octto.com.br', - linkText: 'contato@octto.com.br' - }, - { - icon: 'ri-map-pin-line', - title: t('contact.address'), - description: t('contact.addressDescription'), - link: 'https://maps.google.com', - linkText: t('contact.viewOnMap') - } - ] + items: [] as ContactInfo[] }; + // Montar items dinamicamente baseado nas configurações + const contactItems: ContactInfo[] = []; + + if (settings.whatsapp || settings.phone) { + const phoneNumber = settings.whatsapp || settings.phone; + contactItems.push({ + icon: 'ri-whatsapp-line', + title: t('contact.phone'), + description: t('contact.phoneDescription'), + link: settings.whatsapp ? `https://wa.me/55${settings.whatsapp.replace(/\D/g, '')}` : `tel:${phoneNumber?.replace(/\D/g, '')}`, + linkText: phoneNumber || '' + }); + } + + if (settings.email) { + contactItems.push({ + icon: 'ri-mail-send-line', + title: t('contact.email'), + description: t('contact.emailDescription'), + link: `mailto:${settings.email}`, + linkText: settings.email + }); + } + + if (settings.address) { + contactItems.push({ + icon: 'ri-map-pin-line', + title: t('contact.address'), + description: settings.address, + link: `https://maps.google.com/maps?q=${encodeURIComponent(settings.address)}`, + linkText: t('contact.viewOnMap') + }); + } + + // Usar items do CMS se existir, senão usar os dinâmicos + const displayItems = info.items?.length > 0 ? info.items : contactItems; + return (
{/* Hero Section */} @@ -164,20 +205,30 @@ export default function ContatoPage() {
- {info.items.map((item, index) => ( -
-
-
- -
-
-

{item.title}

-

{item.description}

- - {item.linkText} - + {displayItems.length > 0 ? ( + displayItems.map((item, index) => ( +
+
+
+ +
+
+

{item.title}

+

{item.description}

+ + {item.linkText} + +
+ )) + ) : ( +
+ +

{t('contact.noInfoConfigured')}

+
+ )} +
))}
diff --git a/frontend/src/app/admin/configuracoes/page.tsx b/frontend/src/app/admin/configuracoes/page.tsx index 175b8c9..1e8f72d 100644 --- a/frontend/src/app/admin/configuracoes/page.tsx +++ b/frontend/src/app/admin/configuracoes/page.tsx @@ -17,7 +17,7 @@ const PRESET_COLORS = [ export default function ConfiguracoesPage() { const { success, error: showError } = useToast(); - const [activeTab, setActiveTab] = useState<'personalizacao' | 'backup'>('personalizacao'); + const [activeTab, setActiveTab] = useState<'personalizacao' | 'logotipo' | 'contato' | 'backup'>('personalizacao'); const [primaryColor, setPrimaryColor] = useState('#FF6B35'); const [customColor, setCustomColor] = useState('#FF6B35'); const [showPartnerBadge, setShowPartnerBadge] = useState(false); @@ -157,7 +157,7 @@ export default function ConfiguracoesPage() {
+ + @@ -413,13 +437,49 @@ export default function ConfiguracoesPage() { {/* Save Button */}
+
+ )} + {/* Tab Content - Logotipo */} + {activeTab === 'logotipo' && ( +
+
+
+
+ +
+
+

Logotipo

+

+ Configure o logotipo que aparece no cabeçalho e rodapé do site. +

+
+
+ +
+ +
+

+ Em Desenvolvimento +

+

+ A funcionalidade de upload de logotipo estará disponível em breve. +

+
+
+
+
+ )} + + {/* Tab Content - Contato */} + {activeTab === 'contato' && ( +
{/* Contact Information Settings */}
@@ -429,7 +489,7 @@ export default function ConfiguracoesPage() {

Informações de Contato

- Configure as informações de contato que aparecem no rodapé do site. + Configure as informações de contato que aparecem na página de contato e no rodapé do site.

@@ -557,16 +617,29 @@ export default function ConfiguracoesPage() { />
- - {/* Save All Settings Button */} - + + {/* Info Alert */} +
+ +
+

+ Sincronização Automática +

+

+ Estas informações serão exibidas automaticamente na página de contato e no rodapé do site. +

+
+
+ + {/* Save All Settings Button */} + )}