Добавление описания профиля и отступа.
Добавлено модальное окно для добавления описание профиля с счётчиком символов и размером до 500 символов, добавлен отступ между изменением пароля и выходом из аккаунта, перекрашена кнопка удаления аккаунта.
This commit is contained in:
107
src/Profile.js
107
src/Profile.js
@@ -19,6 +19,10 @@ const Profile = () => {
|
|||||||
const [new_password, setnew_password] = useState('');
|
const [new_password, setnew_password] = useState('');
|
||||||
const [new_password_confirm, setnew_password_confirm] = useState('');
|
const [new_password_confirm, setnew_password_confirm] = useState('');
|
||||||
const [passwordError, setPasswordError] = useState('');
|
const [passwordError, setPasswordError] = useState('');
|
||||||
|
const [showDescriptionModal, setShowDescriptionModal] = useState(false);
|
||||||
|
const [profileDescription, setProfileDescription] = useState('');
|
||||||
|
const [descriptionError, setDescriptionError] = useState('');
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const checkSession = async () => {
|
const checkSession = async () => {
|
||||||
try {
|
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 = () => {
|
const OpenWindowDelete = () => {
|
||||||
setShowConfirm(true); // Показываем окно подтверждения
|
setShowConfirm(true); // Показываем окно подтверждения
|
||||||
@@ -141,7 +175,23 @@ const Profile = () => {
|
|||||||
const closeWindowUserName = () => {
|
const closeWindowUserName = () => {
|
||||||
setShowConfirmUserName(false); // Показываем окно подтверждения
|
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 () => {
|
const deleteAccount = async () => {
|
||||||
try {
|
try {
|
||||||
await axios.delete('/api/users/me', { withCredentials: true });
|
await axios.delete('/api/users/me', { withCredentials: true });
|
||||||
@@ -171,6 +221,13 @@ const Profile = () => {
|
|||||||
<div className="frame"><p>{user}</p></div>
|
<div className="frame"><p>{user}</p></div>
|
||||||
<button onClick={OpenWindowName}>✎</button>
|
<button onClick={OpenWindowName}>✎</button>
|
||||||
</div>
|
</div>
|
||||||
|
<p>Описание профиля</p>
|
||||||
|
<div className="com">
|
||||||
|
Добавьте краткое описание о себе, которое увидят другие пользователи.
|
||||||
|
</div>
|
||||||
|
<button onClick={openDescriptionModal} className="button-small">
|
||||||
|
{profileDescription ? 'Редактировать описание' : 'Добавить описание'}
|
||||||
|
</button>
|
||||||
<div className="com">Логин</div>
|
<div className="com">Логин</div>
|
||||||
<div className="buttonName">
|
<div className="buttonName">
|
||||||
<div className="frame"><p>{userName}</p></div>
|
<div className="frame"><p>{userName}</p></div>
|
||||||
@@ -178,9 +235,9 @@ const Profile = () => {
|
|||||||
</div>
|
</div>
|
||||||
<p>Изменить пароль</p>
|
<p>Изменить пароль</p>
|
||||||
<div className="com">В целях безопасности мы рекомендуем выбрать пароль, который ещё не использовался вами в других учётных записях.</div>
|
<div className="com">В целях безопасности мы рекомендуем выбрать пароль, который ещё не использовался вами в других учётных записях.</div>
|
||||||
<button onClick={() => setShowChangePassword(true)}className="button-small">Изменить пароль</button>
|
<button onClick={() => setShowChangePassword(true)} className="button-small">Изменить пароль</button>
|
||||||
<button onClick={handleLogout}>Выйти из аккаунта</button>
|
<button onClick={handleLogout} className="margin-top-large">Выйти из аккаунта</button>
|
||||||
<button onClick={OpenWindowDelete}>Удалить аккаунт</button>
|
<button className="Important-button" onClick={OpenWindowDelete}>Удалить аккаунт</button>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
@@ -284,6 +341,48 @@ const Profile = () => {
|
|||||||
</div>
|
</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 && (
|
{showConfirm && (
|
||||||
<div className="confirm-modal">
|
<div className="confirm-modal">
|
||||||
|
|||||||
@@ -191,7 +191,7 @@ input[type="password"] {
|
|||||||
.Important-button {
|
.Important-button {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 12px;
|
padding: 12px;
|
||||||
margin: 8px;
|
margin: 10px auto;
|
||||||
background-color: #e30000;
|
background-color: #e30000;
|
||||||
color: white;
|
color: white;
|
||||||
border: none;
|
border: none;
|
||||||
@@ -278,6 +278,7 @@ button:disabled {
|
|||||||
width: 30%;
|
width: 30%;
|
||||||
min-width: auto;
|
min-width: auto;
|
||||||
height: auto;
|
height: auto;
|
||||||
|
margin-bottom: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.user-info p {
|
.user-info p {
|
||||||
@@ -313,3 +314,32 @@ h3 {
|
|||||||
color: #CAD1D8;
|
color: #CAD1D8;
|
||||||
margin: 0px;
|
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;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user