create-mantiq 0.7.0 → 0.7.2
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.
- package/package.json +2 -1
- package/skeleton/.env.example +64 -0
- package/skeleton/README.md +46 -0
- package/skeleton/app/Console/Commands/.gitkeep +0 -0
- package/skeleton/app/Enums/UserStatus.ts +7 -0
- package/skeleton/app/Http/Controllers/HomeController.ts +78 -0
- package/skeleton/app/Http/Middleware/.gitkeep +0 -0
- package/skeleton/app/Models/User.ts +7 -0
- package/skeleton/app/Providers/AppServiceProvider.ts +25 -0
- package/skeleton/app/Providers/DatabaseServiceProvider.ts +17 -0
- package/skeleton/bootstrap/.gitkeep +0 -0
- package/skeleton/config/ai.ts +51 -0
- package/skeleton/config/app.ts +108 -0
- package/skeleton/config/auth.ts +51 -0
- package/skeleton/config/broadcasting.ts +93 -0
- package/skeleton/config/cache.ts +61 -0
- package/skeleton/config/cors.ts +77 -0
- package/skeleton/config/database.ts +120 -0
- package/skeleton/config/filesystem.ts +58 -0
- package/skeleton/config/hashing.ts +47 -0
- package/skeleton/config/heartbeat.ts +112 -0
- package/skeleton/config/logging.ts +58 -0
- package/skeleton/config/mail.ts +93 -0
- package/skeleton/config/notify.ts +141 -0
- package/skeleton/config/queue.ts +59 -0
- package/skeleton/config/search.ts +96 -0
- package/skeleton/config/services.ts +110 -0
- package/skeleton/config/session.ts +84 -0
- package/skeleton/config/vite.ts +33 -0
- package/skeleton/database/factories/.gitkeep +0 -0
- package/skeleton/database/migrations/001_create_users_table.ts +19 -0
- package/skeleton/database/migrations/002_create_personal_access_tokens_table.ts +22 -0
- package/skeleton/database/seeders/DatabaseSeeder.ts +7 -0
- package/skeleton/index.ts +20 -0
- package/skeleton/mantiq.ts +8 -0
- package/skeleton/package.json +34 -0
- package/skeleton/public/.gitkeep +0 -0
- package/skeleton/routes/api.ts +8 -0
- package/skeleton/routes/channels.ts +23 -0
- package/skeleton/routes/console.ts +24 -0
- package/skeleton/routes/web.ts +6 -0
- package/skeleton/storage/cache/.gitkeep +0 -0
- package/skeleton/storage/framework/.gitkeep +0 -0
- package/skeleton/tests/feature/api.test.ts +14 -0
- package/skeleton/tests/feature/home.test.ts +17 -0
- package/skeleton/tests/unit/example.test.ts +11 -0
- package/skeleton/tsconfig.json +27 -0
- package/src/index.ts +289 -25
- package/src/templates.ts +141 -945
- package/src/terminal.ts +64 -0
- package/stubs/api-only/routes/api.ts.stub +24 -0
- package/stubs/api-only/tests/feature/token-auth.test.ts.stub +69 -0
- package/stubs/auth/api/app/Http/Controllers/ApiAuthController.ts.stub +57 -0
- package/stubs/auth/api/routes/api.ts.stub +24 -0
- package/stubs/auth/api/tests/feature/token-auth.test.ts.stub +69 -0
- package/stubs/auth/shared/app/Http/Requests/LoginRequest.ts.stub +10 -0
- package/stubs/auth/shared/app/Http/Requests/RegisterRequest.ts.stub +11 -0
- package/stubs/auth/web/app/Http/Controllers/AuthController.ts.stub +43 -0
- package/stubs/auth/web/app/Http/Controllers/PageController.ts.stub +66 -0
- package/stubs/auth/web/routes/web.ts.stub +25 -0
- package/stubs/auth/web/svelte/src/App.svelte.stub +77 -0
- package/stubs/auth/web/svelte/src/pages.ts.stub +17 -0
- package/stubs/auth/web/tests/feature/auth.test.ts.stub +69 -0
- package/stubs/auth/web/vue/src/App.vue.stub +74 -0
- package/stubs/auth/web/vue/src/pages.ts.stub +17 -0
- package/stubs/manifest.json +630 -2
- package/stubs/noauth/app/Http/Controllers/PageController.ts.stub +41 -0
- package/stubs/noauth/app/Models/User.ts.stub +5 -0
- package/stubs/noauth/database/migrations/001_create_users_table.ts.stub +17 -0
- package/stubs/noauth/routes/api.ts.stub +16 -0
- package/stubs/noauth/routes/web.ts.stub +15 -0
- package/stubs/noauth/svelte/src/App.svelte.stub +68 -0
- package/stubs/noauth/svelte/src/pages.ts.stub +7 -0
- package/stubs/noauth/vue/src/App.vue.stub +62 -0
- package/stubs/noauth/vue/src/pages.ts.stub +7 -0
- package/stubs/react/src/App.tsx.stub +4 -2
- package/stubs/react/src/components/layout/search-dialog.tsx.stub +2 -2
- package/stubs/react/src/components/layout/sidebar-data.ts.stub +2 -2
- package/stubs/react/src/lib/api.ts.stub +30 -6
- package/stubs/react/src/pages/Login.tsx.stub +3 -3
- package/stubs/react/src/pages/users/dialogs.tsx.stub +7 -26
- package/stubs/react/vite.config.ts.stub +26 -3
- package/stubs/shared/app/Http/Controllers/ApiAuthController.ts.stub +57 -0
- package/stubs/shared/app/Http/Controllers/AuthController.ts.stub +14 -38
- package/stubs/shared/app/Http/Controllers/PageController.ts.stub +3 -3
- package/stubs/shared/app/Http/Controllers/UserController.ts.stub +61 -0
- package/stubs/shared/app/Http/Requests/LoginRequest.ts.stub +10 -0
- package/stubs/shared/app/Http/Requests/RegisterRequest.ts.stub +11 -0
- package/stubs/shared/app/Http/Requests/StoreUserRequest.ts.stub +11 -0
- package/stubs/shared/app/Http/Requests/UpdateUserRequest.ts.stub +11 -0
- package/stubs/shared/config/app.ts.stub +36 -0
- package/stubs/shared/config/vite.ts.stub +8 -0
- package/stubs/shared/database/factories/UserFactory.ts.stub +4 -6
- package/stubs/shared/routes/api.ts.stub +12 -102
- package/stubs/shared/routes/web.ts.stub +5 -3
- package/stubs/shared/tests/feature/auth.test.ts.stub +69 -0
- package/stubs/shared/tests/feature/users.test.ts.stub +90 -0
- package/stubs/svelte/src/App.svelte.stub +1 -1
- package/stubs/svelte/src/lib/api.ts.stub +30 -6
- package/stubs/svelte/src/main.ts.stub +3 -1
- package/stubs/svelte/src/pages/Login.svelte.stub +3 -3
- package/stubs/svelte/vite.config.ts.stub +20 -1
- package/stubs/tailwind-only/react/src/components/layout/app-sidebar.tsx.stub +68 -0
- package/stubs/tailwind-only/react/src/components/layout/authenticated-layout.tsx.stub +57 -0
- package/stubs/tailwind-only/react/src/components/layout/header.tsx.stub +52 -0
- package/stubs/tailwind-only/react/src/components/layout/main.tsx.stub +21 -0
- package/stubs/tailwind-only/react/src/components/layout/nav-group.tsx.stub +185 -0
- package/stubs/tailwind-only/react/src/components/layout/nav-user.tsx.stub +106 -0
- package/stubs/tailwind-only/react/src/components/layout/sidebar-data.ts.stub +58 -0
- package/stubs/tailwind-only/react/src/components/layout/theme-toggle.tsx.stub +36 -0
- package/stubs/tailwind-only/react/src/components/layout/top-nav.tsx.stub +72 -0
- package/stubs/tailwind-only/react/src/lib/utils.ts.stub +6 -0
- package/stubs/tailwind-only/react/src/pages/Dashboard.tsx.stub +205 -0
- package/stubs/tailwind-only/react/src/pages/Login.tsx.stub +122 -0
- package/stubs/tailwind-only/react/src/pages/Register.tsx.stub +137 -0
- package/stubs/tailwind-only/react/src/pages/Users.tsx.stub +426 -0
- package/stubs/tailwind-only/react/src/pages/account/layout.tsx.stub +64 -0
- package/stubs/tailwind-only/react/src/pages/account/preferences.tsx.stub +80 -0
- package/stubs/tailwind-only/react/src/pages/account/profile.tsx.stub +67 -0
- package/stubs/tailwind-only/react/src/pages/account/security.tsx.stub +91 -0
- package/stubs/tailwind-only/react/src/style.css.stub +14 -0
- package/stubs/tailwind-only/svelte/src/lib/components/layout/app-sidebar.svelte.stub +104 -0
- package/stubs/tailwind-only/svelte/src/lib/components/layout/authenticated-layout.svelte.stub +51 -0
- package/stubs/tailwind-only/svelte/src/lib/components/layout/header.svelte.stub +66 -0
- package/stubs/tailwind-only/svelte/src/lib/components/layout/main.svelte.stub +26 -0
- package/stubs/tailwind-only/svelte/src/lib/components/layout/nav-group.svelte.stub +131 -0
- package/stubs/tailwind-only/svelte/src/lib/components/layout/nav-user.svelte.stub +104 -0
- package/stubs/tailwind-only/svelte/src/lib/components/layout/sidebar-data.ts.stub +57 -0
- package/stubs/tailwind-only/svelte/src/lib/components/layout/theme-toggle.svelte.stub +28 -0
- package/stubs/tailwind-only/svelte/src/lib/components/layout/top-nav.svelte.stub +99 -0
- package/stubs/tailwind-only/svelte/src/lib/utils.ts.stub +6 -0
- package/stubs/tailwind-only/svelte/src/pages/Dashboard.svelte.stub +192 -0
- package/stubs/tailwind-only/svelte/src/pages/Login.svelte.stub +120 -0
- package/stubs/tailwind-only/svelte/src/pages/Register.svelte.stub +134 -0
- package/stubs/tailwind-only/svelte/src/pages/Users.svelte.stub +293 -0
- package/stubs/tailwind-only/svelte/src/pages/account/Layout.svelte.stub +61 -0
- package/stubs/tailwind-only/svelte/src/pages/account/Preferences.svelte.stub +81 -0
- package/stubs/tailwind-only/svelte/src/pages/account/Profile.svelte.stub +76 -0
- package/stubs/tailwind-only/svelte/src/pages/account/Security.svelte.stub +140 -0
- package/stubs/tailwind-only/svelte/src/style.css.stub +127 -0
- package/stubs/tailwind-only/vue/src/components/layout/AppSidebar.vue.stub +60 -0
- package/stubs/tailwind-only/vue/src/components/layout/AuthenticatedLayout.vue.stub +73 -0
- package/stubs/tailwind-only/vue/src/components/layout/Header.vue.stub +54 -0
- package/stubs/tailwind-only/vue/src/components/layout/Main.vue.stub +22 -0
- package/stubs/tailwind-only/vue/src/components/layout/NavGroup.vue.stub +107 -0
- package/stubs/tailwind-only/vue/src/components/layout/NavUser.vue.stub +104 -0
- package/stubs/tailwind-only/vue/src/components/layout/ThemeToggle.vue.stub +28 -0
- package/stubs/tailwind-only/vue/src/components/layout/TopNav.vue.stub +86 -0
- package/stubs/tailwind-only/vue/src/components/layout/sidebar-data.ts.stub +57 -0
- package/stubs/tailwind-only/vue/src/lib/utils.ts.stub +7 -0
- package/stubs/tailwind-only/vue/src/pages/Dashboard.vue.stub +195 -0
- package/stubs/tailwind-only/vue/src/pages/Login.vue.stub +121 -0
- package/stubs/tailwind-only/vue/src/pages/Register.vue.stub +137 -0
- package/stubs/tailwind-only/vue/src/pages/Users.vue.stub +401 -0
- package/stubs/tailwind-only/vue/src/pages/account/Layout.vue.stub +56 -0
- package/stubs/tailwind-only/vue/src/pages/account/Preferences.vue.stub +81 -0
- package/stubs/tailwind-only/vue/src/pages/account/Profile.vue.stub +69 -0
- package/stubs/tailwind-only/vue/src/pages/account/Security.vue.stub +85 -0
- package/stubs/tailwind-only/vue/src/style.css.stub +26 -0
- package/stubs/themes/corporate/react/src/components/layout/app-sidebar.tsx.stub +74 -0
- package/stubs/themes/corporate/react/src/components/layout/authenticated-layout.tsx.stub +42 -0
- package/stubs/themes/corporate/react/src/pages/Dashboard.tsx.stub +310 -0
- package/stubs/themes/corporate/react/src/pages/Login.tsx.stub +122 -0
- package/stubs/themes/corporate/react/src/pages/Register.tsx.stub +144 -0
- package/stubs/themes/corporate/react/src/style.css.stub +135 -0
- package/stubs/themes/corporate/svelte/src/pages/Dashboard.svelte.stub +271 -0
- package/stubs/themes/corporate/svelte/src/pages/Login.svelte.stub +117 -0
- package/stubs/themes/corporate/svelte/src/pages/Register.svelte.stub +138 -0
- package/stubs/themes/corporate/svelte/src/style.css.stub +134 -0
- package/stubs/themes/corporate/vue/src/pages/Dashboard.vue.stub +325 -0
- package/stubs/themes/corporate/vue/src/pages/Login.vue.stub +118 -0
- package/stubs/themes/corporate/vue/src/pages/Register.vue.stub +139 -0
- package/stubs/themes/corporate/vue/src/style.css.stub +134 -0
- package/stubs/themes/minimal/react/src/components/layout/app-sidebar.tsx.stub +68 -0
- package/stubs/themes/minimal/react/src/components/layout/authenticated-layout.tsx.stub +42 -0
- package/stubs/themes/minimal/react/src/pages/Dashboard.tsx.stub +166 -0
- package/stubs/themes/minimal/react/src/pages/Login.tsx.stub +95 -0
- package/stubs/themes/minimal/react/src/pages/Register.tsx.stub +73 -0
- package/stubs/themes/minimal/react/src/style.css.stub +142 -0
- package/stubs/themes/minimal/svelte/src/pages/Dashboard.svelte.stub +149 -0
- package/stubs/themes/minimal/svelte/src/pages/Login.svelte.stub +90 -0
- package/stubs/themes/minimal/svelte/src/pages/Register.svelte.stub +70 -0
- package/stubs/themes/minimal/svelte/src/style.css.stub +142 -0
- package/stubs/themes/minimal/vue/src/pages/Dashboard.vue.stub +163 -0
- package/stubs/themes/minimal/vue/src/pages/Login.vue.stub +91 -0
- package/stubs/themes/minimal/vue/src/pages/Register.vue.stub +73 -0
- package/stubs/themes/minimal/vue/src/style.css.stub +142 -0
- package/stubs/themes/starter/react/src/components/layout/app-sidebar.tsx.stub +74 -0
- package/stubs/themes/starter/react/src/components/layout/authenticated-layout.tsx.stub +42 -0
- package/stubs/themes/starter/react/src/pages/Dashboard.tsx.stub +236 -0
- package/stubs/themes/starter/react/src/pages/Login.tsx.stub +131 -0
- package/stubs/themes/starter/react/src/pages/Register.tsx.stub +145 -0
- package/stubs/themes/starter/react/src/style.css.stub +141 -0
- package/stubs/themes/starter/svelte/src/pages/Dashboard.svelte.stub +212 -0
- package/stubs/themes/starter/svelte/src/pages/Login.svelte.stub +126 -0
- package/stubs/themes/starter/svelte/src/pages/Register.svelte.stub +139 -0
- package/stubs/themes/starter/svelte/src/style.css.stub +141 -0
- package/stubs/themes/starter/vue/src/pages/Dashboard.vue.stub +228 -0
- package/stubs/themes/starter/vue/src/pages/Login.vue.stub +127 -0
- package/stubs/themes/starter/vue/src/pages/Register.vue.stub +140 -0
- package/stubs/themes/starter/vue/src/style.css.stub +141 -0
- package/stubs/themes/workspace/react/src/components/layout/app-sidebar.tsx.stub +97 -0
- package/stubs/themes/workspace/react/src/components/layout/authenticated-layout.tsx.stub +42 -0
- package/stubs/themes/workspace/react/src/pages/Dashboard.tsx.stub +304 -0
- package/stubs/themes/workspace/react/src/pages/Login.tsx.stub +131 -0
- package/stubs/themes/workspace/react/src/pages/Register.tsx.stub +82 -0
- package/stubs/themes/workspace/react/src/style.css.stub +138 -0
- package/stubs/themes/workspace/svelte/src/pages/Dashboard.svelte.stub +215 -0
- package/stubs/themes/workspace/svelte/src/pages/Login.svelte.stub +124 -0
- package/stubs/themes/workspace/svelte/src/pages/Register.svelte.stub +76 -0
- package/stubs/themes/workspace/svelte/src/style.css.stub +134 -0
- package/stubs/themes/workspace/vue/src/pages/Dashboard.vue.stub +220 -0
- package/stubs/themes/workspace/vue/src/pages/Login.vue.stub +128 -0
- package/stubs/themes/workspace/vue/src/pages/Register.vue.stub +80 -0
- package/stubs/themes/workspace/vue/src/style.css.stub +134 -0
- package/stubs/vue/src/App.vue.stub +2 -1
- package/stubs/vue/src/lib/api.ts.stub +30 -6
- package/stubs/vue/src/main.ts.stub +3 -1
- package/stubs/vue/src/pages/Login.vue.stub +3 -3
- package/stubs/vue/vite.config.ts.stub +20 -1
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
@import "tailwindcss";
|
|
2
|
+
@custom-variant dark (&:where(.dark, .dark *));
|
|
3
|
+
|
|
4
|
+
/*
|
|
5
|
+
* shadcn/ui theme — Starter
|
|
6
|
+
*
|
|
7
|
+
* Bold, gradient-heavy palette with violet/purple primary.
|
|
8
|
+
* Dark sidebar in both light and dark modes for a two-tone SaaS feel.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
@theme inline {
|
|
12
|
+
--color-background: var(--background);
|
|
13
|
+
--color-foreground: var(--foreground);
|
|
14
|
+
--color-card: var(--card);
|
|
15
|
+
--color-card-foreground: var(--card-foreground);
|
|
16
|
+
--color-popover: var(--popover);
|
|
17
|
+
--color-popover-foreground: var(--popover-foreground);
|
|
18
|
+
--color-primary: var(--primary);
|
|
19
|
+
--color-primary-foreground: var(--primary-foreground);
|
|
20
|
+
--color-secondary: var(--secondary);
|
|
21
|
+
--color-secondary-foreground: var(--secondary-foreground);
|
|
22
|
+
--color-muted: var(--muted);
|
|
23
|
+
--color-muted-foreground: var(--muted-foreground);
|
|
24
|
+
--color-accent: var(--accent);
|
|
25
|
+
--color-accent-foreground: var(--accent-foreground);
|
|
26
|
+
--color-destructive: var(--destructive);
|
|
27
|
+
--color-destructive-foreground: var(--destructive-foreground);
|
|
28
|
+
--color-border: var(--border);
|
|
29
|
+
--color-input: var(--input);
|
|
30
|
+
--color-ring: var(--ring);
|
|
31
|
+
--color-chart-1: var(--chart-1);
|
|
32
|
+
--color-chart-2: var(--chart-2);
|
|
33
|
+
--color-chart-3: var(--chart-3);
|
|
34
|
+
--color-chart-4: var(--chart-4);
|
|
35
|
+
--color-chart-5: var(--chart-5);
|
|
36
|
+
--color-sidebar: var(--sidebar);
|
|
37
|
+
--color-sidebar-foreground: var(--sidebar-foreground);
|
|
38
|
+
--color-sidebar-primary: var(--sidebar-primary);
|
|
39
|
+
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
|
40
|
+
--color-sidebar-accent: var(--sidebar-accent);
|
|
41
|
+
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
|
42
|
+
--color-sidebar-border: var(--sidebar-border);
|
|
43
|
+
--color-sidebar-ring: var(--sidebar-ring);
|
|
44
|
+
--radius-sm: calc(var(--radius) - 4px);
|
|
45
|
+
--radius-md: calc(var(--radius) - 2px);
|
|
46
|
+
--radius-lg: var(--radius);
|
|
47
|
+
--radius-xl: calc(var(--radius) + 4px);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
:root {
|
|
51
|
+
--radius: 0.625rem;
|
|
52
|
+
--background: oklch(0.985 0.002 286);
|
|
53
|
+
--foreground: oklch(0.141 0.005 285.823);
|
|
54
|
+
--card: oklch(1 0 0);
|
|
55
|
+
--card-foreground: oklch(0.141 0.005 285.823);
|
|
56
|
+
--popover: oklch(1 0 0);
|
|
57
|
+
--popover-foreground: oklch(0.141 0.005 285.823);
|
|
58
|
+
--primary: oklch(0.606 0.25 292.717);
|
|
59
|
+
--primary-foreground: oklch(0.985 0 0);
|
|
60
|
+
--secondary: oklch(0.967 0.001 286.375);
|
|
61
|
+
--secondary-foreground: oklch(0.21 0.006 285.885);
|
|
62
|
+
--muted: oklch(0.967 0.001 286.375);
|
|
63
|
+
--muted-foreground: oklch(0.552 0.016 285.938);
|
|
64
|
+
--accent: oklch(0.967 0.001 286.375);
|
|
65
|
+
--accent-foreground: oklch(0.21 0.006 285.885);
|
|
66
|
+
--destructive: oklch(0.577 0.245 27.325);
|
|
67
|
+
--destructive-foreground: oklch(0.577 0.245 27.325);
|
|
68
|
+
--border: oklch(0.92 0.004 286.32);
|
|
69
|
+
--input: oklch(0.92 0.004 286.32);
|
|
70
|
+
--ring: oklch(0.606 0.25 292.717);
|
|
71
|
+
--chart-1: oklch(0.606 0.25 292.717);
|
|
72
|
+
--chart-2: oklch(0.546 0.245 262.881);
|
|
73
|
+
--chart-3: oklch(0.6 0.118 184.714);
|
|
74
|
+
--chart-4: oklch(0.828 0.189 84.429);
|
|
75
|
+
--chart-5: oklch(0.769 0.188 70.08);
|
|
76
|
+
/* Dark sidebar even in light mode */
|
|
77
|
+
--sidebar: oklch(0.16 0.015 286);
|
|
78
|
+
--sidebar-foreground: oklch(0.95 0.002 286);
|
|
79
|
+
--sidebar-primary: oklch(0.7 0.2 292.717);
|
|
80
|
+
--sidebar-primary-foreground: oklch(0.985 0 0);
|
|
81
|
+
--sidebar-accent: oklch(0.22 0.012 286);
|
|
82
|
+
--sidebar-accent-foreground: oklch(0.95 0.002 286);
|
|
83
|
+
--sidebar-border: oklch(0.25 0.01 286);
|
|
84
|
+
--sidebar-ring: oklch(0.7 0.2 292.717);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.dark {
|
|
88
|
+
--background: oklch(0.13 0.015 286);
|
|
89
|
+
--foreground: oklch(0.985 0 0);
|
|
90
|
+
--card: oklch(0.17 0.012 286);
|
|
91
|
+
--card-foreground: oklch(0.985 0 0);
|
|
92
|
+
--popover: oklch(0.17 0.012 286);
|
|
93
|
+
--popover-foreground: oklch(0.985 0 0);
|
|
94
|
+
--primary: oklch(0.7 0.2 292.717);
|
|
95
|
+
--primary-foreground: oklch(0.16 0.04 292.717);
|
|
96
|
+
--secondary: oklch(0.269 0.006 286.033);
|
|
97
|
+
--secondary-foreground: oklch(0.985 0 0);
|
|
98
|
+
--muted: oklch(0.269 0.006 286.033);
|
|
99
|
+
--muted-foreground: oklch(0.708 0.014 286.067);
|
|
100
|
+
--accent: oklch(0.269 0.006 286.033);
|
|
101
|
+
--accent-foreground: oklch(0.985 0 0);
|
|
102
|
+
--destructive: oklch(0.704 0.191 22.216);
|
|
103
|
+
--destructive-foreground: oklch(0.704 0.191 22.216);
|
|
104
|
+
--border: oklch(0.274 0.006 286.033);
|
|
105
|
+
--input: oklch(0.274 0.006 286.033);
|
|
106
|
+
--ring: oklch(0.7 0.2 292.717);
|
|
107
|
+
--chart-1: oklch(0.7 0.2 292.717);
|
|
108
|
+
--chart-2: oklch(0.623 0.214 262.881);
|
|
109
|
+
--chart-3: oklch(0.769 0.188 70.08);
|
|
110
|
+
--chart-4: oklch(0.627 0.265 303.9);
|
|
111
|
+
--chart-5: oklch(0.645 0.246 16.439);
|
|
112
|
+
--sidebar: oklch(0.13 0.015 286);
|
|
113
|
+
--sidebar-foreground: oklch(0.95 0.002 286);
|
|
114
|
+
--sidebar-primary: oklch(0.7 0.2 292.717);
|
|
115
|
+
--sidebar-primary-foreground: oklch(0.985 0 0);
|
|
116
|
+
--sidebar-accent: oklch(0.22 0.012 286);
|
|
117
|
+
--sidebar-accent-foreground: oklch(0.95 0.002 286);
|
|
118
|
+
--sidebar-border: oklch(0.25 0.01 286);
|
|
119
|
+
--sidebar-ring: oklch(0.7 0.2 292.717);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
@layer base {
|
|
123
|
+
* {
|
|
124
|
+
@apply border-border;
|
|
125
|
+
}
|
|
126
|
+
body {
|
|
127
|
+
@apply bg-background text-foreground;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
@keyframes fadeUp {
|
|
132
|
+
from { opacity: 0; transform: translateY(8px); }
|
|
133
|
+
to { opacity: 1; transform: translateY(0); }
|
|
134
|
+
}
|
|
135
|
+
.animate-fade-up { animation: fadeUp 0.4s ease-out; }
|
|
136
|
+
|
|
137
|
+
@keyframes gradient-shift {
|
|
138
|
+
0%, 100% { background-position: 0% 50%; }
|
|
139
|
+
50% { background-position: 100% 50%; }
|
|
140
|
+
}
|
|
141
|
+
.animate-gradient { animation: gradient-shift 6s ease infinite; background-size: 200% 200%; }
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import AuthenticatedLayout from '@/components/layout/AuthenticatedLayout.vue'
|
|
3
|
+
import Header from '@/components/layout/Header.vue'
|
|
4
|
+
import Main from '@/components/layout/Main.vue'
|
|
5
|
+
import { Button } from '@/components/ui/button'
|
|
6
|
+
import {
|
|
7
|
+
Card,
|
|
8
|
+
CardContent,
|
|
9
|
+
CardHeader,
|
|
10
|
+
CardTitle,
|
|
11
|
+
} from '@/components/ui/card'
|
|
12
|
+
import {
|
|
13
|
+
Rocket,
|
|
14
|
+
Users,
|
|
15
|
+
TrendingUp,
|
|
16
|
+
ArrowRight,
|
|
17
|
+
Zap,
|
|
18
|
+
Shield,
|
|
19
|
+
Globe,
|
|
20
|
+
Bell,
|
|
21
|
+
FileText,
|
|
22
|
+
BookOpen,
|
|
23
|
+
MessageCircle,
|
|
24
|
+
Headphones,
|
|
25
|
+
} from 'lucide-vue-next'
|
|
26
|
+
import { type Component } from 'vue'
|
|
27
|
+
|
|
28
|
+
const props = withDefaults(defineProps<{
|
|
29
|
+
appName?: string
|
|
30
|
+
currentUser?: { id: number; name: string; email: string; role: string } | null
|
|
31
|
+
navigate?: (href: string) => void
|
|
32
|
+
}>(), {
|
|
33
|
+
appName: 'Mantiq',
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
const activityItems: { color: string; icon: Component; title: string; description: string; time: string }[] = [
|
|
37
|
+
{
|
|
38
|
+
color: 'border-violet-500',
|
|
39
|
+
icon: Rocket,
|
|
40
|
+
title: 'New deployment completed',
|
|
41
|
+
description: 'Production v2.4.1 deployed successfully',
|
|
42
|
+
time: '2 minutes ago',
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
color: 'border-blue-500',
|
|
46
|
+
icon: Users,
|
|
47
|
+
title: 'Team member joined',
|
|
48
|
+
description: 'Sarah Connor accepted the invitation',
|
|
49
|
+
time: '15 minutes ago',
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
color: 'border-emerald-500',
|
|
53
|
+
icon: Shield,
|
|
54
|
+
title: 'Security scan passed',
|
|
55
|
+
description: 'All 142 checks passed with no vulnerabilities',
|
|
56
|
+
time: '1 hour ago',
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
color: 'border-amber-500',
|
|
60
|
+
icon: Bell,
|
|
61
|
+
title: 'Usage alert triggered',
|
|
62
|
+
description: 'API calls reached 80% of monthly quota',
|
|
63
|
+
time: '3 hours ago',
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
color: 'border-red-500',
|
|
67
|
+
icon: Globe,
|
|
68
|
+
title: 'Domain verified',
|
|
69
|
+
description: 'app.example.com DNS propagation complete',
|
|
70
|
+
time: '5 hours ago',
|
|
71
|
+
},
|
|
72
|
+
]
|
|
73
|
+
|
|
74
|
+
const quickLinks: { icon: Component; label: string; href: string }[] = [
|
|
75
|
+
{ icon: FileText, label: 'Documentation', href: '#' },
|
|
76
|
+
{ icon: BookOpen, label: 'API Reference', href: '#' },
|
|
77
|
+
{ icon: MessageCircle, label: 'Community', href: '#' },
|
|
78
|
+
{ icon: Headphones, label: 'Support', href: '#' },
|
|
79
|
+
]
|
|
80
|
+
</script>
|
|
81
|
+
|
|
82
|
+
<template>
|
|
83
|
+
<AuthenticatedLayout
|
|
84
|
+
:current-user="currentUser"
|
|
85
|
+
:app-name="appName"
|
|
86
|
+
:navigate="navigate"
|
|
87
|
+
active-path="/dashboard"
|
|
88
|
+
>
|
|
89
|
+
<Header :navigate="navigate" />
|
|
90
|
+
<Main>
|
|
91
|
+
<div class="space-y-6">
|
|
92
|
+
<!-- Welcome Banner -->
|
|
93
|
+
<Card class="border-0 bg-gradient-to-r from-violet-600 to-indigo-600 text-white shadow-lg">
|
|
94
|
+
<CardContent class="p-8">
|
|
95
|
+
<div class="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
|
|
96
|
+
<div>
|
|
97
|
+
<h2 class="text-3xl font-bold tracking-tight">
|
|
98
|
+
Welcome back, {{ currentUser?.name ?? 'there' }}!
|
|
99
|
+
</h2>
|
|
100
|
+
<p class="mt-2 text-lg text-white/80">
|
|
101
|
+
Your dashboard is looking great. Here's a quick summary.
|
|
102
|
+
</p>
|
|
103
|
+
</div>
|
|
104
|
+
<Button
|
|
105
|
+
variant="outline"
|
|
106
|
+
class="shrink-0 border-white/30 bg-white/10 text-white backdrop-blur-sm hover:bg-white/20 hover:text-white"
|
|
107
|
+
>
|
|
108
|
+
View Reports
|
|
109
|
+
<ArrowRight class="ml-2 h-4 w-4" />
|
|
110
|
+
</Button>
|
|
111
|
+
</div>
|
|
112
|
+
</CardContent>
|
|
113
|
+
</Card>
|
|
114
|
+
|
|
115
|
+
<!-- Stats Strip -->
|
|
116
|
+
<div class="grid gap-4 sm:grid-cols-2 lg:grid-cols-4">
|
|
117
|
+
<Card>
|
|
118
|
+
<CardContent class="p-6">
|
|
119
|
+
<div class="flex items-center gap-4">
|
|
120
|
+
<div class="flex h-12 w-12 shrink-0 items-center justify-center rounded-xl bg-gradient-to-br from-violet-500 to-purple-600 text-white shadow-md">
|
|
121
|
+
<Users class="h-6 w-6" />
|
|
122
|
+
</div>
|
|
123
|
+
<div>
|
|
124
|
+
<p class="text-sm font-medium text-muted-foreground">Total Users</p>
|
|
125
|
+
<p class="text-2xl font-bold">12,345</p>
|
|
126
|
+
</div>
|
|
127
|
+
</div>
|
|
128
|
+
</CardContent>
|
|
129
|
+
</Card>
|
|
130
|
+
|
|
131
|
+
<Card>
|
|
132
|
+
<CardContent class="p-6">
|
|
133
|
+
<div class="flex items-center gap-4">
|
|
134
|
+
<div class="flex h-12 w-12 shrink-0 items-center justify-center rounded-xl bg-gradient-to-br from-blue-500 to-cyan-500 text-white shadow-md">
|
|
135
|
+
<TrendingUp class="h-6 w-6" />
|
|
136
|
+
</div>
|
|
137
|
+
<div>
|
|
138
|
+
<p class="text-sm font-medium text-muted-foreground">Revenue</p>
|
|
139
|
+
<p class="text-2xl font-bold">$89,432</p>
|
|
140
|
+
</div>
|
|
141
|
+
</div>
|
|
142
|
+
</CardContent>
|
|
143
|
+
</Card>
|
|
144
|
+
|
|
145
|
+
<Card>
|
|
146
|
+
<CardContent class="p-6">
|
|
147
|
+
<div class="flex items-center gap-4">
|
|
148
|
+
<div class="flex h-12 w-12 shrink-0 items-center justify-center rounded-xl bg-gradient-to-br from-amber-500 to-orange-500 text-white shadow-md">
|
|
149
|
+
<Zap class="h-6 w-6" />
|
|
150
|
+
</div>
|
|
151
|
+
<div>
|
|
152
|
+
<p class="text-sm font-medium text-muted-foreground">Active Now</p>
|
|
153
|
+
<p class="text-2xl font-bold">573</p>
|
|
154
|
+
</div>
|
|
155
|
+
</div>
|
|
156
|
+
</CardContent>
|
|
157
|
+
</Card>
|
|
158
|
+
|
|
159
|
+
<Card>
|
|
160
|
+
<CardContent class="p-6">
|
|
161
|
+
<div class="flex items-center gap-4">
|
|
162
|
+
<div class="flex h-12 w-12 shrink-0 items-center justify-center rounded-xl bg-gradient-to-br from-emerald-500 to-green-500 text-white shadow-md">
|
|
163
|
+
<Shield class="h-6 w-6" />
|
|
164
|
+
</div>
|
|
165
|
+
<div>
|
|
166
|
+
<p class="text-sm font-medium text-muted-foreground">Uptime</p>
|
|
167
|
+
<p class="text-2xl font-bold">99.98%</p>
|
|
168
|
+
</div>
|
|
169
|
+
</div>
|
|
170
|
+
</CardContent>
|
|
171
|
+
</Card>
|
|
172
|
+
</div>
|
|
173
|
+
|
|
174
|
+
<!-- Two Column Section -->
|
|
175
|
+
<div class="grid gap-6 lg:grid-cols-3">
|
|
176
|
+
<!-- Activity Feed -->
|
|
177
|
+
<Card class="lg:col-span-2">
|
|
178
|
+
<CardHeader>
|
|
179
|
+
<CardTitle>Recent Activity</CardTitle>
|
|
180
|
+
</CardHeader>
|
|
181
|
+
<CardContent>
|
|
182
|
+
<div class="space-y-4">
|
|
183
|
+
<div
|
|
184
|
+
v-for="(item, index) in activityItems"
|
|
185
|
+
:key="index"
|
|
186
|
+
:class="[
|
|
187
|
+
'flex items-start gap-4 rounded-lg border-l-4 bg-muted/30 p-4',
|
|
188
|
+
item.color,
|
|
189
|
+
]"
|
|
190
|
+
>
|
|
191
|
+
<div class="mt-0.5 text-muted-foreground">
|
|
192
|
+
<component :is="item.icon" class="h-5 w-5" />
|
|
193
|
+
</div>
|
|
194
|
+
<div class="flex-1 space-y-1">
|
|
195
|
+
<p class="text-sm font-medium leading-none">{{ item.title }}</p>
|
|
196
|
+
<p class="text-sm text-muted-foreground">{{ item.description }}</p>
|
|
197
|
+
</div>
|
|
198
|
+
<span class="shrink-0 text-xs text-muted-foreground">{{ item.time }}</span>
|
|
199
|
+
</div>
|
|
200
|
+
</div>
|
|
201
|
+
</CardContent>
|
|
202
|
+
</Card>
|
|
203
|
+
|
|
204
|
+
<!-- Quick Links -->
|
|
205
|
+
<Card>
|
|
206
|
+
<CardHeader>
|
|
207
|
+
<CardTitle>Quick Links</CardTitle>
|
|
208
|
+
</CardHeader>
|
|
209
|
+
<CardContent>
|
|
210
|
+
<div class="space-y-2">
|
|
211
|
+
<button
|
|
212
|
+
v-for="link in quickLinks"
|
|
213
|
+
:key="link.label"
|
|
214
|
+
type="button"
|
|
215
|
+
class="flex w-full items-center gap-3 rounded-lg p-3 text-left transition-colors hover:bg-muted"
|
|
216
|
+
>
|
|
217
|
+
<component :is="link.icon" class="h-5 w-5 text-muted-foreground" />
|
|
218
|
+
<span class="flex-1 text-sm font-medium">{{ link.label }}</span>
|
|
219
|
+
<ArrowRight class="h-4 w-4 text-muted-foreground" />
|
|
220
|
+
</button>
|
|
221
|
+
</div>
|
|
222
|
+
</CardContent>
|
|
223
|
+
</Card>
|
|
224
|
+
</div>
|
|
225
|
+
</div>
|
|
226
|
+
</Main>
|
|
227
|
+
</AuthenticatedLayout>
|
|
228
|
+
</template>
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { ref } from 'vue'
|
|
3
|
+
import { post } from '@/lib/api'
|
|
4
|
+
import { Button } from '@/components/ui/button'
|
|
5
|
+
import { Input } from '@/components/ui/input'
|
|
6
|
+
import { Label } from '@/components/ui/label'
|
|
7
|
+
|
|
8
|
+
const props = withDefaults(defineProps<{
|
|
9
|
+
appName?: string
|
|
10
|
+
navigate?: (href: string) => void
|
|
11
|
+
}>(), {
|
|
12
|
+
appName: 'Mantiq',
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
const email = ref('')
|
|
16
|
+
const password = ref('')
|
|
17
|
+
const error = ref('')
|
|
18
|
+
const loading = ref(false)
|
|
19
|
+
|
|
20
|
+
async function handleSubmit() {
|
|
21
|
+
error.value = ''
|
|
22
|
+
loading.value = true
|
|
23
|
+
const { ok, data } = await post('/login', { email: email.value, password: password.value })
|
|
24
|
+
if (ok) props.navigate?.('/dashboard')
|
|
25
|
+
else error.value = data?.error ?? 'Invalid email or password. Please try again.'
|
|
26
|
+
loading.value = false
|
|
27
|
+
}
|
|
28
|
+
</script>
|
|
29
|
+
|
|
30
|
+
<template>
|
|
31
|
+
<div class="min-h-screen flex bg-background">
|
|
32
|
+
<!-- Left gradient panel -->
|
|
33
|
+
<div class="hidden lg:flex lg:w-1/2 relative overflow-hidden bg-gradient-to-br from-violet-600 via-purple-600 to-indigo-700 animate-gradient">
|
|
34
|
+
<!-- Floating decorative circles -->
|
|
35
|
+
<div class="absolute -top-20 -left-20 h-72 w-72 rounded-full bg-white/10 blur-3xl" />
|
|
36
|
+
<div class="absolute top-1/3 right-10 h-48 w-48 rounded-full bg-indigo-400/20 blur-2xl" />
|
|
37
|
+
<div class="absolute bottom-20 left-1/4 h-56 w-56 rounded-full bg-purple-300/15 blur-3xl" />
|
|
38
|
+
|
|
39
|
+
<div class="relative z-10 flex flex-col justify-center p-16 text-white">
|
|
40
|
+
<h1 class="text-5xl font-bold leading-tight tracking-tight">
|
|
41
|
+
Build something<br />amazing.
|
|
42
|
+
</h1>
|
|
43
|
+
<p class="mt-4 text-xl text-white/70">
|
|
44
|
+
Join thousands of developers shipping faster with {{ appName }}.
|
|
45
|
+
</p>
|
|
46
|
+
|
|
47
|
+
<!-- Testimonial card -->
|
|
48
|
+
<div class="mt-12 rounded-2xl bg-white/10 p-6 backdrop-blur-sm">
|
|
49
|
+
<p class="text-lg leading-relaxed text-white/90">
|
|
50
|
+
"This framework completely changed how we build web apps. We shipped our MVP in half the time."
|
|
51
|
+
</p>
|
|
52
|
+
<div class="mt-4">
|
|
53
|
+
<p class="font-semibold">Alex Rivera</p>
|
|
54
|
+
<p class="text-sm text-white/60">CTO at LaunchPad</p>
|
|
55
|
+
</div>
|
|
56
|
+
</div>
|
|
57
|
+
</div>
|
|
58
|
+
</div>
|
|
59
|
+
|
|
60
|
+
<!-- Right form panel -->
|
|
61
|
+
<div class="flex flex-1 flex-col items-center justify-center px-6 py-12">
|
|
62
|
+
<!-- Logo -->
|
|
63
|
+
<div class="mb-10 flex items-center gap-3">
|
|
64
|
+
<div class="flex h-9 w-9 items-center justify-center rounded-lg bg-gradient-to-br from-violet-600 to-indigo-600 text-white text-sm font-bold">
|
|
65
|
+
M
|
|
66
|
+
</div>
|
|
67
|
+
<span class="text-lg font-semibold tracking-tight">{{ appName }}</span>
|
|
68
|
+
</div>
|
|
69
|
+
|
|
70
|
+
<div class="w-full max-w-sm">
|
|
71
|
+
<div class="mb-8 text-center">
|
|
72
|
+
<h1 class="text-2xl font-bold tracking-tight">Sign in</h1>
|
|
73
|
+
<p class="mt-2 text-sm text-muted-foreground">
|
|
74
|
+
Enter your credentials to continue
|
|
75
|
+
</p>
|
|
76
|
+
</div>
|
|
77
|
+
|
|
78
|
+
<div v-if="error" class="mb-6 rounded-md border border-destructive px-4 py-3 text-sm text-destructive">
|
|
79
|
+
{{ error }}
|
|
80
|
+
</div>
|
|
81
|
+
|
|
82
|
+
<form class="space-y-4" @submit.prevent="handleSubmit">
|
|
83
|
+
<div class="space-y-2">
|
|
84
|
+
<Label for="email">Email</Label>
|
|
85
|
+
<Input
|
|
86
|
+
id="email"
|
|
87
|
+
v-model="email"
|
|
88
|
+
type="email"
|
|
89
|
+
required
|
|
90
|
+
placeholder="you@example.com"
|
|
91
|
+
autocomplete="email"
|
|
92
|
+
/>
|
|
93
|
+
</div>
|
|
94
|
+
<div class="space-y-2">
|
|
95
|
+
<Label for="password">Password</Label>
|
|
96
|
+
<Input
|
|
97
|
+
id="password"
|
|
98
|
+
v-model="password"
|
|
99
|
+
type="password"
|
|
100
|
+
required
|
|
101
|
+
placeholder="Enter your password"
|
|
102
|
+
autocomplete="current-password"
|
|
103
|
+
/>
|
|
104
|
+
</div>
|
|
105
|
+
<Button
|
|
106
|
+
type="submit"
|
|
107
|
+
class="w-full bg-gradient-to-r from-violet-600 to-indigo-600 text-white hover:from-violet-700 hover:to-indigo-700"
|
|
108
|
+
:disabled="loading"
|
|
109
|
+
>
|
|
110
|
+
{{ loading ? 'Signing in...' : 'Sign in' }}
|
|
111
|
+
</Button>
|
|
112
|
+
</form>
|
|
113
|
+
|
|
114
|
+
<p class="mt-6 text-center text-sm text-muted-foreground">
|
|
115
|
+
Don't have an account?{{ ' ' }}
|
|
116
|
+
<button
|
|
117
|
+
type="button"
|
|
118
|
+
class="font-medium text-primary underline underline-offset-4"
|
|
119
|
+
@click="navigate?.('/register')"
|
|
120
|
+
>
|
|
121
|
+
Register
|
|
122
|
+
</button>
|
|
123
|
+
</p>
|
|
124
|
+
</div>
|
|
125
|
+
</div>
|
|
126
|
+
</div>
|
|
127
|
+
</template>
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { ref } from 'vue'
|
|
3
|
+
import { post } from '@/lib/api'
|
|
4
|
+
import { Button } from '@/components/ui/button'
|
|
5
|
+
import { Input } from '@/components/ui/input'
|
|
6
|
+
import { Label } from '@/components/ui/label'
|
|
7
|
+
|
|
8
|
+
const props = withDefaults(defineProps<{
|
|
9
|
+
appName?: string
|
|
10
|
+
navigate?: (href: string) => void
|
|
11
|
+
}>(), {
|
|
12
|
+
appName: 'Mantiq',
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
const name = ref('')
|
|
16
|
+
const email = ref('')
|
|
17
|
+
const password = ref('')
|
|
18
|
+
const error = ref('')
|
|
19
|
+
const loading = ref(false)
|
|
20
|
+
|
|
21
|
+
async function handleSubmit() {
|
|
22
|
+
error.value = ''
|
|
23
|
+
loading.value = true
|
|
24
|
+
const { ok, data } = await post('/register', { name: name.value, email: email.value, password: password.value })
|
|
25
|
+
if (ok) props.navigate?.('/dashboard')
|
|
26
|
+
else error.value = data?.error?.message ?? data?.error ?? 'Registration failed. Please try again.'
|
|
27
|
+
loading.value = false
|
|
28
|
+
}
|
|
29
|
+
</script>
|
|
30
|
+
|
|
31
|
+
<template>
|
|
32
|
+
<div class="min-h-screen flex bg-background">
|
|
33
|
+
<!-- Left gradient panel -->
|
|
34
|
+
<div class="hidden lg:flex lg:w-1/2 relative overflow-hidden bg-gradient-to-br from-violet-600 via-purple-600 to-indigo-700 animate-gradient">
|
|
35
|
+
<!-- Floating decorative circles -->
|
|
36
|
+
<div class="absolute -top-20 -right-20 h-72 w-72 rounded-full bg-white/10 blur-3xl" />
|
|
37
|
+
<div class="absolute top-1/2 left-10 h-48 w-48 rounded-full bg-indigo-400/20 blur-2xl" />
|
|
38
|
+
<div class="absolute bottom-10 right-1/4 h-56 w-56 rounded-full bg-purple-300/15 blur-3xl" />
|
|
39
|
+
|
|
40
|
+
<div class="relative z-10 flex flex-col justify-center p-16 text-white">
|
|
41
|
+
<h1 class="text-5xl font-bold leading-tight tracking-tight">
|
|
42
|
+
Start your<br />journey.
|
|
43
|
+
</h1>
|
|
44
|
+
<p class="mt-4 text-xl text-white/70">
|
|
45
|
+
Create your account and start building something extraordinary with {{ appName }}.
|
|
46
|
+
</p>
|
|
47
|
+
|
|
48
|
+
<!-- Testimonial card -->
|
|
49
|
+
<div class="mt-12 rounded-2xl bg-white/10 p-6 backdrop-blur-sm">
|
|
50
|
+
<p class="text-lg leading-relaxed text-white/90">
|
|
51
|
+
"From idea to production in days, not months. The developer experience is unmatched."
|
|
52
|
+
</p>
|
|
53
|
+
<div class="mt-4">
|
|
54
|
+
<p class="font-semibold">Jamie Chen</p>
|
|
55
|
+
<p class="text-sm text-white/60">Founder at NovaTech</p>
|
|
56
|
+
</div>
|
|
57
|
+
</div>
|
|
58
|
+
</div>
|
|
59
|
+
</div>
|
|
60
|
+
|
|
61
|
+
<!-- Right form panel -->
|
|
62
|
+
<div class="flex flex-1 flex-col items-center justify-center px-6 py-12">
|
|
63
|
+
<!-- Logo -->
|
|
64
|
+
<div class="mb-10 flex items-center gap-3">
|
|
65
|
+
<div class="flex h-9 w-9 items-center justify-center rounded-lg bg-gradient-to-br from-violet-600 to-indigo-600 text-white text-sm font-bold">
|
|
66
|
+
M
|
|
67
|
+
</div>
|
|
68
|
+
<span class="text-lg font-semibold tracking-tight">{{ appName }}</span>
|
|
69
|
+
</div>
|
|
70
|
+
|
|
71
|
+
<div class="w-full max-w-sm">
|
|
72
|
+
<div class="mb-8 text-center">
|
|
73
|
+
<h1 class="text-2xl font-bold tracking-tight">Create an account</h1>
|
|
74
|
+
<p class="mt-2 text-sm text-muted-foreground">
|
|
75
|
+
Get started with {{ appName }} today
|
|
76
|
+
</p>
|
|
77
|
+
</div>
|
|
78
|
+
|
|
79
|
+
<div v-if="error" class="mb-6 rounded-md border border-destructive px-4 py-3 text-sm text-destructive">
|
|
80
|
+
{{ error }}
|
|
81
|
+
</div>
|
|
82
|
+
|
|
83
|
+
<form class="space-y-4" @submit.prevent="handleSubmit">
|
|
84
|
+
<div class="space-y-2">
|
|
85
|
+
<Label for="name">Name</Label>
|
|
86
|
+
<Input
|
|
87
|
+
id="name"
|
|
88
|
+
v-model="name"
|
|
89
|
+
required
|
|
90
|
+
placeholder="John Doe"
|
|
91
|
+
autocomplete="name"
|
|
92
|
+
/>
|
|
93
|
+
</div>
|
|
94
|
+
<div class="space-y-2">
|
|
95
|
+
<Label for="email">Email</Label>
|
|
96
|
+
<Input
|
|
97
|
+
id="email"
|
|
98
|
+
v-model="email"
|
|
99
|
+
type="email"
|
|
100
|
+
required
|
|
101
|
+
placeholder="you@example.com"
|
|
102
|
+
autocomplete="email"
|
|
103
|
+
/>
|
|
104
|
+
</div>
|
|
105
|
+
<div class="space-y-2">
|
|
106
|
+
<Label for="password">Password</Label>
|
|
107
|
+
<Input
|
|
108
|
+
id="password"
|
|
109
|
+
v-model="password"
|
|
110
|
+
type="password"
|
|
111
|
+
required
|
|
112
|
+
placeholder="Create a strong password"
|
|
113
|
+
autocomplete="new-password"
|
|
114
|
+
:minlength="8"
|
|
115
|
+
/>
|
|
116
|
+
<p class="text-xs text-muted-foreground">Must be at least 8 characters</p>
|
|
117
|
+
</div>
|
|
118
|
+
<Button
|
|
119
|
+
type="submit"
|
|
120
|
+
class="w-full bg-gradient-to-r from-violet-600 to-indigo-600 text-white hover:from-violet-700 hover:to-indigo-700"
|
|
121
|
+
:disabled="loading"
|
|
122
|
+
>
|
|
123
|
+
{{ loading ? 'Creating account...' : 'Create account' }}
|
|
124
|
+
</Button>
|
|
125
|
+
</form>
|
|
126
|
+
|
|
127
|
+
<p class="mt-6 text-center text-sm text-muted-foreground">
|
|
128
|
+
Already have an account?{{ ' ' }}
|
|
129
|
+
<button
|
|
130
|
+
type="button"
|
|
131
|
+
class="font-medium text-primary underline underline-offset-4"
|
|
132
|
+
@click="navigate?.('/login')"
|
|
133
|
+
>
|
|
134
|
+
Sign in
|
|
135
|
+
</button>
|
|
136
|
+
</p>
|
|
137
|
+
</div>
|
|
138
|
+
</div>
|
|
139
|
+
</div>
|
|
140
|
+
</template>
|