Skip to content

Commit 3e0fc50

Browse files
authored
Merge pull request #23 from NextStepFinalProject/NXD-27-Edit-feed-page
Nxd 27 edit feed page
2 parents dd8fac4 + 56a490c commit 3e0fc50

File tree

3 files changed

+120
-38
lines changed

3 files changed

+120
-38
lines changed

nextstep-frontend/src/App.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import './App.css';
77
import Feed from './pages/Feed';
88
import Footer from './components/Footer';
99
import RequireAuth from './hoc/RequireAuth';
10-
import NewPost from './pages/NewPost';
1110
import PostDetails from './pages/PostDetails';
1211
import Chat from './pages/Chat';
1312
import Resume from './pages/Resume';
@@ -74,7 +73,6 @@ const App: React.FC = () => {
7473
<Routes>
7574
<Route path="/feed" element={<RequireAuth><Layout className="feed"><Feed /></Layout></RequireAuth>} />
7675
<Route path="/profile" element={<RequireAuth><Layout className="profile"><Profile /></Layout></RequireAuth>} />
77-
<Route path="/new-post" element={<RequireAuth><Layout className="new-post"><NewPost /></Layout></RequireAuth>} />
7876
<Route path="/post/:postId" element={<RequireAuth><Layout className="post-details"><PostDetails /></Layout></RequireAuth>} />
7977
<Route path="/chat" element={<RequireAuth><Layout className="chat"><Chat /></Layout></RequireAuth>} />
8078
<Route path="/resume" element={<RequireAuth><Layout className="resume"><Resume /></Layout></RequireAuth>} />

nextstep-frontend/src/pages/NewPost.tsx renamed to nextstep-frontend/src/components/NewPost.tsx

Lines changed: 65 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,31 @@
11
import React, { useState } from 'react';
2-
import { Container, Button, Typography, Box } from '@mui/material';
3-
import { useNavigate } from 'react-router-dom';
4-
import { config } from '../config';
2+
import {
3+
Button,
4+
Typography,
5+
Container,
6+
Modal,
7+
Snackbar,
8+
Alert,
9+
} from '@mui/material';
510
import FroalaEditor from 'react-froala-wysiwyg';
611
import 'froala-editor/css/froala_style.min.css';
712
import 'froala-editor/css/froala_editor.pkgd.min.css';
813
import 'froala-editor/js/plugins/image.min.js';
914
import api from "../serverApi.ts";
1015
import { getUserAuth } from '../handlers/userAuth.ts';
16+
import { config } from '../config.ts';
1117

12-
const NewPost: React.FC = () => {
18+
type Props = {
19+
open: boolean;
20+
onClose: () => void;
21+
onPostCreated?: () => void;
22+
};
23+
24+
const NewPostModal: React.FC<Props> = ({ open, onClose, onPostCreated }) => {
1325
const [title, setTitle] = useState('');
1426
const [content, setContent] = useState('');
15-
const navigate = useNavigate();
1627
const auth = getUserAuth();
28+
const [error, setError] = useState<string | null>(null);
1729

1830
const handleSubmit = async (e: React.FormEvent) => {
1931
e.preventDefault();
@@ -25,25 +37,48 @@ const NewPost: React.FC = () => {
2537
content,
2638
});
2739

28-
navigate('/feed'); // Redirect to feed after successful post creation
40+
onClose();
41+
onPostCreated?.(); // Refresh feed if needed
2942
} catch (error) {
30-
console.error('Error creating post:', error);
43+
setError('Error creating post: ' + error);
3144
}
3245
};
3346

3447
return (
35-
<Container component="main" maxWidth="md">
36-
<Box sx={{ display: 'flex', flexDirection: 'column', alignItems: 'center', mt: 8 }}>
37-
<Typography component="h1" variant="h4" gutterBottom>
48+
<Modal open={open} onClose={onClose}>
49+
<Container
50+
maxWidth="md"
51+
sx={{
52+
mt: 10,
53+
backgroundColor: 'background.paper',
54+
borderRadius: 2,
55+
p: 4,
56+
width: '40%',
57+
overflowY: 'auto',
58+
height: '80vh',
59+
color: 'text.primary',
60+
}}
61+
>
62+
<Typography variant="h5" gutterBottom color="text.primary">
3863
Create New Post
3964
</Typography>
40-
<form onSubmit={handleSubmit} style={{ width: '90vh', overflowY: 'scroll', height: '60vh', marginTop: '1rem' }}>
65+
<form onSubmit={handleSubmit}>
4166
<input
4267
type="text"
4368
placeholder="Title"
4469
value={title}
4570
onChange={(e) => setTitle(e.target.value)}
46-
style={{ width: '100%', marginBottom: '1rem', padding: '10px', fontSize: '16px' }}
71+
style={{
72+
width: '100%',
73+
marginBottom: '1rem',
74+
padding: '10px',
75+
fontSize: '16px',
76+
backgroundColor: 'transparent',
77+
color: 'inherit',
78+
border: '1px solid',
79+
borderColor: 'divider',
80+
borderRadius: '4px',
81+
}}
4782
required
4883
/>
4984
<FroalaEditor
@@ -94,33 +129,37 @@ const NewPost: React.FC = () => {
94129
editor.image.insert(imageUrl, null, null, editor.image.get());
95130
})
96131
.catch(error => {
97-
console.error('Error uploading image:', error);
132+
setError('Error uploading image: ' + error);
98133
});
99134

100135
return false; // Prevent default upload
101136
},
102137
'image.error': function (error: any, response: any) {
103-
console.error('Image upload error:', error, response);
138+
setError('Image upload error: ' + error + ', response: ' + response);
104139
}
105140
}
106141
}}
107142
/>
108-
<Button type="submit" fullWidth variant="contained" color="primary" sx={{ mt: 3, mb: 2 }}>
143+
<Button type="submit" fullWidth variant="contained" color="primary" sx={{ mt: 3}}>
109144
Submit
110145
</Button>
111-
<Button
112-
fullWidth
113-
variant="outlined"
114-
color="secondary"
115-
onClick={() => navigate('/feed')}
116-
sx={{ mt: 2 }}
117-
>
118-
Back to Feed
146+
<Button fullWidth onClick={onClose} sx={{ mt: 1 }}>
147+
Cancel
119148
</Button>
120149
</form>
121-
</Box>
122-
</Container>
150+
<Snackbar
151+
open={!!error}
152+
autoHideDuration={6000}
153+
onClose={() => setError(null)}
154+
anchorOrigin={{ vertical: 'top', horizontal: 'center' }}
155+
>
156+
<Alert severity="error" onClose={() => setError(null)}>
157+
{error}
158+
</Alert>
159+
</Snackbar>
160+
</Container>
161+
</Modal>
123162
);
124163
};
125164

