feat(frontend): Update nuxt-ui, add login, signup, logout
This commit is contained in:
@@ -23,3 +23,11 @@ Couldn't read your auth config. Error: Could not locate the bindings file. Tried
|
|||||||
https://github.com/WiseLibs/better-sqlite3/issues/1320
|
https://github.com/WiseLibs/better-sqlite3/issues/1320
|
||||||
|
|
||||||
https://github.com/WiseLibs/better-sqlite3/issues/146
|
https://github.com/WiseLibs/better-sqlite3/issues/146
|
||||||
|
|
||||||
|
### This version of Node.js requires NODE_MODULE_VERSION 131.
|
||||||
|
|
||||||
|
```
|
||||||
|
rm -fr node_modules; pnpm store prune
|
||||||
|
```
|
||||||
|
|
||||||
|
https://github.com/elizaOS/eliza/pull/665
|
||||||
|
|||||||
@@ -1,2 +1,16 @@
|
|||||||
@import 'tailwindcss';
|
@import 'tailwindcss' theme(static);
|
||||||
@import '@nuxt/ui-pro';
|
@import '@nuxt/ui-pro';
|
||||||
|
|
||||||
|
@theme static {
|
||||||
|
--color-green-50: #effdf5;
|
||||||
|
--color-green-100: #d9fbe8;
|
||||||
|
--color-green-200: #b3f5d1;
|
||||||
|
--color-green-300: #75edae;
|
||||||
|
--color-green-400: #00dc82;
|
||||||
|
--color-green-500: #00c16a;
|
||||||
|
--color-green-600: #00a155;
|
||||||
|
--color-green-700: #007f45;
|
||||||
|
--color-green-800: #016538;
|
||||||
|
--color-green-900: #0a5331;
|
||||||
|
--color-green-950: #052e16;
|
||||||
|
}
|
||||||
|
|||||||
185
legalconsenthub/components/UserMenu.vue
Normal file
185
legalconsenthub/components/UserMenu.vue
Normal file
@@ -0,0 +1,185 @@
|
|||||||
|
<template>
|
||||||
|
<UDropdownMenu
|
||||||
|
:items="items"
|
||||||
|
:content="{ align: 'center', collisionPadding: 12 }"
|
||||||
|
:ui="{ content: collapsed ? 'w-48' : 'w-(--reka-dropdown-menu-trigger-width)' }"
|
||||||
|
>
|
||||||
|
<UButton
|
||||||
|
v-bind="{
|
||||||
|
...user,
|
||||||
|
label: collapsed ? undefined : user?.name,
|
||||||
|
trailingIcon: collapsed ? undefined : 'i-lucide-chevrons-up-down'
|
||||||
|
}"
|
||||||
|
color="neutral"
|
||||||
|
variant="ghost"
|
||||||
|
block
|
||||||
|
:square="collapsed"
|
||||||
|
class="data-[state=open]:bg-(--ui-bg-elevated)"
|
||||||
|
:ui="{
|
||||||
|
trailingIcon: 'text-(--ui-text-dimmed)'
|
||||||
|
}"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<template #chip-leading="{ item }">
|
||||||
|
<span
|
||||||
|
:style="{ '--chip': `var(--color-${(item as any).chip}-400)` }"
|
||||||
|
class="ms-0.5 size-2 rounded-full bg-(--chip)"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</UDropdownMenu>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { DropdownMenuItem } from '@nuxt/ui'
|
||||||
|
|
||||||
|
defineProps<{
|
||||||
|
collapsed?: boolean
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const colorMode = useColorMode()
|
||||||
|
const appConfig = useAppConfig()
|
||||||
|
|
||||||
|
const colors = [
|
||||||
|
'red',
|
||||||
|
'orange',
|
||||||
|
'amber',
|
||||||
|
'yellow',
|
||||||
|
'lime',
|
||||||
|
'green',
|
||||||
|
'emerald',
|
||||||
|
'teal',
|
||||||
|
'cyan',
|
||||||
|
'sky',
|
||||||
|
'blue',
|
||||||
|
'indigo',
|
||||||
|
'violet',
|
||||||
|
'purple',
|
||||||
|
'fuchsia',
|
||||||
|
'pink',
|
||||||
|
'rose'
|
||||||
|
]
|
||||||
|
const neutrals = ['slate', 'gray', 'zinc', 'neutral', 'stone']
|
||||||
|
|
||||||
|
const { data: session } = await useSession(useFetch)
|
||||||
|
|
||||||
|
const user = ref({
|
||||||
|
name: session?.value?.user?.name,
|
||||||
|
avatar: {
|
||||||
|
src: '/_nuxt/public/favicon.ico',
|
||||||
|
alt: session?.value?.user?.name
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const items = computed<DropdownMenuItem[][]>(() => [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
type: 'label',
|
||||||
|
label: user.value.name,
|
||||||
|
avatar: user.value.avatar
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{
|
||||||
|
label: 'Profile',
|
||||||
|
icon: 'i-lucide-user'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Settings',
|
||||||
|
icon: 'i-lucide-settings',
|
||||||
|
to: '/settings'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{
|
||||||
|
label: 'Theme',
|
||||||
|
icon: 'i-lucide-palette',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
label: 'Primary',
|
||||||
|
slot: 'chip',
|
||||||
|
chip: appConfig.ui.colors.primary,
|
||||||
|
content: {
|
||||||
|
align: 'center',
|
||||||
|
collisionPadding: 16
|
||||||
|
},
|
||||||
|
children: colors.map((color) => ({
|
||||||
|
label: color,
|
||||||
|
chip: color,
|
||||||
|
slot: 'chip',
|
||||||
|
checked: appConfig.ui.colors.primary === color,
|
||||||
|
type: 'checkbox',
|
||||||
|
onSelect: (e) => {
|
||||||
|
e.preventDefault()
|
||||||
|
|
||||||
|
appConfig.ui.colors.primary = color
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Neutral',
|
||||||
|
slot: 'chip',
|
||||||
|
chip: appConfig.ui.colors.neutral,
|
||||||
|
content: {
|
||||||
|
align: 'end',
|
||||||
|
collisionPadding: 16
|
||||||
|
},
|
||||||
|
children: neutrals.map((color) => ({
|
||||||
|
label: color,
|
||||||
|
chip: color,
|
||||||
|
slot: 'chip',
|
||||||
|
type: 'checkbox',
|
||||||
|
checked: appConfig.ui.colors.neutral === color,
|
||||||
|
onSelect: (e) => {
|
||||||
|
e.preventDefault()
|
||||||
|
|
||||||
|
appConfig.ui.colors.neutral = color
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Appearance',
|
||||||
|
icon: 'i-lucide-sun-moon',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
label: 'Light',
|
||||||
|
icon: 'i-lucide-sun',
|
||||||
|
type: 'checkbox',
|
||||||
|
checked: colorMode.value === 'light',
|
||||||
|
onSelect(e: Event) {
|
||||||
|
e.preventDefault()
|
||||||
|
|
||||||
|
colorMode.preference = 'light'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Dark',
|
||||||
|
icon: 'i-lucide-moon',
|
||||||
|
type: 'checkbox',
|
||||||
|
checked: colorMode.value === 'dark',
|
||||||
|
onUpdateChecked(checked: boolean) {
|
||||||
|
if (checked) {
|
||||||
|
colorMode.preference = 'dark'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onSelect(e: Event) {
|
||||||
|
e.preventDefault()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{
|
||||||
|
label: 'Log out',
|
||||||
|
icon: 'i-lucide-log-out',
|
||||||
|
async onSelect(e: Event) {
|
||||||
|
e.preventDefault()
|
||||||
|
signOut()
|
||||||
|
await navigateTo('/login')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
])
|
||||||
|
</script>
|
||||||
16
legalconsenthub/layouts/auth.vue
Normal file
16
legalconsenthub/layouts/auth.vue
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<template>
|
||||||
|
<div class="h-screen flex items-center justify-center overlay">
|
||||||
|
<UButton
|
||||||
|
icon="i-lucide-chevron-left"
|
||||||
|
to="/"
|
||||||
|
size="xl"
|
||||||
|
color="neutral"
|
||||||
|
variant="subtle"
|
||||||
|
class="absolute left-8 top-8 rounded-full"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<UPageCard variant="subtle" class="max-w-sm w-full">
|
||||||
|
<slot />
|
||||||
|
</UPageCard>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@@ -3,6 +3,7 @@
|
|||||||
<UDashboardSearch />
|
<UDashboardSearch />
|
||||||
|
|
||||||
<UDashboardSidebar
|
<UDashboardSidebar
|
||||||
|
v-model:open="open"
|
||||||
collapsible
|
collapsible
|
||||||
resizable
|
resizable
|
||||||
class="bg-(--ui-bg-elevated)/25"
|
class="bg-(--ui-bg-elevated)/25"
|
||||||
@@ -21,15 +22,17 @@
|
|||||||
|
|
||||||
<UNavigationMenu :collapsed="collapsed" :items="links[1]" orientation="vertical" class="mt-auto" />
|
<UNavigationMenu :collapsed="collapsed" :items="links[1]" orientation="vertical" class="mt-auto" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<template #footer="{ collapsed }">
|
||||||
|
<UserMenu :collapsed="collapsed" />
|
||||||
|
</template>
|
||||||
</UDashboardSidebar>
|
</UDashboardSidebar>
|
||||||
|
|
||||||
<slot />
|
<slot />
|
||||||
|
|
||||||
<!-- <HelpSlideover /> -->
|
|
||||||
<!-- <NotificationsSlideover /> -->
|
|
||||||
</UDashboardGroup>
|
</UDashboardGroup>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
const links = [[], []]
|
const links = [[], []]
|
||||||
|
const open = ref(false)
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
7
legalconsenthub/middleware/auth.ts
Normal file
7
legalconsenthub/middleware/auth.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
export default defineNuxtRouteMiddleware(async (_to, _from) => {
|
||||||
|
const { data: session } = await useSession(useFetch)
|
||||||
|
|
||||||
|
if (!session.value) {
|
||||||
|
return navigateTo('/login')
|
||||||
|
}
|
||||||
|
})
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
export default defineNuxtConfig({
|
export default defineNuxtConfig({
|
||||||
modules: ['@nuxt/ui-pro', '@nuxt/eslint'],
|
sourcemap: true,
|
||||||
|
modules: ['@nuxt/ui-pro', '@nuxt/eslint', '@pinia/nuxt'],
|
||||||
css: ['~/assets/css/main.css'],
|
css: ['~/assets/css/main.css'],
|
||||||
runtimeConfig: {
|
runtimeConfig: {
|
||||||
public: {
|
public: {
|
||||||
|
|||||||
@@ -7,29 +7,31 @@
|
|||||||
"dev": "nuxt dev",
|
"dev": "nuxt dev",
|
||||||
"generate": "nuxt generate",
|
"generate": "nuxt generate",
|
||||||
"preview": "nuxt preview",
|
"preview": "nuxt preview",
|
||||||
"postinstall": "nuxt prepare",
|
"postinstall": "nuxt prepare && pnpm run fix:bettersqlite",
|
||||||
"format": "prettier . --write",
|
"format": "prettier . --write",
|
||||||
"type-check": "nuxi typecheck",
|
"type-check": "nuxi typecheck",
|
||||||
"lint": "eslint .",
|
"lint": "eslint .",
|
||||||
"lint:fix": "eslint . --fix",
|
"lint:fix": "eslint . --fix",
|
||||||
"api:generate": "openapi-generator-cli generate -i ../legalconsenthub-backend/api/legalconsenthub.yml -g typescript-fetch -o .api-client",
|
"api:generate": "openapi-generator-cli generate -i ../legalconsenthub-backend/api/legalconsenthub.yml -g typescript-fetch -o .api-client",
|
||||||
"fix:bettersqlite": "cd node_modules/better-sqlite3 && npx node-gyp rebuild && cd ../.."
|
"fix:bettersqlite": "cd node_modules/better-sqlite3 && pnpm dlx node-gyp rebuild && cd ../.."
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@nuxt/ui-pro": "3.0.0-alpha.13",
|
"@nuxt/ui-pro": "3.0.1",
|
||||||
"better-auth": "^1.1.16",
|
"@pinia/nuxt": "0.10.1",
|
||||||
"better-sqlite3": "^11.8.1",
|
"better-auth": "1.1.16",
|
||||||
"nuxt": "^3.15.4",
|
"better-sqlite3": "11.8.1",
|
||||||
|
"nuxt": "3.16.1",
|
||||||
|
"pinia": "3.0.1",
|
||||||
"vue": "latest",
|
"vue": "latest",
|
||||||
"vue-router": "latest"
|
"vue-router": "latest"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@nuxt/eslint": "^1.1.0",
|
"@nuxt/eslint": "1.1.0",
|
||||||
"@openapitools/openapi-generator-cli": "^2.16.3",
|
"@openapitools/openapi-generator-cli": "2.16.3",
|
||||||
"@types/better-sqlite3": "^7.6.12",
|
"@types/better-sqlite3": "7.6.12",
|
||||||
"eslint": "^9.20.1",
|
"eslint": "9.20.1",
|
||||||
"prettier": "3.5.1",
|
"prettier": "3.5.1",
|
||||||
"typescript": "^5.7.3",
|
"typescript": "5.7.3",
|
||||||
"vue-tsc": "^2.2.2"
|
"vue-tsc": "2.2.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,6 +39,10 @@ import { ComplianceStatus, type PagedApplicationFormDto } from '~/.api-client'
|
|||||||
import { useApplicationFormValidator } from '~/composables/useApplicationFormValidator'
|
import { useApplicationFormValidator } from '~/composables/useApplicationFormValidator'
|
||||||
import type { FormElementId } from '~/types/FormElement'
|
import type { FormElementId } from '~/types/FormElement'
|
||||||
|
|
||||||
|
definePageMeta({
|
||||||
|
middleware: ['auth']
|
||||||
|
})
|
||||||
|
|
||||||
const { getAllApplicationFormTemplates } = useApplicationFormTemplate()
|
const { getAllApplicationFormTemplates } = useApplicationFormTemplate()
|
||||||
const { createApplicationForm } = useApplicationForm()
|
const { createApplicationForm } = useApplicationForm()
|
||||||
const { validateFormElements, getHighestComplianceStatus } = useApplicationFormValidator()
|
const { validateFormElements, getHighestComplianceStatus } = useApplicationFormValidator()
|
||||||
|
|||||||
@@ -52,6 +52,11 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { ApplicationFormDto, PagedApplicationFormDto } from '~/.api-client'
|
import type { ApplicationFormDto, PagedApplicationFormDto } from '~/.api-client'
|
||||||
|
|
||||||
|
definePageMeta({
|
||||||
|
middleware: ['auth']
|
||||||
|
})
|
||||||
|
|
||||||
const { getAllApplicationForms, deleteApplicationFormById } = useApplicationForm()
|
const { getAllApplicationForms, deleteApplicationFormById } = useApplicationForm()
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
|
|
||||||
|
|||||||
@@ -1,45 +1,113 @@
|
|||||||
<template>
|
<template>
|
||||||
<UDashboardPanel id="home">
|
<UAuthForm
|
||||||
<template #header>
|
:fields="fields"
|
||||||
<UDashboardNavbar title="Home" :ui="{ right: 'gap-3' }">
|
:schema="schema"
|
||||||
<template #leading>
|
:providers="providers"
|
||||||
<UDashboardSidebarCollapse />
|
title="Welcome back"
|
||||||
</template>
|
icon="i-lucide-lock"
|
||||||
|
@submit="onSubmit"
|
||||||
<template #right>
|
>
|
||||||
<UDropdownMenu :items="items">
|
<template #description>
|
||||||
<UButton icon="i-lucide-plus" size="md" class="rounded-full" />
|
Don't have an account? <ULink to="/signup" class="text-primary-500 font-medium">Sign up</ULink>.
|
||||||
</UDropdownMenu>
|
|
||||||
</template>
|
|
||||||
</UDashboardNavbar>
|
|
||||||
|
|
||||||
<UDashboardToolbar>
|
|
||||||
<template #left> toolbar left </template>
|
|
||||||
</UDashboardToolbar>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #body>
|
<template #password-hint>
|
||||||
<div>
|
<ULink to="/" class="text-primary-500 font-medium">Forgot password?</ULink>
|
||||||
<pre>{{ session }}</pre>
|
|
||||||
<h1>{{ session.data ? 'Du bist eingeloggt' : 'Nicht eingeloggt' }}</h1>
|
|
||||||
<button v-if="session?.data" @click="authClient.signOut()">Sign out</button>
|
|
||||||
</div>
|
|
||||||
<Register />
|
|
||||||
<Login />
|
|
||||||
</template>
|
</template>
|
||||||
</UDashboardPanel>
|
|
||||||
|
<template #footer>
|
||||||
|
By signing in, you agree to our <ULink to="/" class="text-primary-500 font-medium">Terms of Service</ULink>.
|
||||||
|
</template>
|
||||||
|
</UAuthForm>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
const session = authClient.useSession()
|
import * as z from 'zod'
|
||||||
|
import type { FormSubmitEvent } from '@nuxt/ui'
|
||||||
|
|
||||||
const items = [
|
definePageMeta({ layout: 'auth' })
|
||||||
[
|
|
||||||
{
|
useSeoMeta({ title: 'Login' })
|
||||||
label: 'Neuer Mitbestimmungsantrag',
|
|
||||||
icon: 'i-lucide-send',
|
const toast = useToast()
|
||||||
to: '/create'
|
|
||||||
}
|
const fields = [
|
||||||
]
|
{
|
||||||
|
name: 'email',
|
||||||
|
type: 'text' as const,
|
||||||
|
label: 'Email',
|
||||||
|
placeholder: 'Enter your email',
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'password',
|
||||||
|
label: 'Password',
|
||||||
|
type: 'password' as const,
|
||||||
|
placeholder: 'Enter your password'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'remember',
|
||||||
|
label: 'Remember me',
|
||||||
|
type: 'checkbox' as const
|
||||||
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
const providers = [
|
||||||
|
{
|
||||||
|
label: 'Google',
|
||||||
|
icon: 'i-simple-icons-google',
|
||||||
|
onClick: () => {
|
||||||
|
toast.add({ title: 'Google', description: 'Login with Google' })
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'GitHub',
|
||||||
|
icon: 'i-simple-icons-github',
|
||||||
|
onClick: () => {
|
||||||
|
toast.add({ title: 'GitHub', description: 'Login with GitHub' })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const schema = z.object({
|
||||||
|
email: z.string().email('Invalid email'),
|
||||||
|
password: z.string().min(8, 'Must be at least 8 characters')
|
||||||
|
})
|
||||||
|
|
||||||
|
type Schema = z.output<typeof schema>
|
||||||
|
|
||||||
|
function onSubmit(payload: FormSubmitEvent<Schema>) {
|
||||||
|
if (!payload.data.email || !payload.data.password) {
|
||||||
|
alert('Bitte alle Felder ausfüllen')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
authClient.signIn.email(
|
||||||
|
{
|
||||||
|
email: payload.data.email,
|
||||||
|
password: payload.data.password
|
||||||
|
},
|
||||||
|
{
|
||||||
|
onRequest: () => {
|
||||||
|
// TODO: Show loading spinner
|
||||||
|
console.log('Sending login request')
|
||||||
|
},
|
||||||
|
onResponse: () => {
|
||||||
|
// TODO: Hide loading spinner
|
||||||
|
console.log('Receiving login response')
|
||||||
|
},
|
||||||
|
onSuccess: async (ctx) => {
|
||||||
|
console.log('Successfully logged in!', ctx)
|
||||||
|
await navigateTo('/')
|
||||||
|
},
|
||||||
|
onError: (ctx) => {
|
||||||
|
console.log(ctx.error.message)
|
||||||
|
useToast().add({
|
||||||
|
title: 'Fehler bei der Anmeldung',
|
||||||
|
description: ctx.error.message,
|
||||||
|
color: 'error'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
107
legalconsenthub/pages/signup.vue
Normal file
107
legalconsenthub/pages/signup.vue
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
<template>
|
||||||
|
<UAuthForm
|
||||||
|
:fields="fields"
|
||||||
|
:schema="schema"
|
||||||
|
:providers="providers"
|
||||||
|
title="Create an account"
|
||||||
|
:submit="{ label: 'Create account' }"
|
||||||
|
@submit="onSubmit"
|
||||||
|
>
|
||||||
|
<template #description>
|
||||||
|
Already have an account? <ULink to="/login" class="text-primary-500 font-medium">Login</ULink>.
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #footer>
|
||||||
|
By signing up, you agree to our <ULink to="/" class="text-primary-500 font-medium">Terms of Service</ULink>.
|
||||||
|
</template>
|
||||||
|
</UAuthForm>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import * as z from 'zod'
|
||||||
|
import type { FormSubmitEvent } from '@nuxt/ui'
|
||||||
|
|
||||||
|
definePageMeta({ layout: 'auth' })
|
||||||
|
|
||||||
|
useSeoMeta({ title: 'Sign up' })
|
||||||
|
|
||||||
|
const toast = useToast()
|
||||||
|
|
||||||
|
const fields = [
|
||||||
|
{
|
||||||
|
name: 'name',
|
||||||
|
type: 'text' as const,
|
||||||
|
label: 'Name',
|
||||||
|
placeholder: 'Enter your name'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'email',
|
||||||
|
type: 'text' as const,
|
||||||
|
label: 'Email',
|
||||||
|
placeholder: 'Enter your email'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'password',
|
||||||
|
label: 'Password',
|
||||||
|
type: 'password' as const,
|
||||||
|
placeholder: 'Enter your password'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const providers = [
|
||||||
|
{
|
||||||
|
label: 'Google',
|
||||||
|
icon: 'i-simple-icons-google',
|
||||||
|
onClick: () => {
|
||||||
|
toast.add({ title: 'Google', description: 'Login with Google' })
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'GitHub',
|
||||||
|
icon: 'i-simple-icons-github',
|
||||||
|
onClick: () => {
|
||||||
|
toast.add({ title: 'GitHub', description: 'Login with GitHub' })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const schema = z.object({
|
||||||
|
name: z.string().min(1, 'Name is required'),
|
||||||
|
email: z.string().email('Invalid email'),
|
||||||
|
password: z.string().min(8, 'Must be at least 8 characters')
|
||||||
|
})
|
||||||
|
|
||||||
|
type Schema = z.output<typeof schema>
|
||||||
|
|
||||||
|
function onSubmit(payload: FormSubmitEvent<Schema>) {
|
||||||
|
signUp.email(
|
||||||
|
{
|
||||||
|
email: payload.data.email,
|
||||||
|
password: payload.data.password,
|
||||||
|
name: payload.data.name
|
||||||
|
},
|
||||||
|
{
|
||||||
|
onRequest: () => {
|
||||||
|
// TODO: Show loading spinner
|
||||||
|
console.log('Sending register request')
|
||||||
|
},
|
||||||
|
onResponse: () => {
|
||||||
|
// TODO: Hide loading spinner
|
||||||
|
console.log('Receiving register response')
|
||||||
|
},
|
||||||
|
onSuccess: async () => {
|
||||||
|
console.log('Successfully registered!')
|
||||||
|
await navigateTo('/')
|
||||||
|
},
|
||||||
|
onError: (ctx) => {
|
||||||
|
console.log(ctx.error.message)
|
||||||
|
useToast().add({
|
||||||
|
title: 'Fehler bei der Registrierung',
|
||||||
|
description: ctx.error.message,
|
||||||
|
color: 'error'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
4288
legalconsenthub/pnpm-lock.yaml
generated
4288
legalconsenthub/pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -3,3 +3,5 @@ import { createAuthClient } from 'better-auth/vue'
|
|||||||
export const authClient = createAuthClient({
|
export const authClient = createAuthClient({
|
||||||
baseURL: 'http://localhost:3000'
|
baseURL: 'http://localhost:3000'
|
||||||
})
|
})
|
||||||
|
|
||||||
|
export const { signIn, signOut, signUp, useSession, forgetPassword, resetPassword } = authClient
|
||||||
|
|||||||
Reference in New Issue
Block a user