183 |
184 | {post && post.title}
185 |
186 | {
187 | (!type || type != "powner") ?
188 | <>
189 |
190 | {post && post.views}
191 |
192 |
193 |
194 |
195 | |
196 |
197 |
198 | {/*
*/}
199 | {post && post.likes ? post.likes : 0}
200 |
{"" + ""}
201 |
202 |
203 |
204 | {/*
*/}
205 |
206 |
207 | >
208 | :
209 | <>
210 |
211 | >
212 | }
213 |
214 |
215 |
216 |
217 | {post && post.description}
218 |
219 | {(type && type === "powner")
220 | ?
221 | <>
222 |
223 |
224 | {/*
*/}
225 | {post && post.views}
226 |
227 |
228 |
{"" + ""}
229 |
230 | {/*
*/}
231 |
232 | |
233 |
234 | {/*
*/}
235 | {post && post.likes ? post.likes : 0}
236 |
{"" + ""}
237 |
238 |
239 |
240 | {/*
*/}
241 |
242 | |
243 |
editposts(post._id)}> Edit
244 | |
245 |
deleteposts(post._id)}> Delete
246 | {/*
*/}
247 | {/*
*/}
248 |
249 |
256 | console.log("shared successfully!")
257 | }
258 | >
259 |
260 | Share
261 |
262 |
263 |
264 | >
265 | :
266 | <>
267 |
268 |
269 | {!user ?
270 |
271 |
272 |
273 | :
274 | (post && post.user && post.user._id) &&
275 |
276 |
277 |
278 | }
279 | {post && post.user ?
280 |
281 | :
282 | <>>}
283 |
284 |
285 | {!user ?
286 | {(post && post.user && post.user.name )? post.user.name : "N/A"}
287 | :
288 | {post && post.user.name}
289 | }
290 | {localTimeString}
291 |
292 |
293 | {!heart ?
{ if (!user) { navigate("/auth") } else handleheart() }} /> :
294 | { if (!user) { navigate("/auth") } else handleheartfalse() }} width="25px" height="25px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" stroke="#000000" strokeWidth="0.648">
295 | }
296 | {type === "main" ?
297 | <>
298 |
299 | {sbook2 && {
300 | if (!user) { navigate("/auth") } else { setbookmark(); setsbook2(false) }
301 | }}
302 | />
303 | }
304 | {!sbook2 && { if (!user) { navigate("/auth") } else dellbookmarl(); setsbook2(true) }} />
306 | }
307 |
308 | >
309 | :
310 | <>>
311 | }
312 | {/* hhhhkk */}
313 | {type && type === "profile_bookmark" ?
314 | <>
315 | {!sbook ?
316 | <>
317 | {
318 | setbookmark();
319 | }}
320 | />
321 | >
322 | :
323 | <>
324 | { dellbookmarl(); }} />
326 |
327 | >
328 | }
329 | >
330 | :
331 | <>>
332 |
333 | }
334 |
335 |
{
336 | showmenu(false)
337 | }} onMouseOver={() => { showmenu(true); }} />
338 | { showmenu(true); }}
339 | onMouseLeave={() => {
340 | showmenu(false)
341 | }}>
342 |
349 | console.log("shared successfully!")
350 | }
351 | >
352 |
353 |
354 |
355 |
356 | Share
357 |
358 |
359 |
360 |
361 |
362 |
363 |
364 | {/* */}
365 |
366 |
367 |
368 | {/*
*/}
369 | {/*
370 |
371 |
*/}
372 |
373 | >}
374 |
375 |
376 | );
377 | }
378 |
379 | export default PostCard;
380 |
--------------------------------------------------------------------------------
/client/src/components/home/post/Posts.js:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useState } from "react";
2 | import "./post.css";
3 | import { getAllPost } from "../../../helpers";
4 | import PostCard from "./PostCard";
5 | import InfiniteScroll from "react-infinite-scroll-component";
6 | import { DotLoader } from "react-spinners";
7 | import { useDispatch, useSelector } from "react-redux";
8 | import { PuffLoader } from "react-spinners";
9 | // import { Puff}
10 |
11 | function Posts({category}) {
12 | const LIMIT = 6;
13 | const [totalPosts, setTotalPost] = useState(0);
14 | const [activePage, setActivePage] = useState(1);
15 | const dispatch = useDispatch()
16 | const { posts } = useSelector(state => ({ ...state }))
17 | useEffect(() => {
18 | if (posts.length === 0) {
19 | x();
20 | }
21 | }, []);
22 |
23 | const x = async () => {
24 | try {
25 | // setUser(datad.user)
26 | const data = await getAllPost(activePage, LIMIT, category);
27 | dispatch({ type: "SET_POSTS", payload: data.posts })
28 | setActivePage(activePage + 1);
29 | setTotalPost(data.total);
30 | } catch (error) {
31 | // console.log(error);
32 | throw error;
33 | }
34 | };
35 |
36 | return (
37 |
43 |
44 |
45 | }
46 | endMessage={
47 | posts.length && (
48 |
49 | Looks like You have reached to the end.?!
50 |
51 | )
52 | }
53 | >
54 | {(posts && posts.length === 0) ? (
55 |
58 | ) : (
59 |
60 |
61 | {posts.map((post, i) => {
62 |
63 | return
;
65 | })}
66 |
67 | )}
68 |
69 | );
70 | }
71 |
72 | export default Posts;
--------------------------------------------------------------------------------
/client/src/components/home/post/post.css:
--------------------------------------------------------------------------------
1 | .posts_container {
2 | margin: 1.2rem 8rem;
3 | display: grid;
4 | grid-template-columns: repeat(2, 1fr);
5 | grid-auto-flow: auto;
6 | grid-gap: 1.2rem;
7 | }
8 |
9 | .item {
10 | background-color: whitesmoke;
11 | }
12 |
13 | .posts_container .item {
14 | border: .5px solid rgb(206, 200, 200);
15 | display: flex;
16 | gap: 2.3rem;
17 | transition: all 0.2s;
18 | border-radius: 6px;
19 | overflow: hidden;
20 | -webkit-box-shadow: 0px 1px 12px -2px rgba(0, 0, 0, 0.69);
21 | -moz-box-shadow: 0px 1px 12px -2px rgba(0, 0, 0, 0.69);
22 | box-shadow: 0px 1px 12px -2px rgba(0, 0, 0, 0.69);
23 | }
24 |
25 | .profile_data24 {
26 | /* position: relative; */
27 | /* display: flex; */
28 | /* gap:3px; */
29 | text-decoration: none;
30 | /* margin-top: 10px; */
31 | /* float: left; */
32 | /* bottom:0px; */
33 | /* top:60px; */
34 | /* left:2px; */
35 | /* font-size: 15px; */
36 | }
37 |
38 | .view_post_profile {
39 | font-size: 16px;
40 | color: grey;
41 | display: flex;
42 | justify-items: center;
43 | align-items: center;
44 | }
45 |
46 | .sharepostmy {
47 | width: 100%;
48 | text-align: center;
49 | background-color: rgb(218, 236, 252);
50 | border-radius: 40px;
51 | }
52 |
53 | .sharepostmy:hover {
54 | cursor: pointer;
55 | transform: scale(1.1);
56 | box-shadow:black;
57 | }
58 |
59 | .bluev {
60 | color: blue;
61 | text-decoration: none;
62 | }
63 |
64 | .imgscp {
65 | border: solid 1px black;
66 | border-radius: 50%;
67 | }
68 |
69 | .post_date {
70 | font-size: 20px;
71 | color: rgb(93, 93, 93);
72 | }
73 |
74 | .posts_container .item:hover {
75 | transform: scale(1.02);
76 | -webkit-box-shadow: 1px 2px 6px 0px rgba(161, 152, 161, 1);
77 | -moz-box-shadow: 1px 2px 6px 0px rgba(161, 152, 161, 1);
78 | box-shadow: 1px 2px 6px 0px rgba(161, 152, 161, 1);
79 | }
80 |
81 | .posts_container .item .left {
82 | width: 40%;
83 | height: 250px;
84 | overflow: hidden;
85 | }
86 |
87 | .backwhi {
88 | background: linear-gradient(to bottom, white, red);
89 | /* z-index: 999999; */
90 | height: 200px;
91 | display: block;
92 | position: absolute;
93 | overflow: hidden;
94 | }
95 |
96 | .posts_container .item .right {
97 | width: 60%;
98 | display: flex;
99 | flex-direction: column;
100 | }
101 |
102 | .posts_container .item .right .title {
103 | color: black;
104 | font-size: 1rem;
105 | line-height: 1.25;
106 | cursor: pointer;
107 | flex: 4;
108 | }
109 |
110 | .posts_container .item .right .title:hover {
111 | color: rgb(71, 65, 65);
112 | }
113 |
114 | .posts_container .item .right .description {
115 | padding-right: 5px;
116 | color: #888;
117 | font-size: 0.9rem;
118 | line-height: 1.5;
119 | font-weight: 400;
120 | flex: 4;
121 | overflow: hidden;
122 | margin-top: -50px;
123 | }
124 |
125 | .posts_container .item .right .profile_data {
126 | display: flex;
127 | padding: 5px;
128 | gap: 0.6rem;
129 | position: relative;
130 | top: -15px;
131 | left: -5px;
132 | cursor: pointer;
133 | flex: 2;
134 | align-items: center;
135 |
136 | }
137 |
138 |
139 | .posts_container .item .right .profile_data .user_image {
140 | background: white;
141 | height: 45px;
142 | width: 45px;
143 | border-radius: 50%;
144 | overflow: hidden;
145 | }
146 |
147 | .posts_container .item .right .profile_data .user_middle {
148 | display: flex;
149 | flex-direction: column;
150 | gap: 0.2rem;
151 | }
152 |
153 | .posts_container .item .right .profile_data .user_middle span:first-of-type {
154 | font-family: "Times New Roman", Times, serif;
155 | }
156 |
157 | .posts_container .item .right .profile_data .user_middle span:first-of-type a {
158 | text-decoration: none;
159 | color: #0e0d0d;
160 | }
161 |
162 | .posts_container .item .right .profile_data .user_middle span:first-of-type a:hover {
163 | text-decoration: underline;
164 | color: #001392;
165 | }
166 |
167 | .posts_container .item .right .profile_data .user_middle span:last-of-type {
168 | color: #7d7d7d;
169 | font-size: small;
170 | }
171 |
172 | .posts_container .item .right .profile_data .savePost {
173 | position: absolute;
174 | right: 10px;
175 | top: 8px;
176 | }
177 |
178 | .posts_container .item .right .profile_data .savePost svg {
179 | fill: black;
180 | }
181 | .shareprofile{
182 | display: flex;
183 | justify-content: center;
184 | justify-items: center;
185 | align-content: center;
186 | }
187 | .menus2{
188 | border:grey;
189 | box-shadow: 0px 0px 3px 1px rgb(100, 100, 100);
190 | /* max-height:40px; */
191 | height:fit-content;
192 | padding:5px;
193 | position: absolute;
194 | /* right:40px; */
195 | bottom:23px;
196 | right:9px;
197 | margin-right:0px;
198 | cursor:pointer;
199 | font-size:13px;
200 | max-width:150px;
201 | width:fit-content;
202 | z-index:9999;
203 | background-color: white;
204 | }
205 |
206 | .posts_container .item .right .profile_data .savePost svg:hover {
207 | fill: rgb(90, 82, 82);
208 | }
209 |
210 | .posts_container .item .right .profile_data .user_image img {
211 | height: 100%;
212 | width: 100%;
213 | object-fit: cover;
214 | }
215 |
216 | .posts_container .item .left img {
217 | width: 100%;
218 | height: 100%;
219 | object-fit: cover;
220 | }
221 |
222 | .loader-container {
223 | display: flex;
224 | justify-content: center;
225 | align-items: center;
226 | height: 50px;
227 | }
228 |
229 | .post_loader {
230 | display: flex;
231 | justify-content: center;
232 | align-items: center;
233 | height: 50px;
234 | margin-top: 20px;
235 | }
236 |
237 | @media screen and (max-width: 1153px) {
238 | .posts_container .item .right .title {
239 | font-size: 1rem;
240 | }
241 |
242 | .posts_container .item .left {
243 | height: 225px;
244 | }
245 | }
246 |
247 | @media screen and (max-width: 1058px) {
248 | .posts_container .item {
249 | gap: 0.7rem;
250 | }
251 |
252 | .posts_container .item .right .title {
253 | font-size: 1rem;
254 | }
255 | }
256 |
257 | @media screen and (max-width: 1025px) {
258 | .posts_container {
259 | margin: 0.2rem 3rem;
260 | }
261 |
262 | .posts_container .item .right .title {
263 | font-size: 1rem;
264 | }
265 |
266 | .breaker {
267 | margin: 0.4rem 3rem;
268 | }
269 | }
270 |
271 | @media screen and (max-width: 966px) {
272 | .posts_container .item .left {
273 | height: 213px;
274 | }
275 |
276 | .posts_container .item .right .title {
277 | font-size: 0.98rem;
278 | }
279 | }
280 |
281 | @media screen and (max-width: 936px) {
282 | .posts_container .item .right .profile_data {
283 | top: -11px;
284 | }
285 |
286 | .posts_container .item .right .profile_data .user_image {
287 | height: 32px;
288 | width: 32px;
289 | }
290 |
291 | .posts_container .item .right .profile_data {
292 | padding: 2px;
293 | }
294 |
295 | .posts_container .item .left {
296 | height: 198px;
297 | }
298 | }
299 |
300 | @media screen and (max-width: 872px) {
301 | .posts_container {
302 | margin: 0.2rem 2rem;
303 | }
304 | }
305 |
306 | @media screen and (max-width: 820px) {
307 | .posts_container .item .right .description {
308 | font-size: 0.7rem;
309 | line-height: 1.1;
310 | }
311 |
312 | .breaker {
313 | margin: 0.4rem 2rem;
314 | }
315 | }
316 |
317 | @media screen and (max-width: 730px) {
318 | .posts_container .item .right .title {
319 | font-size: 0.79rem;
320 | }
321 |
322 | .links a:first-child span {
323 | font-size: small;
324 | font-weight: 900;
325 | }
326 |
327 | .posts_container .item .right .description {
328 | font-size: 0.4rem;
329 | }
330 |
331 | .posts_container {
332 | margin: 0.2rem 1rem;
333 | }
334 |
335 | .breaker {
336 | margin: 0.4rem 1rem;
337 | }
338 |
339 | .posts_container .item .right .profile_data .savePost {
340 | position: absolute;
341 | right: 11px;
342 | top: 8px;
343 | }
344 | }
345 |
346 | @media screen and (max-width: 682px) {
347 | .posts_container .item .right .title {
348 | font-size: 0.7rem;
349 | margin-top: 13px;
350 | }
351 |
352 | .posts_container .item .right .description {
353 | font-size: 0.4rem;
354 | position: relative;
355 | bottom: 14px;
356 | }
357 | }
358 |
359 | @media screen and (min-width: 682px) {
360 | .posts_container .item .right .title {
361 | margin-top: 13px;
362 | }
363 | }
364 |
365 | @media screen and (min-width: 1160px) {
366 | .posts_container .item .right .title {
367 | font-size: 1.11rem;
368 | }
369 | }
370 |
371 | @media screen and (min-width: 1212px) {
372 | .posts_container .item .right .title {
373 | font-size: 1.22rem;
374 | }
375 | }
376 |
377 | @media screen and (min-width: 1252px) {
378 | .posts_container .item .right .title {
379 | font-size: 1.32rem;
380 | }
381 | }
382 |
383 | @media screen and (max-width: 650px) {
384 | .posts_container .item {
385 | flex-direction: column;
386 | }
387 |
388 | .posts_container .item .left {
389 | width: 100%;
390 | height: 250px;
391 | }
392 |
393 | .posts_container .item .right {
394 | width: 100%;
395 | }
396 |
397 | .posts_container .item .right .title {
398 | font-size: 1.21rem;
399 | margin-top: -7px;
400 | line-height: 20px;
401 | padding: 5px;
402 | }
403 |
404 | .posts_container .item .right .description {
405 | font-size: 1rem;
406 | padding: 5px;
407 | margin-top: 17px;
408 | }
409 |
410 | .posts_container .item .right .profile_data {
411 | left: 0px;
412 | padding: 5px;
413 | }
414 |
415 | z .posts_container .item .right .profile_data .user_image {
416 | height: 45px;
417 | width: 45px;
418 | }
419 |
420 | .posts_container .item .right .profile_data .savePost {
421 | right: 25px;
422 | top: 13px;
423 | }
424 |
425 | .posts_container {
426 | grid-gap: 0.8rem;
427 | }
428 | }
429 |
430 | @media screen and (max-width: 590px) {
431 | .posts_container .item .left {
432 | width: 100%;
433 | height: 185px;
434 | }
435 |
436 | .posts_container .item .right .title {
437 | font-size: 1rem;
438 | line-height: 17px;
439 | }
440 | }
441 |
442 | @media screen and (max-width: 524px) {
443 | .posts_container .item .left {
444 | width: 100%;
445 | height: 149px;
446 | }
447 |
448 | .posts_container .item .right .description {
449 | font-size: 0.7rem;
450 | }
451 |
452 | .posts_container .item .right .profile_data .user_image {
453 | height: 35px;
454 | width: 35px;
455 | }
456 | }
457 |
458 | @media screen and (max-width: 520px) {
459 | .posts_container .item .right .title {
460 | font-size: 0.89rem;
461 | }
462 |
463 | .hidesmall {
464 | display: none;
465 | }
466 | }
467 |
468 | @media screen and (max-width: 437px) {
469 | .posts_container .item .left {
470 | width: 100%;
471 | height: 120px;
472 | }
473 |
474 | .posts_container .item .right .title {
475 | font-size: 0.82rem;
476 | }
477 | }
478 |
479 | @media screen and (max-width: 420px) {
480 | .posts_container {
481 | grid-template-columns: 1fr;
482 | }
483 |
484 | .posts_container .item .left {
485 | width: 100%;
486 | height: 194px;
487 | }
488 |
489 | .posts_container .item .right .title {
490 | font-size: 1.2rem;
491 | line-height: 27px;
492 | }
493 |
494 | .posts_container .item .right .profile_data {
495 | padding: 13px;
496 | }
497 |
498 | .posts_container .item .right .profile_data .savePost {
499 | right: 40px;
500 | top: 15px;
501 | }
502 |
503 | .posts_container p b {
504 | font-size: xx-small;
505 | }
506 |
507 | .posts_container .item {
508 | -webkit-box-shadow: 1px 2px 3px 0px rgba(189, 189, 189, 1);
509 | -moz-box-shadow: 1px 2px 3px 0px rgba(189, 189, 189, 1);
510 | box-shadow: 1px 2px 3px 0px rgba(189, 189, 189, 1);
511 | flex-direction: column;
512 | }
513 | }
--------------------------------------------------------------------------------
/client/src/components/profile/userprofile.css:
--------------------------------------------------------------------------------
1 | .profile_container {
2 | background: rgb(57, 62, 0);
3 | background: radial-gradient(circle, rgba(57, 62, 0, 0.3617822128851541) 23%, rgba(0, 247, 103, 0.362) 100%, rgba(60, 164, 163, 0.7903536414565826) 100%);
4 | }
5 |
6 | .profile {
7 | max-width: 600px;
8 | margin: 0 auto;
9 | padding: 20px;
10 | box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1);
11 | position: relative;
12 | top: 90px;
13 | background: rgb(9, 9, 121);
14 | background: radial-gradient(circle, rgba(9, 9, 121, 1) 0%, rgba(2, 0, 36, 0.6783088235294117) 100%, rgba(0, 212, 255, 1) 100%);
15 | }
16 |
17 | .profile-photo {
18 | margin-bottom: 20px;
19 | position: relative;
20 | text-align: center;
21 | width: 100%;
22 | display: flex;
23 | justify-content: center;
24 | }
25 | .profile-sub{
26 | margin-top:100px;
27 | margin-left:20px;
28 | margin-right:20px;
29 | margin-bottom: 10px;
30 | }
31 | .bookmark-main{
32 | margin-bottom: 19px;
33 | /* margin-left:1rem; */
34 | margin-right: 1rem;
35 | }
36 | .heading1{
37 | margin-bottom: 10px;
38 | cursor: pointer;
39 | }
40 |
41 | .profile .preview_img {
42 | background-image: url('https://res.cloudinary.com/dttyhvsnv/image/upload/v1677430557/default_pic_gxoa10.png');
43 | width: 200px;
44 | height: 200px;
45 | background-position: center center;
46 | background-size: cover;
47 | object-fit: contain;
48 | border-radius: 50%;
49 | margin-top: 10px;
50 | overflow: hidden;
51 | }
52 |
53 |
54 | .profile-photo label {
55 | display: block;
56 | font-size: 20px;
57 | margin-bottom: 10px;
58 | }
59 |
60 |
61 | .profile-photo img {
62 | height: 100%;
63 | width: 100%;
64 | object-fit: cover;
65 | }
66 |
67 | .profile-photo .filename {
68 | display: block;
69 | font-size: 16px;
70 | margin-top: 5px;
71 | text-align: center;
72 | }
73 |
74 | .profile form {
75 | display: flex;
76 | flex-direction: column;
77 | align-items: center;
78 | }
79 |
80 | .profile label {
81 | font-size: 20px;
82 | margin-bottom: 10px;
83 | }
84 |
85 | .profile textarea {
86 | width: 100%;
87 | padding: 10px;
88 | font-size: 16px;
89 | border-radius: 5px;
90 | border: 1px solid #ccc;
91 | margin-bottom: 20px;
92 | }
93 |
94 |
95 | .profile .image_button {
96 | display: flex;
97 | justify-content: center;
98 | margin-bottom: 10px;
99 | }
100 |
101 | .profile .image_button button {
102 | color: rgb(255, 255, 255);
103 | padding: 10px;
104 | margin: 5px;
105 | border: none;
106 | outline: none;
107 | border-radius: 4px;
108 | background-color: rgb(15, 15, 87, 0.8);
109 | transition: all .2s;
110 | }
111 |
112 | .profile .image_button button:hover {
113 | background-color: rgb(15, 15, 87);
114 | cursor: pointer;
115 | transform: scale(1.01);
116 | }
117 |
118 | .hreffor {
119 | color: rgb(209, 236, 255);
120 | }
121 |
122 | .profile button[type=submit] {
123 | color: rgb(0, 0, 0);
124 | padding: 10px;
125 | margin: 5px;
126 | border: none;
127 | outline: none;
128 | border-radius: 4px;
129 | background-color: rgba(104, 214, 7, 0.8);
130 | width: 100%;
131 | }
132 |
133 | .profile button[type=submit]:hover {
134 | background-color: rgba(127, 255, 16, 0.8);
135 | }
136 |
137 | .profile .button:hover {
138 | background-color: rgb(15, 15, 87);
139 | }
140 |
141 |
142 | .about_me {
143 | min-height: 60px;
144 | background-color: #ffffff;
145 | width: 100%;
146 | text-align: center;
147 | border-radius: 6px;
148 | }
149 |
150 | .change_about {
151 | color: rgb(255, 255, 255);
152 | padding: 10px;
153 | margin: 5px;
154 | border: none;
155 | outline: none;
156 | border-radius: 4px;
157 | background-color: rgb(15, 15, 87, 0.8);
158 | font-size: 16px;
159 | margin-top: 6px;
160 | transition: all .2s;
161 | }
162 |
163 | .change_about:hover {
164 | background-color: rgb(15, 15, 87);
165 | }
166 |
167 | .my_profile_error {
168 | color: red;
169 | }
170 |
171 | @media screen and (max-width: 480px) {
172 | .profile {
173 | padding: 10px;
174 | }
175 |
176 | label,
177 | textarea,
178 | button {
179 | font-size: 16px;
180 | }
181 | }
182 |
183 | .change_about {
184 | cursor: pointer;
185 | }
186 |
187 | .jenc {
188 | font-size: 17px;
189 | color: white;
190 | cursor: pointer;
191 | background-color: green;
192 | transition: 300ms;
193 | }
194 |
195 | .jenc:hover {
196 | transition: 300ms;
197 | transform: scale(1.03);
198 | }
199 |
200 | .profile {
201 | border-radius: 10px;
202 | }
203 |
204 |
205 |
206 |
207 |
208 |
209 | /* */
210 |
211 |
212 | .itemp{
213 | text-decoration: none;
214 | background-color: whitesmoke;
215 | height:200px;
216 | width:340px;
217 | display:flex;
218 | margin-bottom:10px;
219 | border-radius: 10px 10px 10px 10px;
220 | border:solid 1px white;
221 | gap:0.3rem;
222 | }
223 | .leftp{
224 | width:260px;
225 | overflow: hidden;
226 | height:200px;
227 | margin-bottom:10px;
228 | border-radius: 10px;
229 | }
230 | .leftimgp{
231 | width:200px;
232 | height:200px;
233 | /* margin:auto; */
234 | margin-left:-30px;
235 | /* over */
236 | border-radius: 10px 10px;
237 | }
238 | .post-containerp {
239 | width:100%;
240 | max-width: 100%;
241 | margin: 1.2rem 2rem;
242 | display: flex;
243 | flex-direction: row;
244 | gap:1rem;
245 | overflow-y: hidden;
246 | overflow-x: scroll;
247 | margin-bottom: 10px;
248 | }
249 | .post-containerp::-webkit-scrollbar{
250 | display:none;
251 | }
252 | .pointer{
253 | cursor: pointer;
254 | }
255 | .imgscp2{
256 | cursor: pointer;
257 | height:30px;
258 | width:30px;
259 | border-radius: 50%;
260 | }
261 | .profile_data2{
262 | position: relative;
263 | display: flex;
264 | gap:8px;
265 | text-decoration: none;
266 | margin-top: 10px;
267 | float: left;
268 | bottom:0px;
269 | top:60px;
270 | left:10px;
271 | cursor: pointer;
272 | font-size: 15px;
273 | }
274 | .view_post{
275 | font-size: 12px;
276 | color:grey;
277 | display: flex;
278 | justify-items: center;
279 | align-items: center;
280 | }
281 | .view_post_profile{
282 | font-size: 16px;
283 | color:grey;
284 | display: flex;
285 | justify-items: center;
286 | align-items: center;
287 | }
288 | .profile_data24{
289 | position: relative;
290 | display: flex;
291 | gap:3px;
292 | text-decoration: none;
293 | margin-top: 10px;
294 | float: left;
295 | bottom:0px;
296 | top:60px;
297 | left:2px;
298 | font-size: 15px;
299 | }
300 | .user_name2{
301 | color:black;
302 | text-decoration: none;
303 | /* display: none; */
304 | }
305 | .user_middle2{
306 | color:black;
307 | text-decoration: none;
308 | /* background-color: pink; */
309 | }
310 | .itemp:hover{
311 | transform: scale(1.021);
312 | transition: 200ms;
313 | }
314 | .blackfont{
315 | color:black;
316 | text-decoration: none;
317 | }
318 | .blackfont:active{
319 | color:black;
320 | text-decoration: none;
321 | }
322 |
323 | .red{
324 | color:red;
325 | text-decoration: none;
326 | cursor: pointer;
327 | transition: 200ms;
328 | }
329 | .bluev{
330 | color:blue;
331 | text-decoration: none;
332 | }
333 | .red:hover{
334 | color:brown;
335 | font-weight: 700;
336 |
337 | transition: 200ms;
338 | }
339 | .post-containerp2{
340 | background-color: whitesmoke;
341 | border-radius: 10px;
342 | border:solid 1px white;
343 | margin-top:1rem;
344 | }
345 | .uf22{
346 | background-color: white;
347 | padding:10px;
348 | border-radius: 10px;
349 | text-decoration: none;
350 | top:0px;
351 | }
352 | .uf2{
353 | text-decoration: none;
354 |
355 | }
356 |
357 | .pf22{
358 | display: grid;
359 | gap:20px;
360 | width:100%;
361 | /* height:300px; */
362 | margin-top:0px;
363 | overflow-x: scroll;
364 | top:0px;
365 | grid-template-columns: auto auto auto auto auto;
366 | }
367 | @media screen and (max-width: 1100px) {
368 | .pf22{
369 |
370 | grid-template-columns: auto auto auto auto ;
371 | }
372 | }
373 | @media screen and (max-width: 900px) {
374 | .pf22{
375 |
376 | grid-template-columns: auto auto auto ;
377 | }
378 | }
379 | @media screen and (max-width: 700px) {
380 | .pf22{
381 |
382 | grid-template-columns: auto auto ;
383 | }
384 | .uf22{
385 | width: 170px;
386 | overflow: scroll;
387 | justify-content: left;
388 | justify-items: center;
389 | text-decoration: none;
390 | }
391 | .uf22::-webkit-scrollbar{
392 | display:none
393 | }
394 | .sm{
395 | font-size:17px;
396 | }
397 | .ssm{
398 | font-size:12px;
399 | }
400 | }
401 | @media screen and (max-width: 500px) {
402 | .pf22{
403 |
404 | grid-template-columns: auto auto;
405 | gap:5px
406 | }
407 | }
408 | @media screen and (max-width: 465px) {
409 | .pf22{
410 | margin:auto;
411 | margin-left:10%;
412 | grid-template-columns: auto;
413 | gap:5px;
414 | }
415 | }
416 | .pf22::-webkit-scrollbar{
417 | display:none
418 | }
419 |
420 | .post-containerp22{
421 | border-radius: 10px;
422 | }
423 | .follpage{
424 | margin:auto;
425 | margin-top: 100px;
426 | text-align: center;
427 | display: flex;
428 | justify-content: center;
429 | gap:60px;
430 | font-weight: 600;
431 | }
432 | .following, .follower{
433 | background-color: rgb(207, 224, 255);
434 | border-radius: 5px;
435 | padding:5px;
436 | border: solid 1px white;
437 | }
--------------------------------------------------------------------------------
/client/src/components/profileOftherUser/ProfileOfOtherUser.js:
--------------------------------------------------------------------------------
1 | import axios from "axios";
2 | import "./profileOfOtherUser.css";
3 | import React, { useEffect, useState } from "react";
4 | import { useParams } from "react-router-dom";
5 | import { Link, useNavigate } from "react-router-dom";
6 | import {
7 | getUser,
8 | startfollow,
9 | checkfollowing,
10 | unfollow,
11 | getfollowercount,
12 | getfollowingcount,
13 | }
14 | from "../../helpers";
15 |
16 | import Navbar from "../Navbar";
17 | import Footer from "../footer/Footer";
18 | import * as htmlToImage from 'html-to-image';
19 | import { toPng, toJpeg, toBlob, toPixelData, toSvg } from 'html-to-image';
20 | import { jsPDF } from "jspdf";
21 | import { useDispatch, useSelector } from "react-redux";
22 |
23 | function ProfileOfOtherUser() {
24 | const { userID } = useParams();
25 | const { user } = useSelector((state) => ({ ...state }));
26 | const [otherUser, setOtherUser] = useState({});
27 | const [sc, sfc] = useState(true);
28 | const navigate = useNavigate();
29 |
30 | const [folc, setfollc] = useState(0);
31 | const [folcd, setfollcd] = useState(0);
32 | useEffect(() => {
33 | userData();
34 | }, []);
35 |
36 | const userData = async () => {
37 |
38 | if(userID===user.id){
39 | // const navigateToHome = () => {
40 | navigate("/profile");
41 | // };
42 | }
43 | const data = await getUser(userID);
44 | setOtherUser(data._doc);
45 | const sfcr = await checkfollowing(user.id, userID);
46 | if(sfcr){
47 | if (sfcr.msg === "ok") {
48 | sfc(true);
49 | }
50 | else {
51 | sfc(false);
52 | }}
53 |
54 | const datas = await getfollowercount(userID);
55 | const data2 = await getfollowingcount(userID);
56 | setfollcd(data2.data.msg);
57 | setfollc(datas.data.msg);
58 | };
59 |
60 | const startfollowfun = async () => {
61 | try {
62 | const data = await startfollow(user.id, otherUser._id);
63 | if(data.msg==="ok"){
64 | sfc(true);
65 |
66 | setfollc(folc+1)
67 |
68 | }
69 | else{
70 | alert("Some error occurred, try again later");
71 | }
72 | } catch (error) {
73 | // console.log("error in following")
74 | }
75 | }
76 | const unfollowfun = async () => {
77 | try {
78 | const data = await unfollow(user.id, otherUser._id);
79 | if(data.msg==="ok"){
80 | sfc(false);
81 | setfollc(folc-1)
82 | }
83 | else{
84 | alert("Some error occurred, try again later");
85 |
86 | }
87 | // window.location.reload();
88 | } catch (error) {
89 | // console.log(error)
90 | // console.log("error in unfollowing")
91 | }
92 | }
93 |
94 | return (
95 |
96 |
97 |
98 |
99 |
window.open(otherUser?.picture
107 | ? otherUser.picture
108 | : "https://res.cloudinary.com/dttyhvsnv/image/upload/v1677430557/default_pic_gxoa10.png"
109 | , "_blank")}
110 | />
111 |
{otherUser.name}
112 |
113 |
{otherUser?.about}
114 |
115 |
116 | {!user?
117 |
navigate("/auth")}>+FOLLOW
118 | :
119 | <>
120 | {!sc?
121 |
startfollowfun()}>+FOLLOW
122 | :
123 | (
unfollowfun()}>FOLLOWING
)
124 | }
125 | >}
126 |
127 |
128 |
129 |
130 | Following: {folcd}
131 |
132 |
133 | Followers: {folc}
134 |
135 |
136 |
137 |
138 | );
139 | }
140 |
141 | export default ProfileOfOtherUser;
142 |
--------------------------------------------------------------------------------
/client/src/components/profileOftherUser/profileOfOtherUser.css:
--------------------------------------------------------------------------------
1 | .ProfileOfOtherUser {
2 | width: 100%;
3 |
4 | }
5 |
6 | .user_wrapper {
7 | text-align: center;
8 | margin-top: 65px;
9 | margin: auto;
10 | }
11 |
12 | .user_wrapper .user_image {
13 | width: 100%;
14 | margin: auto;
15 | margin-top: 75px;
16 | display: flex;
17 | flex-direction: column;
18 | /* justify-content: center; */
19 | }
20 |
21 | .user_wrapper .user_image img {
22 | margin: auto;
23 | }
24 |
25 | .user_wrapper .user_image span {
26 | font-weight: 600;
27 | color: rgb(39, 39, 39);
28 | margin-top: 7px;
29 | }
30 |
31 | .user_wrapper .user_about {
32 | color: black;
33 | font-size: 15px;
34 | text-align: center;
35 | }
36 |
37 | .aboutn {
38 | font-size: 30px;
39 | }
40 |
41 | @media screen and (max-width:420px) {
42 | .user_wrapper {
43 | width: 92%;
44 | }
45 | }
46 |
47 | @media screen and (max-width:800px) {
48 | .user_wrapper {
49 | width: 85%;
50 | }
51 | }
52 | @media screen and (max-width:440px) {
53 |
54 | .aboutn{
55 | margin-top:400px;
56 | }
57 | .user_about{
58 | margin-top:280px;
59 | }
60 | .marg{
61 | margin-top:300px;
62 | }
63 | }
64 | @media screen and (max-width:440px) {
65 |
66 | .aboutn{
67 | margin-top:400px;
68 | }
69 | .user_about{
70 | margin-top:280px;
71 | }
72 | .marg{
73 | margin-top:350px;
74 | }
75 | }
76 |
77 | .imgpro {
78 | width: 300px;
79 | position: relative;
80 | /* height:200px; */
81 | /* width:auto; */
82 | }
83 |
84 | .user_about {
85 | font-family: 'Gill Sans', 'Gill Sans MT', Calibri, 'Trebuchet MS', sans-serif;
86 | }
87 | .cent{
88 | text-align: center;
89 | cursor: pointer;
90 | margin-top:15px;
91 | }
92 | .user_wrapper {
93 | margin: auto;
94 | }
--------------------------------------------------------------------------------
/client/src/components/write/Editor.js:
--------------------------------------------------------------------------------
1 | import React, { useState, useRef, useMemo, useEffect } from "react";
2 | import JoditEditor from "jodit-react";
3 | import "./editor.css";
4 | import { useSelector } from "react-redux";
5 | import { createPost, dataURItoBlob, uplaodImages } from "../../helpers";
6 | import { PulseLoader } from "react-spinners";
7 | import { useNavigate } from "react-router-dom";
8 | import dompurify from "dompurify";
9 | import Footer from "../footer/Footer";
10 |
11 | const Editor = ({ placeholder, prevdata, pflag }) => {
12 | const navigate = useNavigate();
13 | const { user } = useSelector((state) => ({ ...state }));
14 | const inputref = useRef(null);
15 | const editor = useRef(null);
16 | const [content, setContent] = useState("");
17 | const [title, setTitle] = useState("");
18 | const [description, setDescription] = useState("");
19 | const [category, setCategory] = useState();
20 | const [image, setimage] = useState("");
21 | const [error, setError] = useState("");
22 | const [loading, setLoading] = useState("");
23 | const [mflag, setmflag] = useState(false);
24 | const scroll = useRef();
25 | useEffect(() => {
26 | scroll.current?.scrollIntoView({ behavior: "smooth" });
27 | }, [error]);
28 |
29 |
30 | const config = useMemo(() => {
31 | return {
32 | readonly: false,
33 | placeholder: placeholder || "Start Typing...",
34 | sanitize: dompurify.sanitize,
35 | extraStyles: `img {max-width: 100%}`,
36 | };
37 | }, [placeholder]);
38 |
39 | const handleChange = (e) => {
40 | const { name, value } = e.target;
41 | if (name === "title") {
42 | setTitle(value);
43 | } else if (name === "description") {
44 | setDescription(value);
45 | }
46 | };
47 |
48 | const handleSelect = (e) => {
49 | setCategory(e.target.value);
50 | };
51 |
52 | const handleImage = (e) => {
53 | let file = e.target.files[0];
54 |
55 | if (file.size > 1024 * 1024) {
56 | setError(`${file.name} size is too large max 1mb allowed.`);
57 | return;
58 | }
59 |
60 | const reader = new FileReader();
61 |
62 | reader.onload = (readerEvent) => {
63 | const img = new Image();
64 | img.src = readerEvent.target.result;
65 |
66 | img.onload = function () {
67 | if (this.naturalWidth < 1000 || this.naturalHeight < 600) {
68 | setError(
69 | "Image resolution is too low, please select an image with a resolution of at least 1000x600."
70 | );
71 | } else {
72 | setimage(readerEvent.target.result);
73 | setError("");
74 | }
75 | };
76 | };
77 |
78 | reader.readAsDataURL(file);
79 | };
80 |
81 | const handleSubmit = async (e) => {
82 | try {
83 | e.preventDefault();
84 | if (!title || !description || !content || !category || !image) {
85 | setError("All field are required with image of your post !");
86 | return;
87 | } else {
88 | setError("");
89 | }
90 | if (title.length < 10 || title.length > 90) {
91 | setError("Title must be between 10 to 90 characters !");
92 | return;
93 | } else {
94 | setError("");
95 | }
96 | if (description.length < 50 || description.length > 120) {
97 | setError("Description must be between 50 to 100 characters !");
98 | return;
99 | } else {
100 | setError("");
101 | }
102 | if (image !== "") {
103 | setLoading(true);
104 | const img = dataURItoBlob(image);
105 | const path = `${user.name}/blog_images`;
106 | let formData = new FormData();
107 | formData.append("path", path);
108 | formData.append("file", img);
109 | const postImg = await uplaodImages(formData, user?.token);
110 | const cleanHtml = dompurify.sanitize(content, { FORCE_BODY: true });
111 |
112 | const post = await createPost(
113 | title,
114 | description,
115 | postImg[0].url,
116 | category,
117 | user.id,
118 | user?.token,
119 | cleanHtml
120 | );
121 | if (post) {
122 | navigate("/");
123 | }
124 | setLoading(false);
125 | }
126 | } catch (error) {
127 | setLoading(false);
128 | // console.log(error)
129 | setError(error.response.data.message);
130 | }
131 | };
132 |
133 | return (
134 |
214 | );
215 | };
216 |
217 | export default Editor;
218 |
--------------------------------------------------------------------------------
/client/src/components/write/EditorP.js:
--------------------------------------------------------------------------------
1 | import React, { useState, useRef, useMemo, useEffect } from "react";
2 | import JoditEditor from "jodit-react";
3 | import "./editor.css";
4 | import { useSelector } from "react-redux";
5 | import { createPost, dataURItoBlob, uplaodImages, editPost } from "../../helpers";
6 | import { PulseLoader } from "react-spinners";
7 | import { useNavigate } from "react-router-dom";
8 | import dompurify from "dompurify";
9 | import Footer from "../footer/Footer";
10 |
11 | const EditpostP = ({ placeholder, prevdata, pflag, post }) => {
12 | const navigate = useNavigate();
13 | const { user } = useSelector((state) => ({ ...state }));
14 | const inputref = useRef(null);
15 | const editor = useRef(null);
16 | const [content, setContent] = useState("");
17 | const [title, setTitle] = useState("");
18 | const [description, setDescription] = useState("");
19 | const [category, setCategory] = useState();
20 | const [image, setimage] = useState("");
21 | const [error, setError] = useState("");
22 | const [loading, setLoading] = useState("");
23 | const [cimage, setcimage] = useState(false);
24 | const [mflag, setmflag] = useState(false);
25 | const scroll = useRef();
26 | useEffect(() => {
27 | scroll.current?.scrollIntoView({ behavior: "smooth" });
28 | }, [error]);
29 |
30 | useEffect(() => {
31 | if (post.user._id == user.id && pflag) {
32 | setmflag(true);
33 | setContent(post.content);
34 | setTitle(post.title);
35 | setDescription(post.description);
36 | setCategory(post.category);
37 | setimage(post.image);
38 | }
39 | else {
40 | navigate("/createpost");
41 | }
42 | }, [])
43 |
44 | const config = useMemo(() => {
45 | return {
46 | readonly: false,
47 | placeholder: placeholder || "",
48 | sanitize: dompurify.sanitize,
49 | extraStyles: `img {max-width: 100%}`,
50 | };
51 | }, [placeholder]);
52 |
53 | const handleChange = (e) => {
54 | const { name, value } = e.target;
55 | if (name === "title") {
56 | setTitle(value);
57 | } else if (name === "description") {
58 | setDescription(value);
59 | }
60 | };
61 |
62 | const handleSelect = (e) => {
63 | setCategory(e.target.value);
64 | };
65 |
66 | const handleImage = (e) => {
67 | let file = e.target.files[0];
68 |
69 | if (file.size > 1024 * 1024) {
70 | setError(`${file.name} size is too large max 1mb allowed.`);
71 | return;
72 | }
73 |
74 | const reader = new FileReader();
75 |
76 | reader.onload = (readerEvent) => {
77 | const img = new Image();
78 | img.src = readerEvent.target.result;
79 |
80 | img.onload = function () {
81 | if (this.naturalWidth < 1000 || this.naturalHeight < 600) {
82 | setError(
83 | "Image resolution is too low, please select an image with a resolution of at least 1000x600."
84 | );
85 | } else {
86 | setimage(readerEvent.target.result);
87 | setError("");
88 | }
89 | };
90 | };
91 | setcimage(true);
92 |
93 | reader.readAsDataURL(file);
94 | };
95 | const handleEdit = async (e) => {
96 | try {
97 | e.preventDefault();
98 | if (!title || !description || !content || !category || !image) {
99 | setError("All field are required with image of your post !");
100 | return;
101 | } else {
102 | setError("");
103 | }
104 | if (title.length < 10 || title.length > 90) {
105 | setError("Title must be between 10 to 90 characters !");
106 | return;
107 | } else {
108 | setError("");
109 | }
110 | if (description.length < 50 || description.length > 120) {
111 | setError("Description must be between 50 to 100 characters !");
112 | return;
113 | } else {
114 | setError("");
115 | }
116 | if(cimage){
117 | setLoading(true);
118 | const path = `${user.name}/blog_images`;
119 | const img = dataURItoBlob(image);
120 | let formData = new FormData();
121 | formData.append("path", path);
122 | formData.append("file", img);
123 | const postImg = await uplaodImages(formData, user?.token);
124 | }
125 | const cleanHtml = dompurify.sanitize(content, { FORCE_BODY: true });
126 | // const cleanHtml = dompurify.sanitize(post.content, { FORCE_BODY: true });
127 | const posted = await editPost(
128 | title,
129 | description,
130 | image,
131 | category,
132 | user.id,
133 | user?.token,
134 | cleanHtml,
135 | post._id
136 | );
137 | if (posted) {
138 | navigate("/");
139 | }
140 | } catch (error) {
141 | setLoading(false);
142 | // console.log(error)
143 | // setError(error.response.data.message);
144 | }
145 | }
146 | const handleSubmit = async (e) => {
147 | try {
148 | e.preventDefault();
149 | if (!title || !description || !content || !category || !image) {
150 | setError("All field are required with image of your post !");
151 | return;
152 | } else {
153 | setError("");
154 | }
155 | if (title.length < 10 || title.length > 90) {
156 | setError("Title must be between 10 to 90 characters !");
157 | return;
158 | } else {
159 | setError("");
160 | }
161 | if (description.length < 50 || description.length > 120) {
162 | setError("Description must be between 50 to 100 characters !");
163 | return;
164 | } else {
165 | setError("");
166 | }
167 |
168 | if (image !== "") {
169 | setLoading(true);
170 | const img = dataURItoBlob(image);
171 | const path = `${user.name}/blog_images`;
172 | let formData = new FormData();
173 | formData.append("path", path);
174 | formData.append("file", img);
175 | const postImg = await uplaodImages(formData, user?.token);
176 | const cleanHtml = dompurify.sanitize(content, { FORCE_BODY: true });
177 | // const cleanHtml = dompurify.sanitize(post.content, { FORCE_BODY: true });
178 | const post = await createPost(
179 | title,
180 | description,
181 | postImg[0].url,
182 | category,
183 | user.id,
184 | user?.token,
185 | cleanHtml
186 | );
187 | if (post) {
188 |
189 | // navigate("/");
190 | }
191 | }
192 | } catch (error) {
193 | setLoading(false);
194 | console.log(error)
195 | setError(error.response.data.message);
196 | }
197 | };
198 |
199 | return (
200 | // <>
201 |
202 | // >
203 |
204 |
304 | );
305 | };
306 |
307 |
308 | export default EditpostP
--------------------------------------------------------------------------------
/client/src/components/write/editor.css:
--------------------------------------------------------------------------------
1 | .WritePost {
2 | min-height: 100vh;
3 | width: 100%;
4 | position: relative;
5 |
6 | }
7 |
8 | .WritePost .editor {
9 | width: 70%;
10 | margin: auto;
11 | }
12 |
13 |
14 | .WritePost .editor .form {
15 | position: relative;
16 | top: 95px;
17 | }
18 |
19 | .form .photoButton {
20 | text-align: center;
21 | width: 100%;
22 | margin-top: 10px;
23 | margin-bottom: 10px;
24 | background-color: rgba(167, 129, 249, 0.827);
25 | padding: 0.41rem;
26 | transition: all .2s ease-in-out;
27 | cursor: pointer;
28 | font-size: 1.2rem;
29 | font-weight: 500;
30 | }
31 |
32 | .catoo {
33 | background-color: white;
34 | }
35 |
36 | .btnsubt {
37 | color: white;
38 | font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
39 | background-color: green;
40 | }
41 |
42 | .form .photoButton:hover {
43 | background-color: rgb(205, 7, 255);
44 | color: white;
45 | transition: 300ms;
46 | }
47 |
48 | .selectedImg {
49 | height: 400px;
50 | border: 1px solid black;
51 | width: 100%;
52 | }
53 |
54 | .selectedImg img {
55 | height: 100%;
56 | width: 100%;
57 | object-fit: cover;
58 | }
59 |
60 | .WritePost .editor .form input[type="file"] {
61 | display: none;
62 | }
63 |
64 | .WritePost .editor .form label {
65 | display: block;
66 | margin-bottom: 8px;
67 | font-weight: bold;
68 | }
69 |
70 | .WritePost .editor .form input[type="text"] {
71 | display: block;
72 | width: 98.5%;
73 | padding: 8px;
74 | font-size: 16px;
75 | border: 1px solid #ccc;
76 | border-radius: 4px;
77 | margin-bottom: 16px;
78 | }
79 |
80 | .editor select {
81 | font-size: 14px;
82 | padding: 8px;
83 | border-radius: 3px;
84 | border: none;
85 | background-color: #b6b6b6;
86 | color: rgb(0, 0, 0);
87 | cursor: pointer;
88 | transition: all 0.3s ease;
89 | margin-bottom: 10px;
90 | }
91 |
92 | .editor select:hover {
93 | background-color: #9f9f9f;
94 | }
95 |
96 | .editor select:focus {
97 | outline: none;
98 | box-shadow: 0 0 8px 0 rgba(0, 0, 0, 0.2);
99 | }
100 |
101 | .editor button[type=submit] {
102 | width: 100%;
103 | padding: 0.6rem;
104 | margin: 0.2rem;
105 | background: rgb(25, 190, 25);
106 | outline: none;
107 | border: none;
108 | transition: all 0.2s ease-in-out;
109 | font-size: 1.2rem;
110 | font-weight: 550;
111 | cursor: pointer;
112 | margin-top: 10px;
113 | }
114 |
115 |
116 | .editor button[type=submit]:hover {
117 | background: rgb(30, 226, 30);
118 | z-index: 100000;
119 | }
120 |
121 | .WritePost .editor .errorPopup {
122 | text-align: center;
123 | width: 98.5%;
124 | padding: .6rem;
125 | margin: 0.2rem;
126 | background: rgb(255, 0, 0);
127 | outline: none;
128 | border: none;
129 | transition: all 0.2s ease-in-out;
130 | font-size: 1rem;
131 | font-weight: 400;
132 | color: white;
133 | z-index: 100000;
134 | margin-top: 10px;
135 | }
136 |
137 | @media screen and (max-width:645px) {
138 | .WritePost .editor {
139 | width: 78%;
140 | margin: auto;
141 | }
142 |
143 | }
144 |
145 | @media screen and (max-width:535px) {
146 | .WritePost .editor {
147 | width: 83%;
148 | margin: auto;
149 | }
150 |
151 | }
152 |
153 | @media screen and (max-width:431px) {
154 | .selectedImg {
155 | height: 312px;
156 | }
157 |
158 | }
--------------------------------------------------------------------------------
/client/src/helpers/index.js:
--------------------------------------------------------------------------------
1 | import axios from "axios";
2 |
3 | export const clearCookie = (cookieName) => {
4 | document.cookie = `${cookieName}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;`;
5 | };
6 | export const checkifverify = async (mail) => {
7 | try {
8 | const { data } = await axios.post(
9 | `${process.env.REACT_APP_BACKEND_URL}/checkifverify`, {
10 | mail
11 | }
12 | )
13 | return data;
14 | } catch (error) {
15 | return { msg: "error" };
16 | }
17 | }
18 |
19 | export const checkotpv = async (mail, otp) => {
20 | try {
21 | const { data } = await axios.post(
22 | `${process.env.REACT_APP_BACKEND_URL}/checkotpv`, {
23 | mail,
24 | otp
25 | }
26 | )
27 | return data;
28 | } catch (error) {
29 | return { msg: "error in sending mail" };
30 | }
31 | }
32 | export const sendmail = async (mail, name) => {
33 | try {
34 | const { data } = await axios.post(
35 | `${process.env.REACT_APP_BACKEND_URL}/sendmail`, {
36 | mail,
37 | name
38 | }
39 | )
40 | return data;
41 | } catch (error) {
42 | return { msg: "error in sending mail" };
43 | }
44 | }
45 | export const increaseView = async (id) => {
46 | try {
47 | const { data } = await axios.post(
48 | `${process.env.REACT_APP_BACKEND_URL}/increaseView`, {
49 | id,
50 | }
51 | )
52 | return data;
53 | } catch (error) {
54 | return { msg: "error in increasing view" };
55 | }
56 | }
57 | export const getView = async (id) => {
58 | try {
59 | const { data } = await axios.post(
60 | `${process.env.REACT_APP_BACKEND_URL}/getView`, {
61 | id,
62 | }
63 | )
64 | return data;
65 | } catch (error) {
66 | return { msg: "error in getting view mail" };
67 | }
68 | }
69 | export const getLikes = async (id) => {
70 | try {
71 | const { data } = await axios.post(
72 | `${process.env.REACT_APP_BACKEND_URL}/getLikes`, {
73 | id,
74 | }
75 | )
76 | return data;
77 | } catch (error) {
78 | // console.log(error);
79 | return { msg: "error in getting likes" };
80 | }
81 | }
82 | export const uplaodImages = async (formData, token = null) => {
83 | try {
84 | const { data } = await axios.post(
85 | `${process.env.REACT_APP_BACKEND_URL}/uploadImages`,
86 | formData,
87 | {
88 | headers: {
89 | Authorization: `Bearer ${token}`,
90 | "content-type": "multipart/form-data",
91 | },
92 | withCredentials: true,
93 | }
94 | );
95 | return data;
96 | } catch (error) {
97 | return error.response.data.message;
98 | }
99 | };
100 |
101 | export const dataURItoBlob = (dataURI) => {
102 | // convert base64/URLEncoded data component to raw binary data held in a string
103 | var byteString;
104 | if (dataURI.split(",")[0].indexOf("base64") >= 0)
105 | byteString = atob(dataURI.split(",")[1]);
106 | else byteString = unescape(dataURI.split(",")[1]);
107 |
108 | // separate out the mime component
109 | var mimeString = dataURI.split(",")[0].split(":")[1].split(";")[0];
110 |
111 | // write the bytes of the string to a typed array
112 | var ia = new Uint8Array(byteString.length);
113 | for (var i = 0; i < byteString.length; i++) {
114 | ia[i] = byteString.charCodeAt(i);
115 | }
116 |
117 | return new Blob([ia], { type: mimeString });
118 | };
119 |
120 | export const createPost = async (
121 | title,
122 | description,
123 | image,
124 | category,
125 | userId,
126 | token = null,
127 | cleanHtml
128 | ) => {
129 | try {
130 | const { data } = await axios.post(
131 | `${process.env.REACT_APP_BACKEND_URL}/post`,
132 | {
133 | title,
134 | description,
135 | image,
136 | category,
137 | user: userId,
138 | content: cleanHtml,
139 | },
140 |
141 | {
142 | headers: {
143 | Authorization: `Bearer ${token}`,
144 | },
145 | withCredentials: true,
146 | }
147 | );
148 | return data;
149 | } catch (error) {
150 | return error.response.data.message;
151 | }
152 | };
153 | export const editPost = async (
154 | title,
155 | description,
156 | image,
157 | category,
158 | userId,
159 | token = null,
160 | cleanHtml,
161 | id
162 | ) => {
163 | try {
164 | const { data } = await axios.post(
165 | `${process.env.REACT_APP_BACKEND_URL}/editPost`,
166 | {
167 | title,
168 | description,
169 | image,
170 | category,
171 | user: userId,
172 | content: cleanHtml,
173 | id:id
174 | },
175 |
176 | {
177 | headers: {
178 | Authorization: `Bearer ${token}`,
179 | },
180 | withCredentials: true,
181 | }
182 | );
183 | return data;
184 | } catch (error) {
185 | return error.response.data.message;
186 | }
187 | };
188 |
189 | export const createcomment = async (
190 |
191 | name,
192 | image,
193 | content,
194 | id1,
195 | id2
196 |
197 | ) => {
198 | try {
199 | const { data } = await axios.post(
200 | `${process.env.REACT_APP_BACKEND_URL}/postcomment`,
201 | {
202 | name,
203 | image,
204 | content,
205 | id1,
206 | id2
207 | }
208 | )
209 | return data
210 | } catch (error) {
211 | // console.log("error in postcomment indexjs ", error)
212 | return;
213 | }
214 | }
215 |
216 | export const fetchprof = async (id) => {
217 | try {
218 | var { data } = await axios.post(
219 | `${process.env.REACT_APP_BACKEND_URL}/fetchprof`,
220 | {
221 | id,
222 |
223 | }
224 |
225 | )
226 | // data = [...data, { msg: "ok" }];
227 | return data;
228 | } catch (error) {
229 | // console.log(error);
230 | return { msg: "error" };
231 | }
232 | }
233 | export const getcomment = async (id) => {
234 | try {
235 | var { data } = await axios.post(
236 | `${process.env.REACT_APP_BACKEND_URL}/getcomment`,
237 | {
238 | id,
239 |
240 | }
241 |
242 | )
243 | data = [...data, { msg: "ok" }];
244 | return data;
245 | } catch (error) {
246 | // console.log(error);
247 | return { msg: "error" };
248 | }
249 | }
250 | export const getfollowercount = async (id) => {
251 | try {
252 | const data = await axios.post(
253 | `${process.env.REACT_APP_BACKEND_URL}/countfollower`, {
254 | id
255 | })
256 | return data
257 | } catch (error) {
258 | return { msg: "error" }
259 | }
260 | }
261 |
262 |
263 | export const getallpostdata = async (id) => {
264 | try {
265 | const data = await axios.post(
266 | `${process.env.REACT_APP_BACKEND_URL}/getallpostdata`, {
267 | id
268 | })
269 | return data
270 | } catch (error) {
271 | // console.log(error);
272 | // console.log(error);
273 | return { msg: "error" }
274 | }
275 | }
276 | export const getfollowingcount = async (id) => {
277 | try {
278 | const data = await axios.post(
279 | `${process.env.REACT_APP_BACKEND_URL}/countfollowing`, {
280 | id
281 | })
282 | return data
283 | } catch (error) {
284 | return { msg: "error" }
285 | }
286 | }
287 |
288 | export const showbookmarks = async (id) => {
289 | try {
290 | const data = await axios.post(
291 | `${process.env.REACT_APP_BACKEND_URL}/showbookmarks`, {
292 | id
293 | })
294 | return data;
295 | } catch (error) {
296 | return { msg: "error" }
297 | }
298 | }
299 | export const showLikemarks = async (id) => {
300 | try {
301 | const data = await axios.post(
302 | `${process.env.REACT_APP_BACKEND_URL}/showLikemarks`, {
303 | id
304 | })
305 | return data;
306 | } catch (error) {
307 | return { msg: "error" }
308 | }
309 | }
310 |
311 | export const reportcontent = async (pid, postid, userid, name1, name2, reason) => {
312 | try {
313 | var { data } = await axios.post(
314 | `${process.env.REACT_APP_BACKEND_URL}/reportcontent`, {
315 | pid,
316 | postid,
317 | userid,
318 | name1,
319 | name2,
320 | reason
321 | }
322 | )
323 | return data;
324 | } catch (error) {
325 | // console.log("error in Reporting", error);
326 | return { msg: error };
327 | }
328 | }
329 | export const deletebookmark = async (postid, userid) => {
330 | try {
331 | var { data } = await axios.post(
332 | `${process.env.REACT_APP_BACKEND_URL}/deletebookmark`, {
333 | postid,
334 | userid
335 | }
336 | )
337 | return data;
338 | } catch (error) {
339 | // console.log("error in Bookmark", error);
340 | return { msg: error };
341 | }
342 | }
343 | export const deletelikes = async (postid, userid) => {
344 | try {
345 | var { data } = await axios.post(
346 | `${process.env.REACT_APP_BACKEND_URL}/deletelikes`, {
347 | postid,
348 | userid
349 | }
350 | )
351 | return data;
352 | } catch (error) {
353 | // console.log("error in Liked removing", error);
354 | return { msg: error };
355 | }
356 | }
357 |
358 | export const deletepost = async (postid, userid) => {
359 | try {
360 | var { data } = await axios.post(
361 | `${process.env.REACT_APP_BACKEND_URL}/deletepost`, {
362 | postid,
363 | userid
364 | }
365 | )
366 | return data;
367 | } catch (error) {
368 | // console.log("error in deleting post", error);
369 | return { msg: error };
370 | }
371 | }
372 | export const checkbookmark = async (postid, userid) => {
373 | try {
374 | var { data } = await axios.post(
375 | `${process.env.REACT_APP_BACKEND_URL}/checkbookmark`, {
376 | postid,
377 | userid
378 | }
379 | )
380 | return data;
381 | } catch (error) {
382 | // console.log("error in Bookmark", error);
383 | return { msg: error };
384 | }
385 | }
386 | export const checklikes = async (postid, userid) => {
387 | try {
388 | var { data } = await axios.post(
389 | `${process.env.REACT_APP_BACKEND_URL}/checklikes`, {
390 | postid,
391 | userid
392 | }
393 | )
394 | return data;
395 | } catch (error) {
396 | // console.log("error in checklikes", error);
397 | return { msg: error };
398 | }
399 | }
400 |
401 | export const fetchfollowing = async (id) => {
402 | try {
403 | var { data } = await axios.post(
404 | `${process.env.REACT_APP_BACKEND_URL}/fetchfollowing`, {
405 | id,
406 | }
407 | )
408 | return data;
409 | } catch (error) {
410 | // console.log("error in fetch followers", error);
411 | return;
412 | }
413 | }
414 | export const changeabout = async (about, id) => {
415 | try {
416 | var { data } = await axios.post(
417 | `${process.env.REACT_APP_BACKEND_URL}/changeabout`, {
418 | about, id,
419 | }
420 | )
421 | return data;
422 | } catch (error) {
423 | // console.log("error in fetch followers", error);
424 | return;
425 | }
426 | }
427 | export const startfollow = async (id, id2) => {
428 | try {
429 | var { data } = await axios.post(
430 | `${process.env.REACT_APP_BACKEND_URL}/startfollow`, {
431 | id,
432 | id2
433 | }
434 | )
435 | return data;
436 | } catch (error) {
437 | // console.log("error in start following", error);
438 | return;
439 | }
440 | }
441 | export const unfollow = async (id, id2) => {
442 | try {
443 | var { data } = await axios.post(
444 | `${process.env.REACT_APP_BACKEND_URL}/unfollow`, {
445 | id,
446 | id2
447 | }
448 | )
449 | return data;
450 | } catch (error) {
451 | // console.log("error in start following", error);
452 | return;
453 | }
454 | }
455 | export const checkfollowing = async (id, id2) => {
456 | try {
457 | var { data } = await axios.post(
458 | `${process.env.REACT_APP_BACKEND_URL}/checkfollow`, {
459 | id,
460 | id2
461 | }
462 | )
463 | return data;
464 | } catch (error) {
465 | // console.log("error in fetch check following", error);
466 | return;
467 | }
468 | }
469 | export const showmyposts = async (id) => {
470 | try {
471 | var { data } = await axios.post(
472 | `${process.env.REACT_APP_BACKEND_URL}/showmyposts`, {
473 | id
474 | }
475 | )
476 | return data;
477 | } catch (error) {
478 | // console.log("error in Bookmark", error);
479 | return;
480 | }
481 | }
482 | export const increaseLike = async (id) => {
483 | try {
484 | var { data } = await axios.post(
485 | `${process.env.REACT_APP_BACKEND_URL}/increaseLike`, {
486 | id
487 | }
488 | )
489 | return data;
490 | } catch (error) {
491 | // console.log("error in likes increase", error);
492 | return;
493 | }
494 | }
495 | export const decreastLike = async (id) => {
496 | try {
497 | var { data } = await axios.post(
498 | `${process.env.REACT_APP_BACKEND_URL}/decreastLike`, {
499 | id
500 | }
501 | )
502 | return data;
503 | } catch (error) {
504 | // console.log("error in likes decrease", error);
505 | return;
506 | }
507 | }
508 | export const searchresult = async (id2,) => {
509 | try {
510 | var { data } = await axios.post(
511 | `${process.env.REACT_APP_BACKEND_URL}/searchresult`, {
512 | id2
513 | }
514 | )
515 | return data;
516 | } catch (error) {
517 | // console.log("error in Bookmark", error);
518 | return;
519 | }
520 | }
521 | export const bookmark = async (postid, userid) => {
522 | try {
523 | var { data } = await axios.post(
524 | `${process.env.REACT_APP_BACKEND_URL}/setbookmark`, {
525 | postid,
526 | userid
527 | }
528 | )
529 | return data;
530 | } catch (error) {
531 | // console.log("error in Bookmark", error);
532 | return;
533 | }
534 | }
535 |
536 | export const likes = async (postid, userid) => {
537 | try {
538 | var { data } = await axios.post(
539 | `${process.env.REACT_APP_BACKEND_URL}/setlikes`, {
540 | postid,
541 | userid
542 | }
543 | )
544 | return data;
545 | } catch (error) {
546 | // console.log("error in Likes", error);
547 | return;
548 | }
549 | }
550 | export const getallLikes = async (userid) => {
551 | try {
552 | var { data } = await axios.post(
553 | `${process.env.REACT_APP_BACKEND_URL}/getallLikes`, {
554 | userid
555 | }
556 | )
557 | return data;
558 | } catch (error) {
559 | // console.log("error in Likes", error);
560 | return;
561 | }
562 | }
563 | export const getallBookmarks = async (userid) => {
564 | try {
565 | var { data } = await axios.post(
566 | `${process.env.REACT_APP_BACKEND_URL}/getallBookmarks`, {
567 | userid
568 | }
569 | )
570 | return data;
571 | } catch (error) {
572 | // console.log("error in Likes", error);
573 | return;
574 | }
575 | }
576 |
577 | export const getAllPost = async (activePage, LIMIT,mpost) => {
578 | try {
579 | const { data } = await axios.post(
580 | `${process.env.REACT_APP_BACKEND_URL}/getallpost`,
581 | {
582 | params: {
583 | page: activePage,
584 | size: LIMIT,
585 | },
586 | mpost
587 | }
588 | );
589 | return data;
590 |
591 | } catch (error) {
592 | return error;
593 | }
594 | };
595 |
596 | export const getarticle = async (id) => {
597 | try {
598 | var { data } = await axios.post(
599 | `${process.env.REACT_APP_BACKEND_URL}/getarticle`, {
600 | id
601 | }
602 | )
603 | return data;
604 | } catch (error) {
605 | // console.log("error in getting article", error);
606 | return error;
607 | }
608 | }
609 |
610 | export const uploadProfilePicture = async (picture, about, token = null) => {
611 | try {
612 | const { data } = await axios.put(
613 | `${process.env.REACT_APP_BACKEND_URL}/uploadprofile`,
614 | {
615 | picture,
616 | about,
617 | },
618 |
619 | {
620 | headers: {
621 | Authorization: `Bearer ${token}`,
622 | },
623 | withCredentials: true,
624 | }
625 | );
626 | return data;
627 | } catch (error) {
628 | return error.response.data.message;
629 | }
630 | };
631 |
632 | export const getUser = async (userId) => {
633 | try {
634 | const { data } = await axios.get(
635 | `${process.env.REACT_APP_BACKEND_URL}/getUser/${userId}`
636 | );
637 | return data;
638 | } catch (error) {
639 | return error.response.data.message;
640 | }
641 | };
642 |
--------------------------------------------------------------------------------
/client/src/index.css:
--------------------------------------------------------------------------------
1 | :root {
2 | --main: #F0A826
3 | }
4 |
5 | * {
6 | margin: 0;
7 | padding: 0;
8 | box-sizing: border-box;
9 | }
10 |
11 |
12 | body {
13 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
14 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
15 | sans-serif;
16 | -webkit-font-smoothing: antialiased;
17 | -moz-osx-font-smoothing: grayscale;
18 |
19 |
20 | }
21 |
22 |
23 | code {
24 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
25 | monospace;
26 | }
--------------------------------------------------------------------------------
/client/src/index.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import ReactDOM from "react-dom/client";
3 | import "./index.css";
4 | import App from "./App";
5 | import { BrowserRouter } from "react-router-dom";
6 | import { Provider } from "react-redux";
7 | import { createStore, applyMiddleware } from 'redux';
8 | import { composeWithDevTools } from '@redux-devtools/extension';
9 | import rootReducer from "./reducers";
10 |
11 | const store = createStore(rootReducer, composeWithDevTools());
12 |
13 |
14 | const root = ReactDOM.createRoot(document.getElementById("root"));
15 | root.render(
16 |
17 |
18 |
19 |
20 |
21 | );
22 |
--------------------------------------------------------------------------------
/client/src/pages/ArticlePage.js:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useState } from 'react'
2 | import { useParams, useNavigate } from 'react-router-dom'
3 | import Article from '../components/article/Article';
4 | import Navbar from '../components/Navbar';
5 | import { getarticle, increaseView } from '../helpers/index'
6 | import '../components/article/article.css'
7 | function ArticlePage() {
8 | const navigate = useNavigate();
9 | const [post, setpost] = useState({});
10 | const { postID } = useParams();
11 | useEffect(() => {
12 | const init = async () => {
13 | await increaseView(postID);
14 | try {
15 | const dt = await getarticle(postID);
16 | if (dt.response && (dt.response.status === 404 || dt.response.status === 400)) {
17 | navigate("/404");
18 | }
19 | setpost(dt.msg);
20 | return;
21 | }
22 | catch (error) {
23 | if (error.msg == "!article") {
24 | navigate("/404");
25 | }
26 | else if (error.msg == "!user") {
27 | navigate("/404");
28 | }
29 | else if (error.msg === "error") navigate("/404");
30 | // console.log(error);
31 | return;
32 | }
33 | };
34 | init();
35 | }, [])
36 | if (!post || post.image === undefined || post.length === 0) {
37 | return <>
38 |
39 |
40 |
41 |
42 |
43 |
Loading....
44 |
You can comment, save, bookmark and download page
45 |
46 | >
47 | }
48 | else
49 | return (
50 |
54 | )
55 | // const location = useLocation()
56 | // const { post } = location.state;
57 | // if(location.state.ooo){
58 | // return (
59 | //
)
63 | // }else {
64 | // return (
65 | //
)
69 | // }
70 | }
71 |
72 | export default ArticlePage
--------------------------------------------------------------------------------
/client/src/pages/Auth.js:
--------------------------------------------------------------------------------
1 | import { useState } from "react";
2 | import { TfiEmail } from "react-icons/tfi";
3 | import { CiLock } from "react-icons/ci";
4 | import { TiUser } from "react-icons/ti";
5 | import { Link, useNavigate } from "react-router-dom";
6 | import axios from "axios";
7 | import { useDispatch } from "react-redux";
8 | import Cookies from "js-cookie";
9 | import {
10 | checkifverify,
11 | sendmail,
12 | checkotpv
13 | } from "../helpers/index"
14 |
15 | function Auth() {
16 | const dispatch = useDispatch();
17 | const navigate = useNavigate();
18 | const [state, setState] = useState("Sign Up");
19 | const [success, setSuccess] = useState("");
20 | const [error, setError] = useState("");
21 | const [otpv, cotpv] = useState("");
22 | const [vo, svo] = useState(false);
23 | const [cs, scs] = useState("");
24 | const userInfos = {
25 | email: "",
26 | password: "",
27 | name: "",
28 | };
29 |
30 | const [user, setUser] = useState(userInfos);
31 | const { email, password, name } = user;
32 |
33 | const handleRegisterChange = (e) => {
34 | const { name, value } = e.target;
35 | setUser({ ...user, [name]: value });
36 | };
37 |
38 | const handleSubmit = async () => {
39 | var temail = email.toLowerCase()
40 |
41 | if (state === "Log In") {
42 | try {
43 | if (!temail || !password) {
44 | setError('All feilds are required !')
45 | return;
46 | }
47 | const data = await checkifverify(temail);
48 | if (data.msg === "ok") {
49 |
50 | }
51 | else if (
52 | data.msg === 'ne'
53 | ) {
54 | setError("Please Sign Up First ");
55 | return;
56 | }
57 | else {
58 | setError("Please Sign up and Verify Your Email ");
59 | return;
60 | }
61 | } catch (error) {
62 | // console.log(error);
63 | }
64 | logIn();
65 | } else {
66 | if (!name || !temail || !password) {
67 | setError('All feilds are required !')
68 | return;
69 | }
70 | if (vo === false) {
71 | setError('An OTP has been send to your mail for verification')
72 | const datas = await sendmail(temail, name);
73 | scs(true);
74 | }
75 | }
76 | };
77 | const checkotp = async () => {
78 | try {
79 | var temail = email.toLowerCase()
80 |
81 | const data = await checkotpv(temail, otpv);
82 | } catch (error) {
83 | setError('An Error Occurred')
84 | // console.log("cannot verify otp")
85 | }
86 | }
87 | const logIn = async () => {
88 | try {
89 | var temail = email.toLowerCase()
90 | const { data } = await axios.post(
91 | `${process.env.REACT_APP_BACKEND_URL}/login`,
92 | {
93 | temail,
94 | password,
95 | }
96 | );
97 | setError('')
98 | setSuccess("Success !")
99 | setTimeout(() => {
100 | dispatch({ type: "LOGIN", payload: data });
101 | Cookies.set("user", JSON.stringify(data), { expires: 15 });
102 | navigate("/");
103 | }, 2000);
104 | } catch (error) {
105 | // console.log(error)
106 | setError(error.response.data.message);
107 | }
108 | };
109 |
110 | const signUp = async () => {
111 | try {
112 | var temail = email.toLowerCase()
113 | const { data } = await axios.post(
114 | `${process.env.REACT_APP_BACKEND_URL}/register`,
115 | {
116 | name,
117 | temail,
118 | password,
119 | }
120 | );
121 |
122 | setError('')
123 | setSuccess(data.message)
124 | const { message, ...rest } = data;
125 | setTimeout(() => {
126 | dispatch({ type: "LOGIN", payload: rest });
127 | Cookies.set("user", JSON.stringify(rest), { expires: 15 });
128 | navigate("/");
129 | }, 2000);
130 | } catch (error) {
131 | setError(error.response.data.message);
132 | }
133 | };
134 | const verifyOTP = async () => {
135 | try {
136 | var temail = email.toLowerCase()
137 | const data = await checkotpv(temail, otpv);
138 | if (data.msg === 'ok') {
139 | setError("OTP Matched");
140 | signUp();
141 | }
142 | else {
143 | setError("OTP do not match");
144 | }
145 | } catch (error) {
146 | setError("ERROR OCCURRED!");
147 | // console.log("error in matching")
148 | }
149 | }
150 | const signUpWithGoogle = () => {
151 | window.open(`${process.env.REACT_APP_BACKEND_URL}/auth/google`, "_self");
152 | }
153 |
154 | return (
155 |
156 |
157 |
158 |
159 |
{state}
160 |
161 |
162 |
{
169 | setState("Log In");
170 | setError("")
171 | }}
172 | >
173 | Log In
174 |
175 |
{
182 | setState("Sign Up");
183 | setError("")
184 |
185 | }}
186 | >
187 | Sign Up
188 |
189 |
190 | {state === "Log In" ? (
191 |
192 | {/*
193 |
194 |
signUpWithGoogle()} >Log in with Google
195 |
196 |
197 |
198 |
Log in with Facebook
199 |
*/}
200 |
201 |
202 | {/*
... ; */}
203 |
signUpWithGoogle()}>Sign In with Google
204 |
205 |
206 | ) : (
207 |
208 |
209 |
210 | {/*
... ; */}
211 |
signUpWithGoogle()}>Sign Up with Google
212 |
213 |
214 |
215 | )}
216 | {/*
or */}
217 | OR
218 |
265 | {error &&
{error} }
266 | {success &&
{success} }
267 | {state === "Sign Up" ? (
268 |
269 | By signing up, you agree to our terms of service and
270 | privacy policy . No credit card required.
271 |
272 | ) : (
273 |
274 | Don't remember your password?
275 |
276 | )}
277 | {(cs) && state === "Sign Up" ?
278 |
279 | {state === "Sign Up" ? "Verify OTP" : "LOG IN"}
280 |
281 | :
282 |
283 | {state === "Sign Up" ? "SIGN UP FOR FREE" : "LOG IN"}
284 |
285 | }
286 |
287 |
288 | );
289 | }
290 |
291 | export default Auth;
292 |
--------------------------------------------------------------------------------
/client/src/pages/HomePage.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import Breaker from "../components/home/breaker/Breaker";
3 | import Posts from "../components/home/post/Posts";
4 | import Navbar from "../components/Navbar";
5 | import Card from "../components/home/card/Card";
6 | import Cookies from "js-cookie";
7 | import { useNavigate } from "react-router-dom";
8 | import { useDispatch } from "react-redux";
9 | import { useState } from "react";
10 | import Footer from "../components/footer/Footer";
11 | function HomePage({ user, category }) {
12 | const navigate = useNavigate();
13 | const dispatch = useDispatch();
14 | const [mpost, setmpost] = useState(category);
15 | const [flag, setflag] = useState(false);
16 | const handleLoad = async () => {
17 | if (user === null || user === undefined) {
18 | await fetch(`${process.env.REACT_APP_BACKEND_URL}/login/success`, {
19 | method: "POST",
20 | credentials: "include",
21 | withCredentials: true,
22 | headers: {
23 | Accept: "application/json",
24 | "Content-Type": "application/json",
25 | "Access-Control-Allow-Credentials": true,
26 | },
27 | })
28 | .then((data) => {
29 | if (data.status === 201) return data.json();
30 | throw new Error("Authentication Failed!");
31 | })
32 | .then((data) => {
33 | dispatch({ type: "LOGIN", payload: data });
34 | Cookies.set("user", JSON.stringify(data), { expires: 15 });
35 | navigate("/");
36 | })
37 | .catch((err) => {
38 | // console.log(err);
39 | });
40 |
41 | }
42 | };
43 | React.useEffect(() => {
44 | handleLoad();
45 | }, []
46 | )
47 | return (
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 | );
56 | }
57 |
58 | export default HomePage;
59 |
--------------------------------------------------------------------------------
/client/src/pages/Profile.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import UserProfile from '../components/profile/UserProfile'
3 |
4 | function Profile() {
5 | return (
6 |
7 |
8 |
9 | )
10 | }
11 |
12 | export default Profile;
--------------------------------------------------------------------------------
/client/src/pages/ResetPassword.js:
--------------------------------------------------------------------------------
1 | import axios from "axios";
2 | import { useState } from "react";
3 | import "./resetPassword.css";
4 | import { Link, useNavigate, Navigate } from "react-router-dom";
5 |
6 | function ResetPassword() {
7 | const [email, setEmail] = useState("");
8 | const [code, setcode] = useState("");
9 | const [pass, setpass] = useState("");
10 | const [foundUser, setFoundUser] = useState(null);
11 | const [foundsend, setFoundsend] = useState(null);
12 | const [open, setopen] = useState(null);
13 |
14 | const navigate = useNavigate();
15 |
16 | const handleInputChange = (event) => {
17 | setEmail(event.target.value);
18 | };
19 |
20 | const handleSearchClick = async () => {
21 | try {
22 | const { data } = await axios.post(
23 | `${process.env.REACT_APP_BACKEND_URL}/findOutUser`,
24 | {
25 | email,
26 | }
27 | );
28 |
29 | setFoundUser(data[0])
30 |
31 |
32 | } catch (error) {
33 | if(error.response.status===400){
34 | alert(error.response.data.message);
35 | return;
36 | }
37 | if(error.response.status===404){
38 | alert(error.response.data.message);
39 | return;
40 | }
41 | }
42 | };
43 | const sendCode = async () => {
44 | try {
45 | const { data } = await axios.post(
46 | `${process.env.REACT_APP_BACKEND_URL}/sendResetPasswordCode`, { email: foundUser.email, code: code });
47 | setFoundsend(true);
48 | } catch (error) {
49 | // console.log(error.message);
50 | }
51 | };
52 |
53 | const validate = async (e) => {
54 | e.preventDefault()
55 | try {
56 | const { data } = await axios.post(
57 | `${process.env.REACT_APP_BACKEND_URL}/validateResetCode`, { email: foundUser.email, code: code });
58 | if (data.message === "ok") {
59 | setFoundsend(false);
60 | setopen(true);
61 | }
62 | else {
63 | alert(data.message)
64 | }
65 |
66 | } catch (error) {
67 | // console.log(error.message)
68 | }
69 | }
70 | const changep = async (e) => {
71 | e.preventDefault();
72 | if (pass.length <= 8) {
73 | alert("PASSWORD LENGTH SHOULD BE MORE THAN 8")
74 | return;
75 | }
76 | if (!pass) {
77 | return;
78 | }
79 |
80 | try {
81 | const { data } = await axios.post(
82 | `${process.env.REACT_APP_BACKEND_URL}/changePassword`, { email: foundUser.email, password: pass });
83 | if (data.message === "ok") {
84 | alert("Password Changed");
85 | setTimeout(() => {
86 | navigate("/");
87 | }, 2000);
88 | }
89 | else {
90 | alert(data.message)
91 | }
92 | } catch (error) {
93 | alert(error.message)
94 | }
95 | }
96 | return (
97 |
98 | {" "}
99 | {/* Add the "user-search" class to the container */}
100 |
Email address:
101 |
108 |
109 | Search
110 |
111 | {foundUser ? (
112 |
113 |
Name: {foundUser.name}
114 |
Email: {foundUser.email}
115 |
picture:
116 |
send code
117 |
118 | ) : (
119 |
120 | No user found with that email address.
121 |
122 | )}
123 |
124 |
138 |
139 |
140 |
153 |
154 |
155 | );
156 | }
157 |
158 | export default ResetPassword;
159 |
--------------------------------------------------------------------------------
/client/src/pages/TopicPage.js:
--------------------------------------------------------------------------------
1 | import React, { useEffect } from 'react'
2 |
3 | import { useParams, useNavigate } from 'react-router-dom'
4 | import { getAllPost } from '../helpers';
5 | import HomePage from './HomePage';
6 |
7 |
8 | const TopicPage = ({user}) => {
9 | const { id } = useParams();
10 | return (
11 | <>
12 |
13 | >
14 | )
15 | }
16 |
17 | export default TopicPage
--------------------------------------------------------------------------------
/client/src/pages/not_found.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { Link } from 'react-router-dom'
3 |
4 | const Not_found = () => {
5 | return (
6 |
16 |
404
22 |
Page Not Found
27 |
28 |
e.target.style.backgroundColor = '#0056b3'}
37 | onMouseOut={(e) => e.target.style.backgroundColor = '#007bff'}>
38 | GO TO HOME
39 |
40 |
41 |
56 |
57 |
58 | )
59 | }
60 |
61 | export default Not_found
--------------------------------------------------------------------------------
/client/src/pages/resetPassword.css:
--------------------------------------------------------------------------------
1 | .user-search {
2 | max-width: 500px;
3 | margin: 0 auto;
4 | padding: 20px;
5 | border: 1px solid #ccc;
6 | border-radius: 5px;
7 | }
8 |
9 | .user-search label {
10 | display: block;
11 | margin-bottom: 10px;
12 | }
13 |
14 | .hidden {
15 | display: none;
16 | }
17 |
18 | .user-search-input {
19 | width: 350px;
20 | height: 40px;
21 | font-size: 15px;
22 | border-radius: 6px;
23 | }
24 |
25 | .user-search input[type="text"] {
26 | display: block;
27 | width: 100%;
28 | padding: 10px;
29 | font-size: 16px;
30 | border: 1px solid #ccc;
31 | border-radius: 5px;
32 | }
33 |
34 | .imgres {
35 | width: 300px;
36 | }
37 |
38 | .user-search button {
39 | display: block;
40 | margin-top: 10px;
41 | padding: 10px;
42 | font-size: 16px;
43 | background-color: #007bff;
44 | color: #fff;
45 | border: none;
46 | border-radius: 5px;
47 | cursor: pointer;
48 | transition: background-color 0.2s;
49 | }
50 |
51 | .user-search button:hover {
52 | background-color: #0062cc;
53 | }
54 |
55 | .user-search p {
56 | margin-top: 10px;
57 | }
58 |
59 | @media only screen and (max-width: 600px) {
60 | .user-search {
61 | max-width: 100%;
62 | padding: 10px;
63 | }
64 |
65 | .user-search input[type="text"] {
66 | font-size: 14px;
67 | margin-bottom: 10px;
68 | }
69 |
70 | .user-search button {
71 | font-size: 14px;
72 | padding: 8px;
73 | margin-bottom: 10px;
74 | }
75 |
76 | .user-search p {
77 | margin-top: 10px;
78 | margin-bottom: 10px;
79 | }
80 | }
--------------------------------------------------------------------------------
/client/src/pages/write/Editpost.js:
--------------------------------------------------------------------------------
1 | import React, { useState } from 'react'
2 | import EditpostP from '../../components/write/EditorP'
3 | import { useParams, useNavigate } from 'react-router-dom'
4 | import { getarticle } from '../../helpers/index'
5 | import Navbar from '../../components/Navbar'
6 |
7 | const Editpost = () => {
8 | const navigate = useNavigate();
9 | const [post, setpost] = useState({});
10 | const { id } = useParams();
11 | React.useEffect(() => {
12 | x();
13 | }, [])
14 | const x = async () => {
15 | try {
16 | const dt = await getarticle(id);
17 | if (dt.response && (dt.response.status === 404 || dt.response.status === 400)) {
18 | // navigate("/404");
19 | }
20 | setpost(dt.msg);
21 | return;
22 | }
23 | catch (error) {
24 | if (error.msg == "!article") {
25 | // navigate("/404");
26 | }
27 | else if (error.msg == "!user") {
28 | // navigate("/404");
29 | }
30 | // else if (error.msg === "error") navigate("/404");
31 | // console.log(error);
32 | return;
33 | }
34 | }
35 | if (!post || !post.user) {
36 | return <>
37 |
38 |
39 |
40 |
41 |
42 |
Loading....
43 |
You can comment, save, bookmark and download page
44 |
45 | >
46 | }
47 | else {
48 | return (
49 | <>
50 |
51 |
52 |
53 |
54 | >
55 | )
56 | }
57 | }
58 |
59 | export default Editpost
--------------------------------------------------------------------------------
/client/src/pages/write/WritePost.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import Editor from '../../components/write/Editor'
3 | import Navbar from '../../components/Navbar'
4 |
5 | function WritePost() {
6 | return (
7 |
8 |
9 |
10 |
11 | )
12 | }
13 |
14 | export default WritePost
--------------------------------------------------------------------------------
/client/src/reducers/index.js:
--------------------------------------------------------------------------------
1 | import { combineReducers } from "redux";
2 | import { userReducer } from "./userReducer";
3 | import { postReducer } from "./postReducer";
4 |
5 |
6 |
7 | const rootReducer = combineReducers({
8 | user: userReducer,
9 | posts: postReducer,
10 |
11 | });
12 |
13 | export default rootReducer;
--------------------------------------------------------------------------------
/client/src/reducers/postReducer.js:
--------------------------------------------------------------------------------
1 |
2 | let posts = [];
3 |
4 | export function postReducer(state = posts, action) {
5 | switch (action.type) {
6 | case "SET_POSTS":
7 | try{
8 | return [...state, ...action.payload];
9 | }
10 | catch(e){
11 | return [...state, action.payload];
12 | }
13 | default:
14 | return state;
15 | }
16 | }
17 |
18 |
--------------------------------------------------------------------------------
/client/src/reducers/userReducer.js:
--------------------------------------------------------------------------------
1 |
2 | import Cookies from "js-cookie";
3 | export function userReducer(state = Cookies.get("user") ? JSON.parse(Cookies.get("user")) : null, action) {
4 | switch (action.type) {
5 | case "LOGIN":
6 | return action.payload;
7 | case "LOGOUT":
8 | return null;
9 | case "UPDATEPICTURE":
10 | return { ...state, picture: action.payload.picture, about: action.payload.about };
11 | case "VERIFY":
12 | return { ...state, verified: action.payload };
13 | case "LIKE":
14 | return { likes: action.payload, ...state };
15 | case "BOOKMARK":
16 | return { ...state, bookmarks: action.payload };
17 | default:
18 | return state;
19 | }
20 | }
21 |
22 |
--------------------------------------------------------------------------------
/client/src/routes/LoggedInRoutes.js:
--------------------------------------------------------------------------------
1 | import { useSelector } from "react-redux";
2 | import { Navigate, Outlet, useNavigate } from "react-router-dom";
3 |
4 | export default function LoggedInRoutes() {
5 | const { user } = useSelector((state) => ({ ...state }));
6 |
7 | return user ? : ;
8 | }
9 |
--------------------------------------------------------------------------------
/client/src/routes/NotAllowedLoggedInRoutes.js:
--------------------------------------------------------------------------------
1 | import { useSelector } from "react-redux";
2 | import { Navigate, Outlet } from "react-router-dom";
3 |
4 | export default function NotAllowedLoggedInRoutes() {
5 | const { user } = useSelector((state) => ({ ...state }));
6 |
7 | return user ? : ;
8 | }
9 |
--------------------------------------------------------------------------------