adriano2005 commited on
Commit
9853253
·
verified ·
1 Parent(s): 2795167

Rename index.html to app/page.tsx

Browse files
Files changed (2) hide show
  1. app/page.tsx +81 -0
  2. index.html +0 -19
app/page.tsx ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // app/page.tsx
2
+ import { Suspense } from 'react';
3
+ import { z } from 'zod';
4
+ import { ProductGrid } from '@/components/ui/product-grid';
5
+ import { ProductGridSkeleton } from '@/components/ui/skeletons';
6
+ import { HeroSection } from '@/components/marketing/hero';
7
+ import { db } from '@/lib/db'; // Drizzle ORM setup
8
+
9
+ // 🔐 [SHIFT-LEFT SECURITY]: Schema Zod para validar a fronteira de dados do banco
10
+ // "Parse, Don't Validate"
11
+ const ProductSchema = z.object({
12
+ id: z.string().uuid(),
13
+ name: z.string().min(1),
14
+ price: z.number().positive(),
15
+ imageUrl: z.string().url(),
16
+ slug: z.string(),
17
+ });
18
+
19
+ type Product = z.infer<typeof ProductSchema>;
20
+
21
+ // ⚡ [OTIMIZAÇÃO DE PERFORMANCE]: Revalidação de cache a cada 60 segundos (ISR)
22
+ export const revalidate = 60;
23
+
24
+ // Função pura para buscar dados, operando exclusivamente no servidor
25
+ async function getFeaturedProducts(): Promise<Product[]> {
26
+ try {
27
+ // 🎯 [DECISÃO ARQUITETURAL]: Drizzle ORM para consultas SQL tipadas e baixo overhead
28
+ const rawProducts = await db.query.products.findMany({
29
+ limit: 12,
30
+ where: (products, { eq }) => eq(products.isFeatured, true),
31
+ });
32
+
33
+ // Validação estrita: se o DB retornar dados corrompidos, a página quebra graciosamente,
34
+ // evitando injetar dados maliciosos ou nulos na UI.
35
+ return z.array(ProductSchema).parse(rawProducts);
36
+ } catch (error) {
37
+ console.error('Falha ao buscar produtos:', error);
38
+ // Early return com fallback array para não derrubar a página inteira
39
+ return [];
40
+ }
41
+ }
42
+
43
+ // ♿ [A11y & SEO STRICT]: Uso de tags semânticas (main, section) e meta dados corretos
44
+ export default async function StorefrontIndex() {
45
+ const productsPromise = getFeaturedProducts();
46
+
47
+ return (
48
+ <main className="flex min-h-screen flex-col items-center justify-between">
49
+ <HeroSection
50
+ title="Nova Coleção 2026"
51
+ subtitle="A performance que você exige. O design que você merece."
52
+ />
53
+
54
+ <section
55
+ aria-labelledby="featured-products-heading"
56
+ className="w-full max-w-7xl px-4 py-12 md:px-8"
57
+ >
58
+ <h2 id="featured-products-heading" className="text-3xl font-bold tracking-tight mb-8">
59
+ Destaques da Semana
60
+ </h2>
61
+
62
+ {/* ⚡ [OTIMIZAÇÃO DE PERFORMANCE/INP]: Streaming UI com Suspense.
63
+ O usuário vê o esqueleto enquanto o banco de dados resolve a query. */}
64
+ <Suspense fallback={<ProductGridSkeleton count={12} />}>
65
+ <FeaturedProducts loader={productsPromise} />
66
+ </Suspense>
67
+ </section>
68
+ </main>
69
+ );
70
+ }
71
+
72
+ // Componente assíncrono isolado para consumir a promise
73
+ async function FeaturedProducts({ loader }: { loader: Promise<Product[]> }) {
74
+ const products = await loader;
75
+
76
+ if (products.length === 0) {
77
+ return <p className="text-muted-foreground">Nenhum produto encontrado no momento.</p>;
78
+ }
79
+
80
+ return <ProductGrid products={products} />;
81
+ }
index.html DELETED
@@ -1,19 +0,0 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>