diff --git a/src/Profile.js b/src/Profile.js index 9cf03cf..501a8f0 100644 --- a/src/Profile.js +++ b/src/Profile.js @@ -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 && (
+
+ + + {isUploading &&
Загружается...
} +

Привет, {user}! Добро пожаловать в личный кабинет.

Здесь ты сможешь управлять данными своей учётной записи.

Информация об учётной записи

diff --git a/src/css/App.css b/src/css/App.css index 0e18f5a..f2ceadd 100644 --- a/src/css/App.css +++ b/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; @@ -362,4 +363,118 @@ 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; } \ No newline at end of file