wexts 4.1.0 → 4.1.5

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 (199) hide show
  1. package/README.md +49 -49
  2. package/bin/wexts.cjs +2 -2
  3. package/package.json +153 -148
  4. package/templates/.dockerignore +43 -43
  5. package/templates/.env.example +17 -17
  6. package/templates/Dockerfile +60 -60
  7. package/templates/Procfile +1 -1
  8. package/templates/README.md +67 -67
  9. package/templates/api-sdk.ts +115 -115
  10. package/templates/docker-compose.yml +34 -34
  11. package/templates/nestjs-api/.env.example +3 -3
  12. package/templates/nestjs-api/README.md +87 -87
  13. package/templates/nestjs-api/nest-cli.json +6 -6
  14. package/templates/nestjs-api/package.json +40 -40
  15. package/templates/nestjs-api/prisma/migrations/20251123205437_init/migration.sql +24 -24
  16. package/templates/nestjs-api/prisma/migrations/migration_lock.toml +3 -3
  17. package/templates/nestjs-api/prisma/schema.prisma +29 -29
  18. package/templates/nestjs-api/src/app.module.ts +17 -17
  19. package/templates/nestjs-api/src/auth/auth.controller.ts +27 -27
  20. package/templates/nestjs-api/src/auth/auth.module.ts +37 -37
  21. package/templates/nestjs-api/src/auth/auth.service.ts +86 -86
  22. package/templates/nestjs-api/src/auth/dto/auth.dto.ts +22 -22
  23. package/templates/nestjs-api/src/auth/guards/jwt-auth.guard.ts +5 -5
  24. package/templates/nestjs-api/src/auth/strategies/jwt.strategy.ts +27 -27
  25. package/templates/nestjs-api/src/main.ts +32 -32
  26. package/templates/nestjs-api/src/prisma/prisma.module.ts +9 -9
  27. package/templates/nestjs-api/src/prisma/prisma.service.ts +14 -14
  28. package/templates/nestjs-api/src/todos/dto/todo.dto.ts +24 -24
  29. package/templates/nestjs-api/src/todos/todos.controller.ts +39 -39
  30. package/templates/nestjs-api/src/todos/todos.module.ts +11 -11
  31. package/templates/nestjs-api/src/todos/todos.service.ts +53 -53
  32. package/templates/nestjs-api/src/users/users.controller.ts +14 -14
  33. package/templates/nestjs-api/src/users/users.module.ts +12 -12
  34. package/templates/nestjs-api/src/users/users.service.ts +19 -19
  35. package/templates/nestjs-api/tsconfig.json +39 -39
  36. package/templates/nextjs-web/README.md +76 -76
  37. package/templates/nextjs-web/app/actions/auth.ts +108 -108
  38. package/templates/nextjs-web/app/dashboard/error.tsx +39 -39
  39. package/templates/nextjs-web/app/dashboard/loading.tsx +14 -14
  40. package/templates/nextjs-web/app/dashboard/page.tsx +5 -5
  41. package/templates/nextjs-web/app/globals.css +93 -93
  42. package/templates/nextjs-web/app/layout.tsx +29 -29
  43. package/templates/nextjs-web/app/login/page.tsx +5 -5
  44. package/templates/nextjs-web/app/page.tsx +28 -28
  45. package/templates/nextjs-web/app/register/page.tsx +5 -5
  46. package/templates/nextjs-web/components/ui/button.tsx +56 -56
  47. package/templates/nextjs-web/components/ui/card.tsx +79 -79
  48. package/templates/nextjs-web/components/ui/input.tsx +25 -25
  49. package/templates/nextjs-web/components/ui/label.tsx +24 -24
  50. package/templates/nextjs-web/features/auth/LoginForm.tsx +140 -140
  51. package/templates/nextjs-web/features/auth/RegisterForm.tsx +159 -159
  52. package/templates/nextjs-web/features/auth/api.ts +35 -35
  53. package/templates/nextjs-web/features/auth/index.ts +3 -3
  54. package/templates/nextjs-web/features/dashboard/DashboardView.tsx +204 -204
  55. package/templates/nextjs-web/features/dashboard/api.ts +9 -9
  56. package/templates/nextjs-web/features/dashboard/components.tsx +74 -74
  57. package/templates/nextjs-web/features/dashboard/index.ts +3 -3
  58. package/templates/nextjs-web/hooks/index.ts +4 -4
  59. package/templates/nextjs-web/lib/api-client.ts +89 -89
  60. package/templates/nextjs-web/lib/api.ts +115 -115
  61. package/templates/nextjs-web/lib/axios-global-config.ts +17 -17
  62. package/templates/nextjs-web/lib/utils.ts +6 -6
  63. package/templates/nextjs-web/lib/wexts-client.ts +4 -4
  64. package/templates/nextjs-web/next-env.d.ts +6 -6
  65. package/templates/nextjs-web/next.config.ts +20 -20
  66. package/templates/nextjs-web/package.json +37 -37
  67. package/templates/nextjs-web/postcss.config.js +6 -6
  68. package/templates/nextjs-web/tailwind.config.ts +69 -69
  69. package/templates/nextjs-web/tsconfig.json +41 -41
  70. package/templates/nixpacks.toml +11 -11
  71. package/templates/root-package.json +31 -31
  72. package/templates/server.ts +66 -66
  73. package/templates/tsconfig.json +30 -30
  74. package/dist/chunk-2KAQYLVN.js +0 -1
  75. package/dist/chunk-2KAQYLVN.js.map +0 -1
  76. package/dist/chunk-2LJVUMXW.js +0 -228
  77. package/dist/chunk-2LJVUMXW.js.map +0 -1
  78. package/dist/chunk-342VRT25.mjs +0 -504
  79. package/dist/chunk-342VRT25.mjs.map +0 -1
  80. package/dist/chunk-7HNQWJWV.js +0 -504
  81. package/dist/chunk-7HNQWJWV.js.map +0 -1
  82. package/dist/chunk-7QKLIVRF.js +0 -94
  83. package/dist/chunk-7QKLIVRF.js.map +0 -1
  84. package/dist/chunk-7SSCNCTW.mjs +0 -137
  85. package/dist/chunk-7SSCNCTW.mjs.map +0 -1
  86. package/dist/chunk-7TLSPR65.mjs +0 -95
  87. package/dist/chunk-7TLSPR65.mjs.map +0 -1
  88. package/dist/chunk-7WULUGLH.mjs +0 -22
  89. package/dist/chunk-7WULUGLH.mjs.map +0 -1
  90. package/dist/chunk-AVMQJWYD.js +0 -95
  91. package/dist/chunk-AVMQJWYD.js.map +0 -1
  92. package/dist/chunk-BG56B4DE.js +0 -106
  93. package/dist/chunk-BG56B4DE.js.map +0 -1
  94. package/dist/chunk-CLM5PNSG.mjs +0 -496
  95. package/dist/chunk-CLM5PNSG.mjs.map +0 -1
  96. package/dist/chunk-DNLGCKTT.js +0 -31
  97. package/dist/chunk-DNLGCKTT.js.map +0 -1
  98. package/dist/chunk-JHOVXH3X.mjs +0 -65
  99. package/dist/chunk-JHOVXH3X.mjs.map +0 -1
  100. package/dist/chunk-MXINIFPC.js +0 -105
  101. package/dist/chunk-MXINIFPC.js.map +0 -1
  102. package/dist/chunk-O4II6N34.js +0 -137
  103. package/dist/chunk-O4II6N34.js.map +0 -1
  104. package/dist/chunk-SE32ZPOZ.js +0 -496
  105. package/dist/chunk-SE32ZPOZ.js.map +0 -1
  106. package/dist/chunk-UAL54DVV.mjs +0 -106
  107. package/dist/chunk-UAL54DVV.mjs.map +0 -1
  108. package/dist/chunk-WCKSKU3C.js +0 -65
  109. package/dist/chunk-WCKSKU3C.js.map +0 -1
  110. package/dist/chunk-WU6FW77M.mjs +0 -105
  111. package/dist/chunk-WU6FW77M.mjs.map +0 -1
  112. package/dist/chunk-XE4OXN2W.js +0 -12
  113. package/dist/chunk-XE4OXN2W.js.map +0 -1
  114. package/dist/chunk-YBM3IJEA.mjs +0 -94
  115. package/dist/chunk-YBM3IJEA.mjs.map +0 -1
  116. package/dist/chunk-YN6WIWNQ.mjs +0 -228
  117. package/dist/chunk-YN6WIWNQ.mjs.map +0 -1
  118. package/dist/chunk-YSLEF5C5.mjs +0 -1
  119. package/dist/chunk-YSLEF5C5.mjs.map +0 -1
  120. package/dist/chunk-ZX7QIN24.mjs +0 -31
  121. package/dist/chunk-ZX7QIN24.mjs.map +0 -1
  122. package/dist/cli/index.d.mts +0 -23
  123. package/dist/cli/index.d.ts +0 -23
  124. package/dist/cli/index.js +0 -716
  125. package/dist/cli/index.js.map +0 -1
  126. package/dist/cli/index.mjs +0 -718
  127. package/dist/cli/index.mjs.map +0 -1
  128. package/dist/client/index.d.mts +0 -21
  129. package/dist/client/index.d.ts +0 -21
  130. package/dist/client/index.js +0 -13
  131. package/dist/client/index.js.map +0 -1
  132. package/dist/client/index.mjs +0 -13
  133. package/dist/client/index.mjs.map +0 -1
  134. package/dist/codegen/index.d.mts +0 -2
  135. package/dist/codegen/index.d.ts +0 -2
  136. package/dist/codegen/index.js +0 -16
  137. package/dist/codegen/index.js.map +0 -1
  138. package/dist/codegen/index.mjs +0 -16
  139. package/dist/codegen/index.mjs.map +0 -1
  140. package/dist/decorators-BT1FFqN0.d.mts +0 -29
  141. package/dist/decorators-DvS58PqC.d.ts +0 -29
  142. package/dist/dev-server/index.d.mts +0 -1
  143. package/dist/dev-server/index.d.ts +0 -1
  144. package/dist/dev-server/index.js +0 -13
  145. package/dist/dev-server/index.js.map +0 -1
  146. package/dist/dev-server/index.mjs +0 -13
  147. package/dist/dev-server/index.mjs.map +0 -1
  148. package/dist/index-7QeQEf37.d.ts +0 -92
  149. package/dist/index-7RvU-jGE.d.mts +0 -66
  150. package/dist/index-7RvU-jGE.d.ts +0 -66
  151. package/dist/index-8nzxy0NN.d.mts +0 -92
  152. package/dist/index-Co5ZsLqq.d.ts +0 -58
  153. package/dist/index-D94W1__r.d.mts +0 -58
  154. package/dist/index-DQmyVp6F.d.mts +0 -27
  155. package/dist/index-KL_1BrQb.d.ts +0 -27
  156. package/dist/index.d.mts +0 -294
  157. package/dist/index.d.ts +0 -294
  158. package/dist/index.js +0 -424
  159. package/dist/index.js.map +0 -1
  160. package/dist/index.mjs +0 -424
  161. package/dist/index.mjs.map +0 -1
  162. package/dist/nest/index.d.mts +0 -3
  163. package/dist/nest/index.d.ts +0 -3
  164. package/dist/nest/index.js +0 -38
  165. package/dist/nest/index.js.map +0 -1
  166. package/dist/nest/index.mjs +0 -38
  167. package/dist/nest/index.mjs.map +0 -1
  168. package/dist/next/index.d.mts +0 -66
  169. package/dist/next/index.d.ts +0 -66
  170. package/dist/next/index.js +0 -289
  171. package/dist/next/index.js.map +0 -1
  172. package/dist/next/index.mjs +0 -251
  173. package/dist/next/index.mjs.map +0 -1
  174. package/dist/rpc/index.d.mts +0 -2
  175. package/dist/rpc/index.d.ts +0 -2
  176. package/dist/rpc/index.js +0 -23
  177. package/dist/rpc/index.js.map +0 -1
  178. package/dist/rpc/index.mjs +0 -23
  179. package/dist/rpc/index.mjs.map +0 -1
  180. package/dist/runtime/index.d.mts +0 -55
  181. package/dist/runtime/index.d.ts +0 -55
  182. package/dist/runtime/index.js +0 -221
  183. package/dist/runtime/index.js.map +0 -1
  184. package/dist/runtime/index.mjs +0 -221
  185. package/dist/runtime/index.mjs.map +0 -1
  186. package/dist/types/index.d.mts +0 -12
  187. package/dist/types/index.d.ts +0 -12
  188. package/dist/types/index.js +0 -2
  189. package/dist/types/index.js.map +0 -1
  190. package/dist/types/index.mjs +0 -3
  191. package/dist/types/index.mjs.map +0 -1
  192. package/dist/types-7d_fC-C3.d.mts +0 -32
  193. package/dist/types-7d_fC-C3.d.ts +0 -32
  194. package/dist/vercel-builder/index.d.mts +0 -58
  195. package/dist/vercel-builder/index.d.ts +0 -58
  196. package/dist/vercel-builder/index.js +0 -330
  197. package/dist/vercel-builder/index.js.map +0 -1
  198. package/dist/vercel-builder/index.mjs +0 -330
  199. package/dist/vercel-builder/index.mjs.map +0 -1
