@create-lft-app/nextjs 2.0.1 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/package.json +3 -2
  2. package/template/CLAUDE.md +279 -0
  3. package/template/drizzle.config.ts +12 -0
  4. package/template/package.json +31 -6
  5. package/template/proxy.ts +12 -0
  6. package/template/src/app/(auth)/dashboard/dashboard-content.tsx +124 -0
  7. package/template/src/app/(auth)/dashboard/page.tsx +9 -0
  8. package/template/src/app/(auth)/layout.tsx +7 -0
  9. package/template/src/app/(auth)/users/page.tsx +9 -0
  10. package/template/src/app/(auth)/users/users-content.tsx +26 -0
  11. package/template/src/app/(public)/layout.tsx +7 -0
  12. package/template/src/app/(public)/login/page.tsx +17 -0
  13. package/template/src/app/api/webhooks/route.ts +20 -0
  14. package/template/src/app/layout.tsx +13 -12
  15. package/template/src/app/providers.tsx +27 -0
  16. package/template/src/components/layout/{midday-sidebar.tsx → sidebar.tsx} +2 -7
  17. package/template/src/components/tables/data-table-column-header.tsx +68 -0
  18. package/template/src/components/tables/data-table-pagination.tsx +99 -0
  19. package/template/src/components/tables/data-table-toolbar.tsx +50 -0
  20. package/template/src/components/tables/data-table-view-options.tsx +59 -0
  21. package/template/src/components/tables/data-table.tsx +128 -0
  22. package/template/src/components/tables/index.ts +5 -0
  23. package/template/src/components/ui/animations/index.ts +44 -0
  24. package/template/src/components/ui/button.tsx +50 -21
  25. package/template/src/components/ui/card.tsx +27 -3
  26. package/template/src/components/ui/dialog.tsx +38 -35
  27. package/template/src/components/ui/motion.tsx +197 -0
  28. package/template/src/components/ui/page-transition.tsx +166 -0
  29. package/template/src/components/ui/sheet.tsx +65 -41
  30. package/template/src/config/navigation.ts +69 -0
  31. package/template/src/config/site.ts +12 -0
  32. package/template/src/db/index.ts +12 -0
  33. package/template/src/db/schema/index.ts +1 -0
  34. package/template/src/db/schema/users.ts +16 -0
  35. package/template/src/db/seed.ts +39 -0
  36. package/template/src/hooks/index.ts +3 -0
  37. package/template/src/hooks/useDataTable.ts +82 -0
  38. package/template/src/hooks/useDebounce.ts +49 -0
  39. package/template/src/hooks/useMediaQuery.ts +36 -0
  40. package/template/src/lib/date/config.ts +34 -0
  41. package/template/src/lib/date/formatters.ts +120 -0
  42. package/template/src/lib/date/index.ts +19 -0
  43. package/template/src/lib/excel/exporter.ts +89 -0
  44. package/template/src/lib/excel/index.ts +14 -0
  45. package/template/src/lib/excel/parser.ts +96 -0
  46. package/template/src/lib/query-client.ts +35 -0
  47. package/template/src/lib/supabase/client.ts +5 -2
  48. package/template/src/lib/supabase/proxy.ts +67 -0
  49. package/template/src/lib/supabase/server.ts +6 -4
  50. package/template/src/lib/supabase/types.ts +53 -0
  51. package/template/src/lib/validations/common.ts +75 -0
  52. package/template/src/lib/validations/index.ts +20 -0
  53. package/template/src/modules/auth/actions/auth-actions.ts +51 -4
  54. package/template/src/modules/auth/components/login-form.tsx +68 -0
  55. package/template/src/modules/auth/hooks/useAuth.ts +38 -0
  56. package/template/src/modules/auth/hooks/useAuthMutations.ts +43 -0
  57. package/template/src/modules/auth/hooks/useAuthQueries.ts +43 -0
  58. package/template/src/modules/auth/index.ts +12 -0
  59. package/template/src/modules/auth/schemas/auth.schema.ts +32 -0
  60. package/template/src/modules/auth/stores/useAuthStore.ts +37 -0
  61. package/template/src/modules/users/actions/users-actions.ts +94 -0
  62. package/template/src/modules/users/columns.tsx +86 -0
  63. package/template/src/modules/users/components/users-list.tsx +22 -0
  64. package/template/src/modules/users/hooks/useUsers.ts +39 -0
  65. package/template/src/modules/users/hooks/useUsersMutations.ts +55 -0
  66. package/template/src/modules/users/hooks/useUsersQueries.ts +35 -0
  67. package/template/src/modules/users/index.ts +12 -0
  68. package/template/src/modules/users/schemas/users.schema.ts +23 -0
  69. package/template/src/modules/users/stores/useUsersStore.ts +60 -0
  70. package/template/src/stores/index.ts +1 -0
  71. package/template/src/stores/useUiStore.ts +55 -0
  72. package/template/src/types/api.ts +28 -0
  73. package/template/src/types/index.ts +2 -0
  74. package/template/src/types/table.ts +34 -0
  75. package/template/supabase/config.toml +94 -0
  76. package/template/tsconfig.json +2 -1
  77. package/template/tsconfig.tsbuildinfo +1 -0
  78. package/template/src/app/dashboard/page.tsx +0 -111
  79. package/template/src/components/dashboard/widget.tsx +0 -113
  80. package/template/src/test/test.js +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@create-lft-app/nextjs",
