Добавление описания профиля и отступа.

Добавлено модальное окно для добавления описание профиля с счётчиком символов и размером до 500 символов, добавлен отступ между изменением пароля и выходом из аккаунта, перекрашена кнопка удаления аккаунта.
This commit is contained in:
genzof
2026-02-15 21:16:36 +03:00
parent 29c580d26d
commit 5d023b8785
2 changed files with 134 additions and 5 deletions

View File

@@ -19,6 +19,10 @@ const Profile = () => {
const [new_password, setnew_password] = useState('');
const [new_password_confirm, setnew_password_confirm] = useState('');
const [passwordError, setPasswordError] = useState('');
const [showDescriptionModal, setShowDescriptionModal] = useState(false);
const [profileDescription, setProfileDescription] = useState('');
const [descriptionError, setDescriptionError] = useState('');
useEffect(() => {
const checkSession = async () => {
try {
@@ -117,6 +121,36 @@ const Profile = () => {
}
};
const saveProfileDescription = async (e) => {
e.preventDefault();
setDescriptionError('');
try {
await axios.put('/api/users/change_description',
{ new_description: profileDescription },
{ withCredentials: true }
);
try {
const response = await axios.get('/api/users/me');
setUser(response.data.display_name);
setUserName(response.data.username);
// Обновляем описание, если оно есть в ответе
if (response.data.description) {
setProfileDescription(response.data.description);
}
} catch (err) {
setError('Ошибка обновления данных профиля');
}
setShowDescriptionModal(false); // Закрываем модальное окно
} catch (err) {
setDescriptionError(
err.response?.data?.detail || 'Ошибка при сохранении описания'
);
}
};
const OpenWindowDelete = () => {
setShowConfirm(true); // Показываем окно подтверждения
@@ -141,7 +175,23 @@ const Profile = () => {
const closeWindowUserName = () => {
setShowConfirmUserName(false); // Показываем окно подтверждения
};
const openDescriptionModal = async () => {
setDescriptionError('');
try {
const response = await axios.get('/api/users/me');
setProfileDescription(response.data.description || '');
setShowDescriptionModal(true);
} catch (err) {
setError('Не удалось загрузить данные профиля');
console.error('Ошибка загрузки данных пользователя:', err);
}
};
const closeDescriptionModal = () => {
setShowDescriptionModal(false);
setDescriptionError('');
};
const deleteAccount = async () => {
try {
await axios.delete('/api/users/me', { withCredentials: true });
@@ -171,6 +221,13 @@ const Profile = () => {
<div className="frame"><p>{user}</p></div>
<button onClick={OpenWindowName}></button>
</div>
<p>Описание профиля</p>
<div className="com">
Добавьте краткое описание о себе, которое увидят другие пользователи.
</div>
<button onClick={openDescriptionModal} className="button-small">
{profileDescription ? 'Редактировать описание' : 'Добавить описание'}
</button>
<div className="com">Логин</div>
<div className="buttonName">
<div className="frame"><p>{userName}</p></div>
@@ -178,9 +235,9 @@ const Profile = () => {
</div>
<p>Изменить пароль</p>
<div className="com">В целях безопасности мы рекомендуем выбрать пароль, который ещё не использовался вами в других учётных записях.</div>
<button onClick={() => setShowChangePassword(true)}className="button-small">Изменить пароль</button>
<button onClick={handleLogout}>Выйти из аккаунта</button>
<button onClick={OpenWindowDelete}>Удалить аккаунт</button>
<button onClick={() => setShowChangePassword(true)} className="button-small">Изменить пароль</button>
<button onClick={handleLogout} className="margin-top-large">Выйти из аккаунта</button>
<button className="Important-button" onClick={OpenWindowDelete}>Удалить аккаунт</button>
</div>
)}
@@ -284,6 +341,48 @@ const Profile = () => {
</div>
)}
{showDescriptionModal && (
<div className="confirm-modal">
<div className="modal-content">
<h3>{profileDescription ? 'Редактировать описание профиля' : 'Добавить описание профиля'}</h3>
{descriptionError && (
<div className="error" style={{ color: 'red' }}>
{descriptionError}
</div>
)}
<form onSubmit={saveProfileDescription}>
<div className="form-group">
<label>Описание:</label>
<textarea
className="description-textarea"
value={profileDescription}
onChange={(e) => setProfileDescription(e.target.value)}
placeholder="Расскажите о себе, своих интересах или профессиональных навыках..."
rows={6}
maxLength={500}
required
/>
<div className="char-counter">
{profileDescription.length}/500 символов
</div>
</div>
<div className="modal-buttons">
<button type="submit">Сохранить описание</button>
<button
type="button"
onClick={closeDescriptionModal}
>
Отменить
</button>
</div>
</form>
</div>
</div>
)}
{/* Всплывающее окно подтверждения */}
{showConfirm && (
<div className="confirm-modal">

View File

@@ -191,7 +191,7 @@ input[type="password"] {
.Important-button {
width: 100%;
padding: 12px;
margin: 8px;
margin: 10px auto;
background-color: #e30000;
color: white;
border: none;
@@ -278,6 +278,7 @@ button:disabled {
width: 30%;
min-width: auto;
height: auto;
margin-bottom: auto;
}
.user-info p {
@@ -313,3 +314,32 @@ h3 {
color: #CAD1D8;
margin: 0px;
}
.description-textarea {
width: 100%;
padding: 12px;
border: 1px solid #ddd;
border-radius: 6px;
font-family: inherit;
resize: vertical;
min-height: 120px;
max-height: 200px;
box-sizing: border-box;
}
.description-textarea:focus {
outline: none;
border-color: #007bff;
box-shadow: 0 0 0 2px rgba(0, 123, 255, 0.25);
}
.char-counter {
text-align: right;
color: #6c757d;
font-size: 0.875rem;
margin-top: 4px;
}
.margin-top-large {
margin-top: 10em;
}