Changeset ae83647 for petify-frontend/src/views/LoginView.vue
- Timestamp:
- 06/26/26 16:32:12 (2 days ago)
- Branches:
- master
- Parents:
- fa32d0f
- File:
-
- 1 edited
-
petify-frontend/src/views/LoginView.vue (modified) (9 diffs)
Legend:
- Unmodified
- Added
- Removed
-
petify-frontend/src/views/LoginView.vue
rfa32d0f rae83647 29 29 <div v-if="error" class="alert alert-danger auth-alert" role="alert"> 30 30 <strong class="me-1">Oops.</strong>{{ error }} 31 </div> 32 <div v-if="forgotSuccess" class="alert alert-success auth-alert" role="alert"> 33 {{ forgotSuccess }} 31 34 </div> 32 35 … … 113 116 <!-- Remember me --> 114 117 <div class="d-flex justify-content-between align-items-center mt-2 mb-3"> 115 116 117 <!-- enable later if you implement route -->118 < !-- <RouterLink class="link small accent" to="/forgot">Forgot password?</RouterLink> -->118 <span></span> 119 <button class="link-button small accent" type="button" @click="toggleForgotPassword"> 120 Forgot password? 121 </button> 119 122 </div> 120 123 … … 123 126 <span v-if="loading" class="spinner-border spinner-border-sm me-2" aria-hidden="true"></span> 124 127 {{ loading ? 'Logging in…' : 'Log in' }} 128 </button> 129 </form> 130 131 <form v-if="showForgotPassword" class="forgot-panel mt-4" @submit.prevent="submitForgotPassword"> 132 <label class="form-label" for="forgot-identifier">Username or email</label> 133 <div class="input-group auth-input"> 134 <span class="input-group-text"> 135 <svg width="18" height="18" viewBox="0 0 24 24" fill="none"> 136 <path 137 d="M4 6.5A2.5 2.5 0 0 1 6.5 4h11A2.5 2.5 0 0 1 20 6.5v11a2.5 2.5 0 0 1-2.5 2.5h-11A2.5 2.5 0 0 1 4 17.5v-11Zm2.5-.5a.5.5 0 0 0-.5.5v.8l6 3.7 6-3.7v-.8a.5.5 0 0 0-.5-.5h-11Zm11.5 3.6-5.5 3.4a1 1 0 0 1-1 0L6 9.6v7.9a.5.5 0 0 0 .5.5h11a.5.5 0 0 0 .5-.5V9.6Z" 138 fill="currentColor" 139 opacity=".85" 140 /> 141 </svg> 142 </span> 143 <input 144 id="forgot-identifier" 145 v-model.trim="forgotIdentifier" 146 class="form-control" 147 type="text" 148 autocomplete="username" 149 required 150 placeholder="username or email" 151 /> 152 </div> 153 <div v-if="forgotError" class="text-danger small mt-2">{{ forgotError }}</div> 154 <button class="btn btn-outline-primary w-100 mt-3" type="submit" :disabled="forgotLoading"> 155 <span v-if="forgotLoading" class="spinner-border spinner-border-sm me-2" aria-hidden="true"></span> 156 {{ forgotLoading ? 'Sending...' : 'Send temporary password' }} 125 157 </button> 126 158 </form> … … 144 176 import { useRoute, useRouter } from 'vue-router' 145 177 import { useAuthStore } from '../stores/auth' 178 import { forgotPassword } from '../api/auth' 146 179 147 180 const auth = useAuthStore() … … 153 186 const loading = ref(false) 154 187 const error = ref<string | null>(null) 188 const forgotLoading = ref(false) 189 const forgotError = ref<string | null>(null) 190 const forgotSuccess = ref<string | null>(null) 191 const showForgotPassword = ref(false) 192 const forgotIdentifier = ref('') 155 193 156 194 const showPassword = ref(false) … … 159 197 function togglePassword() { 160 198 showPassword.value = !showPassword.value 199 } 200 201 function toggleForgotPassword() { 202 showForgotPassword.value = !showForgotPassword.value 203 forgotError.value = null 204 forgotSuccess.value = null 205 if (showForgotPassword.value && !forgotIdentifier.value) { 206 forgotIdentifier.value = username.value 207 } 161 208 } 162 209 … … 175 222 } finally { 176 223 loading.value = false 224 } 225 } 226 227 async function submitForgotPassword() { 228 forgotError.value = null 229 forgotSuccess.value = null 230 forgotLoading.value = true 231 try { 232 forgotSuccess.value = await forgotPassword({ identifier: forgotIdentifier.value }) 233 showForgotPassword.value = false 234 } catch (e) { 235 forgotError.value = e instanceof Error ? e.message : String(e) 236 } finally { 237 forgotLoading.value = false 177 238 } 178 239 } … … 276 337 } 277 338 339 .forgot-panel { 340 border-top: 1px solid rgba(31, 41, 55, 0.1); 341 padding-top: 1rem; 342 } 343 278 344 /* Input styling */ 279 345 .auth-input .input-group-text { … … 371 437 } 372 438 439 .link-button { 440 border: 0; 441 background: transparent; 442 padding: 0; 443 text-decoration: none; 444 } 445 446 .link-button.accent { 447 color: #ff7a18; 448 font-weight: 600; 449 } 450 451 .link-button.accent:hover { 452 color: #e76610; 453 } 454 373 455 /* Respect reduced motion */ 374 456 @media (prefers-reduced-motion: reduce) {
Note:
See TracChangeset
for help on using the changeset viewer.