3
- "version": "2.0.1",
3
+ "version": "3.0.0",
4
4
  "description": "Next.js template para proyectos LFT con Midday Design System",
5
5
  "type": "module",
6
6
  "bin": {
@@ -12,6 +12,7 @@
12
12
  "!template/node_modules",
13
13
  "!template/.next",
14
14
  "!template/package-lock.json",
15
+ "!template/pnpm-lock.yaml",
15
16
  "!template/next-env.d.ts",
16
17
  "!template/.env*"
17
18
  ],
@@ -30,7 +31,7 @@
30
31
  "license": "MIT",
31
32
  "repository": {
32
33
  "type": "git",
33
- "url": "https://github.com/Test-Boiler/create-lft-nextjs"
34
+ "url": "https://github.com/somosdcg/next-boiler"
34
35
  },
35
36
  "publishConfig": {
36
37
  "access": "public"
@@ -0,0 +1,279 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## 🚨 CRITICAL: MANDATORY ARCHITECTURAL PATTERN 🚨
6
+
7
+ **⚠️ BEFORE WRITING ANY CODE, YOU MUST READ AND FOLLOW THIS PATTERN ⚠️**
8
+
9
+ This section is **NON-NEGOTIABLE** and MUST be followed in **100% of cases** when creating or modifying features in this codebase.
10
+
11
+ ## ⚠️ The Most Common Mistake (DON'T DO THIS!)
12
+
13
+ ```typescript
14
+ // ❌ WRONG - NEVER IMPORT MUTATIONS OR QUERIES DIRECTLY IN COMPONENTS
15
+ import { useEntityMutations } from '@/modules/[entity]/hooks/useEntityMutations'
16
+ import { useEntityQueries } from '@/modules/[entity]/hooks/useEntityQueries'
17
+
18
+ export function MyComponent() {
19
+ const { createEntity } = useEntityMutations() // ❌ ARCHITECTURAL VIOLATION
20
+ const { entities } = useEntityQueries() // ❌ ARCHITECTURAL VIOLATION
21
+ }
22
+
23
+ // ✅ CORRECT - ALWAYS USE THE UNIFIED HOOK
24
+ import { useEntity } from '@/modules/[entity]/hooks/useEntity'
25
+
26
+ export function MyComponent() {
27
+ const { createEntity, entities } = useEntity() // ✅ CORRECT PATTERN
28
+ }
29
+ ```
30
+
31
+ ## 🚨 MANDATORY Pattern: Store → Queries → Mutations → Unified Hook → Component
32
+
33
+ **THIS IS THE ONLY ACCEPTABLE ARCHITECTURE FOR THIS CODEBASE.**
34
+
35
+ Every module MUST follow this exact structure:
36
+
37
+ ```
38
+ modules/
39
+ └── [entity]/
40
+ ├── actions/
41
+ │ └── [entity]-actions.ts # Server actions with RLS
42
+ ├── components/
43
+ │ ├── [entity]-list.tsx # Component imports ONLY unified hook
44
+ │ ├── [entity]-form.tsx
45
+ │ └── [entity]-detail.tsx
46
+ ├── hooks/
47
+ │ ├── use[Entity]Queries.ts # TanStack Query (read operations)
48
+ │ ├── use[Entity]Mutations.ts # TanStack Mutations (write operations)
49
+ │ └── use[Entity].ts # UNIFIED HOOK (components use THIS)
50
+ ├── stores/
51
+ │ └── use[Entity]Store.ts # Zustand store (UI state only)
52
+ ├── schemas/
53
+ │ └── [entity].schema.ts # Zod validation schemas
54
+ ├── columns.tsx # TanStack Table column definitions (if needed)
55
+ └── index.ts # Barrel export
56
+ ```
57
+
58
+ ## 📋 Mandatory Implementation Checklist
59
+
60
+ Before writing ANY code, verify this checklist:
61
+
62
+ - [ ] **Step 1**: Create Drizzle schema in `db/schema/[entity].ts`
63
+ - [ ] **Step 2**: Create Zod schemas in `modules/[entity]/schemas/[entity].schema.ts`
64
+ - [ ] **Step 3**: Create Server actions in `modules/[entity]/actions/[entity]-actions.ts`
65
+ - [ ] **Step 4**: Create Zustand store with separate state/actions selectors using `useShallow` in `modules/[entity]/stores/`
66
+ - [ ] **Step 5**: Create Queries hook in `modules/[entity]/hooks/use[Entity]Queries.ts`
67
+ - [ ] **Step 6**: Create Mutations hook with cache invalidation in `modules/[entity]/hooks/use[Entity]Mutations.ts`
68
+ - [ ] **Step 7**: Create Unified hook that combines store + queries + mutations in `modules/[entity]/hooks/use[Entity].ts`
69
+ - [ ] **Step 8**: Components ONLY import the unified hook (NEVER queries/mutations directly)
70
+ - [ ] **Step 9**: Test with `pnpm typecheck && pnpm lint` before committing
71
+
72
+ ## 🔴 NEVER DO THIS (Anti-Patterns)
73
+
74
+ ```typescript
75
+ // ❌ NEVER: Import queries or mutations directly in components
76
+ import { useEntityQueries } from '@/modules/[entity]/hooks/useEntityQueries'
77
+ import { useEntityMutations } from '@/modules/[entity]/hooks/useEntityMutations'
78
+
79
+ // ❌ NEVER: Consume entire store (causes re-renders)
80
+ const store = useEntityStore()
81
+
82
+ // ❌ NEVER: Manual data fetching in useEffect
83
+ useEffect(() => {
84
+ fetch('/api/entities').then(setData)
85
+ }, [])
86
+
87
+ // ❌ NEVER: Server actions without authenticated user context (RLS won't work)
88
+ export async function deleteEntity(id: string) {
89
+ const supabase = createClient() // Anonymous client - RLS will fail!
90
+ await supabase.from('entities').delete().eq('id', id)
91
+ }
92
+ ```
93
+
94
+ ## ✅ ALWAYS DO THIS (Correct Patterns)
95
+
96
+ ```typescript
97
+ // ✅ ALWAYS: Use the unified hook in components
98
+ import { useEntity } from '@/modules/[entity]/hooks/useEntity'
99
+
100
+ // ✅ ALWAYS: Use separate selectors with useShallow
101
+ import { useEntityStore } from '@/modules/[entity]/stores/useEntityStore'
102
+ import { useShallow } from 'zustand/react/shallow'
103
+
104
+ const state = useEntityStore(useShallow((s) => s.state))
105
+ const actions = useEntityStore(useShallow((s) => s.actions))
106
+
107
+ // ✅ ALWAYS: Use TanStack Query for data fetching
108
+ const { data } = useQuery({ queryKey: ['entities'], queryFn: fetchEntities })
109
+
110
+ // ✅ ALWAYS: Use authenticated Supabase client in server actions (RLS enforced)
111
+ 'use server'
112
+
113
+ import { createClient } from '@/lib/supabase/server'
114
+
115
+ export async function deleteEntity(id: string) {
116
+ const supabase = await createClient() // Authenticated client with user context
117
+ const { data: { user } } = await supabase.auth.getUser()
118
+
119
+ if (!user) throw new Error('Unauthorized')
120
+
121
+ // RLS policies will automatically enforce authorization
122
+ const { error } = await supabase.from('entities').delete().eq('id', id)
123
+
124
+ if (error) throw error
125
+ }
126
+ ```
127
+
128
+ ## 📁 Complete Project Structure
129
+
130
+ ```
131
+ src/
132
+ ├── app/
133
+ │ ├── (auth)/ # Rutas autenticadas
134
+ │ │ ├── dashboard/
135
+ │ │ │ └── page.tsx
136
+ │ │ └── layout.tsx
137
+ │ ├── (public)/ # Rutas públicas
138
+ │ │ ├── login/
139
+ │ │ │ └── page.tsx
140
+ │ │ └── layout.tsx
141
+ │ ├── api/
142
+ │ │ └── webhooks/
143
+ │ │ └── route.ts
144
+ │ ├── layout.tsx
145
+ │ ├── page.tsx
146
+ │ └── providers.tsx
147
+
148
+ ├── modules/ # Feature-based modules
149
+ │ ├── auth/
150
+ │ │ ├── actions/
151
+ │ │ │ └── auth-actions.ts
152
+ │ │ ├── components/
153
+ │ │ │ └── login-form.tsx
154
+ │ │ ├── hooks/
155
+ │ │ │ ├── useAuthQueries.ts
156
+ │ │ │ ├── useAuthMutations.ts
157
+ │ │ │ └── useAuth.ts
158
+ │ │ ├── stores/
159
+ │ │ │ └── useAuthStore.ts
160
+ │ │ ├── schemas/
161
+ │ │ │ └── auth.schema.ts
162
+ │ │ └── index.ts
163
+ │ └── users/
164
+ │ ├── actions/
165
+ │ │ └── users-actions.ts
166
+ │ ├── components/
167
+ │ │ ├── users-list.tsx
168
+ │ │ ├── users-form.tsx
169
+ │ │ └── users-detail.tsx
170
+ │ ├── hooks/
171
+ │ │ ├── useUsersQueries.ts
172
+ │ │ ├── useUsersMutations.ts
173
+ │ │ └── useUsers.ts
174
+ │ ├── stores/
175
+ │ │ └── useUsersStore.ts
176
+ │ ├── schemas/
177
+ │ │ └── users.schema.ts
178
+ │ ├── columns.tsx
179
+ │ └── index.ts
180
+
181
+ ├── components/
182
+ │ ├── ui/ # Radix custom components
183
+ │ │ ├── button.tsx
184
+ │ │ ├── dialog.tsx
185
+ │ │ └── index.ts
186
+ │ ├── tables/ # TanStack Table components
187
+ │ │ ├── data-table.tsx
188
+ │ │ ├── data-table-pagination.tsx
189
+ │ │ ├── data-table-toolbar.tsx
190
+ │ │ ├── data-table-column-header.tsx
191
+ │ │ └── index.ts
192
+ │ ├── layout/
193
+ │ │ ├── header.tsx
194
+ │ │ └── sidebar.tsx
195
+ │ └── shared/
196
+ │ └── ...
197
+
198
+ ├── stores/ # Global Zustand stores
199
+ │ ├── useUiStore.ts
200
+ │ └── index.ts
201
+
202
+ ├── hooks/ # Global hooks
203
+ │ ├── useMediaQuery.ts
204
+ │ ├── useDebounce.ts
205
+ │ └── useDataTable.ts
206
+
207
+ ├── lib/
208
+ │ ├── supabase/
209
+ │ │ ├── client.ts
210
+ │ │ ├── server.ts
211
+ │ │ ├── proxy.ts
212
+ │ │ └── types.ts
213
+ │ ├── excel/
214
+ │ │ ├── parser.ts
215
+ │ │ ├── exporter.ts
216
+ │ │ └── index.ts
217
+ │ ├── date/
218
+ │ │ ├── config.ts
219
+ │ │ ├── formatters.ts
220
+ │ │ └── index.ts
221
+ │ ├── validations/
222
+ │ │ ├── common.ts
223
+ │ │ └── index.ts
224
+ │ ├── query-client.ts
225
+ │ └── utils.ts
226
+
227
+ ├── db/
228
+ │ ├── schema/
229
+ │ │ ├── users.ts
230
+ │ │ └── index.ts
231
+ │ ├── migrations/
232
+ │ ├── index.ts
233
+ │ └── seed.ts
234
+
235
+ ├── types/
236
+ │ ├── api.ts
237
+ │ ├── table.ts
238
+ │ └── index.ts
239
+
240
+ ├── config/
241
+ │ ├── site.ts
242
+ │ └── navigation.ts
243
+
244
+ └── styles/
245
+ └── globals.css
246
+
247
+ supabase/
248
+ ├── functions/
249
+ │ ├── process-excel/
250
+ │ │ └── index.ts
251
+ │ └── send-notification/
252
+ │ └── index.ts
253
+ ├── migrations/
254
+ └── config.toml
255
+
256
+ # Root files
257
+ ├── .env.local
258
+ ├── .env.example
259
+ ├── drizzle.config.ts
260
+ ├── proxy.ts
261
+ ├── next.config.ts
262
+ ├── package.json
263
+ ├── tsconfig.json
264
+ └── tailwind.config.ts
265
+ ```
266
+
267
+ ## 🛠️ Tech Stack
268
+
269
+ - **Framework**: Next.js 16 (App Router)
270
+ - **State Management**: Zustand 5
271
+ - **Data Fetching**: TanStack Query 5
272
+ - **Tables**: TanStack Table 8
273
+ - **Database**: Supabase + Drizzle ORM
274
+ - **Validation**: Zod
275
+ - **UI**: Radix UI + Tailwind CSS
276
+ - **Forms**: React Hook Form + Zod resolver
277
+ - **Excel**: xlsx (SheetJS)
278
+ - **Dates**: dayjs
279
+ - **Package Manager**: pnpm
@@ -0,0 +1,12 @@
1
+ import { defineConfig } from 'drizzle-kit'
2
+
3
+ export default defineConfig({
4
+ schema: './src/db/schema/index.ts',
5
+ out: './src/db/migrations',
6
+ dialect: 'postgresql',
7
+ dbCredentials: {
8
+ url: process.env.DATABASE_URL!,
9
+ },
10
+ verbose: true,
11
+ strict: true,
12
+ })
@@ -6,12 +6,18 @@
6
6
  "dev": "next dev --turbopack",
7
7
  "build": "next build",
8
8
  "start": "next start",
9
- "lint": "next lint"
9
+ "lint": "next lint",
10
+ "db:generate": "drizzle-kit generate",
11
+ "db:migrate": "drizzle-kit migrate",
12
+ "db:push": "drizzle-kit push",
13
+ "db:studio": "drizzle-kit studio",
14
+ "db:seed": "tsx src/db/seed.ts"
10
15
  },
