add messeges, add posts in profile
This commit is contained in:
@@ -7,6 +7,7 @@ import Footer from './components/Footer';
|
|||||||
import Register from './components/Register';
|
import Register from './components/Register';
|
||||||
import Login from './components/Login';
|
import Login from './components/Login';
|
||||||
import Profile from './components/Profile';
|
import Profile from './components/Profile';
|
||||||
|
import Messages from './components/Messages';
|
||||||
import styles from './App.module.css';
|
import styles from './App.module.css';
|
||||||
|
|
||||||
const App = () => {
|
const App = () => {
|
||||||
@@ -29,6 +30,7 @@ const App = () => {
|
|||||||
<Route path="/register" element={<Register />} />
|
<Route path="/register" element={<Register />} />
|
||||||
<Route path="/login" element={!isAuthenticated ? <Login onLogin={handleLogin} /> : <Navigate to="/profile" />} />
|
<Route path="/login" element={!isAuthenticated ? <Login onLogin={handleLogin} /> : <Navigate to="/profile" />} />
|
||||||
<Route path="/profile" element={isAuthenticated ? <Profile /> : <Navigate to="/login" />} />
|
<Route path="/profile" element={isAuthenticated ? <Profile /> : <Navigate to="/login" />} />
|
||||||
|
<Route path="/messages" element={isAuthenticated ? <Messages /> : <Navigate to="/login" />} />
|
||||||
<Route path="/" element={<Home />} /> {/* Главная страница */}
|
<Route path="/" element={<Home />} /> {/* Главная страница */}
|
||||||
</Routes>
|
</Routes>
|
||||||
</main>
|
</main>
|
||||||
|
|||||||
@@ -15,7 +15,10 @@ const Header = ({ isAuthenticated, onLogout }) => {
|
|||||||
</div>
|
</div>
|
||||||
{!isAuthenticated && <Link to="/register" className={styles.registerLink}>Зарегистрироваться</Link>}
|
{!isAuthenticated && <Link to="/register" className={styles.registerLink}>Зарегистрироваться</Link>}
|
||||||
{isAuthenticated && (
|
{isAuthenticated && (
|
||||||
<button className={styles.logoutButton} onClick={onLogout}>Выйти</button>
|
<>
|
||||||
|
<Link to="/messages" className={styles.messagesLink}>Перейти к сообщениям</Link>
|
||||||
|
<button className={styles.logoutButton} onClick={onLogout}>Выйти</button>
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
</header>
|
</header>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -30,6 +30,16 @@
|
|||||||
text-decoration: underline; /* Подчеркивание при наведении */
|
text-decoration: underline; /* Подчеркивание при наведении */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.messagesLink {
|
||||||
|
color: #ff4500; /* Оранжевый цвет ссылки */
|
||||||
|
text-decoration: none;
|
||||||
|
margin-right: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.messagesLink:hover {
|
||||||
|
text-decoration: underline; /* Подчеркивание при наведении */
|
||||||
|
}
|
||||||
|
|
||||||
.logoutButton {
|
.logoutButton {
|
||||||
background-color: #ff4500; /* Оранжевая кнопка */
|
background-color: #ff4500; /* Оранжевая кнопка */
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
|
|||||||
15
src/components/Messages.js
Normal file
15
src/components/Messages.js
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
// src/components/Messages.js
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import styles from './Messages.module.css';
|
||||||
|
|
||||||
|
const Messages = () => {
|
||||||
|
return (
|
||||||
|
<div className={styles.messagesContainer}>
|
||||||
|
<h2>Сообщения</h2>
|
||||||
|
<p>Здесь будут ваши сообщения.</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Messages;
|
||||||
20
src/components/Messages.module.css
Normal file
20
src/components/Messages.module.css
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
/* src/components/Messages.module.css */
|
||||||
|
|
||||||
|
.messagesContainer {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background-color: #1a1a1a; /* Темный фон */
|
||||||
|
color: #ffffff; /* Белый текст */
|
||||||
|
padding: 16px; /* Добавляем отступы */
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.messagesContainer h2 {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.messagesContainer p {
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
@@ -1,13 +1,128 @@
|
|||||||
// src/components/Profile.js
|
// src/components/Profile.js
|
||||||
|
|
||||||
import React from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import styles from './Profile.module.css';
|
import styles from './Profile.module.css';
|
||||||
|
|
||||||
const Profile = () => {
|
const Profile = () => {
|
||||||
|
const [profilePicture, setProfilePicture] = useState(null);
|
||||||
|
const [posts, setPosts] = useState([]);
|
||||||
|
const [newPostText, setNewPostText] = useState('');
|
||||||
|
const [newPostMusic, setNewPostMusic] = useState(null);
|
||||||
|
const [newPostImage, setNewPostImage] = useState(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// Загружаем посты из localStorage при монтировании компонента
|
||||||
|
const savedPosts = JSON.parse(localStorage.getItem('posts')) || [];
|
||||||
|
setPosts(savedPosts);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// Сохраняем посты в localStorage при изменении
|
||||||
|
localStorage.setItem('posts', JSON.stringify(posts));
|
||||||
|
}, [posts]);
|
||||||
|
|
||||||
|
const handleProfilePictureChange = (e) => {
|
||||||
|
const file = e.target.files[0];
|
||||||
|
if (file) {
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.onloadend = () => {
|
||||||
|
setProfilePicture(reader.result);
|
||||||
|
};
|
||||||
|
reader.readAsDataURL(file);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleNewPostMusicChange = (e) => {
|
||||||
|
const file = e.target.files[0];
|
||||||
|
if (file) {
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.onloadend = () => {
|
||||||
|
setNewPostMusic(reader.result);
|
||||||
|
};
|
||||||
|
reader.readAsDataURL(file);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleNewPostImageChange = (e) => {
|
||||||
|
const file = e.target.files[0];
|
||||||
|
if (file) {
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.onloadend = () => {
|
||||||
|
setNewPostImage(reader.result);
|
||||||
|
};
|
||||||
|
reader.readAsDataURL(file);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const addPost = () => {
|
||||||
|
if (!newPostText || !newPostMusic) {
|
||||||
|
alert('Пожалуйста, заполните текст и добавьте музыку.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const newPost = {
|
||||||
|
id: posts.length + 1,
|
||||||
|
musicUrl: newPostMusic,
|
||||||
|
text: newPostText,
|
||||||
|
image: newPostImage
|
||||||
|
};
|
||||||
|
|
||||||
|
setPosts([...posts, newPost]);
|
||||||
|
setNewPostText('');
|
||||||
|
setNewPostMusic(null);
|
||||||
|
setNewPostImage(null);
|
||||||
|
};
|
||||||
|
|
||||||
|
const deletePost = (id) => {
|
||||||
|
const updatedPosts = posts.filter(post => post.id !== id);
|
||||||
|
setPosts(updatedPosts);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.profileContainer}>
|
<div className={styles.profileContainer}>
|
||||||
<h2>Профиль</h2>
|
<div className={styles.profileHeader}>
|
||||||
<p>Добро пожаловать в ваш профиль!</p>
|
<div className={styles.profilePicture}>
|
||||||
|
{profilePicture ? (
|
||||||
|
<img src={profilePicture} alt="Profile" />
|
||||||
|
) : (
|
||||||
|
<div className={styles.defaultPicture}>
|
||||||
|
<span>Фото</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<input type="file" accept="image/*" onChange={handleProfilePictureChange} className={styles.fileInput} />
|
||||||
|
</div>
|
||||||
|
<div className={styles.profileInfo}>
|
||||||
|
<h2>Имя Пользователя</h2>
|
||||||
|
<button className={styles.editButton}>Редактировать профиль</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className={styles.postsContainer}>
|
||||||
|
<h3>Посты</h3>
|
||||||
|
<div className={styles.newPostForm}>
|
||||||
|
<textarea
|
||||||
|
value={newPostText}
|
||||||
|
onChange={(e) => setNewPostText(e.target.value)}
|
||||||
|
placeholder="Введите текст поста"
|
||||||
|
className={styles.postTextarea}
|
||||||
|
/>
|
||||||
|
<div className={styles.fileInputs}>
|
||||||
|
<input type="file" accept="audio/*" onChange={handleNewPostMusicChange} className={styles.fileInput} />
|
||||||
|
<input type="file" accept="image/*" onChange={handleNewPostImageChange} className={styles.fileInput} />
|
||||||
|
</div>
|
||||||
|
<button className={styles.addPostButton} onClick={addPost}>Добавить пост</button>
|
||||||
|
</div>
|
||||||
|
{posts.map((post) => (
|
||||||
|
<div key={post.id} className={styles.post}>
|
||||||
|
{post.image && <img src={post.image} alt={`Post ${post.id}`} />}
|
||||||
|
<audio controls>
|
||||||
|
<source src={post.musicUrl} type="audio/mpeg" />
|
||||||
|
Ваш браузер не поддерживает воспроизведение аудио.
|
||||||
|
</audio>
|
||||||
|
<p>{post.text}</p>
|
||||||
|
<button className={styles.deletePostButton} onClick={() => deletePost(post.id)}>Удалить пост</button>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -5,16 +5,162 @@
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
height: 100vh;
|
|
||||||
background-color: #1a1a1a; /* Темный фон */
|
background-color: #1a1a1a; /* Темный фон */
|
||||||
color: #ffffff; /* Белый текст */
|
color: #ffffff; /* Белый текст */
|
||||||
padding: 16px; /* Добавляем отступы */
|
padding: 16px; /* Добавляем отступы */
|
||||||
|
min-height: 100vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
.profileContainer h2 {
|
.profileHeader {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profilePicture {
|
||||||
|
position: relative;
|
||||||
|
margin-right: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profilePicture img {
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
border-radius: 50%;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profilePicture .defaultPicture {
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: #444;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
color: #ffffff;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profilePicture .fileInput {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
opacity: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profileInfo h2 {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editButton {
|
||||||
|
background-color: #ff4500; /* Оранжевая кнопка */
|
||||||
|
color: #ffffff;
|
||||||
|
border: none;
|
||||||
|
padding: 8px 16px;
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editButton:hover {
|
||||||
|
background-color: #e63900; /* Тёмная оранжевая кнопка при наведении */
|
||||||
|
}
|
||||||
|
|
||||||
|
.postsContainer {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 600px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.postsContainer h3 {
|
||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.profileContainer p {
|
.newPostForm {
|
||||||
font-size: 18px;
|
background-color: #282828; /* Средний темный фон */
|
||||||
|
padding: 16px;
|
||||||
|
border-radius: 8px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.postTextarea {
|
||||||
|
width: 100%;
|
||||||
|
height: 100px;
|
||||||
|
padding: 8px;
|
||||||
|
border: 1px solid #444;
|
||||||
|
border-radius: 4px;
|
||||||
|
background-color: #1a1a1a; /* Темный фон для инпутов */
|
||||||
|
color: #ffffff; /* Белый текст */
|
||||||
|
margin-bottom: 16px;
|
||||||
|
resize: vertical;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fileInputs {
|
||||||
|
display: flex;
|
||||||
|
gap: 16px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fileInput {
|
||||||
|
background-color: #ff4500; /* Оранжевая кнопка */
|
||||||
|
color: #ffffff;
|
||||||
|
border: none;
|
||||||
|
padding: 8px 16px;
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fileInput:hover {
|
||||||
|
background-color: #e63900; /* Тёмная оранжевая кнопка при наведении */
|
||||||
|
}
|
||||||
|
|
||||||
|
.addPostButton {
|
||||||
|
background-color: #ff4500; /* Оранжевая кнопка */
|
||||||
|
color: #ffffff;
|
||||||
|
border: none;
|
||||||
|
padding: 8px 16px;
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.addPostButton:hover {
|
||||||
|
background-color: #e63900; /* Тёмная оранжевая кнопка при наведении */
|
||||||
|
}
|
||||||
|
|
||||||
|
.post {
|
||||||
|
background-color: #282828; /* Средний темный фон */
|
||||||
|
padding: 16px;
|
||||||
|
border-radius: 8px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.post img {
|
||||||
|
width: 100%;
|
||||||
|
height: auto;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.post audio {
|
||||||
|
width: 100%;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.post p {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.deletePostButton {
|
||||||
|
background-color: #ff4500; /* Оранжевая кнопка */
|
||||||
|
color: #ffffff;
|
||||||
|
border: none;
|
||||||
|
padding: 8px 16px;
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.deletePostButton:hover {
|
||||||
|
background-color: #e63900; /* Тёмная оранжевая кнопка при наведении */
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user