Guia de Referência do Desenvolvedor

Um documento vivo que descreve os principais padrões de arquitetura e configurações deste projeto.

Padrão para Operações no Servidor (Server Actions)
Para garantir segurança e centralização, todas as operações que precisam ser executadas no servidor seguem um padrão de 3 etapas.

Passo 1: A Server Action

A lógica principal é definida em uma função `async` exportada de um arquivo `actions.ts`. Este arquivo **deve** começar com a diretiva `"use server"`.

// Em src/app/some-route/actions.ts
'use server';

import { getFirestoreAdmin } from '@/firebase/admin';

export async function ourServerAction(formData: FormData) {
  const data = formData.get('someData');
  
  try {
    const firestoreAdmin = await getFirestoreAdmin();
    // ...sua lógica segura aqui...
    
    return { success: true, message: 'Operação concluída!' };
  } catch (error) {
    return { success: false, error: 'Falha na operação.' };
  }
}

Passo 2: Acesso aos Serviços do Firebase Admin

O arquivo `src/firebase/admin.ts` centraliza a inicialização do Firebase Admin SDK. Ele garante que a inicialização ocorra apenas uma vez (padrão singleton) e fornece funções `async` para obter as instâncias dos serviços.

// Em src/firebase/admin.ts

let firestoreAdmin: Firestore;

function initializeAdminApp() {
  // ...lógica de inicialização...
}

export async function getFirestoreAdmin() {
  if (!firestoreAdmin) {
    initializeAdminApp();
  }
  return firestoreAdmin;
}

Passo 3: Chamada a partir do Componente Cliente

O componente de cliente importa a `Server Action` e a chama diretamente. O hook `useTransition` é usado para gerenciar estados de carregamento e fornecer feedback ao usuário sem bloquear a interface.

// Em um componente cliente, ex: src/app/some-route/page.tsx
'use client';

import { useState, useTransition } from 'react';
import { ourServerAction } from './actions';

export default function MyPage() {
  const [isPending, startTransition] = useTransition();

  const handleAction = () => {
    const formData = new FormData();
    formData.append('someData', 'valor');

    startTransition(async () => {
      const result = await ourServerAction(formData);
      if (result.success) {
        // Exibir toast de sucesso
      } else {
        // Exibir toast de erro
      }
    });
  };

  return (
    <button onClick={handleAction} disabled={isPending}>
      {isPending ? 'Executando...' : 'Executar Ação no Servidor'}
    </button>
  );
}