11
16
  "dependencies": {
12
17
  "next": "^16.0.0",
13
18
  "react": "^19.0.0",
14
19
  "react-dom": "^19.0.0",
20
+
15
21
  "@radix-ui/react-accordion": "^1.2.0",
16
22
  "@radix-ui/react-alert-dialog": "^1.1.0",
17
23
  "@radix-ui/react-avatar": "^1.1.0",
@@ -31,21 +37,38 @@
31
37
  "@radix-ui/react-switch": "^1.1.0",
32
38
  "@radix-ui/react-tabs": "^1.1.0",
33
39
  "@radix-ui/react-tooltip": "^1.1.0",
40
+
34
41
  "class-variance-authority": "^0.7.0",
35
42
  "clsx": "^2.1.0",
36
43
  "tailwind-merge": "^2.5.0",
37
44
  "lucide-react": "^0.400.0",
45
+
38
46
  "react-hook-form": "^7.50.0",
39
47
  "@hookform/resolvers": "^3.9.0",
48
+ "zod": "^3.23.0",
49
+
40
50
  "cmdk": "^1.0.0",
41
- "react-day-picker": "^9.0.0",
42
- "date-fns": "^4.0.0",
43
51
  "sonner": "^1.5.0",
44
52
  "next-themes": "^0.4.0",
45
53
  "tw-animate-css": "^1.2.0",
46
- "zod": "^3.23.0",
54
+ "react-day-picker": "^9.4.0",
55
+
47
56
  "@supabase/supabase-js": "^2.45.0",
48
- "@supabase/ssr": "^0.5.0"
57
+ "@supabase/ssr": "^0.5.0",
58
+
59
+ "zustand": "^5.0.0",
60
+
61
+ "@tanstack/react-query": "^5.60.0",
62
+ "@tanstack/react-query-devtools": "^5.60.0",
63
+ "@tanstack/react-table": "^8.20.0",
64
+
65
+ "drizzle-orm": "^0.36.0",
66
+ "postgres": "^3.4.0",
67
+
68
+ "xlsx": "^0.18.5",
69
+ "dayjs": "^1.11.0",
70
+
71
+ "framer-motion": "^11.15.0"
49
72
  },
