/
itp_practice
/
itp_frontend
Обзор
Документация
Войти
/
itp_practice
/
itp_frontend
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
master
src/components/UpdateEmailModal.vue
188 строк
6 KB
vivanenko
profile edit
29 май 2025, 19:57
29 май 2025, 19:57
ec6c7e9
Код
Авторство
О чём код?
<template> <div class="modal" id="update-email-modal" v-show="isVisible"> <div class="modal__overlay absolute top-0 left-0 w-full h-full bg-black/70 backdrop-blur" @click="closeModal"></div> <div class="modal__container relative w-full max-w-lg mx-auto mt-12 bg-bgdark rounded-lg shadow-2xl overflow-hidden transition-all duration-300"> <button class="modal__close absolute top-4 right-4 bg-transparent border-none text-2xl text-white/70 cursor-pointer transition-all duration-300 hover:text-white" @click="closeModal" >×</button> <div class="modal__content p-7"> <h3 class="modal__title text-2xl mb-7 text-center text-white">Обновить Email</h3> <form @submit.prevent="handleUpdateEmail" class="flex flex-col gap-5"> <!-- Current Email (readonly) --> <div class="form-group relative"> <label for="current-email" class="block mb-2 text-white/70">Текущий Email</label> <input type="email" id="current-email" :value="currentUser?.email || ''" disabled class="w-full px-4 py-3 bg-white/5 border border-white/20 rounded-lg text-white/50 text-base cursor-not-allowed" > </div> <!-- New Email --> <div class="form-group relative"> <label for="new-email" class="block mb-2 text-white/70">Новый Email *</label> <input type="email" id="new-email" v-model="formData.newEmail" required placeholder="Введите новый email" class="w-full px-4 py-3 bg-white/5 border border-white/10 rounded-lg text-white text-base transition-all duration-300 focus:border-primary focus:outline-none focus:shadow" :disabled="loading" > </div> <!-- Error Message --> <div v-if="error" class="text-red-400 text-sm"> {{ error }} </div> <!-- Submit Button --> <button type="submit" class="w-full bg-blue-500 hover:bg-blue-600 text-white py-3 rounded-lg transition duration-200 flex items-center justify-center" :disabled="loading || !isFormValid" :class="{'opacity-70 cursor-not-allowed': loading || !isFormValid}" > <span v-if="loading" class="inline-block mr-2"> <svg class="animate-spin h-5 w-5 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"> <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle> <path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 714 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path> </svg> </span> {{ loading ? 'Обновление...' : 'Обновить Email' }} </button> <!-- Cancel Button --> <button type="button" @click="closeModal" class="w-full bg-gray-600 hover:bg-gray-700 text-white py-3 rounded-lg transition duration-200" :disabled="loading" > Отмена </button> </form> </div> </div> </div> </template> <script setup> import { ref, computed, inject } from 'vue'; import { api } from '@/services/api'; import { useAlerts } from '@/composables/useAlerts'; // Props const props = defineProps({ currentUser: { type: Object, required: true } }); // Emits const emit = defineEmits(['user-updated', 'modal-closed']); // Composables const { showSuccess, showError } = useAlerts(); // Reactive state const isVisible = ref(false); const loading = ref(false); const error = ref(''); const formData = ref({ newEmail: '' }); // Computed const isFormValid = computed(() => { return formData.value.newEmail && formData.value.newEmail !== props.currentUser?.email && formData.value.newEmail.includes('@'); }); // Methods const openModal = () => { isVisible.value = true; resetForm(); }; const closeModal = () => { isVisible.value = false; resetForm(); emit('modal-closed'); }; const resetForm = () => { formData.value = { newEmail: '' }; error.value = ''; loading.value = false; }; /** * Business Logic Layer - обновление email пользователя */ const handleUpdateEmail = async () => { try { loading.value = true; error.value = ''; // Data Access Layer - запрос на обновление email const response = await api.put('/user/email', { email: formData.value.newEmail }); // Success handling showSuccess('Email успешно обновлен'); emit('user-updated'); closeModal(); } catch (e) { // Error handling if (e.response?.status === 422) { error.value = 'Проверьте корректность данных'; } else if (e.response?.status === 409) { error.value = 'Email уже используется другим пользователем'; } else { error.value = e.response?.data?.message || 'Ошибка при обновлении email'; } showError(error.value); } finally { loading.value = false; } }; // Expose methods for external access defineExpose({ openModal, closeModal }); </script> <style scoped> .modal { position: fixed; top: 0; left: 0; width: 100%; height: 100%; z-index: 1000; } .bg-bgdark { background-color: #1a1a1a; } .border-primary { border-color: #3b82f6; } </style>