create-nara 0.1.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.
- package/README.md +17 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +50 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +3 -0
- package/dist/template.d.ts +8 -0
- package/dist/template.js +68 -0
- package/package.json +28 -0
- package/templates/base/.env.example +3 -0
- package/templates/base/tsconfig.json +14 -0
- package/templates/minimal/routes/web.ts +11 -0
- package/templates/minimal/server.ts +10 -0
- package/templates/svelte/resources/js/app.ts +12 -0
- package/templates/svelte/resources/js/components/DarkModeToggle.svelte +67 -0
- package/templates/svelte/resources/js/components/Header.svelte +240 -0
- package/templates/svelte/resources/js/components/NaraIcon.svelte +3 -0
- package/templates/svelte/resources/js/components/Pagination.svelte +55 -0
- package/templates/svelte/resources/js/components/UserModal.svelte +234 -0
- package/templates/svelte/resources/js/components/helper.ts +300 -0
- package/templates/svelte/resources/js/pages/auth/forgot-password.svelte +97 -0
- package/templates/svelte/resources/js/pages/auth/login.svelte +138 -0
- package/templates/svelte/resources/js/pages/auth/register.svelte +176 -0
- package/templates/svelte/resources/js/pages/auth/reset-password.svelte +106 -0
- package/templates/svelte/resources/js/pages/dashboard.svelte +224 -0
- package/templates/svelte/resources/js/pages/landing.svelte +446 -0
- package/templates/svelte/resources/js/pages/profile.svelte +368 -0
- package/templates/svelte/resources/js/pages/users.svelte +260 -0
- package/templates/svelte/resources/views/inertia.html +12 -0
- package/templates/svelte/routes/web.ts +17 -0
- package/templates/svelte/server.ts +12 -0
- package/templates/svelte/vite.config.ts +19 -0
- package/templates/vue/resources/js/app.ts +14 -0
- package/templates/vue/resources/js/components/DarkModeToggle.vue +81 -0
- package/templates/vue/resources/js/components/Header.vue +251 -0
- package/templates/vue/resources/js/components/NaraIcon.vue +5 -0
- package/templates/vue/resources/js/components/Pagination.vue +71 -0
- package/templates/vue/resources/js/components/UserModal.vue +276 -0
- package/templates/vue/resources/js/components/index.ts +5 -0
- package/templates/vue/resources/js/pages/auth/forgot-password.vue +105 -0
- package/templates/vue/resources/js/pages/auth/login.vue +142 -0
- package/templates/vue/resources/js/pages/auth/register.vue +183 -0
- package/templates/vue/resources/js/pages/auth/reset-password.vue +115 -0
- package/templates/vue/resources/js/pages/dashboard.vue +233 -0
- package/templates/vue/resources/js/pages/landing.vue +358 -0
- package/templates/vue/resources/js/pages/profile.vue +370 -0
- package/templates/vue/resources/js/pages/users.vue +264 -0
- package/templates/vue/resources/views/inertia.html +12 -0
- package/templates/vue/routes/web.ts +17 -0
- package/templates/vue/server.ts +12 -0
- package/templates/vue/vite.config.ts +19 -0
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { onMount } from 'svelte';
|
|
3
|
+
import { inertia, router } from '@inertiajs/svelte'
|
|
4
|
+
import { Toast } from '../../Components/helper';
|
|
5
|
+
import NaraIcon from '../../Components/NaraIcon.svelte';
|
|
6
|
+
import { fade, fly } from 'svelte/transition';
|
|
7
|
+
|
|
8
|
+
onMount(() => {
|
|
9
|
+
// Logic for onMount if needed in future
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
interface LoginForm {
|
|
13
|
+
email: string;
|
|
14
|
+
password: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
let form: LoginForm = {
|
|
18
|
+
email: '',
|
|
19
|
+
password: '',
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
let { error }: { error?: string } = $props();
|
|
23
|
+
|
|
24
|
+
$effect(() => {
|
|
25
|
+
if (error) Toast(error, 'error');
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
function submitForm(): void {
|
|
29
|
+
router.post("/login", { email: form.email, password: form.password })
|
|
30
|
+
}
|
|
31
|
+
</script>
|
|
32
|
+
|
|
33
|
+
<div class="min-h-screen bg-white dark:bg-black text-slate-900 dark:text-slate-100 flex overflow-hidden">
|
|
34
|
+
|
|
35
|
+
<!-- Left Panel: Form -->
|
|
36
|
+
<div class="w-full lg:w-1/2 flex flex-col justify-between p-8 lg:p-12 z-10 relative">
|
|
37
|
+
<div>
|
|
38
|
+
<a href="/" class="text-2xl font-bold tracking-tighter flex items-center gap-2">
|
|
39
|
+
<NaraIcon />
|
|
40
|
+
<span>NARA.</span>
|
|
41
|
+
</a>
|
|
42
|
+
</div>
|
|
43
|
+
|
|
44
|
+
<div class="max-w-md w-full mx-auto" in:fly={{ y: 20, duration: 800 }}>
|
|
45
|
+
<h1 class="text-4xl lg:text-5xl font-bold tracking-tight mb-2">Welcome Back.</h1>
|
|
46
|
+
<p class="text-slate-500 dark:text-slate-400 mb-10 text-lg">Enter your credentials to access the grid.</p>
|
|
47
|
+
|
|
48
|
+
<!-- Google Login Button -->
|
|
49
|
+
<div class="flex flex-col space-y-4 mb-8">
|
|
50
|
+
<a href="/google/redirect"
|
|
51
|
+
class="group relative w-full flex items-center justify-center px-6 py-4 border border-slate-200 dark:border-white/10 rounded-xl bg-slate-50 dark:bg-white/5 hover:bg-slate-100 dark:hover:bg-white/10 transition-all duration-300">
|
|
52
|
+
<svg class="h-5 w-5 mr-3 transition-transform group-hover:scale-110" viewBox="0 0 24 24">
|
|
53
|
+
<path d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z" fill="#4285F4"/>
|
|
54
|
+
<path d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z" fill="#34A853"/>
|
|
55
|
+
<path d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z" fill="#FBBC05"/>
|
|
56
|
+
<path d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z" fill="#EA4335"/>
|
|
57
|
+
</svg>
|
|
58
|
+
<span class="font-medium text-slate-700 dark:text-slate-200">Continue with Google</span>
|
|
59
|
+
</a>
|
|
60
|
+
|
|
61
|
+
<div class="relative py-2">
|
|
62
|
+
<div class="absolute inset-0 flex items-center">
|
|
63
|
+
<div class="w-full border-t border-slate-200 dark:border-white/10"></div>
|
|
64
|
+
</div>
|
|
65
|
+
<div class="relative flex justify-center text-xs uppercase tracking-widest">
|
|
66
|
+
<span class="bg-white dark:bg-black px-4 text-slate-400">Or via email</span>
|
|
67
|
+
</div>
|
|
68
|
+
</div>
|
|
69
|
+
</div>
|
|
70
|
+
|
|
71
|
+
<form class="space-y-5" on:submit|preventDefault={submitForm}>
|
|
72
|
+
<div class="space-y-1">
|
|
73
|
+
<label for="email" class="block text-sm font-medium text-slate-700 dark:text-slate-300 ml-1">Email</label>
|
|
74
|
+
<input bind:value={form.email} required type="text" name="email" id="email"
|
|
75
|
+
class="w-full px-5 py-4 bg-slate-50 dark:bg-white/5 border border-slate-200 dark:border-white/10 rounded-xl focus:ring-2 focus:ring-primary-500/50 focus:border-primary-500 outline-none transition-all dark:text-white placeholder:text-slate-400"
|
|
76
|
+
placeholder="nara@example.com" >
|
|
77
|
+
</div>
|
|
78
|
+
|
|
79
|
+
<div class="space-y-1">
|
|
80
|
+
<label for="password" class="block text-sm font-medium text-slate-700 dark:text-slate-300 ml-1">Password</label>
|
|
81
|
+
<input bind:value={form.password} required type="password" name="password" id="password"
|
|
82
|
+
placeholder="••••••••"
|
|
83
|
+
class="w-full px-5 py-4 bg-slate-50 dark:bg-white/5 border border-slate-200 dark:border-white/10 rounded-xl focus:ring-2 focus:ring-primary-500/50 focus:border-primary-500 outline-none transition-all dark:text-white placeholder:text-slate-400" >
|
|
84
|
+
</div>
|
|
85
|
+
|
|
86
|
+
<div class="flex items-center justify-end">
|
|
87
|
+
<a href="/forgot-password" use:inertia class="text-sm font-medium text-slate-500 hover:text-primary-500 transition-colors">Forgot password?</a>
|
|
88
|
+
</div>
|
|
89
|
+
|
|
90
|
+
<button type="submit"
|
|
91
|
+
class="group w-full relative overflow-hidden rounded-xl bg-slate-900 dark:bg-white text-white dark:text-black font-bold text-lg py-4 transition-transform active:scale-[0.98]">
|
|
92
|
+
<span class="relative z-10">LOGIN</span>
|
|
93
|
+
<div class="absolute inset-0 bg-primary-500 transform translate-y-full transition-transform duration-300 group-hover:translate-y-0"></div>
|
|
94
|
+
</button>
|
|
95
|
+
|
|
96
|
+
<p class="text-center text-slate-500 dark:text-slate-400 mt-6">
|
|
97
|
+
Don't have an account? <a href="/register" use:inertia class="font-bold text-primary-600 dark:text-primary-400 hover:underline">Sign up</a>
|
|
98
|
+
</p>
|
|
99
|
+
</form>
|
|
100
|
+
</div>
|
|
101
|
+
|
|
102
|
+
<div class="text-xs text-slate-400 dark:text-slate-600">
|
|
103
|
+
© 2025 NARA INC.
|
|
104
|
+
</div>
|
|
105
|
+
</div>
|
|
106
|
+
|
|
107
|
+
<!-- Right Panel: Visual -->
|
|
108
|
+
<div class="hidden lg:flex w-1/2 bg-surface-card-dark relative overflow-hidden items-center justify-center">
|
|
109
|
+
<div class="absolute inset-0 bg-[url('https://grainy-gradients.vercel.app/noise.svg')] opacity-30"></div>
|
|
110
|
+
|
|
111
|
+
<!-- Abstract blobs -->
|
|
112
|
+
<div class="absolute top-0 right-0 w-[600px] h-[600px] bg-primary-500/20 rounded-full blur-[120px] -translate-y-1/2 translate-x-1/2"></div>
|
|
113
|
+
<div class="absolute bottom-0 left-0 w-[600px] h-[600px] bg-accent-500/10 rounded-full blur-[120px] translate-y-1/2 -translate-x-1/2"></div>
|
|
114
|
+
|
|
115
|
+
<div class="relative z-10 max-w-lg text-center p-12">
|
|
116
|
+
<h2 class="text-6xl font-bold tracking-tighter text-white mb-6 leading-[0.9]">
|
|
117
|
+
PURE <br/>
|
|
118
|
+
<span class="text-transparent bg-clip-text bg-gradient-to-r from-primary-400 to-info-300">VELOCITY</span>
|
|
119
|
+
</h2>
|
|
120
|
+
<p class="text-xl text-slate-400 font-serif italic">
|
|
121
|
+
"The only thing faster than Nara is the thought of using it."
|
|
122
|
+
</p>
|
|
123
|
+
|
|
124
|
+
<!-- Code Snippet Decoration -->
|
|
125
|
+
<div class="mt-12 text-left bg-black/50 backdrop-blur-md rounded-xl border border-white/10 p-6 font-mono text-xs text-slate-300 shadow-2xl transform rotate-3 hover:rotate-0 transition-transform duration-500">
|
|
126
|
+
<div class="flex gap-2 mb-4">
|
|
127
|
+
<div class="w-3 h-3 rounded-full bg-red-500"></div>
|
|
128
|
+
<div class="w-3 h-3 rounded-full bg-yellow-500"></div>
|
|
129
|
+
<div class="w-3 h-3 rounded-full bg-green-500"></div>
|
|
130
|
+
</div>
|
|
131
|
+
<div>
|
|
132
|
+
<span class="text-purple-400">const</span> <span class="text-blue-400">future</span> = <span class="text-purple-400">await</span> nara.<span class="text-yellow-300">load</span>();<br/>
|
|
133
|
+
<span class="text-slate-500">// Welcome to the new standard.</span>
|
|
134
|
+
</div>
|
|
135
|
+
</div>
|
|
136
|
+
</div>
|
|
137
|
+
</div>
|
|
138
|
+
</div>
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { onMount } from 'svelte';
|
|
3
|
+
import { inertia, router } from '@inertiajs/svelte'
|
|
4
|
+
import { password_generator, Toast } from '../../Components/helper';
|
|
5
|
+
import NaraIcon from '../../Components/NaraIcon.svelte';
|
|
6
|
+
import { fade, fly } from 'svelte/transition';
|
|
7
|
+
|
|
8
|
+
onMount(() => {
|
|
9
|
+
// Logic for onMount if needed in future
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
interface RegisterForm {
|
|
13
|
+
email: string;
|
|
14
|
+
password: string;
|
|
15
|
+
name: string;
|
|
16
|
+
phone: string;
|
|
17
|
+
password_confirmation: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
let form: RegisterForm = {
|
|
21
|
+
email: '',
|
|
22
|
+
password: '',
|
|
23
|
+
name: '',
|
|
24
|
+
phone: '',
|
|
25
|
+
password_confirmation: '',
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
let { error }: { error?: string } = $props();
|
|
29
|
+
|
|
30
|
+
$effect(() => {
|
|
31
|
+
if (error) Toast(error, 'error');
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
function submitForm(): void {
|
|
35
|
+
if (form.password != form.password_confirmation) {
|
|
36
|
+
Toast("Password dan konfirmasi password harus sama", "error");
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
form.phone = form.phone.toString()
|
|
41
|
+
router.post("/register", form as any)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function generatePassword(): void {
|
|
45
|
+
const retVal = password_generator(10);
|
|
46
|
+
form.password = retVal
|
|
47
|
+
form.password_confirmation = retVal
|
|
48
|
+
}
|
|
49
|
+
</script>
|
|
50
|
+
|
|
51
|
+
<div class="min-h-screen bg-white dark:bg-black text-slate-900 dark:text-slate-100 flex overflow-hidden">
|
|
52
|
+
|
|
53
|
+
<!-- Right Panel: Visual (Swapped for Register) -->
|
|
54
|
+
<div class="hidden lg:flex w-1/2 bg-surface-card-dark relative overflow-hidden items-center justify-center order-2 lg:order-1">
|
|
55
|
+
<div class="absolute inset-0 bg-[url('https://grainy-gradients.vercel.app/noise.svg')] opacity-30"></div>
|
|
56
|
+
|
|
57
|
+
<!-- Abstract blobs -->
|
|
58
|
+
<div class="absolute top-0 left-0 w-[600px] h-[600px] bg-info-500/20 rounded-full blur-[120px] -translate-y-1/2 -translate-x-1/2"></div>
|
|
59
|
+
<div class="absolute bottom-0 right-0 w-[600px] h-[600px] bg-primary-500/10 rounded-full blur-[120px] translate-y-1/2 translate-x-1/2"></div>
|
|
60
|
+
|
|
61
|
+
<div class="relative z-10 max-w-lg text-center p-12">
|
|
62
|
+
<h2 class="text-6xl font-bold tracking-tighter text-white mb-6 leading-[0.9]">
|
|
63
|
+
JOIN THE <br/>
|
|
64
|
+
<span class="text-transparent bg-clip-text bg-gradient-to-r from-info-400 to-accent-300">REVOLUTION</span>
|
|
65
|
+
</h2>
|
|
66
|
+
<p class="text-xl text-slate-400 font-serif italic">
|
|
67
|
+
"Build what others can't. Ship when others don't."
|
|
68
|
+
</p>
|
|
69
|
+
|
|
70
|
+
<!-- Terminal Decoration -->
|
|
71
|
+
<div class="mt-12 text-left bg-black/50 backdrop-blur-md rounded-xl border border-white/10 p-6 font-mono text-xs text-slate-300 shadow-2xl transform -rotate-2 hover:rotate-0 transition-transform duration-500">
|
|
72
|
+
<div class="flex gap-2 mb-4">
|
|
73
|
+
<div class="w-3 h-3 rounded-full bg-slate-700"></div>
|
|
74
|
+
<div class="w-3 h-3 rounded-full bg-slate-700"></div>
|
|
75
|
+
<div class="w-3 h-3 rounded-full bg-slate-700"></div>
|
|
76
|
+
</div>
|
|
77
|
+
<div class="space-y-2">
|
|
78
|
+
<div><span class="text-primary-400">$</span> init user --new</div>
|
|
79
|
+
<div class="text-slate-500">Creating workspace...</div>
|
|
80
|
+
<div class="text-slate-500">Allocating resources...</div>
|
|
81
|
+
<div><span class="text-info-400">✓</span> User created successfully.</div>
|
|
82
|
+
</div>
|
|
83
|
+
</div>
|
|
84
|
+
</div>
|
|
85
|
+
</div>
|
|
86
|
+
|
|
87
|
+
<!-- Left Panel: Form -->
|
|
88
|
+
<div class="w-full lg:w-1/2 flex flex-col justify-between p-8 lg:p-12 z-10 relative overflow-y-auto order-1 lg:order-2">
|
|
89
|
+
<div>
|
|
90
|
+
<a href="/" class="text-2xl font-bold tracking-tighter flex items-center gap-2 justify-end lg:justify-start">
|
|
91
|
+
<NaraIcon />
|
|
92
|
+
<span>NARA.</span>
|
|
93
|
+
</a>
|
|
94
|
+
</div>
|
|
95
|
+
|
|
96
|
+
<div class="max-w-md w-full mx-auto mt-8 lg:mt-0" in:fly={{ y: 20, duration: 800 }}>
|
|
97
|
+
<h1 class="text-4xl lg:text-5xl font-bold tracking-tight mb-2">Create Account.</h1>
|
|
98
|
+
<p class="text-slate-500 dark:text-slate-400 mb-8 text-lg">Start building your legacy.</p>
|
|
99
|
+
|
|
100
|
+
<!-- Google Signup Button -->
|
|
101
|
+
<div class="flex flex-col space-y-4 mb-8">
|
|
102
|
+
<a href="/google/redirect"
|
|
103
|
+
class="group relative w-full flex items-center justify-center px-6 py-4 border border-slate-200 dark:border-white/10 rounded-xl bg-slate-50 dark:bg-white/5 hover:bg-slate-100 dark:hover:bg-white/10 transition-all duration-300">
|
|
104
|
+
<svg class="h-5 w-5 mr-3 transition-transform group-hover:scale-110" viewBox="0 0 24 24">
|
|
105
|
+
<path d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z" fill="#4285F4"/>
|
|
106
|
+
<path d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z" fill="#34A853"/>
|
|
107
|
+
<path d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z" fill="#FBBC05"/>
|
|
108
|
+
<path d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z" fill="#EA4335"/>
|
|
109
|
+
</svg>
|
|
110
|
+
<span class="font-medium text-slate-700 dark:text-slate-200">Sign up with Google</span>
|
|
111
|
+
</a>
|
|
112
|
+
|
|
113
|
+
<div class="relative py-2">
|
|
114
|
+
<div class="absolute inset-0 flex items-center">
|
|
115
|
+
<div class="w-full border-t border-slate-200 dark:border-white/10"></div>
|
|
116
|
+
</div>
|
|
117
|
+
<div class="relative flex justify-center text-xs uppercase tracking-widest">
|
|
118
|
+
<span class="bg-white dark:bg-black px-4 text-slate-400">Or via email</span>
|
|
119
|
+
</div>
|
|
120
|
+
</div>
|
|
121
|
+
</div>
|
|
122
|
+
|
|
123
|
+
<form class="space-y-4" on:submit|preventDefault={submitForm}>
|
|
124
|
+
<div class="space-y-1">
|
|
125
|
+
<label for="name" class="block text-sm font-medium text-slate-700 dark:text-slate-300 ml-1">Full Name</label>
|
|
126
|
+
<input bind:value={form.name} required type="text" name="name" id="name"
|
|
127
|
+
class="w-full px-5 py-3 bg-slate-50 dark:bg-white/5 border border-slate-200 dark:border-white/10 rounded-xl focus:ring-2 focus:ring-info-500/50 focus:border-info-500 outline-none transition-all dark:text-white placeholder:text-slate-400"
|
|
128
|
+
placeholder="Rama Ren" >
|
|
129
|
+
</div>
|
|
130
|
+
|
|
131
|
+
<div class="space-y-1">
|
|
132
|
+
<label for="email" class="block text-sm font-medium text-slate-700 dark:text-slate-300 ml-1">Email</label>
|
|
133
|
+
<input bind:value={form.email} required type="text" name="email" id="email"
|
|
134
|
+
class="w-full px-5 py-3 bg-slate-50 dark:bg-white/5 border border-slate-200 dark:border-white/10 rounded-xl focus:ring-2 focus:ring-info-500/50 focus:border-info-500 outline-none transition-all dark:text-white placeholder:text-slate-400"
|
|
135
|
+
placeholder="nara@example.com" >
|
|
136
|
+
</div>
|
|
137
|
+
|
|
138
|
+
<div class="grid grid-cols-2 gap-4">
|
|
139
|
+
<div class="space-y-1">
|
|
140
|
+
<label for="password" class="block text-sm font-medium text-slate-700 dark:text-slate-300 ml-1">Password</label>
|
|
141
|
+
<input bind:value={form.password} required type="password" name="password" id="password"
|
|
142
|
+
placeholder="••••••••"
|
|
143
|
+
class="w-full px-5 py-3 bg-slate-50 dark:bg-white/5 border border-slate-200 dark:border-white/10 rounded-xl focus:ring-2 focus:ring-info-500/50 focus:border-info-500 outline-none transition-all dark:text-white placeholder:text-slate-400" >
|
|
144
|
+
</div>
|
|
145
|
+
<div class="space-y-1">
|
|
146
|
+
<label for="confirm-password" class="block text-sm font-medium text-slate-700 dark:text-slate-300 ml-1">Confirm</label>
|
|
147
|
+
<input bind:value={form.password_confirmation} type="password" name="confirm-password" id="confirm-password"
|
|
148
|
+
placeholder="••••••••"
|
|
149
|
+
class="w-full px-5 py-3 bg-slate-50 dark:bg-white/5 border border-slate-200 dark:border-white/10 rounded-xl focus:ring-2 focus:ring-info-500/50 focus:border-info-500 outline-none transition-all dark:text-white placeholder:text-slate-400" >
|
|
150
|
+
</div>
|
|
151
|
+
</div>
|
|
152
|
+
|
|
153
|
+
<div class="flex justify-end">
|
|
154
|
+
<button type="button" on:click="{generatePassword}" class="text-xs font-mono text-info-400 hover:text-info-300 transition-colors flex items-center gap-1">
|
|
155
|
+
<svg class="w-3 h-3" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 12V7C21 6.46957 20.7893 5.96086 20.4142 5.58579C20.0391 5.21071 19.5304 5 19 5H5C4.46957 5 3.96086 5.21071 3.58579 5.58579C3.21071 5.96086 3 6.46957 3 7V17C3 17.5304 3.21071 18.0391 3.58579 18.4142C3.96086 18.7893 4.46957 19 5 19H12" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
|
156
|
+
GENERATE SECURE PASSWORD
|
|
157
|
+
</button>
|
|
158
|
+
</div>
|
|
159
|
+
|
|
160
|
+
<button type="submit"
|
|
161
|
+
class="group w-full relative overflow-hidden rounded-xl bg-slate-900 dark:bg-white text-white dark:text-black font-bold text-lg py-4 transition-transform active:scale-[0.98] mt-4">
|
|
162
|
+
<span class="relative z-10">CREATE ACCOUNT</span>
|
|
163
|
+
<div class="absolute inset-0 bg-info-500 transform translate-y-full transition-transform duration-300 group-hover:translate-y-0"></div>
|
|
164
|
+
</button>
|
|
165
|
+
|
|
166
|
+
<p class="text-center text-slate-500 dark:text-slate-400 mt-6">
|
|
167
|
+
Already have an account? <a href="/login" use:inertia class="font-bold text-info-500 dark:text-info-400 hover:underline">Login</a>
|
|
168
|
+
</p>
|
|
169
|
+
</form>
|
|
170
|
+
</div>
|
|
171
|
+
|
|
172
|
+
<div class="text-xs text-slate-400 dark:text-slate-600 mt-8 lg:mt-0 text-right lg:text-left">
|
|
173
|
+
© 2025 NARA INC.
|
|
174
|
+
</div>
|
|
175
|
+
</div>
|
|
176
|
+
</div>
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { inertia, router } from '@inertiajs/svelte'
|
|
3
|
+
import NaraIcon from '../../Components/NaraIcon.svelte';
|
|
4
|
+
import DarkModeToggle from '../../Components/DarkModeToggle.svelte';
|
|
5
|
+
import { password_generator, Toast } from '../../Components/helper';
|
|
6
|
+
|
|
7
|
+
interface ResetPasswordForm {
|
|
8
|
+
password: string;
|
|
9
|
+
password_confirmation: string;
|
|
10
|
+
id: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
let { id, error }: { id: string, error?: string } = $props();
|
|
14
|
+
|
|
15
|
+
$effect(() => {
|
|
16
|
+
if (error) Toast(error, 'error');
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
let form: ResetPasswordForm = {
|
|
20
|
+
password: '',
|
|
21
|
+
password_confirmation: '',
|
|
22
|
+
id
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function generatePassword(): void {
|
|
26
|
+
const retVal = password_generator(10);
|
|
27
|
+
form.password = retVal
|
|
28
|
+
form.password_confirmation = retVal
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function submitForm(): void {
|
|
32
|
+
if (form.password != form.password_confirmation) {
|
|
33
|
+
Toast("Password dan konfirmasi password harus sama", "error")
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
router.post(`/reset-password`, form as any)
|
|
38
|
+
}
|
|
39
|
+
</script>
|
|
40
|
+
|
|
41
|
+
<section class="min-h-screen bg-gradient-to-b from-slate-950 via-slate-900 to-slate-950 text-slate-50">
|
|
42
|
+
<!-- Header with dark mode toggle -->
|
|
43
|
+
<header class="fixed inset-x-0 top-0 z-40 border-b border-slate-800/60 bg-slate-950/80 backdrop-blur-xl">
|
|
44
|
+
<div class="max-w-6xl mx-auto flex h-16 items-center justify-between px-4 sm:h-20 sm:px-6 lg:px-8">
|
|
45
|
+
<a href="/" use:inertia class="flex items-center gap-2">
|
|
46
|
+
<img src="/public/nara.png" alt="Nara logo" class="h-7 w-7 rounded-lg object-cover" />
|
|
47
|
+
<div class="flex flex-col leading-tight">
|
|
48
|
+
<span class="text-sm font-semibold tracking-tight text-slate-50">Nara</span>
|
|
49
|
+
<span class="text-[10px] uppercase tracking-[0.22em] text-slate-500">TypeScript framework</span>
|
|
50
|
+
</div>
|
|
51
|
+
</a>
|
|
52
|
+
<div class="flex items-center gap-3">
|
|
53
|
+
<DarkModeToggle />
|
|
54
|
+
</div>
|
|
55
|
+
</div>
|
|
56
|
+
</header>
|
|
57
|
+
|
|
58
|
+
<div class="flex flex-col items-center justify-center px-6 py-8 mx-auto min-h-screen lg:py-0">
|
|
59
|
+
<div class="flex items-center mb-6 text-2xl font-semibold text-slate-50">
|
|
60
|
+
<NaraIcon></NaraIcon>
|
|
61
|
+
</div>
|
|
62
|
+
<div class="w-full max-w-md rounded-3xl border border-slate-800/80 bg-slate-900/70 backdrop-blur-xl shadow-[0_24px_80px_rgba(15,23,42,0.8)] md:mt-0 sm:max-w-md xl:p-0">
|
|
63
|
+
<div class="p-6 space-y-4 md:space-y-6 sm:p-8">
|
|
64
|
+
<h1 class="text-xl font-bold leading-tight tracking-tight text-slate-50 md:text-2xl">
|
|
65
|
+
Reset Password
|
|
66
|
+
</h1>
|
|
67
|
+
|
|
68
|
+
<form class="space-y-4 md:space-y-6" on:submit|preventDefault={submitForm}>
|
|
69
|
+
<div>
|
|
70
|
+
<label for="password" class="block mb-2 text-sm font-medium text-slate-200">Password Baru</label>
|
|
71
|
+
<input
|
|
72
|
+
bind:value={form.password}
|
|
73
|
+
type="password"
|
|
74
|
+
name="password"
|
|
75
|
+
id="password"
|
|
76
|
+
placeholder="••••••••"
|
|
77
|
+
class="bg-slate-900/70 border border-slate-700 text-slate-50 sm:text-sm rounded-lg focus:ring-2 focus:ring-primary-400 focus:border-primary-400 focus:outline-none block w-full py-2.5 px-3 placeholder-slate-500"
|
|
78
|
+
required
|
|
79
|
+
>
|
|
80
|
+
<button type="button" on:click={generatePassword} class="text-xs text-slate-400 mt-1">Generate Password</button>
|
|
81
|
+
</div>
|
|
82
|
+
<div>
|
|
83
|
+
<label for="confirm-password" class="block mb-2 text-sm font-medium text-slate-200">Konfirmasi Password</label>
|
|
84
|
+
<input
|
|
85
|
+
bind:value={form.password_confirmation}
|
|
86
|
+
type="password"
|
|
87
|
+
name="confirm-password"
|
|
88
|
+
id="confirm-password"
|
|
89
|
+
placeholder="••••••••"
|
|
90
|
+
class="bg-slate-900/70 border border-slate-700 text-slate-50 sm:text-sm rounded-lg focus:ring-2 focus:ring-primary-400 focus:border-primary-400 focus:outline-none block w-full py-2.5 px-3 placeholder-slate-500"
|
|
91
|
+
required
|
|
92
|
+
>
|
|
93
|
+
</div>
|
|
94
|
+
|
|
95
|
+
<button type="submit" class="w-full text-sm font-medium rounded-full px-5 py-2.5 text-slate-950 bg-primary-400 hover:bg-primary-300 focus:ring-4 focus:outline-none focus:ring-primary-300">
|
|
96
|
+
Reset Password
|
|
97
|
+
</button>
|
|
98
|
+
|
|
99
|
+
<p class="text-sm font-light text-slate-400">
|
|
100
|
+
Ingat password Anda? <a href="/login" use:inertia class="font-medium text-primary-400 hover:underline">Login disini</a>
|
|
101
|
+
</p>
|
|
102
|
+
</form>
|
|
103
|
+
</div>
|
|
104
|
+
</div>
|
|
105
|
+
</div>
|
|
106
|
+
</section>
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { fly } from 'svelte/transition';
|
|
3
|
+
import { page as inertiaPage, inertia } from '@inertiajs/svelte';
|
|
4
|
+
import Header from '../Components/Header.svelte';
|
|
5
|
+
import type { User } from '../types';
|
|
6
|
+
|
|
7
|
+
export let users: User[] = [];
|
|
8
|
+
export let search: string = '';
|
|
9
|
+
export let filter: string = 'all';
|
|
10
|
+
export let total: number = 0;
|
|
11
|
+
export let page: number = 1;
|
|
12
|
+
export let limit: number = 10;
|
|
13
|
+
export let totalPages: number = 1;
|
|
14
|
+
export let hasNext: boolean = false;
|
|
15
|
+
export let hasPrev: boolean = false;
|
|
16
|
+
|
|
17
|
+
const currentUser = $inertiaPage.props.user as User | undefined;
|
|
18
|
+
|
|
19
|
+
// Get current hour for greeting
|
|
20
|
+
const hour = new Date().getHours();
|
|
21
|
+
const greeting = hour < 12 ? 'Good morning' : hour < 18 ? 'Good afternoon' : 'Good evening';
|
|
22
|
+
</script>
|
|
23
|
+
|
|
24
|
+
<Header group="dashboard" />
|
|
25
|
+
|
|
26
|
+
<div class="min-h-screen bg-surface-light dark:bg-surface-dark text-slate-900 dark:text-slate-100 transition-colors duration-500 overflow-x-hidden selection:bg-primary-400 selection:text-black">
|
|
27
|
+
|
|
28
|
+
<!-- Background Effects -->
|
|
29
|
+
<div class="fixed inset-0 pointer-events-none z-0">
|
|
30
|
+
<div class="absolute top-0 right-0 w-[800px] h-[800px] bg-primary-500/5 rounded-full blur-3xl -mr-96 -mt-96"></div>
|
|
31
|
+
<div class="absolute bottom-0 left-0 w-[600px] h-[600px] bg-accent-500/5 rounded-full blur-3xl -ml-64 -mb-64"></div>
|
|
32
|
+
</div>
|
|
33
|
+
|
|
34
|
+
<!-- Hero Section -->
|
|
35
|
+
<section class="relative px-6 sm:px-12 lg:px-24 pt-24 pb-20">
|
|
36
|
+
<div class="max-w-[90rem] mx-auto">
|
|
37
|
+
|
|
38
|
+
<!-- Giant Welcome -->
|
|
39
|
+
<div class="mb-16" in:fly={{ y: 50, duration: 800 }}>
|
|
40
|
+
<p class="text-xs font-bold uppercase tracking-[0.3em] text-primary-600 dark:text-primary-400 mb-6">
|
|
41
|
+
{greeting}
|
|
42
|
+
</p>
|
|
43
|
+
<h1 class="text-[8vw] sm:text-[6vw] lg:text-[5vw] leading-[0.9] font-bold tracking-tighter">
|
|
44
|
+
Welcome back,
|
|
45
|
+
<span class="block text-transparent bg-clip-text bg-gradient-to-r from-primary-500 to-info-300 dark:from-primary-400 dark:to-info-300">
|
|
46
|
+
{$inertiaPage.props.user?.name || 'Commander'}
|
|
47
|
+
</span>
|
|
48
|
+
</h1>
|
|
49
|
+
</div>
|
|
50
|
+
|
|
51
|
+
<!-- Stats Grid - Radical Cards -->
|
|
52
|
+
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4 mb-20" in:fly={{ y: 30, duration: 800, delay: 200 }}>
|
|
53
|
+
|
|
54
|
+
<!-- Card: Total Users -->
|
|
55
|
+
<div class="group relative h-48 bg-surface-card-light dark:bg-surface-card-dark border border-slate-200 dark:border-white/5 hover:border-primary-500/50 dark:hover:border-primary-500/30 p-6 flex flex-col justify-between transition-all duration-500 overflow-hidden rounded-2xl">
|
|
56
|
+
<div class="absolute top-0 right-0 p-24 bg-primary-500/5 rounded-full blur-3xl -mr-12 -mt-12 group-hover:bg-primary-500/10 transition-colors duration-500"></div>
|
|
57
|
+
|
|
58
|
+
<div class="relative z-10 flex justify-between items-start">
|
|
59
|
+
<div class="p-2 bg-white dark:bg-white/5 rounded-lg border border-slate-200 dark:border-white/10 group-hover:scale-110 transition-transform duration-300">
|
|
60
|
+
<svg class="w-5 h-5 text-primary-600 dark:text-primary-400" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
|
|
61
|
+
<path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
62
|
+
<circle cx="9" cy="7" r="4" stroke-linecap="round" stroke-linejoin="round"/>
|
|
63
|
+
<path d="M23 21v-2a4 4 0 0 0-3-3.87" stroke-linecap="round" stroke-linejoin="round"/>
|
|
64
|
+
<path d="M16 3.13a4 4 0 0 1 0 7.75" stroke-linecap="round" stroke-linejoin="round"/>
|
|
65
|
+
</svg>
|
|
66
|
+
</div>
|
|
67
|
+
<span class="text-[10px] font-mono opacity-40 uppercase">Users</span>
|
|
68
|
+
</div>
|
|
69
|
+
|
|
70
|
+
<div class="relative z-10">
|
|
71
|
+
<p class="text-4xl font-bold tracking-tight mb-1">{total || users?.length || 0}</p>
|
|
72
|
+
<p class="text-xs text-slate-500 dark:text-slate-400">Total registered</p>
|
|
73
|
+
</div>
|
|
74
|
+
</div>
|
|
75
|
+
|
|
76
|
+
<!-- Card: Current Page -->
|
|
77
|
+
<div class="group relative h-48 bg-surface-card-light dark:bg-surface-card-dark border border-slate-200 dark:border-white/5 hover:border-accent-500/50 dark:hover:border-accent-500/30 p-6 flex flex-col justify-between transition-all duration-500 overflow-hidden rounded-2xl">
|
|
78
|
+
<div class="absolute top-0 right-0 p-24 bg-accent-500/5 rounded-full blur-3xl -mr-12 -mt-12 group-hover:bg-accent-500/10 transition-colors duration-500"></div>
|
|
79
|
+
|
|
80
|
+
<div class="relative z-10 flex justify-between items-start">
|
|
81
|
+
<div class="p-2 bg-white dark:bg-white/5 rounded-lg border border-slate-200 dark:border-white/10 group-hover:scale-110 transition-transform duration-300">
|
|
82
|
+
<svg class="w-5 h-5 text-accent-600 dark:text-accent-400" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
|
|
83
|
+
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" stroke-linecap="round" stroke-linejoin="round"/>
|
|
84
|
+
<polyline points="14 2 14 8 20 8" stroke-linecap="round" stroke-linejoin="round"/>
|
|
85
|
+
</svg>
|
|
86
|
+
</div>
|
|
87
|
+
<span class="text-[10px] font-mono opacity-40 uppercase">Page</span>
|
|
88
|
+
</div>
|
|
89
|
+
|
|
90
|
+
<div class="relative z-10">
|
|
91
|
+
<p class="text-4xl font-bold tracking-tight mb-1">{page}<span class="text-lg text-slate-400">/{totalPages}</span></p>
|
|
92
|
+
<p class="text-xs text-slate-500 dark:text-slate-400">Current view</p>
|
|
93
|
+
</div>
|
|
94
|
+
</div>
|
|
95
|
+
|
|
96
|
+
<!-- Card: Filter Status -->
|
|
97
|
+
<div class="group relative h-48 bg-surface-card-light dark:bg-surface-card-dark border border-slate-200 dark:border-white/5 hover:border-warning-500/50 dark:hover:border-warning-500/30 p-6 flex flex-col justify-between transition-all duration-500 overflow-hidden rounded-2xl">
|
|
98
|
+
<div class="absolute top-0 right-0 p-24 bg-warning-500/5 rounded-full blur-3xl -mr-12 -mt-12 group-hover:bg-warning-500/10 transition-colors duration-500"></div>
|
|
99
|
+
|
|
100
|
+
<div class="relative z-10 flex justify-between items-start">
|
|
101
|
+
<div class="p-2 bg-white dark:bg-white/5 rounded-lg border border-slate-200 dark:border-white/10 group-hover:scale-110 transition-transform duration-300">
|
|
102
|
+
<svg class="w-5 h-5 text-warning-600 dark:text-warning-400" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
|
|
103
|
+
<polygon points="22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3" stroke-linecap="round" stroke-linejoin="round"/>
|
|
104
|
+
</svg>
|
|
105
|
+
</div>
|
|
106
|
+
<span class="text-[10px] font-mono opacity-40 uppercase">Filter</span>
|
|
107
|
+
</div>
|
|
108
|
+
|
|
109
|
+
<div class="relative z-10">
|
|
110
|
+
<p class="text-2xl font-bold tracking-tight mb-1 capitalize">{filter}</p>
|
|
111
|
+
<p class="text-xs text-slate-500 dark:text-slate-400">Active filter</p>
|
|
112
|
+
</div>
|
|
113
|
+
</div>
|
|
114
|
+
|
|
115
|
+
<!-- Card: Account Status -->
|
|
116
|
+
<div class="group relative h-48 bg-slate-900 dark:bg-slate-100 text-white dark:text-slate-900 p-6 flex flex-col justify-between transition-all duration-500 overflow-hidden rounded-2xl">
|
|
117
|
+
<div class="absolute inset-0 bg-[url('https://grainy-gradients.vercel.app/noise.svg')] opacity-20"></div>
|
|
118
|
+
|
|
119
|
+
<div class="relative z-10 flex justify-between items-start">
|
|
120
|
+
<div class="p-2 bg-white/10 dark:bg-black/5 rounded-lg border border-white/10 dark:border-black/5 group-hover:scale-110 transition-transform duration-300">
|
|
121
|
+
<svg class="w-5 h-5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
|
|
122
|
+
<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" stroke-linecap="round" stroke-linejoin="round"/>
|
|
123
|
+
</svg>
|
|
124
|
+
</div>
|
|
125
|
+
<span class="text-[10px] font-mono opacity-60 uppercase">Status</span>
|
|
126
|
+
</div>
|
|
127
|
+
|
|
128
|
+
<div class="relative z-10">
|
|
129
|
+
<p class="text-2xl font-bold tracking-tight mb-1">{$inertiaPage.props.user?.is_admin ? 'Admin' : 'User'}</p>
|
|
130
|
+
<div class="flex items-center gap-2">
|
|
131
|
+
<span class="inline-flex h-2 w-2 rounded-full bg-primary-400 animate-pulse"></span>
|
|
132
|
+
<p class="text-xs opacity-80">{$inertiaPage.props.user?.is_verified ? 'Verified' : 'Unverified'}</p>
|
|
133
|
+
</div>
|
|
134
|
+
</div>
|
|
135
|
+
</div>
|
|
136
|
+
</div>
|
|
137
|
+
|
|
138
|
+
<!-- Account Details Section -->
|
|
139
|
+
<div class="grid grid-cols-1 lg:grid-cols-12 gap-8" in:fly={{ y: 30, duration: 800, delay: 400 }}>
|
|
140
|
+
|
|
141
|
+
<!-- Left: Quick Info -->
|
|
142
|
+
<div class="lg:col-span-5">
|
|
143
|
+
<span class="block text-xs font-bold uppercase tracking-[0.2em] text-slate-400 dark:text-slate-500 mb-6">Account Details</span>
|
|
144
|
+
|
|
145
|
+
<div class="space-y-4">
|
|
146
|
+
<div class="group p-6 border border-slate-200 dark:border-white/5 rounded-2xl hover:bg-slate-50 dark:hover:bg-white/5 transition-all duration-300">
|
|
147
|
+
<div class="flex items-center justify-between">
|
|
148
|
+
<div>
|
|
149
|
+
<p class="text-[10px] uppercase tracking-[0.2em] text-slate-400 mb-2">Email Address</p>
|
|
150
|
+
<p class="text-lg font-medium">{$inertiaPage.props.user?.email}</p>
|
|
151
|
+
</div>
|
|
152
|
+
<span class="px-3 py-1 text-[10px] font-bold uppercase tracking-wider rounded-full {$inertiaPage.props.user?.is_verified ? 'bg-primary-500/10 text-primary-600 dark:text-primary-400' : 'bg-warning-500/10 text-warning-600 dark:text-warning-400'}">
|
|
153
|
+
{$inertiaPage.props.user?.is_verified ? 'Verified' : 'Pending'}
|
|
154
|
+
</span>
|
|
155
|
+
</div>
|
|
156
|
+
</div>
|
|
157
|
+
|
|
158
|
+
<div class="group p-6 border border-slate-200 dark:border-white/5 rounded-2xl hover:bg-slate-50 dark:hover:bg-white/5 transition-all duration-300">
|
|
159
|
+
<p class="text-[10px] uppercase tracking-[0.2em] text-slate-400 mb-2">Search Query</p>
|
|
160
|
+
<p class="text-lg font-medium font-mono">{search || '—'}</p>
|
|
161
|
+
</div>
|
|
162
|
+
</div>
|
|
163
|
+
</div>
|
|
164
|
+
|
|
165
|
+
<!-- Right: Quick Actions -->
|
|
166
|
+
<div class="lg:col-span-7">
|
|
167
|
+
<span class="block text-xs font-bold uppercase tracking-[0.2em] text-slate-400 dark:text-slate-500 mb-6">Quick Actions</span>
|
|
168
|
+
|
|
169
|
+
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
|
170
|
+
<a
|
|
171
|
+
href="/users"
|
|
172
|
+
use:inertia
|
|
173
|
+
class="group relative p-6 border border-slate-200 dark:border-white/5 rounded-2xl hover:border-primary-500/50 transition-all duration-300 overflow-hidden"
|
|
174
|
+
>
|
|
175
|
+
<div class="absolute inset-0 bg-primary-500/5 transform translate-y-full group-hover:translate-y-0 transition-transform duration-500"></div>
|
|
176
|
+
<div class="relative z-10">
|
|
177
|
+
<div class="flex items-center justify-between mb-4">
|
|
178
|
+
<div class="h-10 w-10 bg-primary-500/10 rounded-full flex items-center justify-center">
|
|
179
|
+
<svg class="w-5 h-5 text-primary-600 dark:text-primary-400" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
|
|
180
|
+
<path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
181
|
+
<circle cx="9" cy="7" r="4" stroke-linecap="round" stroke-linejoin="round"/>
|
|
182
|
+
<path d="M23 21v-2a4 4 0 0 0-3-3.87" stroke-linecap="round" stroke-linejoin="round"/>
|
|
183
|
+
<path d="M16 3.13a4 4 0 0 1 0 7.75" stroke-linecap="round" stroke-linejoin="round"/>
|
|
184
|
+
</svg>
|
|
185
|
+
</div>
|
|
186
|
+
<svg class="w-4 h-4 text-slate-400 group-hover:translate-x-1 transition-transform" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
187
|
+
<path d="M5 12h14M12 5l7 7-7 7" stroke-linecap="round" stroke-linejoin="round"/>
|
|
188
|
+
</svg>
|
|
189
|
+
</div>
|
|
190
|
+
<h3 class="text-lg font-bold mb-1">Manage Users</h3>
|
|
191
|
+
<p class="text-xs text-slate-500 dark:text-slate-400">View and manage all registered users</p>
|
|
192
|
+
</div>
|
|
193
|
+
</a>
|
|
194
|
+
|
|
195
|
+
<a
|
|
196
|
+
href="/profile"
|
|
197
|
+
use:inertia
|
|
198
|
+
class="group relative p-6 border border-slate-200 dark:border-white/5 rounded-2xl hover:border-accent-500/50 transition-all duration-300 overflow-hidden"
|
|
199
|
+
>
|
|
200
|
+
<div class="absolute inset-0 bg-accent-500/5 transform translate-y-full group-hover:translate-y-0 transition-transform duration-500"></div>
|
|
201
|
+
<div class="relative z-10">
|
|
202
|
+
<div class="flex items-center justify-between mb-4">
|
|
203
|
+
<div class="h-10 w-10 bg-accent-500/10 rounded-full flex items-center justify-center">
|
|
204
|
+
<svg class="w-5 h-5 text-accent-600 dark:text-accent-400" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
|
|
205
|
+
<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
206
|
+
<circle cx="12" cy="7" r="4" stroke-linecap="round" stroke-linejoin="round"/>
|
|
207
|
+
</svg>
|
|
208
|
+
</div>
|
|
209
|
+
<svg class="w-4 h-4 text-slate-400 group-hover:translate-x-1 transition-transform" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
210
|
+
<path d="M5 12h14M12 5l7 7-7 7" stroke-linecap="round" stroke-linejoin="round"/>
|
|
211
|
+
</svg>
|
|
212
|
+
</div>
|
|
213
|
+
<h3 class="text-lg font-bold mb-1">Edit Profile</h3>
|
|
214
|
+
<p class="text-xs text-slate-500 dark:text-slate-400">Update your account information</p>
|
|
215
|
+
</div>
|
|
216
|
+
</a>
|
|
217
|
+
</div>
|
|
218
|
+
</div>
|
|
219
|
+
</div>
|
|
220
|
+
|
|
221
|
+
</div>
|
|
222
|
+
</section>
|
|
223
|
+
|
|
224
|
+
</div>
|