50
73
  "devDependencies": {
51
74
  "@types/node": "^22.0.0",
@@ -56,6 +79,8 @@
56
79
  "eslint-config-next": "^16.0.0",
57
80
  "tailwindcss": "^4.0.0",
58
81
  "@tailwindcss/postcss": "^4.0.0",
59
- "tailwindcss-animate": "^1.0.0"
82
+ "tailwindcss-animate": "^1.0.0",
83
+ "drizzle-kit": "^0.28.0",
84
+ "tsx": "^4.19.0"
60
85
  }
61
86
  }
@@ -0,0 +1,12 @@
1
+ import { type NextRequest } from 'next/server'
2
+ import { updateSession } from '@/lib/supabase/proxy'
3
+
4
+ export async function proxy(request: NextRequest) {
5
+ return await updateSession(request)
6
+ }
7
+
8
+ export const config = {
9
+ unstable_allowDynamic: [
10
+ '/node_modules/@supabase/**',
11
+ ],
12
+ }
@@ -0,0 +1,124 @@
1
+ 'use client'
2
+
3
+ import {
4
+ PageTransition,
5
+ PageHeader,
6
+ PageTitle,
7
+ PageDescription,
8
+ MotionDiv,
9
+ staggerContainer,
10
+ staggerItem,
11
+ } from '@/components/ui/animations'
12
+ import {
13
+ Card,
14
+ CardHeader,
15
+ CardTitle,
16
+ CardDescription,
17
+ CardContent,
18
+ } from '@/components/ui/card'
19
+ import { Users, FileText, TrendingUp, DollarSign } from 'lucide-react'
20
+
21
+ interface DashboardContentProps {
22
+ userEmail: string
23
+ }
24
+
25
+ const stats = [
26
+ {
27
+ title: 'Usuarios Totales',
28
+ value: '2,350',
29
+ description: '+180 este mes',
30
+ icon: Users,
31
+ },
32
+ {
33
+ title: 'Documentos',
34
+ value: '12,234',
35
+ description: '+1,234 esta semana',
36
+ icon: FileText,
37
+ },
38
+ {
39
+ title: 'Crecimiento',
40
+ value: '+23%',
41
+ description: 'vs mes anterior',
42
+ icon: TrendingUp,
43
+ },
44
+ {
45
+ title: 'Ingresos',
46
+ value: '$45,231',
47
+ description: '+20.1% este mes',
48
+ icon: DollarSign,
49
+ },
50
+ ]
51
+
52
+ export function DashboardContent({ userEmail }: DashboardContentProps) {
53
+ return (
54
+ <PageTransition className="flex flex-1 flex-col gap-6 p-6">
55
+ <PageHeader>
56
+ <PageTitle>Dashboard</PageTitle>
57
+ <PageDescription>Bienvenido, {userEmail}</PageDescription>
58
+ </PageHeader>
59
+
60
+ <MotionDiv
61
+ variants={staggerContainer}
62
+ initial="hidden"
63
+ animate="visible"
64
+ className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4"
65
+ >
66
+ {stats.map((stat) => (
67
+ <MotionDiv key={stat.title} variants={staggerItem}>
68
+ <Card className="h-full">
69
+ <CardHeader className="flex flex-row items-center justify-between pb-2">
70
+ <CardTitle className="text-sm font-medium">
71
+ {stat.title}
72
+ </CardTitle>
73
+ <stat.icon className="h-4 w-4 text-muted-foreground" />
74
+ </CardHeader>
75
+ <CardContent>
76
+ <div className="text-2xl font-bold">{stat.value}</div>
77
+ <CardDescription>{stat.description}</CardDescription>
78
+ </CardContent>
79
+ </Card>
80
+ </MotionDiv>
81
+ ))}
82
+ </MotionDiv>
83
+
84
+ <MotionDiv
85
+ variants={staggerContainer}
86
+ initial="hidden"
87
+ animate="visible"
88
+ className="grid grid-cols-1 lg:grid-cols-2 gap-4"
89
+ >
90
+ <MotionDiv variants={staggerItem}>
91
+ <Card className="h-[400px]">
92
+ <CardHeader>
93
+ <CardTitle>Actividad Reciente</CardTitle>
94
+ <CardDescription>
95
+ Últimas acciones en el sistema
96
+ </CardDescription>
97
+ </CardHeader>
98
+ <CardContent>
99
+ <div className="flex items-center justify-center h-[280px] text-muted-foreground">
100
+ Gráfico de actividad
101
+ </div>
102
+ </CardContent>
103
+ </Card>
104
+ </MotionDiv>
105
+
106
+ <MotionDiv variants={staggerItem}>
107
+ <Card className="h-[400px]">
108
+ <CardHeader>
109
+ <CardTitle>Resumen</CardTitle>
110
+ <CardDescription>
111
+ Estadísticas generales del período
112
+ </CardDescription>
113
+ </CardHeader>
114
+ <CardContent>
115
+ <div className="flex items-center justify-center h-[280px] text-muted-foreground">
116
+ Gráfico de resumen
117
+ </div>
118
+ </CardContent>
119
+ </Card>
120
+ </MotionDiv>
121
+ </MotionDiv>
122
+ </PageTransition>
123
+ )
124
+ }
@@ -0,0 +1,9 @@
1
+ import { createClient } from '@/lib/supabase/server'
2
+ import { DashboardContent } from './dashboard-content'
3
+
4
+ export default async function DashboardPage() {
5
+ const supabase = await createClient()
6
+ const { data: { user } } = await supabase.auth.getUser()
7
+
8
+ return <DashboardContent userEmail={user?.email ?? ''} />
9
+ }
@@ -0,0 +1,7 @@
1
+ export default function AuthLayout({
2
+ children,
3
+ }: {
4
+ children: React.ReactNode
5
+ }) {
6
+ return <>{children}</>
7
+ }
@@ -0,0 +1,9 @@
1
+ import { createClient } from '@/lib/supabase/server'
2
+ import { UsersContent } from './users-content'
3
+
4
+ export default async function UsersPage() {
5
+ const supabase = await createClient()
6
+ const { data: { user } } = await supabase.auth.getUser()
7
+
8
+ return <UsersContent userEmail={user?.email ?? ''} />
9
+ }
@@ -0,0 +1,26 @@
1
+ 'use client'
2
+
3
+ import {
4
+ PageTransition,
5
+ PageHeader,
6
+ PageTitle,
7
+ PageDescription,
8
+ } from '@/components/ui/animations'
9
+ import { UsersList } from '@/modules/users'
10
+
11
+ interface UsersContentProps {
12
+ userEmail: string
13
+ }
14
+
15
+ export function UsersContent({ userEmail }: UsersContentProps) {
16
+ return (
17
+ <PageTransition className="flex flex-1 flex-col gap-6 p-6">
18
+ <PageHeader>
19
+ <PageTitle>Usuarios</PageTitle>
20
+ <PageDescription>Gestión de usuarios del sistema</PageDescription>
21
+ </PageHeader>
22
+
23
+ <UsersList />
24
+ </PageTransition>
25
+ )
26
+ }
@@ -0,0 +1,7 @@
1
+ export default function PublicLayout({
2
+ children,
3
+ }: {
4
+ children: React.ReactNode
5
+ }) {
6
+ return <>{children}</>
7
+ }
@@ -0,0 +1,17 @@
1
+ import { LoginForm } from '@/modules/auth/components/login-form'
2
+
3
+ export default function LoginPage() {
4
+ return (
5
+ <div className="flex min-h-screen items-center justify-center">
6
+ <div className="w-full max-w-md space-y-8 px-4">
7
+ <div className="text-center">
8
+ <h1 className="text-2xl font-bold">Iniciar sesión</h1>
9
+ <p className="mt-2 text-muted-foreground">
10
+ Ingresa tus credenciales para acceder
11
+ </p>
12
+ </div>
13
+ <LoginForm />
14
+ </div>
15
+ </div>
16
+ )
17
+ }
@@ -0,0 +1,20 @@
1
+ import { NextRequest, NextResponse } from 'next/server'
2
+
3
+ export async function POST(request: NextRequest) {
4
+ try {
5
+ const body = await request.json()
6
+
7
+ // Verificar firma del webhook aquí
8
+ // const signature = request.headers.get('x-webhook-signature')
9
+
10
+ console.log('Webhook received:', body)
11
+
12
+ return NextResponse.json({ received: true })
13
+ } catch (error) {
14
+ console.error('Webhook error:', error)
15
+ return NextResponse.json(
16
+ { error: 'Webhook processing failed' },
17
+ { status: 500 }
18
+ )
19
+ }
20
+ }
@@ -1,10 +1,10 @@
1
1
  import type { Metadata } from "next"
