Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions nextstep-frontend/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import './App.css';
import Feed from './pages/Feed';
import Footer from './components/Footer';
import RequireAuth from './hoc/RequireAuth';
import NewPost from './pages/NewPost';
import PostDetails from './pages/PostDetails';
import Chat from './pages/Chat';
import Resume from './pages/Resume';
Expand Down Expand Up @@ -74,7 +73,6 @@ const App: React.FC = () => {
<Routes>
<Route path="/feed" element={<RequireAuth><Layout className="feed"><Feed /></Layout></RequireAuth>} />
<Route path="/profile" element={<RequireAuth><Layout className="profile"><Profile /></Layout></RequireAuth>} />
<Route path="/new-post" element={<RequireAuth><Layout className="new-post"><NewPost /></Layout></RequireAuth>} />
<Route path="/post/:postId" element={<RequireAuth><Layout className="post-details"><PostDetails /></Layout></RequireAuth>} />
<Route path="/chat" element={<RequireAuth><Layout className="chat"><Chat /></Layout></RequireAuth>} />
<Route path="/resume" element={<RequireAuth><Layout className="resume"><Resume /></Layout></RequireAuth>} />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,31 @@
import React, { useState } from 'react';
import { Container, Button, Typography, Box } from '@mui/material';
import { useNavigate } from 'react-router-dom';
import { config } from '../config';
import {
Button,
Typography,
Container,
Modal,
Snackbar,
Alert,
} from '@mui/material';
import FroalaEditor from 'react-froala-wysiwyg';
import 'froala-editor/css/froala_style.min.css';
import 'froala-editor/css/froala_editor.pkgd.min.css';
import 'froala-editor/js/plugins/image.min.js';
import api from "../serverApi.ts";
import { getUserAuth } from '../handlers/userAuth.ts';
import { config } from '../config.ts';

const NewPost: React.FC = () => {
type Props = {
open: boolean;
onClose: () => void;
onPostCreated?: () => void;
};

const NewPostModal: React.FC<Props> = ({ open, onClose, onPostCreated }) => {
const [title, setTitle] = useState('');
const [content, setContent] = useState('');
const navigate = useNavigate();
const auth = getUserAuth();
const [error, setError] = useState<string | null>(null);

const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
Expand All @@ -25,25 +37,48 @@ const NewPost: React.FC = () => {
content,
});

navigate('/feed'); // Redirect to feed after successful post creation
onClose();
onPostCreated?.(); // Refresh feed if needed
} catch (error) {
console.error('Error creating post:', error);
setError('Error creating post: ' + error);
}
};

return (
<Container component="main" maxWidth="md">
<Box sx={{ display: 'flex', flexDirection: 'column', alignItems: 'center', mt: 8 }}>
<Typography component="h1" variant="h4" gutterBottom>
<Modal open={open} onClose={onClose}>
<Container
maxWidth="md"
sx={{
mt: 10,
backgroundColor: 'background.paper',
borderRadius: 2,
p: 4,
width: '40%',
overflowY: 'auto',
height: '80vh',
color: 'text.primary',
}}
>
<Typography variant="h5" gutterBottom color="text.primary">
Create New Post
</Typography>
<form onSubmit={handleSubmit} style={{ width: '90vh', overflowY: 'scroll', height: '60vh', marginTop: '1rem' }}>
<form onSubmit={handleSubmit}>
<input
type="text"
placeholder="Title"
value={title}
onChange={(e) => setTitle(e.target.value)}
style={{ width: '100%', marginBottom: '1rem', padding: '10px', fontSize: '16px' }}
style={{
width: '100%',
marginBottom: '1rem',
padding: '10px',
fontSize: '16px',
backgroundColor: 'transparent',
color: 'inherit',
border: '1px solid',
borderColor: 'divider',
borderRadius: '4px',
}}
required
/>
<FroalaEditor
Expand Down Expand Up @@ -94,33 +129,37 @@ const NewPost: React.FC = () => {
editor.image.insert(imageUrl, null, null, editor.image.get());
})
.catch(error => {
console.error('Error uploading image:', error);
setError('Error uploading image: ' + error);
});

return false; // Prevent default upload
},
'image.error': function (error: any, response: any) {
console.error('Image upload error:', error, response);
setError('Image upload error: ' + error + ', response: ' + response);
}
}
}}
/>
<Button type="submit" fullWidth variant="contained" color="primary" sx={{ mt: 3, mb: 2 }}>
<Button type="submit" fullWidth variant="contained" color="primary" sx={{ mt: 3}}>
Submit
</Button>
<Button
fullWidth
variant="outlined"
color="secondary"
onClick={() => navigate('/feed')}
sx={{ mt: 2 }}
>
Back to Feed
<Button fullWidth onClick={onClose} sx={{ mt: 1 }}>
Cancel
</Button>
</form>
</Box>
</Container>
<Snackbar
open={!!error}
autoHideDuration={6000}
onClose={() => setError(null)}
anchorOrigin={{ vertical: 'top', horizontal: 'center' }}
>
<Alert severity="error" onClose={() => setError(null)}>
{error}
</Alert>
</Snackbar>
</Container>
</Modal>
);
};

