Files
kite/frontend/src/components/auth/PasswordStrengthBar.vue
T
curo1305andClaude Sonnet 4.6 3b7d362600 feat(02-02): frontend auth store, router guard, Login/Register views
- frontend/src/stores/auth.js: useAuthStore with accessToken in memory
  only (never browser storage); login() accepts options.backupCode
- frontend/src/api/client.js: extended with Bearer token injection,
  401 auto-refresh retry, all auth/admin API functions, changePassword
- frontend/src/router/index.js: auth routes added (/login, /register,
  /password-reset, /account, /admin); beforeEach guard redirects
  unauthenticated users to /login with redirect param
- frontend/src/layouts/AuthLayout.vue: centered bare layout for auth pages
- frontend/src/views/auth/LoginView.vue: three-step flow (password, TOTP,
  backup code); "Use a backup code instead" link; UI-SPEC copywriting
- frontend/src/views/auth/RegisterView.vue: registration with
  PasswordStrengthBar; HIBP error display; UI-SPEC copywriting
- frontend/src/components/auth/PasswordStrengthBar.vue: 4-segment bar
- frontend/src/components/ui/AppSpinner.vue: animate-spin SVG spinner
- Stub views: PasswordResetView, NewPasswordView, AccountView, AdminView
- .gitignore: exclude frontend/node_modules, dist, package-lock.json

npm run build exits 0. All acceptance criteria verified.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-22 19:45:21 +02:00

69 lines
1.6 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div v-if="password" class="mt-2 space-y-1">
<!-- Strength bar: 4 segments -->
<div class="flex gap-1">
<div
v-for="i in 4"
:key="i"
class="h-1 flex-1 rounded transition-colors duration-200"
:class="i <= strength ? segmentColor : 'bg-gray-200'"
/>
</div>
<!-- Label -->
<div class="flex justify-end">
<span class="text-xs font-semibold" :class="labelColor">{{ label }}</span>
</div>
</div>
</template>
<script setup>
import { computed } from 'vue'
const props = defineProps({
password: {
type: String,
default: '',
},
})
/**
* Strength score 04:
* +1 if length >= 12
* +1 if contains uppercase
* +1 if contains digit
* +1 if contains special character
* Matches backend AUTH-01 rules.
*/
const strength = computed(() => {
const p = props.password
if (!p) return 0
let score = 0
if (p.length >= 12) score++
if (/[A-Z]/.test(p)) score++
if (/[0-9]/.test(p)) score++
if (/[^A-Za-z0-9]/.test(p)) score++
return score
})
const segmentColor = computed(() => {
if (strength.value === 1) return 'bg-red-500'
if (strength.value === 2) return 'bg-amber-500'
if (strength.value === 3) return 'bg-amber-400'
return 'bg-green-500'
})
const labelColor = computed(() => {
if (strength.value === 1) return 'text-red-500'
if (strength.value === 2) return 'text-amber-500'
if (strength.value === 3) return 'text-amber-400'
return 'text-green-500'
})
const label = computed(() => {
if (strength.value === 1) return 'Too weak'
if (strength.value === 2) return 'Weak'
if (strength.value === 3) return 'Fair'
return 'Strong'
})
</script>