126-
export default NewPost;
165+
export default NewPostModal;

nextstep-frontend/src/pages/Feed.tsx

Lines changed: 55 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import { Post } from "../models/Post.tsx";
2626
import api from "../serverApi.ts";
2727
import {getUserAuth} from "../handlers/userAuth.ts";
2828
import defaultProfileImage from '../../assets/defaultProfileImage.jpg'; // Import the default profile image
29+
import NewPostModal from '../components/NewPost.tsx';
2930

3031

3132
const Feed: React.FC = () => {
@@ -42,10 +43,12 @@ const Feed: React.FC = () => {
4243
const [profileImages, setProfileImages] = useState<{ [key: string]: string }>({});
4344
const [currentPage, setCurrentPage] = useState(1);
4445
const [totalPages, setTotalPages] = useState(1);
46+
const [showNewPostModal, setShowNewPostModal] = useState(false);
47+
4548
const auth = getUserAuth();
4649

4750
const handleCreatePost = () => {
48-
navigate('/new-post');
51+
setShowNewPostModal(true);
4952
};
5053

5154
const handleDeletePost = async () => {
@@ -197,20 +200,60 @@ const Feed: React.FC = () => {
197200
<Box sx={{ display: "flex", flexGrow: 1 }}>
198201
<Box sx={{ flexGrow: 1}}>
199202
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 2 }}>
200-
<Button variant="contained" color="primary" onClick={handleCreatePost}>
201-
Create New Post
202-
</Button>
203-
<FormControlLabel
203+
<Card
204+
sx={{
205+
mb: 2,
206+
p: 2,
207+
borderRadius: '12px',
208+
boxShadow: 2,
209+
width: '80vh',
210+
cursor: 'pointer',
211+
'&:hover': {
212+
boxShadow: 4,
213+
backgroundColor: 'rgba(0, 0, 0, 0.03)',
214+
},
215+
}}
216+
>
217+
<Box sx={{ display: 'flex', alignItems: 'center' }}>
218+
<Avatar src={profileImages[auth.userId] || defaultProfileImage} sx={{ mr: 2 }} />
219+
<Box
220+
sx={{
221+
backgroundColor: 'background.paper',
222+
borderRadius: '20px',
223+
px: 2,
224+
py: 1,
225+
flexGrow: 1,
226+
}}
227+
>
228+
<Typography color="text.primary" sx={{ opacity: 0.7 }}>What's on your mind{', ' + auth.username || 'User'}?</Typography>
229+
</Box>
230+
</Box>
231+
<Box sx={{ display: 'flex', justifyContent: 'space-around', mt: 2 }}>
232+
<Button startIcon={<span style={{ color: 'green' }}>📝</span>} sx={{ textTransform: 'none' }}>
233+
Share your resume
234+
</Button>
235+
<Button onClick={handleCreatePost} startIcon={<span style={{ color: 'orange' }}>📤</span>} sx={{ textTransform: 'none' }}>
236+
Create a new post
237+
</Button>
238+
</Box>
239+
</Card>
240+
</Box>
241+
242+
<FormControlLabel
204243
control={
205244
<Switch
206245
checked={filterByUser}
207246
onChange={() => setFilterByUser(!filterByUser)}
208247
color="primary"
209248
/>
210249
}
211-
label="Show My Posts"
212-
/>
213-
</Box>
250+
label="Show only my posts"
251+
/>
252+
<NewPostModal
253+
open={showNewPostModal}
254+
onClose={() => setShowNewPostModal(false)}
255+
onPostCreated={() => loadPosts(currentPage)}
256+
/>
214257
<Box sx={{ width: '100%', maxHeight: '60vh' }}>
215258
{isLoading ? (
216259
<Box sx={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100%' }}>
@@ -220,11 +263,12 @@ const Feed: React.FC = () => {
220263
<Typography color="error">{error}</Typography>
221264
) : (
222265
<>
223-
<List>
266+
<List sx={{ overflowY: 'auto', maxHeight: '80vh' }}>
224267
{posts.map((post) => (
225268
<React.Fragment key={post.id}>
226269
<Card sx={{
227270
mb: 2,
271+
height: '50%',
228272
width: '80vh',
229273
cursor: 'pointer',
230274
transition: 'transform 0.2s, box-shadow 0.2s',
@@ -276,7 +320,7 @@ const Feed: React.FC = () => {
276320
</>
277321
)}
278322
</Box>
279-
<Box sx={{ display: 'flex', justifyContent: 'center', mt: 2 }}>
323+
{ totalPages > 0 && <Box sx={{ display: 'flex', justifyContent: 'center', mt: 20 }}>
280324
<Button
281325
variant="outlined"
282326
onClick={() => handlePageChange(currentPage - 1)}
@@ -293,6 +337,7 @@ const Feed: React.FC = () => {
293337
Next
294338
</Button>
295339
</Box>
340+
}
296341
</Box>
297342
</Box>
298343

0 commit comments

Comments
 (0)