2
2
  import { Inter } from "next/font/google"
3
3
  import "./globals.css"
4
+ import { Providers } from "./providers"
4
5
  import { SidebarProvider } from "@/components/layout/sidebar-context"
5
- import { Sidebar } from "@/components/layout/midday-sidebar"
6
+ import { Sidebar } from "@/components/layout/sidebar"
6
7
  import { MainContent } from "@/components/layout/main-content"
7
- import { Toaster } from "@/components/ui/sonner"
8
8
 
9
9
  const inter = Inter({ subsets: ["latin"] })
10
10
 
@@ -19,17 +19,18 @@ export default function RootLayout({
19
19
  children: React.ReactNode
20
20
  }) {
21
21
  return (
22
- <html lang="es" className="dark" suppressHydrationWarning>
22
+ <html lang="es" suppressHydrationWarning>
23
23
  <body className={`${inter.className} font-sans antialiased`}>
24
- <SidebarProvider>
25
- <div className="min-h-screen bg-background flex">
26
- <Sidebar />
27
- <MainContent>
28
- {children}
29
- </MainContent>
30
- </div>
31
- </SidebarProvider>
32
- <Toaster />
24
+ <Providers>
25
+ <SidebarProvider>
26
+ <div className="min-h-screen bg-background flex">
27
+ <Sidebar />
28
+ <MainContent>
29
+ {children}
30
+ </MainContent>
31
+ </div>
32
+ </SidebarProvider>
33
+ </Providers>
33
34
  </body>
34
35
  </html>
35
36
  )