@@ -1,76 +1,76 @@
1
- # Deprecated Legacy Web Template
2
-
3
- This template predates the verified `examples/hello-rpc` runtime/RPC/security model. It is retained for compatibility and should not be used as the production reference.
4
-
5
- Use `examples/hello-rpc` for the canonical generated-RPC path.
6
-
7
- ---
8
-
9
- # Fusion Next.js Web
10
-
11
- Modern Next.js 16 frontend with wexts integration.
12
-
13
- ## Features
14
-
15
- - ✅ Next.js 16 (App Router)
16
- - ✅ React 19
17
- - ✅ Tailwind CSS v4
18
- - ✅ TypeScript
19
- - ✅ wexts Provider & Hooks
20
- - ✅ Authentication Flow
21
- - ✅ Todo Management Dashboard
22
-
23
- ## Setup
24
-
25
- ```bash
26
- # Install dependencies
27
- npm install
28
-
29
- # Copy environment variables
30
- cp .env.local.example .env.local
31
-
32
- # Update NEXT_PUBLIC_API_URL in .env.local to point to your API
33
-
34
- # Start development server
35
- npm run dev
36
- ```
37
-
38
- ## Project Structure
39
-
40
- ```
41
- app/
42
- ├── layout.tsx # Root layout with FusionProvider
43
- ├── page.tsx # Homepage with auth redirect
44
- ├── globals.css # Global styles
45
- ├── login/
46
- │ └── page.tsx # Login page
47
- ├── register/
48
- │ └── page.tsx # Registration page
49
- └── dashboard/
50
- └── page.tsx # Protected dashboard with todos
51
- ```
52
-
53
- ## Using Fusion Hooks
54
-
55
- ```tsx
56
- import { useFusion, useAuth } from 'wexts/next';
57
-
58
- function MyComponent() {
59
- const { client } = useFusion();
60
- const { user, isAuthenticated } = useAuth();
61
-
62
- // Make API calls
63
- const data = await client.get('/endpoint');
64
- }
65
- ```
66
-
67
- ## Building for Production
68
-
69
- ```bash
70
- npm run build
71
- npm start
72
- ```
73
-
74
- ## Environment Variables
75
-
76
- - `NEXT_PUBLIC_API_URL` - Backend API URL (default: http://localhost:5050)
1
+ # Deprecated Legacy Web Template
2
+
3
+ This template predates the verified `examples/hello-rpc` runtime/RPC/security model. It is retained for compatibility and should not be used as the production reference.
4
+
5
+ Use `examples/hello-rpc` for the canonical generated-RPC path.
6
+
7
+ ---
8
+
9
+ # Fusion Next.js Web
10
+
11
+ Modern Next.js 16 frontend with wexts integration.
12
+
13
+ ## Features
14
+
15
+ - ✅ Next.js 16 (App Router)
16
+ - ✅ React 19
17
+ - ✅ Tailwind CSS v4
18
+ - ✅ TypeScript
19
+ - ✅ wexts Provider & Hooks
20
+ - ✅ Authentication Flow
21
+ - ✅ Todo Management Dashboard
22
+
23
+ ## Setup
24
+
25
+ ```bash
26
+ # Install dependencies
27
+ npm install
28
+
29
+ # Copy environment variables
30
+ cp .env.local.example .env.local
31
+
32
+ # Update NEXT_PUBLIC_API_URL in .env.local to point to your API
33
+
34
+ # Start development server
35
+ npm run dev
36
+ ```
37
+
38
+ ## Project Structure
39
+
40
+ ```
41
+ app/
42
+ ├── layout.tsx # Root layout with FusionProvider
43
+ ├── page.tsx # Homepage with auth redirect
44
+ ├── globals.css # Global styles
45
+ ├── login/
46
+ │ └── page.tsx # Login page
47
+ ├── register/
48
+ │ └── page.tsx # Registration page
49
+ └── dashboard/
50
+ └── page.tsx # Protected dashboard with todos
51
+ ```
52
+
53
+ ## Using Fusion Hooks
54
+
55
+ ```tsx
56
+ import { useFusion, useAuth } from 'wexts/next';
57
+
58
+ function MyComponent() {
59
+ const { client } = useFusion();
60
+ const { user, isAuthenticated } = useAuth();
61
+
62
+ // Make API calls
63
+ const data = await client.get('/endpoint');
64
+ }
65
+ ```
66
+
67
+ ## Building for Production
68
+
69
+ ```bash
70
+ npm run build
71
+ npm start
72
+ ```
73
+
74
+ ## Environment Variables
75
+
76
+ - `NEXT_PUBLIC_API_URL` - Backend API URL (default: http://localhost:5050)
@@ -1,108 +1,108 @@
1
- 'use server';
2
-
3
- import { cookies } from 'next/headers';
4
- import { redirect } from 'next/navigation';
5
- import { api } from '@/lib/api';
6
-
7
- export type ActionState = {
8
- message?: string;
9
- errors?: {
10
- email?: string[];
11
- password?: string[];
12
- };
13
- };
14
-
15
- export async function loginAction(prevState: ActionState, formData: FormData): Promise<ActionState> {
16
- const email = formData.get('email') as string;
17
- const password = formData.get('password') as string;
18
-
19
- const errors: { email?: string[]; password?: string[] } = {};
20
-
21
- if (!email || !email.includes('@')) {
22
- errors.email = ['Invalid email address'];
23
- }
24
-
25
- if (!password || password.length < 6) {
26
- errors.password = ['Password must be at least 6 characters'];
27
- }
28
-
29
- if (Object.keys(errors).length > 0) {
30
- return { errors };
31
- }
32
-
33
- try {
34
- // Legacy SDK call retained for deprecated template compatibility.
35
- const data = await api.auth.login({ email, password });
36
-
37
- // Store JWT token
38
- if (data.access_token) {
39
- const cookieStore = await cookies();
40
- cookieStore.set('wexts_token', data.access_token, {
41
- httpOnly: true,
42
- secure: process.env.NODE_ENV === 'production',
43
- maxAge: 60 * 60 * 24 * 7, // 1 week
44
- path: '/',
45
- });
46
- } else {
47
- return {
48
- message: 'Login failed: No token received',
49
- };
50
- }
51
- } catch (error: any) {
52
- console.error('Login error:', error);
53
- return {
54
- message: error.message || 'Invalid credentials',
55
- };
56
- }
57
-
58
- redirect('/dashboard');
59
- }
60
-
61
- export async function registerAction(prevState: ActionState, formData: FormData): Promise<ActionState> {
62
- const email = formData.get('email') as string;
63
- const password = formData.get('password') as string;
64
- const name = formData.get('name') as string;
65
-
66
- const errors: { email?: string[]; password?: string[] } = {};
67
-
68
- if (!email || !email.includes('@')) {
69
- errors.email = ['Invalid email address'];
70
- }
71
-
72
- if (!password || password.length < 6) {
73
- errors.password = ['Password must be at least 6 characters'];
74
- }
75
-
76
- if (Object.keys(errors).length > 0) {
77
- return { errors };
78
- }
79
-
80
- try {
81
- // Legacy SDK call retained for deprecated template compatibility.
82
- const data = await api.auth.register({ email, password, name });
83
-
84
- // Store JWT token
85
- if (data.access_token) {
86
- const cookieStore = await cookies();
87
- cookieStore.set('wexts_token', data.access_token, {
88
- httpOnly: true,
89
- secure: process.env.NODE_ENV === 'production',
90
- maxAge: 60 * 60 * 24 * 7,
91
- path: '/',
92
- });
93
- }
94
- } catch (error: any) {
95
- console.error('Register error:', error);
96
- return {
97
- message: error.message || 'Registration failed',
98
- };
99
- }
100
-
101
- redirect('/dashboard');
102
- }
103
-
104
- export async function logoutAction() {
105
- const cookieStore = await cookies();
106
- cookieStore.delete('wexts_token');
107
- redirect('/login');
108
- }
1
+ 'use server';
2
+
3
+ import { cookies } from 'next/headers';
4
+ import { redirect } from 'next/navigation';
5
+ import { api } from '@/lib/api';
6
+
7
+ export type ActionState = {
8
+ message?: string;
9
+ errors?: {
10
+ email?: string[];
11
+ password?: string[];
12
+ };
13
+ };
14
+
15
+ export async function loginAction(prevState: ActionState, formData: FormData): Promise<ActionState> {
16
+ const email = formData.get('email') as string;
17
+ const password = formData.get('password') as string;
18
+
19
+ const errors: { email?: string[]; password?: string[] } = {};
20
+
21
+ if (!email || !email.includes('@')) {
22
+ errors.email = ['Invalid email address'];
23
+ }
24
+
25
+ if (!password || password.length < 6) {
26
+ errors.password = ['Password must be at least 6 characters'];
27
+ }
28
+
29
+ if (Object.keys(errors).length > 0) {
30
+ return { errors };
31
+ }
32
+
33
+ try {
34
+ // Legacy SDK call retained for deprecated template compatibility.
35
+ const data = await api.auth.login({ email, password });
36
+
37
+ // Store JWT token
38
+ if (data.access_token) {
39
+ const cookieStore = await cookies();
40
+ cookieStore.set('wexts_token', data.access_token, {
41
+ httpOnly: true,
42
+ secure: process.env.NODE_ENV === 'production',
43
+ maxAge: 60 * 60 * 24 * 7, // 1 week
44
+ path: '/',
45
+ });
46
+ } else {
47
+ return {
48
+ message: 'Login failed: No token received',
49
+ };
50
+ }
51
+ } catch (error: any) {
52
+ console.error('Login error:', error);
53
+ return {
54
+ message: error.message || 'Invalid credentials',
55
+ };
56
+ }
57
+
58
+ redirect('/dashboard');
59
+ }
60
+
61
+ export async function registerAction(prevState: ActionState, formData: FormData): Promise<ActionState> {
62
+ const email = formData.get('email') as string;
63
+ const password = formData.get('password') as string;
64
+ const name = formData.get('name') as string;
65
+
66
+ const errors: { email?: string[]; password?: string[] } = {};
67
+
68
+ if (!email || !email.includes('@')) {
69
+ errors.email = ['Invalid email address'];
70
+ }
71
+
72
+ if (!password || password.length < 6) {
73
+ errors.password = ['Password must be at least 6 characters'];
74
+ }
75
+
76
+ if (Object.keys(errors).length > 0) {
77
+ return { errors };
78
+ }
79
+
80
+ try {
81
+ // Legacy SDK call retained for deprecated template compatibility.
82
+ const data = await api.auth.register({ email, password, name });
83
+
84
+ // Store JWT token
85
+ if (data.access_token) {
86
+ const cookieStore = await cookies();
87
+ cookieStore.set('wexts_token', data.access_token, {
88
+ httpOnly: true,
89
+ secure: process.env.NODE_ENV === 'production',
90
+ maxAge: 60 * 60 * 24 * 7,
91
+ path: '/',
92
+ });
93
+ }
94
+ } catch (error: any) {
95
+ console.error('Register error:', error);
96
+ return {
97
+ message: error.message || 'Registration failed',
98
+ };
99
+ }
100
+
101
+ redirect('/dashboard');
102
+ }
103
+
104
+ export async function logoutAction() {
105
+ const cookieStore = await cookies();
106
+ cookieStore.delete('wexts_token');
107
+ redirect('/login');
108
+ }
@@ -1,39 +1,39 @@
1
- 'use client';
2
-
3
- import { useEffect } from 'react';
4
- import { Button } from '@/components/ui/button';
5
- import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
6
- import { AlertTriangle } from 'lucide-react';
7
-
8
- export default function DashboardError({
9
- error,
10
- reset,
11
- }: {
12
- error: Error & { digest?: string };
13
- reset: () => void;
14
- }) {
15
- useEffect(() => {
16
- console.error(error);
17
- }, [error]);
18
-
19
- return (
20
- <div className="min-h-screen bg-background flex items-center justify-center p-8">
21
- <Card className="glass border-destructive/20 max-w-md w-full">
22
- <CardHeader>
23
- <CardTitle className="text-destructive flex items-center gap-2">
24
- <AlertTriangle className="w-5 h-5" />
25
- Something went wrong
26
- </CardTitle>
27
- </CardHeader>
28
- <CardContent className="space-y-4">
29
- <p className="text-muted-foreground">
30
- We encountered an error while loading your dashboard. Please try again.
31
- </p>
32
- <Button onClick={reset} className="w-full">
33
- Try again
34
- </Button>
35
- </CardContent>
36
- </Card>
37
- </div>
38
- );
39
- }
1
+ 'use client';
2
+
3
+ import { useEffect } from 'react';
4
+ import { Button } from '@/components/ui/button';
5
+ import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
6
+ import { AlertTriangle } from 'lucide-react';
7
+
8
+ export default function DashboardError({
9
+ error,
10
+ reset,
11
+ }: {
12
+ error: Error & { digest?: string };
13
+ reset: () => void;
14
+ }) {
15
+ useEffect(() => {
16
+ console.error(error);
17
+ }, [error]);
18
+
19
+ return (
20
+ <div className="min-h-screen bg-background flex items-center justify-center p-8">
21
+ <Card className="glass border-destructive/20 max-w-md w-full">
22
+ <CardHeader>
23
+ <CardTitle className="text-destructive flex items-center gap-2">
24
+ <AlertTriangle className="w-5 h-5" />
25
+ Something went wrong
26
+ </CardTitle>
27
+ </CardHeader>
28
+ <CardContent className="space-y-4">
29
+ <p className="text-muted-foreground">
30
+ We encountered an error while loading your dashboard. Please try again.
31
+ </p>
32
+ <Button onClick={reset} className="w-full">
33
+ Try again
34
+ </Button>
35
+ </CardContent>
36
+ </Card>
37
+ </div>
38
+ );
39
+ }
@@ -1,14 +1,14 @@
1
- import { Loader2 } from 'lucide-react';
2
-
3
- export default function DashboardLoading() {
4
- return (
5
- <div className="min-h-screen bg-background flex items-center justify-center">
6
- <div className="text-center space-y-4">
7
- <div className="inline-flex items-center justify-center w-16 h-16 rounded-2xl bg-primary/10 text-primary animate-pulse">
8
- <Loader2 className="w-8 h-8 animate-spin" />
9
- </div>
10
- <p className="text-muted-foreground animate-pulse">Loading dashboard...</p>
11
- </div>
12
- </div>
13
- );
14
- }
1
+ import { Loader2 } from 'lucide-react';
2
+
3
+ export default function DashboardLoading() {
4
+ return (
5
+ <div className="min-h-screen bg-background flex items-center justify-center">
6
+ <div className="text-center space-y-4">
7
+ <div className="inline-flex items-center justify-center w-16 h-16 rounded-2xl bg-primary/10 text-primary animate-pulse">
8
+ <Loader2 className="w-8 h-8 animate-spin" />
9
+ </div>
10
+ <p className="text-muted-foreground animate-pulse">Loading dashboard...</p>
11
+ </div>
12
+ </div>
13
+ );
14
+ }
@@ -1,5 +1,5 @@
1
- import { DashboardView } from '@/features/dashboard';
2
-
3
- export default function DashboardPage() {
4
- return <DashboardView />;
5
- }
1
+ import { DashboardView } from '@/features/dashboard';
2
+
3
+ export default function DashboardPage() {
4
+ return <DashboardView />;
5
+ }
@@ -1,93 +1,93 @@
1
- @tailwind base;
2
- @tailwind components;
3
- @tailwind utilities;
4
-
5
- @layer base {
6
- :root {
7
- /* Brand Colors - Deep Violet & Electric Purple */
8
- --background: 260 30% 98%;
9
- --foreground: 260 40% 10%;
10
-
11
- --primary: 265 89% 66%;
12
- --primary-foreground: 210 40% 98%;
13
-
14
- --secondary: 260 20% 90%;
15
- --secondary-foreground: 260 40% 10%;
16
-
17
- --muted: 260 20% 96%;
18
- --muted-foreground: 260 20% 40%;
19
-
20
- --accent: 265 89% 96%;
21
- --accent-foreground: 265 89% 66%;
22
-
23
- --destructive: 0 84% 60%;
24
- --destructive-foreground: 210 40% 98%;
25
-
26
- --border: 260 20% 90%;
27
- --input: 260 20% 90%;
28
- --ring: 265 89% 66%;
29
-
30
- --radius: 1rem;
31
- }
32
-
33
- .dark {
34
- --background: 260 40% 5%;
35
- --foreground: 210 40% 98%;
36
-
37
- --primary: 265 89% 66%;
38
- --primary-foreground: 210 40% 98%;
39
-
40
- --secondary: 260 30% 15%;
41
- --secondary-foreground: 210 40% 98%;
42
-
43
- --muted: 260 30% 15%;
44
- --muted-foreground: 215 20% 65%;
45
-
46
- --accent: 260 30% 15%;
47
- --accent-foreground: 210 40% 98%;
48
-
49
- --destructive: 0 62% 30%;
50
- --destructive-foreground: 210 40% 98%;
51
-
52
- --border: 260 30% 15%;
53
- --input: 260 30% 15%;
54
- --ring: 265 89% 66%;
55
- }
56
- }
57
-
58
- @layer base {
59
- * {
60
- @apply border-border;
61
- }
62
- body {
63
- @apply bg-background text-foreground antialiased;
64
- font-feature-settings: "rlig" 1, "calt" 1;
65
- }
66
- }
67
-
68
- @layer utilities {
69
- .glass {
70
- @apply bg-white/10 backdrop-blur-lg border border-white/20 shadow-xl;
71
- }
72
- .glass-dark {
73
- @apply bg-black/30 backdrop-blur-lg border border-white/10 shadow-xl;
74
- }
75
-
76
- .text-gradient {
77
- @apply bg-clip-text text-transparent bg-gradient-to-r from-violet-600 to-indigo-600 dark:from-violet-400 dark:to-indigo-400;
78
- }
79
-
80
- .animate-float {
81
- animation: float 6s ease-in-out infinite;
82
- }
83
-
84
- .animate-pulse-slow {
85
- animation: pulse 4s cubic-bezier(0.4, 0, 0.6, 1) infinite;
86
- }
87
- }
88
-
89
- @keyframes float {
90
- 0% { transform: translateY(0px); }
91
- 50% { transform: translateY(-20px); }
92
- 100% { transform: translateY(0px); }
93
- }
1
+ @tailwind base;
2
+ @tailwind components;
3
+ @tailwind utilities;
4
+
5
+ @layer base {
6
+ :root {
7
+ /* Brand Colors - Deep Violet & Electric Purple */
8
+ --background: 260 30% 98%;
9
+ --foreground: 260 40% 10%;
10
+
11
+ --primary: 265 89% 66%;
12
+ --primary-foreground: 210 40% 98%;
13
+
14
+ --secondary: 260 20% 90%;
15
+ --secondary-foreground: 260 40% 10%;
16
+
17
+ --muted: 260 20% 96%;
18
+ --muted-foreground: 260 20% 40%;
19
+
20
+ --accent: 265 89% 96%;
21
+ --accent-foreground: 265 89% 66%;
22
+
23
+ --destructive: 0 84% 60%;
24
+ --destructive-foreground: 210 40% 98%;
25
+
26
+ --border: 260 20% 90%;
27
+ --input: 260 20% 90%;
28
+ --ring: 265 89% 66%;
29
+
30
+ --radius: 1rem;
31
+ }
32
+
33
+ .dark {
34
+ --background: 260 40% 5%;
35
+ --foreground: 210 40% 98%;
36
+
37
+ --primary: 265 89% 66%;
38
+ --primary-foreground: 210 40% 98%;
39
+
40
+ --secondary: 260 30% 15%;
41
+ --secondary-foreground: 210 40% 98%;
42
+
43
+ --muted: 260 30% 15%;
44
+ --muted-foreground: 215 20% 65%;
45
+
46
+ --accent: 260 30% 15%;
47
+ --accent-foreground: 210 40% 98%;
48
+
49
+ --destructive: 0 62% 30%;
50
+ --destructive-foreground: 210 40% 98%;
51
+
52
+ --border: 260 30% 15%;
53
+ --input: 260 30% 15%;
54
+ --ring: 265 89% 66%;
55
+ }
56
+ }
57
+
58
+ @layer base {
59
+ * {
60
+ @apply border-border;
61
+ }
62
+ body {
63
+ @apply bg-background text-foreground antialiased;
64
+ font-feature-settings: "rlig" 1, "calt" 1;
65
+ }
66
+ }
67
+
68
+ @layer utilities {
69
+ .glass {
70
+ @apply bg-white/10 backdrop-blur-lg border border-white/20 shadow-xl;
71
+ }
72
+ .glass-dark {
73
+ @apply bg-black/30 backdrop-blur-lg border border-white/10 shadow-xl;
74
+ }
75
+
76
+ .text-gradient {
77
+ @apply bg-clip-text text-transparent bg-gradient-to-r from-violet-600 to-indigo-600 dark:from-violet-400 dark:to-indigo-400;
78
+ }
79
+
80
+ .animate-float {
81
+ animation: float 6s ease-in-out infinite;
82
+ }
83
+
84
+ .animate-pulse-slow {
85
+ animation: pulse 4s cubic-bezier(0.4, 0, 0.6, 1) infinite;
86
+ }
87
+ }
88
+
89
+ @keyframes float {
90
+ 0% { transform: translateY(0px); }
91
+ 50% { transform: translateY(-20px); }
92
+ 100% { transform: translateY(0px); }
93
+ }