149 lines
4.0 KiB
Vue
149 lines
4.0 KiB
Vue
<template>
|
|
<div class="min-h-screen bg-background flex items-center justify-center p-4">
|
|
<Card class="w-full max-w-md">
|
|
<CardHeader>
|
|
<CardTitle class="text-2xl text-center">Create Account</CardTitle>
|
|
<CardDescription class="text-center">
|
|
Sign up to get started with Neo Platform
|
|
</CardDescription>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<div v-if="error" class="mb-4 p-3 bg-destructive/10 text-destructive rounded text-sm">
|
|
{{ error }}
|
|
</div>
|
|
|
|
<div v-if="success" class="mb-4 p-3 bg-green-500/10 text-green-600 rounded text-sm">
|
|
Registration successful! Redirecting to login...
|
|
</div>
|
|
|
|
<form @submit.prevent="handleRegister" class="space-y-4">
|
|
<div class="space-y-2">
|
|
<Label for="tenantId">Tenant ID</Label>
|
|
<Input
|
|
id="tenantId"
|
|
v-model="tenantId"
|
|
type="text"
|
|
required
|
|
placeholder="123"
|
|
/>
|
|
</div>
|
|
|
|
<div class="space-y-2">
|
|
<Label for="email">Email</Label>
|
|
<Input
|
|
id="email"
|
|
v-model="email"
|
|
type="email"
|
|
required
|
|
placeholder="user@example.com"
|
|
/>
|
|
</div>
|
|
|
|
<div class="space-y-2">
|
|
<Label for="password">Password</Label>
|
|
<Input
|
|
id="password"
|
|
v-model="password"
|
|
type="password"
|
|
required
|
|
minlength="6"
|
|
placeholder="••••••••"
|
|
/>
|
|
<p class="text-xs text-muted-foreground">Must be at least 6 characters</p>
|
|
</div>
|
|
|
|
<div class="grid grid-cols-2 gap-4">
|
|
<div class="space-y-2">
|
|
<Label for="firstName">First Name</Label>
|
|
<Input
|
|
id="firstName"
|
|
v-model="firstName"
|
|
type="text"
|
|
placeholder="John"
|
|
/>
|
|
</div>
|
|
|
|
<div class="space-y-2">
|
|
<Label for="lastName">Last Name</Label>
|
|
<Input
|
|
id="lastName"
|
|
v-model="lastName"
|
|
type="text"
|
|
placeholder="Doe"
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<Button
|
|
type="submit"
|
|
:disabled="loading"
|
|
class="w-full"
|
|
>
|
|
{{ loading ? 'Creating account...' : 'Create Account' }}
|
|
</Button>
|
|
</form>
|
|
</CardContent>
|
|
<CardFooter class="flex justify-center">
|
|
<p class="text-sm text-muted-foreground">
|
|
Already have an account?
|
|
<NuxtLink to="/login" class="text-primary hover:underline font-medium">
|
|
Login
|
|
</NuxtLink>
|
|
</p>
|
|
</CardFooter>
|
|
</Card>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
const config = useRuntimeConfig()
|
|
const router = useRouter()
|
|
|
|
const tenantId = ref('123')
|
|
const email = ref('')
|
|
const password = ref('')
|
|
const firstName = ref('')
|
|
const lastName = ref('')
|
|
const loading = ref(false)
|
|
const error = ref('')
|
|
const success = ref(false)
|
|
|
|
const handleRegister = async () => {
|
|
try {
|
|
loading.value = true
|
|
error.value = ''
|
|
success.value = false
|
|
|
|
const response = await fetch(`${config.public.apiBaseUrl}/api/auth/register`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'x-tenant-id': tenantId.value,
|
|
},
|
|
body: JSON.stringify({
|
|
email: email.value,
|
|
password: password.value,
|
|
firstName: firstName.value || undefined,
|
|
lastName: lastName.value || undefined,
|
|
}),
|
|
})
|
|
|
|
if (!response.ok) {
|
|
const data = await response.json()
|
|
throw new Error(data.message || 'Registration failed')
|
|
}
|
|
|
|
success.value = true
|
|
|
|
// Redirect to login after 2 seconds
|
|
setTimeout(() => {
|
|
router.push('/login')
|
|
}, 2000)
|
|
} catch (e: any) {
|
|
error.value = e.message || 'Registration failed'
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
</script>
|