templates2.Base.Nuxt/app/components/AuthForm.vue
w4c-templates a7a56fd5e0
Some checks failed
CI / quality (push) Has been cancelled
chore(template): publish Base.Nuxt
2026-10-11 23:23:38 +03:00

65 lines
2.5 KiB
Vue

<script setup lang="ts">
const props = defineProps<{ mode: 'login' | 'register' }>();
const route = useRoute();
const router = useRouter();
const next = computed(() => (route.query.next as string) || '/dashboard');
const busy = ref(false);
const error = ref<string | null>(null);
const isRegister = computed(() => props.mode === 'register');
async function onSubmit(e: Event) {
e.preventDefault();
busy.value = true;
error.value = null;
const form = new FormData(e.target as HTMLFormElement);
const body = Object.fromEntries(form.entries());
try {
await $fetch(`/api/auth/${props.mode}`, { method: 'POST', body });
await router.push(next.value);
await refreshNuxtData('current-user');
} catch (err: unknown) {
error.value = (err as { statusMessage?: string; message?: string })?.statusMessage || 'Request failed';
busy.value = false;
}
}
</script>
<template>
<div class="card">
<h1 class="text-xl font-semibold">{{ isRegister ? t('auth.registerTitle') : t('auth.loginTitle') }}</h1>
<form class="mt-6 space-y-4" novalidate @submit="onSubmit">
<div v-if="isRegister">
<label class="label" for="name">{{ t('auth.name') }}</label>
<input id="name" name="name" class="input" autocomplete="name">
</div>
<div>
<label class="label" for="email">{{ t('auth.email') }}</label>
<input id="email" name="email" type="email" required class="input" autocomplete="email">
</div>
<div>
<label class="label" for="password">{{ t('auth.password') }}</label>
<input
id="password"
name="password"
type="password"
required
minlength="8"
class="input"
:autocomplete="isRegister ? 'new-password' : 'current-password'"
>
</div>
<p v-if="error" class="text-sm text-red-600">{{ error }}</p>
<button type="submit" class="btn-primary w-full" :disabled="busy">
{{ busy ? '…' : isRegister ? t('auth.submitRegister') : t('auth.submitLogin') }}
</button>
</form>
<p class="muted mt-5 text-center text-sm">
{{ isRegister ? t('auth.hasAccount') : t('auth.noAccount') }}
<NuxtLink :to="isRegister ? '/login' : '/register'" class="font-medium text-brand-600 hover:underline">
{{ isRegister ? t('auth.submitLogin') : t('auth.submitRegister') }}
</NuxtLink>
</p>
<p v-if="!isRegister" class="muted mt-3 text-center text-xs">{{ t('auth.demoHint') }}</p>
</div>
</template>