diff --git a/src/App.css b/src/App.css index 7f7a114..6daa07c 100644 --- a/src/App.css +++ b/src/App.css @@ -33,16 +33,11 @@ font-weight: 700; } .sidebar-items:hover{ - background:#FFF0EA; + background:#BFDBBD; cursor: pointer; border-radius: 5px; } -/* -.navbar{ - -webkit-box-shadow: 0px 1px 10px 0px rgba(71,71,71,0.57); - -moz-box-shadow: 0px 1px 10px 0px rgba(112, 112, 112, 0.57); - box-shadow: 0px 1px 10px 0px rgba(159, 159, 159, 0.57); -} */ + .navbar{ border-bottom: 1px solid #a9a9a9; diff --git a/src/app/auth/CompleteProfile.tsx b/src/app/auth/CompleteProfile.tsx index 1273c16..90b56fe 100644 --- a/src/app/auth/CompleteProfile.tsx +++ b/src/app/auth/CompleteProfile.tsx @@ -53,19 +53,22 @@ export default function CreateAccount() { <> { e.preventDefault(); formik.handleSubmit(); }} > - Complete your profile + + Complete your profile + {error} - + Username - + Name - + Bio { e.preventDefault(); formik.handleSubmit(); }} > - Create your account + + Create your account + {error} - - Email + + + Email + - - Password + + + Password + - + { - e.preventDefault(); - formik.handleSubmit(); - }} > - - - Welcome back - - - Please enter your details - - + { + e.preventDefault(); + formik.handleSubmit(); + }} + > + + + Welcome back + + + Please enter your details + + - - {error} - + + {error} + - - Email - + + Email + + + + + + Password + + togglePasswordVisibility()}> + {showPassword ? : } + + ), + }} + /> + + + + - - - - - - Don't have an account?{" "} - - Sign up for free - - + + + Don't have an account?{" "} + + Sign up for free + + + + + + - - - - + ); } diff --git a/src/app/auth/Register.tsx b/src/app/auth/Register.tsx index cb125ae..0ac84e6 100644 --- a/src/app/auth/Register.tsx +++ b/src/app/auth/Register.tsx @@ -4,6 +4,7 @@ import useRegisterStore from "./hooks/useRegisterStore"; import CreateAccount from "./CreateAccount"; import CompleteProfile from "./CompleteProfile"; import Suggestion from "./Suggestion"; +import AnimatePage from "../../layout/AnimatePage"; export default function Register() { // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-return @@ -16,71 +17,77 @@ export default function Register() { justifyContent="center" alignItems="center" > - + - - - Hello writer! - - - Lets get you on board - - + + + + Hello writer! + + + Lets get you on board + + - {/* + {/* {error} */} - - {activeStep === 0 && } + + {activeStep === 0 && } - {activeStep === 1 && } + {activeStep === 1 && } - {activeStep === 2 && } + {activeStep === 2 && } + + {activeStep != 2 && ( + + + + )} - {activeStep != 2 && ( - - - - )} - + ); } diff --git a/src/app/auth/Suggestion.tsx b/src/app/auth/Suggestion.tsx index 429398f..e25f017 100644 --- a/src/app/auth/Suggestion.tsx +++ b/src/app/auth/Suggestion.tsx @@ -59,19 +59,26 @@ export default function Suggestion() { return ( - + {TAGS.map((tag) => ( handleAddTag(tag)} sx={{ - background: "#474747", + backgroundColor: "primary.main", color: "white", borderRadius: "14px", padding: "5px 10px", "&:hover": { - background: "#333333", + backgroundColor: "primary.main", + opacity: 0.9, }, }} /> @@ -80,14 +87,14 @@ export default function Suggestion() { Selected Topics - + {tags.map((tag) => ( handleDeleteTag(tag)} sx={{ - background: "#474747", + backgroundColor: "primary.main", color: "white", borderRadius: "14px", padding: "5px 10px", diff --git a/src/app/blog/CreateBlog.tsx b/src/app/blog/CreateBlog.tsx index 3696284..78d6268 100644 --- a/src/app/blog/CreateBlog.tsx +++ b/src/app/blog/CreateBlog.tsx @@ -9,16 +9,18 @@ interface BlogImageTypes { } export default function CreateBlog() { - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment - const [blog,setBlog] = useEditorContent((state: any) => [state.blog as BlogImageTypes,state.setBlog,]); -const onTitleChange = (e: React.ChangeEvent) => { + const [blog, setBlog] = useEditorContent((state: any) => [ + state.blog as BlogImageTypes, + state.setBlog, + ]); + const onTitleChange = (e: React.ChangeEvent) => { // eslint-disable-next-line @typescript-eslint/no-unsafe-call setBlog({ ...blog, title: e.target.value, }); - } + }; return ( ) => { justifyContent={"flex-start"} position={"relative"} gap={5} + sx={{ + backgroundColor: "background.main", + }} paddingBottom={5} > - + Create your blog here... ) => { onChange={onTitleChange} variant="standard" sx={{ - background: "#F4F4F4", borderRadius: "5px", padding: "10px", }} @@ -58,40 +62,33 @@ const onTitleChange = (e: React.ChangeEvent) => { alignItems={"center"} sx={{ cursor: "pointer" }} > - + { const selectedFile = e.target.files && e.target.files[0]; // Check if files is not null if (selectedFile) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access - setBlog( - { - coverImage: selectedFile, - } - ) + setBlog({ + coverImage: selectedFile, + }); } }} /> Add a cover image - - - {blog.coverImage && ( - + )} - - + + - + ); diff --git a/src/app/blog/ShowBlog.tsx b/src/app/blog/ShowBlog.tsx index 7ed6258..96a5395 100644 --- a/src/app/blog/ShowBlog.tsx +++ b/src/app/blog/ShowBlog.tsx @@ -9,7 +9,7 @@ import { Typography, } from "@mui/material"; import { useEffect } from "react"; -import { useNavigate, useParams } from "react-router-dom"; +import { useNavigate, useParams } from "react-router-dom"; import APIMethods from "../../lib/axios/api"; import { useState } from "react"; import { Editor, EditorContent } from "@tiptap/react"; @@ -33,7 +33,9 @@ import BookmarkBorderIcon from "@mui/icons-material/BookmarkBorder"; import ShareIcon from "@mui/icons-material/Share"; import CommentSection from "./components/CommentSection"; import UserProfile from "../user/UserProfile"; -// import BookmarkIcon from '@mui/icons-material/Bookmark'; +import AnimatePage from "../../layout/AnimatePage"; +import { Skeleton } from "@mui/material"; +import ImageWithLoading from "./components/ImageWitLoading"; let authorid = ""; export default function ShowBlog() { @@ -44,32 +46,25 @@ export default function ShowBlog() { const [title, setTitle] = useState(""); const [coverImage, setCoverImage] = useState(""); const [likes, setLikes] = useState([]); - const [isFollowing,setIsFollowing] = useState(false); + const [isFollowing, setIsFollowing] = useState(false); const navigate = useNavigate(); - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment const [isLoading, setIsLoading] = useLoadingStore((state: any) => [ - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access state.loading, - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access state.setIsLoading, ]); const fetchBlog = async () => { - // eslint-disable-next-line @typescript-eslint/no-unsafe-call setIsLoading(true); await APIMethods.blog .getSingleBlog({ blogId }) .then((res: SingleBlogTypes) => { console.log(res); - if(res.data.status == 401) { + if (res.data.status == 401) { window.location.href = "/auth/login"; } - if(res.data.status == 404 || res.data.status == 500) - { + if (res.data.status == 404 || res.data.status == 500) { navigate("/404"); - } - else - { + } else { // eslint-disable-next-line @typescript-eslint/no-unsafe-argument setBlog(JSON.parse(res.data.blogs.content)); setAuthor(res.data.blogs.authorName); @@ -77,7 +72,7 @@ export default function ShowBlog() { setTitle(res.data.blogs.title); setCoverImage(res.data.blogs.coverImageURL); setLikes(res.data.blogs.likes); - authorid=res.data.blogs.authorID; + authorid = res.data.blogs.authorID; } }) .catch((e) => { @@ -91,7 +86,7 @@ export default function ShowBlog() { // }; const showProfile = () => { setIsSidebarOpen(!isSidebarOpen); - } + }; useEffect(() => { fetchBlog() @@ -105,25 +100,19 @@ export default function ShowBlog() { const follow = async () => { const data = { - userId:authorid, - id: - { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access - id: (JSON.parse(localStorage.getItem('user') as string))._id - } - } - const followRes = await APIMethods.user.isFollowingUser(data) + userId: authorid, + id: { + id: JSON.parse(localStorage.getItem("user") as string)._id, + }, + }; + const followRes = await APIMethods.user.isFollowingUser(data); console.log(followRes); - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - if(followRes.data.followStatus == 'unfollowing') - { + if (followRes.data.followStatus == "unfollowing") { setIsFollowing(false); - } - else - { + } else { setIsFollowing(true); } - } + }; useEffect(() => { if ( @@ -133,9 +122,7 @@ export default function ShowBlog() { title !== "" && coverImage !== "" ) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-call { - // eslint-disable-next-line @typescript-eslint/no-unsafe-call setIsLoading(false); console.log(isLoading); } @@ -148,35 +135,37 @@ export default function ShowBlog() { } async function likeBlog() { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment const user = JSON.parse( - localStorage.getItem("user") as string + localStorage.getItem("user") as string, ) as unknown as LikeBlogTypes; const userId = user._id; await APIMethods.blog .likeBlog({ userId, blogId }) - .then(async (res:any) => { + .then(async (res: any) => { console.log(res); // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - if(res.data.status == 400) { + if (res.data.status == 400) { window.location.href = "/auth/login"; } const data = { // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - userId: JSON.parse(localStorage.getItem("user") as string)._id as string, + userId: JSON.parse(localStorage.getItem("user") as string) + ._id as string, // eslint-disable-next-line @typescript-eslint/restrict-template-expressions, @typescript-eslint/no-unsafe-member-access - message : `👏 ${JSON.parse(localStorage.getItem("user") as string).displayName} clapped to your post!` - } + message: `👏 ${ + JSON.parse(localStorage.getItem("user") as string).displayName + } clapped to your post!`, + }; // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - await APIMethods.user.addNotification(data) - .then((res:any) => { + await APIMethods.user + .addNotification(data) + .then((res: any) => { console.log(res); }) - .catch((e:any) => { + .catch((e: any) => { console.log(e); }); - fetchBlog() .then((res) => { console.log(res); @@ -234,120 +223,163 @@ export default function ShowBlog() { justifyContent={"start"} alignItems={"center"} padding={5} + sx={{ + backgroundColor: "background.main", + }} > - setIsSidebarOpen(false)} /> - - { - isLoading? + setIsSidebarOpen(false)} + /> + + {isLoading ? ( + - : - - - - - {title} - - - - -
- - {author} - -
- {date} -
- -
- - - - - - - - - + + + ) : ( + + - - {likes.length} - - - + + {title} + + + )} + + + + +
+ + {author} + +
+ {date} +
+
-
- - - - + + - - - - -
+ + + + + + + {likes.length} + + + + + - + + + + - - - } + + + + +
+ + + + +
+ + )}
); } diff --git a/src/app/blog/components/ImageWitLoading.tsx b/src/app/blog/components/ImageWitLoading.tsx new file mode 100644 index 0000000..40adbfb --- /dev/null +++ b/src/app/blog/components/ImageWitLoading.tsx @@ -0,0 +1,33 @@ +import { useState, useEffect } from "react"; +import { Skeleton } from "@mui/material"; + +const ImageWithLoading = ({ src, alt, width, height, ...props }: any) => { + const [loading, setLoading] = useState(true); + + const handleImageLoad = () => { + setLoading(false); + }; + + useEffect(() => { + const img = new Image(); + img.src = src; + img.onload = handleImageLoad; + }, [src]); + + return ( +
+ {loading ? ( + + ) : ( + {alt} + )} +
+ ); +}; + +export default ImageWithLoading; diff --git a/src/app/blog/components/TagInput.tsx b/src/app/blog/components/TagInput.tsx index 9f0f931..f3e2181 100644 --- a/src/app/blog/components/TagInput.tsx +++ b/src/app/blog/components/TagInput.tsx @@ -54,12 +54,15 @@ const TagInput: React.FC = () => { return ( - Select category/categories + + Select category/categories + ( @@ -82,7 +85,12 @@ const TagInput: React.FC = () => { /> + + ); diff --git a/src/app/notifications/Notification.tsx b/src/app/notifications/Notification.tsx index 45eca6d..df84af3 100644 --- a/src/app/notifications/Notification.tsx +++ b/src/app/notifications/Notification.tsx @@ -1,102 +1,107 @@ -import { CircularProgress, Stack, Typography } from '@mui/material' -import { useEffect,useState } from 'react' -import APIMethods from '../../lib/axios/api' -import './notification.css' +import { CircularProgress, Stack, Typography } from "@mui/material"; +import { useEffect, useState } from "react"; +import APIMethods from "../../lib/axios/api"; +import "./notification.css"; export default function Notification() { + const [notifications, setNotifications] = useState([]); - const [notifications, setNotifications] = useState([]) ; + const fetchNotification = async () => { + try { + const userString = localStorage.getItem("user"); + if (userString) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + const userId = JSON.parse(userString)._id as unknown as string; + const response = await APIMethods.user.getNotifications({ userId }); + // console.log(response.data); + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const cachedNotifications = JSON.parse( + localStorage.getItem("notifications") as string, + ); + console.log(cachedNotifications); + if (!cachedNotifications) { + localStorage.setItem( + "notifications", + JSON.stringify(["Welcome to the app!"]), + ); + setNotifications(["Welcome to the app!"]); + } else { + if (response.data == "no new notification") { + //do nothing - const fetchNotification = async () => { - try { - const userString = localStorage.getItem("user"); - if (userString) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - const userId = JSON.parse(userString)._id as unknown as string; - const response = await APIMethods.user.getNotifications({ userId }); - // console.log(response.data); - - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const cachedNotifications = JSON.parse(localStorage.getItem("notifications") as string); - console.log(cachedNotifications) - if(!cachedNotifications){ - localStorage.setItem("notifications", JSON.stringify(['Welcome to the app!'])); - setNotifications(['Welcome to the app!']); - } - else - { - if (response.data=='no new notification'){ - //do nothing - - - if(cachedNotifications) - setNotifications(cachedNotifications as string[]); - - } - else - { - - setNotifications([ - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - ...cachedNotifications, - ...response.data as string[], - ]); - } - } - - } else { - console.log("User not found in localStorage."); - } - } catch (error) { - console.error(error); + if (cachedNotifications) + setNotifications(cachedNotifications as string[]); + } else { + setNotifications([ + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + ...cachedNotifications, + ...(response.data as string[]), + ]); + } } - }; + } else { + console.log("User not found in localStorage."); + } + } catch (error) { + console.error(error); + } + }; - useEffect(() => { - fetchNotification().then((res) => { - console.log(res); - } - ).catch((e) => { - console.log(e); - } - ) - }, []) + useEffect(() => { + fetchNotification() + .then((res) => { + console.log(res); + }) + .catch((e) => { + console.log(e); + }); + }, []); - useEffect(() => { - if(notifications && notifications.length!=0) - {localStorage.setItem("notifications", JSON.stringify(notifications));} - }, [notifications]); + useEffect(() => { + if (notifications && notifications.length != 0) { + localStorage.setItem("notifications", JSON.stringify(notifications)); + } + }, [notifications]); return ( - - - All Notifications - - { - - - notifications.length!=0 ?( - - notifications.slice().reverse().map((singleItem,idx) => { - return ( - - - {singleItem} - - - ) - } - ) - ):( - - - - ) - - } + + + All Notifications + + {notifications.length != 0 ? ( + notifications + .slice() + .reverse() + .map((singleItem, idx) => { + return ( + + {singleItem} + + ); + }) + ) : ( + + - ) - - } - \ No newline at end of file + )} + + ); +} diff --git a/src/app/platform/About.tsx b/src/app/platform/About.tsx index 3e0a3be..5bb68e1 100644 --- a/src/app/platform/About.tsx +++ b/src/app/platform/About.tsx @@ -2,75 +2,87 @@ import { IconButton, Stack, Typography } from "@mui/material"; import TwitterIcon from "@mui/icons-material/Twitter"; import InstagramIcon from "@mui/icons-material/Instagram"; import LinkedInIcon from "@mui/icons-material/LinkedIn"; +import AnimatePage from "../../layout/AnimatePage"; export default function About() { return ( - + - - - - - Know About Us - - - Pensdown is a platform for writers to share their thoughts and ideas - with the world. It is a place where you can write about anything you - want and share it with the world. - + + + - - - - - - - - - + + Know About Us + + + + Pensdown is a platform for writers to share their thoughts and + ideas with the world. It is a place where you can write about + anything you want and share it with the world. + + + + + + + + + + + + + - + ); } diff --git a/src/app/platform/Contact.tsx b/src/app/platform/Contact.tsx index a49d457..fb4c73c 100644 --- a/src/app/platform/Contact.tsx +++ b/src/app/platform/Contact.tsx @@ -1,6 +1,7 @@ import { Button, Stack, TextField, Typography } from "@mui/material"; import APIMethods from "../../lib/axios/api"; import { useState } from "react"; +import AnimatePage from "../../layout/AnimatePage"; export default function Contact() { const [mail, setMail] = useState({ senderEmail: "", @@ -21,82 +22,85 @@ export default function Contact() { }; return ( - - - - - - - - - We would love to hear from you! - - - { - setMail({ ...mail, senderEmail: e.target.value }); - }} - id="standard-basic" - label="Your Email" - variant="standard" - /> - { - setMail({ ...mail, text: e.target.value }); - }} - id="outlined-multiline-static" - label="Something you want to share with us..." - multiline - rows={6} - variant="outlined" - sx={{ - marginTop: "6px", - }} - /> + + + + + - - + + { + setMail({ ...mail, senderEmail: e.target.value }); + }} + id="standard-basic" + label="Your Email" + variant="standard" + /> + { + setMail({ ...mail, text: e.target.value }); + }} + id="outlined-multiline-static" + label="Something you want to share with us..." + multiline + rows={6} + variant="outlined" + sx={{ + marginTop: "6px", + }} + /> + + + + - + ); } diff --git a/src/app/user/AboutUser.tsx b/src/app/user/AboutUser.tsx index b118c70..b9c8c41 100644 --- a/src/app/user/AboutUser.tsx +++ b/src/app/user/AboutUser.tsx @@ -10,6 +10,7 @@ import APIMethods from "../../lib/axios/api"; import { useLocation } from "react-router-dom"; import KeyboardBackspaceIcon from "@mui/icons-material/KeyboardBackspace"; import Loaders from "./components/Loaders"; +import AnimatePage from "../../layout/AnimatePage"; interface LocationState { authorId: string; @@ -91,6 +92,9 @@ export default function AboutUser() { minHeight={"130vh"} justifyContent={"start"} alignItems={"end"} + sx={{ + backgroundColor: "background.main", + }} gap={5} > @@ -100,7 +104,6 @@ export default function AboutUser() { window.location.href = "/"; }} sx={{ - background: "#474747", color: "#fff", borderRadius: "8px", padding: "5px 10px", @@ -113,6 +116,7 @@ export default function AboutUser() { Back to home + @@ -152,7 +156,9 @@ export default function AboutUser() { justifyContent={"start"} height={"fit-content"} > - {profile.displayName} + + {profile.displayName} + {profile.bio} @@ -164,7 +170,7 @@ export default function AboutUser() { alignItems={"center"} gap={1} > - + Jajpur Road , Odisha @@ -174,7 +180,7 @@ export default function AboutUser() { alignItems={"center"} gap={1} > - + India @@ -248,17 +254,17 @@ export default function AboutUser() { width={"100%"} justifyContent={"center"} > - + Followers

{profile.followersCount}

- + Blogs

{profile.blogsCount}

- + Respect

{profile.respect}

@@ -268,6 +274,7 @@ export default function AboutUser() { @@ -286,143 +300,147 @@ export default function AboutUser() {
- + + + + + + - - - - - {isLoading == false && blogs.length == 0 && ( - - No Blogs Yet - - )} - {isLoading ? ( - - - - ) : ( - <> - {blogs.map((blog, idx) => { - return ( - { - window.location.href = `/${blog._id}`; - }} - > + {isLoading == false && blogs.length == 0 && ( + + No Blogs Yet + + )} + {isLoading ? ( + + + + ) : ( + <> + {blogs.map((blog, idx) => { + return ( { + window.location.href = `/${blog._id}`; + }} > - - - - - {blog.title} - - - - - - {(blog.likes as []).length} - + - - - {(blog.comments as []).length} - - + + + {blog.title} + + + + + + {(blog.likes as []).length} + + + + + + {(blog.comments as []).length} + + + - - - {blog.date} + + {blog.date} + - - - - ); - })} - - )} + + + ); + })} + + )} + - +
); } diff --git a/src/app/user/UserProfile.tsx b/src/app/user/UserProfile.tsx index 326e751..cd5e3fe 100644 --- a/src/app/user/UserProfile.tsx +++ b/src/app/user/UserProfile.tsx @@ -7,6 +7,8 @@ import useLoadingStore from "../../lib/store/useLoading"; import CircularProgress from "@mui/material/CircularProgress"; import { useEffect, useState } from "react"; import { useNavigate } from "react-router-dom"; +import LogoutIcon from "@mui/icons-material/Logout"; +import { toast } from "react-hot-toast"; export default function UserProfile({ isOpen, @@ -23,7 +25,6 @@ export default function UserProfile({ ], ); const fetchProfile = async () => { - // eslint-disable-next-line @typescript-eslint/no-unsafe-call setIsLoading(true); await APIMethods.user .getAuthorInfo({ authorId }) @@ -42,14 +43,12 @@ export default function UserProfile({ const data = { userId: authorId, id: { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access id: JSON.parse(localStorage.getItem("user") as string)._id, }, }; const followRes = await APIMethods.user.isFollowingUser(data); console.log(followRes); - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access if (followRes.data.followStatus == "unfollowing") { setIsFollowing(false); } else { @@ -57,6 +56,13 @@ export default function UserProfile({ } }; + const handleLogout = () => { + localStorage.removeItem("user"); + localStorage.removeItem("accessToken"); + window.location.reload(); + toast.error("You have been logged "); + }; + useEffect(() => { fetchProfile() .then(() => { @@ -93,16 +99,44 @@ export default function UserProfile({ bottom={0} minWidth={"26rem"} minHeight={"100vh"} - sx={{ background: "#fff", borderRadius: "8px 0px 0px 8px" }} + sx={{ + background: "#fff", + borderRadius: "8px 0px 0px 8px", + borderColor: "secondary.main", + }} > - + + + {isLoading ? ( @@ -185,27 +219,34 @@ export default function UserProfile({ justifyContent={"center"} alignItems={"center"} paddingX={4} + color={"text.secondary"} > {profile.bio} - Blogs + + Blogs + {profile.blogsCount} - Followers + + Followers + {profile.followersCount} - Respect + + Respect + {profile.respect} @@ -222,7 +263,12 @@ export default function UserProfile({ console.log(err); }); }} - sx={{ background: "#474747" }} + sx={{ + backgroundColor: "secondary.main", + "&:hover": { + backgroundColor: "secondary.main", + }, + }} > {isFollowing ? "Unfollow" : "Follow"} diff --git a/src/app/user/user.css b/src/app/user/user.css index 51c3a51..c6c90f5 100644 --- a/src/app/user/user.css +++ b/src/app/user/user.css @@ -17,6 +17,7 @@ } .single-blog-container:hover{ - background-color: #aeaeae; + background-color: #BFDBBD; cursor: pointer; + transition: 0.5s ease; } \ No newline at end of file diff --git a/src/hooks/useDebounce.ts b/src/hooks/useDebounce.ts new file mode 100644 index 0000000..9e2c8a8 --- /dev/null +++ b/src/hooks/useDebounce.ts @@ -0,0 +1,19 @@ +import { useEffect, useState } from "react"; + +function useDebounce(value: string, delay = 1000) { + const [debounceValue, setDebounceValue] = useState(value); + + useEffect(() => { + const timeout = setTimeout(() => { + setDebounceValue(value); + }, delay); + + return () => { + clearTimeout(timeout); + }; + }, [value, delay]); + + return debounceValue; +} + +export default useDebounce; diff --git a/src/index.css b/src/index.css index fc33201..88f29a7 100644 --- a/src/index.css +++ b/src/index.css @@ -5,4 +5,8 @@ body{ font-family: 'Raleway'; +} + +::selection { + color: green; } \ No newline at end of file diff --git a/src/layout/AnimatePage.tsx b/src/layout/AnimatePage.tsx new file mode 100644 index 0000000..d9eefec --- /dev/null +++ b/src/layout/AnimatePage.tsx @@ -0,0 +1,20 @@ +import React, { ReactNode } from "react"; +import { motion } from "framer-motion"; + +interface AnimateFrameProps { + children: ReactNode; +} + +const AnimatePage: React.FC = ({ children }) => { + return ( + + {children} + + ); +}; + +export default AnimatePage; diff --git a/src/layout/Footer.tsx b/src/layout/Footer.tsx index 02f16ed..0ac4267 100644 --- a/src/layout/Footer.tsx +++ b/src/layout/Footer.tsx @@ -1,38 +1,59 @@ import { Stack, Typography } from "@mui/material"; export default function Footer() { + const year = new Date().getFullYear(); + return ( - - - - - About + + + + + About • - - Contact + + Contact • - - Writer + + Writer • - - Status + + Status - + - - Pensdown © 2023 - + Pensdown © {year} - ) + ); } diff --git a/src/layout/RootLayout.tsx b/src/layout/RootLayout.tsx index 2a3ecde..3bab066 100644 --- a/src/layout/RootLayout.tsx +++ b/src/layout/RootLayout.tsx @@ -6,7 +6,7 @@ const RootLayout = () => { return (
- + diff --git a/src/layout/headeroptions/Header.tsx b/src/layout/headeroptions/Header.tsx index aebf782..234f442 100644 --- a/src/layout/headeroptions/Header.tsx +++ b/src/layout/headeroptions/Header.tsx @@ -14,7 +14,7 @@ export default function Header() { minHeight={"50px"} justifyContent={"center"} sx={{ - background: "#F5F5F5", + backgroundColor: "background.main", }} > Pensdown diff --git a/src/layout/headeroptions/HeaderActions.tsx b/src/layout/headeroptions/HeaderActions.tsx index 465cc82..c7f348c 100644 --- a/src/layout/headeroptions/HeaderActions.tsx +++ b/src/layout/headeroptions/HeaderActions.tsx @@ -10,7 +10,7 @@ import { Stack, TextField, } from "@mui/material"; -import { Link, useLocation, useNavigate } from "react-router-dom"; +import { Link, redirect, useLocation, useNavigate } from "react-router-dom"; import NotificationsIcon from "@mui/icons-material/Notifications"; import useWriterAction from "../../lib/store/useWriterAction"; import { useEffect, useState } from "react"; @@ -71,6 +71,11 @@ const AuthorizedActions = () => { } }, [location.pathname, setIsWriting, setNotWriting]); + console.log("user", localStorage.getItem("user")); + if (!localStorage.getItem("user") || localStorage.getItem("user") == null) { + navigate("/auth/login"); + } + const uploadImageToFirebase = async () => { if (blog == null) return; @@ -84,11 +89,8 @@ const AuthorizedActions = () => { ) as unknown as userTypes; const imageRef = ref( storage, - - // eslint-disable-next-line @typescript-eslint/restrict-template-expressions `cover_images/${user._id}/${user.displayName}/${imageId}`, ); - // eslint-disable-next-line @typescript-eslint/no-unsafe-argument await uploadBytes(imageRef, blog.coverImage); }; @@ -98,7 +100,6 @@ const AuthorizedActions = () => { localStorage.getItem("user") as string, ) as unknown as userTypes; const DBUser = JSON.parse(localStorage.getItem("user") as string); - // eslint-disable-next-line @typescript-eslint/no-unsafe-call setIsLoading(true); const data = { @@ -126,18 +127,15 @@ const AuthorizedActions = () => { return APIMethods.blog.createBlog(data); }) .then(() => { - // eslint-disable-next-line @typescript-eslint/no-unsafe-call setIsLoading(false); console.log("Blog created successfully:"); localStorage.setItem("rich-editor", ""); - // eslint-disable-next-line @typescript-eslint/no-unsafe-call resetBlog(); savedNotify(); navigate("/"); }) .catch((err) => { console.log("Error:", err); - // eslint-disable-next-line @typescript-eslint/no-unsafe-call setIsLoading(false); }); }; @@ -168,9 +166,7 @@ const AuthorizedActions = () => { const handleSearch = (e: any) => { if (e.key === "Enter") { - // eslint-disable-next-line @typescript-eslint/no-unsafe-call setSearch(e.target.value); - // eslint-disable-next-line @typescript-eslint/restrict-template-expressions navigate(`/search/${e.target.value}`); } }; @@ -194,6 +190,7 @@ const AuthorizedActions = () => { sx={{ width: "350px", background: "#FAF8FF", + borderRadius: "6px", marginRight: "20px", }} /> @@ -268,21 +265,25 @@ const UnauthorizedActions = () => {