feat: добавление Добавление функции смены аватарки
Добавлено окно с аватаркой по нажатию на которое добавлена функция загрузки нового аватара и исправлены некоторые недочёты.
This commit is contained in:
@@ -22,15 +22,17 @@ const Profile = () => {
|
||||
const [showDescriptionModal, setShowDescriptionModal] = useState(false);
|
||||
const [profileDescription, setProfileDescription] = useState('');
|
||||
const [descriptionError, setDescriptionError] = useState('');
|
||||
const [avatarUrl, setAvatarUrl] = useState(null);
|
||||
const [isUploading, setIsUploading] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const checkSession = async () => {
|
||||
try {
|
||||
const response = await axios.get('/api/users/me');
|
||||
setUser(response.data.display_name);
|
||||
setUserName(response.data.username)
|
||||
setUserName(response.data.username);
|
||||
setAvatarUrl(response.data.avatar_url || null);
|
||||
} catch (err) {
|
||||
// Если нет сессии - редирект на логин
|
||||
setError('Вы не авторизованы');
|
||||
setTimeout(() => {
|
||||
navigate('/login');
|
||||
@@ -49,6 +51,38 @@ const Profile = () => {
|
||||
setError('Ошибка');
|
||||
}
|
||||
};
|
||||
|
||||
const uploadAvatar = async (event) => {
|
||||
const file = event.target.files[0];
|
||||
if (!file) return;
|
||||
|
||||
setIsUploading(true);
|
||||
setError('');
|
||||
|
||||
try {
|
||||
const formData = new FormData();
|
||||
formData.append('new_avatar', file);
|
||||
|
||||
await axios.put(
|
||||
'/api/users/change_avatar',
|
||||
formData,
|
||||
{
|
||||
withCredentials: true,
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data'
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
window.location.reload();
|
||||
|
||||
} catch (err) {
|
||||
setError(err.response?.data?.detail || 'Ошибка загрузки аватара');
|
||||
} finally {
|
||||
setIsUploading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const NewDisplayName = async (e) => {
|
||||
e.preventDefault();
|
||||
setError('');
|
||||
@@ -213,6 +247,38 @@ const Profile = () => {
|
||||
}
|
||||
{user && (
|
||||
<div className="user-info">
|
||||
<div className="avatar-wrapper">
|
||||
<label className="avatar-upload-label">
|
||||
<input
|
||||
type="file"
|
||||
accept="image/*"
|
||||
onChange={uploadAvatar}
|
||||
disabled={isUploading}
|
||||
className="avatar-file-input"
|
||||
/>
|
||||
|
||||
<div className="avatar-container">
|
||||
{avatarUrl ? (
|
||||
<img
|
||||
src={avatarUrl}
|
||||
alt="Аватар пользователя"
|
||||
className="avatar-image"
|
||||
/>
|
||||
) : (
|
||||
<div className="avatar-placeholder">
|
||||
{user?.charAt(0).toUpperCase()}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/*Overlay с плюсом (появляется при наведении)*/}
|
||||
<div className="avatar-overlay">
|
||||
<div className="plus-icon">+</div>
|
||||
</div>
|
||||
</div>
|
||||
</label>
|
||||
|
||||
{isUploading && <div className="uploading-spinner">Загружается...</div>}
|
||||
</div>
|
||||
<p><strong>Привет, {user}! Добро пожаловать в личный кабинет.</strong></p>
|
||||
<div className="text-block">Здесь ты сможешь управлять данными своей учётной записи.</div>
|
||||
<p>Информация об учётной записи</p>
|
||||
|
||||
119
src/css/App.css
119
src/css/App.css
@@ -235,7 +235,7 @@ button {
|
||||
.frame {
|
||||
background-color: #33404d;
|
||||
margin: 10px 0px;
|
||||
width: 30%;
|
||||
width: 344px;
|
||||
padding: 6px;
|
||||
border-radius: 6px;
|
||||
font-size: 16px;
|
||||
@@ -314,7 +314,8 @@ button:disabled {
|
||||
.buttonName button{
|
||||
background-color: #007bff;
|
||||
margin: 10px 5px;
|
||||
width: 5%;
|
||||
width: 50px;
|
||||
min-width: 50px;
|
||||
padding: 6px;
|
||||
border-radius: 6px;
|
||||
font-size: 20px;
|
||||
@@ -363,3 +364,117 @@ h3 {
|
||||
.margin-top-large {
|
||||
margin-top: 10em;
|
||||
}
|
||||
|
||||
.avatar-wrapper {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
float: right;
|
||||
margin: 30px
|
||||
}
|
||||
|
||||
.avatar-upload-label {
|
||||
display: block;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.avatar-file-input {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
opacity: 0;
|
||||
z-index: 2;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.avatar-container {
|
||||
position: relative;
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
background-color: #e0e0e0;
|
||||
transition: all 0.3s ease;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.avatar-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.avatar-placeholder {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 40px;
|
||||
color: #323332;
|
||||
text-transform: uppercase;
|
||||
transition: background-color 0.3s ease;
|
||||
}
|
||||
|
||||
/*Overlay — серый фон с плюсом*/
|
||||
.avatar-overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(200, 200, 200, 0.8); /* Светло‑серый фон */
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
transition: opacity 0.3s ease, visibility 0.3s ease;
|
||||
border-radius: 50%;
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
/* Плюс в центре */
|
||||
.rounded-plus {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 80px; /* Диаметр круга */
|
||||
height: 80px;
|
||||
background-color: #333333; /* Тёмно‑серый фон плюса */
|
||||
color: white; /* Белый знак "+" */
|
||||
font-size: 96px; /* Размер символа "+" */
|
||||
font-weight: bold;
|
||||
border-radius: 50%; /* Делаем круглым */
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); /* Лёгкая тень */
|
||||
transition: background-color 0.3s ease, transform 0.3s ease;
|
||||
}
|
||||
|
||||
/* Эффект при наведении на плюс (можно убрать, если не нужно) */
|
||||
.avatar-upload-label:hover .rounded-plus {
|
||||
background-color: #323332; /* Темнее при наведении */
|
||||
transform: scale(1.08); /* Лёгкое увеличение */
|
||||
}
|
||||
|
||||
/* Эффект при наведении */
|
||||
.avatar-upload-label:hover .avatar-overlay {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.avatar-upload-label:hover .avatar-container {
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
.avatar-upload-label:hover .avatar-placeholder,
|
||||
.avatar-upload-label:hover .avatar-image {
|
||||
filter: brightness(0.9);
|
||||
}
|
||||
|
||||
/* Индикатор загрузки */
|
||||
.uploading-spinner {
|
||||
margin-top: 10px;
|
||||
font-size: 12px;
|
||||
color: #6c757d;
|
||||
text-align: center;
|
||||
}
|
||||
Reference in New Issue
Block a user