feat: Implement global badge system with Settings model and global PartnerBadge component

This commit is contained in:
Erik
2025-11-29 14:07:47 -03:00
parent 53495de904
commit 70f1541ec0
5 changed files with 163 additions and 32 deletions

View File

@@ -4,6 +4,7 @@ import { useEffect, useState } from "react";
import Link from "next/link";
import { usePageContent } from "@/hooks/usePageContent";
import { useLocale } from "@/contexts/LocaleContext";
import { PartnerBadge } from "@/components/PartnerBadge";
type PortfolioProject = {
id: string;
@@ -54,11 +55,7 @@ export default function Home() {
const hero = content?.hero || {
title: 'Engenharia de Excelência para Seus Projetos',
subtitle: 'Soluções completas em engenharia veicular, mecânica e segurança do trabalho com mais de 15 anos de experiência.',
buttonText: 'Conheça Nossos Serviços',
badge: {
text: 'Coca-Cola',
show: false
}
buttonText: 'Conheça Nossos Serviços'
};
const features = content?.features || {
@@ -167,12 +164,9 @@ export default function Home() {
<div className="container mx-auto px-4 relative z-20">
<div className="max-w-3xl">
{hero.badge?.show && (
<div className="inline-flex items-center gap-3 bg-white/10 backdrop-blur-md border border-white/20 rounded-full px-5 py-2 mb-8 hover:bg-white/20 transition-colors cursor-default">
<i className="ri-verified-badge-fill text-primary text-xl"></i>
<span className="text-sm font-bold tracking-wider uppercase text-white">{t('home.officialProvider')} <span className="text-primary">{hero.badge.text}</span></span>
</div>
)}
<div className="mb-8">
<PartnerBadge />
</div>
<h1 className="text-5xl md:text-6xl font-bold font-headline mb-6 leading-tight">
{hero.title}

View File

@@ -0,0 +1,98 @@
import { NextRequest, NextResponse } from 'next/server';
import { PrismaClient } from '@prisma/client';
import { cookies } from 'next/headers';
import jwt from 'jsonwebtoken';
const prisma = new PrismaClient();
// Middleware de autenticação
async function authenticate(request: NextRequest) {
const cookieStore = await cookies();
const token = cookieStore.get('auth_token')?.value;
if (!token) {
return null;
}
try {
const decoded = jwt.verify(token, process.env.JWT_SECRET!) as { userId: string };
const user = await prisma.user.findUnique({
where: { id: decoded.userId },
select: { id: true, email: true, name: true }
});
return user;
} catch (error) {
return null;
}
}
/**
* GET /api/settings
* Busca configurações globais (público)
*/
export async function GET(request: NextRequest) {
try {
// Buscar ou criar configurações padrão
let settings = await prisma.settings.findFirst();
if (!settings) {
settings = await prisma.settings.create({
data: {
showPartnerBadge: false,
partnerName: 'Coca-Cola'
}
});
}
return NextResponse.json(settings);
} catch (error) {
console.error('Erro ao buscar settings:', error);
return NextResponse.json(
{ error: 'Erro ao buscar configurações' },
{ status: 500 }
);
}
}
/**
* POST /api/settings
* Atualiza configurações globais (admin apenas)
*/
export async function POST(request: NextRequest) {
try {
const user = await authenticate(request);
if (!user) {
return NextResponse.json({ error: 'Não autorizado' }, { status: 401 });
}
const body = await request.json();
const { showPartnerBadge, partnerName } = body;
let settings = await prisma.settings.findFirst();
if (!settings) {
settings = await prisma.settings.create({
data: {
showPartnerBadge: showPartnerBadge ?? false,
partnerName: partnerName ?? 'Coca-Cola'
}
});
} else {
settings = await prisma.settings.update({
where: { id: settings.id },
data: {
...(showPartnerBadge !== undefined && { showPartnerBadge }),
...(partnerName !== undefined && { partnerName })
}
});
}
return NextResponse.json({ success: true, settings });
} catch (error) {
console.error('Erro ao atualizar settings:', error);
return NextResponse.json(
{ error: 'Erro ao atualizar configurações: ' + (error as Error).message },
{ status: 500 }
);
}
}