export default NewPost;
export default NewPostModal;
65 changes: 55 additions & 10 deletions nextstep-frontend/src/pages/Feed.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import { Post } from "../models/Post.tsx";
import api from "../serverApi.ts";
import {getUserAuth} from "../handlers/userAuth.ts";
import defaultProfileImage from '../../assets/defaultProfileImage.jpg'; // Import the default profile image
import NewPostModal from '../components/NewPost.tsx';


const Feed: React.FC = () => {
Expand All @@ -42,10 +43,12 @@ const Feed: React.FC = () => {
const [profileImages, setProfileImages] = useState<{ [key: string]: string }>({});
const [currentPage, setCurrentPage] = useState(1);
const [totalPages, setTotalPages] = useState(1);
const [showNewPostModal, setShowNewPostModal] = useState(false);

const auth = getUserAuth();

const handleCreatePost = () => {
navigate('/new-post');
setShowNewPostModal(true);
};

const handleDeletePost = async () => {
Expand Down Expand Up @@ -197,20 +200,60 @@ const Feed: React.FC = () => {
<Box sx={{ display: "flex", flexGrow: 1 }}>
<Box sx={{ flexGrow: 1}}>
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 2 }}>
<Button variant="contained" color="primary" onClick={handleCreatePost}>
Create New Post
</Button>
<FormControlLabel
<Card
sx={{
mb: 2,
p: 2,
borderRadius: '12px',
boxShadow: 2,
width: '80vh',
cursor: 'pointer',
'&:hover': {
boxShadow: 4,
backgroundColor: 'rgba(0, 0, 0, 0.03)',
},
}}
>
<Box sx={{ display: 'flex', alignItems: 'center' }}>
<Avatar src={profileImages[auth.userId] || defaultProfileImage} sx={{ mr: 2 }} />
<Box
sx={{
backgroundColor: 'background.paper',
borderRadius: '20px',
px: 2,
py: 1,
flexGrow: 1,
}}
>
<Typography color="text.primary" sx={{ opacity: 0.7 }}>What's on your mind{', ' + auth.username || 'User'}?</Typography>
</Box>
</Box>
<Box sx={{ display: 'flex', justifyContent: 'space-around', mt: 2 }}>
<Button startIcon={<span style={{ color: 'green' }}>📝</span>} sx={{ textTransform: 'none' }}>
Share your resume
</Button>
<Button onClick={handleCreatePost} startIcon={<span style={{ color: 'orange' }}>📤</span>} sx={{ textTransform: 'none' }}>
Create a new post
</Button>
</Box>
</Card>
</Box>

<FormControlLabel
control={
<Switch
checked={filterByUser}
onChange={() => setFilterByUser(!filterByUser)}
color="primary"
/>
}
label="Show My Posts"
/>
</Box>
label="Show only my posts"
/>
<NewPostModal
open={showNewPostModal}
onClose={() => setShowNewPostModal(false)}
onPostCreated={() => loadPosts(currentPage)}
/>
<Box sx={{ width: '100%', maxHeight: '60vh' }}>
{isLoading ? (
<Box sx={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100%' }}>
Expand All @@ -220,11 +263,12 @@ const Feed: React.FC = () => {
<Typography color="error">{error}</Typography>
) : (
<>
<List>
<List sx={{ overflowY: 'auto', maxHeight: '80vh' }}>
{posts.map((post) => (
<React.Fragment key={post.id}>
<Card sx={{
mb: 2,
height: '50%',
width: '80vh',
cursor: 'pointer',
transition: 'transform 0.2s, box-shadow 0.2s',
Expand Down Expand Up @@ -276,7 +320,7 @@ const Feed: React.FC = () => {
</>
)}
</Box>
<Box sx={{ display: 'flex', justifyContent: 'center', mt: 2 }}>
{ totalPages > 0 && <Box sx={{ display: 'flex', justifyContent: 'center', mt: 20 }}>
<Button
variant="outlined"
onClick={() => handlePageChange(currentPage - 1)}
Expand All @@ -293,6 +337,7 @@ const Feed: React.FC = () => {
Next
</Button>
</Box>
}
</Box>
</Box>

Expand Down
Loading