feat: sessão #3 — lib (db/auth/email/validations), API routes, NextAuth v5, middleware, páginas account/shelters/shelter-dashboard, Prisma v7 fix

This commit is contained in:
2026-05-21 09:01:59 +01:00
parent e6ebc0909c
commit e62dc9d6e6
44 changed files with 5341 additions and 273 deletions

View File

@@ -1,20 +1,49 @@
import type { Metadata } from "next";
import { Geist, Geist_Mono } from "next/font/google";
import "./globals.css";
import type { Metadata } from 'next';
import { Playfair_Display, Lora, Fragment_Mono } from 'next/font/google';
import './globals.css';
const geistSans = Geist({
variable: "--font-geist-sans",
subsets: ["latin"],
const playfair = Playfair_Display({
subsets: ['latin'],
variable: '--font-playfair',
weight: ['700', '900'],
style: ['normal', 'italic'],
display: 'swap',
});
const geistMono = Geist_Mono({
variable: "--font-geist-mono",
subsets: ["latin"],
const lora = Lora({
subsets: ['latin'],
variable: '--font-lora',
weight: ['400', '500'],
style: ['normal', 'italic'],
display: 'swap',
});
const fragmentMono = Fragment_Mono({
subsets: ['latin'],
variable: '--font-fragment-mono',
weight: ['400'],
display: 'swap',
});
export const metadata: Metadata = {
title: "Create Next App",
description: "Generated by create next app",
title: {
default: 'PawLink — Adopção de Animais em Portugal',
template: '%s | PawLink',
},
description:
'Encontra o teu companheiro para a vida. PawLink conecta adoptantes, doadores e canis em todo o território português.',
keywords: ['adopção animais', 'canis portugal', 'adoptar cão', 'adoptar gato', 'doação canil'],
authors: [{ name: 'PawLink' }],
creator: 'PawLink',
metadataBase: new URL('https://pawlink.pt'),
openGraph: {
type: 'website',
locale: 'pt_PT',
url: 'https://pawlink.pt',
siteName: 'PawLink',
title: 'PawLink — Adopção de Animais em Portugal',
description: 'Encontra o teu companheiro para a vida.',
},
};
export default function RootLayout({
@@ -24,10 +53,36 @@ export default function RootLayout({
}>) {
return (
<html
lang="en"
className={`${geistSans.variable} ${geistMono.variable} h-full antialiased`}
lang="pt"
className={`${playfair.variable} ${lora.variable} ${fragmentMono.variable}`}
suppressHydrationWarning
>
<body className="min-h-full flex flex-col">{children}</body>
<head>
<script
dangerouslySetInnerHTML={{
__html: `
(function() {
try {
var theme = localStorage.getItem('pawlink-theme');
var prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
if (theme === 'dark' || (!theme && prefersDark)) {
document.documentElement.classList.add('dark');
document.documentElement.setAttribute('data-theme', 'dark');
}
} catch(e) {}
})();
`,
}}
/>
</head>
<body
className="min-h-dvh flex flex-col antialiased"
style={{
fontFamily: 'var(--font-lora, var(--font-body, Lora, Georgia, serif))',
}}
>
{children}
</body>
</html>
);
}