Skip to content

Commit

Permalink
Master (#178)
Browse files Browse the repository at this point in the history
  • Loading branch information
harundogdu authored Oct 9, 2023
2 parents 8ca30a8 + ef4a853 commit 833898a
Show file tree
Hide file tree
Showing 16 changed files with 308 additions and 38 deletions.
20 changes: 14 additions & 6 deletions components/Sidebar.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import { useCallback } from "react";
import { useRouter } from "next/router";

import { RiMoreFill } from "react-icons/ri";

import ColorUtils from "@/base/colors";
import SpaceUtils from "@/base/spaces";

import useLoginModal from "@/hooks/useLoginModal";
import useCurrentUser from "@/hooks/useCurrentUser";
import useTweetActionModal from "@/hooks/useTweetActionModal";
Expand All @@ -14,7 +12,6 @@ import SidebarItem from "@/components/SidebarItem";
import Button from "@/components/shared/Button";

import { SidebarItems } from "@/utils/@fake.db";
import { useRouter } from "next/router";

import Avatar from "./Avatar";

Expand All @@ -35,7 +32,17 @@ const Sidebar = () => {
const RenderSidebarItems = useCallback(() => {
const sideBarItems = currentUser?.email
? [...SidebarItems]
: [...SidebarItems].filter((item) => item.public);
.filter((item) => item.active)
.filter((item) => {
if (item.href === "/notifications") {
item.alert = currentUser?.hasNotification;
}
return item;
})
: [...SidebarItems]
.filter((item) => item.active)
.filter((item) => item.public);

return (
<div className="space-y-1">
{sideBarItems.map((item, index) => (
Expand All @@ -46,11 +53,12 @@ const Sidebar = () => {
href={item.href}
onClick={item.onClick}
key={index}
alert={item?.alert}
/>
))}
</div>
);
}, [currentUser?.email]);
}, [currentUser?.email, currentUser?.hasNotification]);
return (
<div className="mt-[0.875rem] px-1 h-full col-span-1 sm:px-4 md:px-6 flex items-start justify-center">
<div className="absolute flex flex-col items-center md:items-start h-full">
Expand Down
25 changes: 21 additions & 4 deletions components/SidebarItem.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { FC, useCallback } from "react";
import { useRouter } from "next/router";

import useWindowSize from "@/hooks/useWindowSize";
import { BsDot } from "react-icons/bs";

import { ISidebarType } from "@/types/sidebar.type";

import useWindowSize from "@/hooks/useWindowSize";
import useLoginModal from "@/hooks/useLoginModal";
import useCurrentUser from "@/hooks/useCurrentUser";

Expand All @@ -13,6 +16,7 @@ const SidebarItem: FC<ISidebarType> = ({
icon: Icon,
secondaryIcon: SecondaryIcon,
public: isPublic,
alert,
}) => {
const { width } = useWindowSize();
const router = useRouter();
Expand Down Expand Up @@ -49,12 +53,22 @@ const SidebarItem: FC<ISidebarType> = ({
SecondaryIcon ? (
<SecondaryIcon size={28} color="#fff" />
) : (
<Icon size={28} color="#fff" />
<>
<Icon size={28} color="#fff" />
{alert ? (
<BsDot size={70} className="text-sky-500 absolute -top-4 left-0" />
) : null}
</>
)
) : (
<Icon size={28} color="#fff" />
<>
<Icon size={28} color="#fff" />
{alert ? (
<BsDot size={70} className="text-sky-500 absolute -top-4 left-0" />
) : null}
</>
);
}, [width, SecondaryIcon, Icon]);
}, [width, SecondaryIcon, Icon, alert]);

return (
<div
Expand All @@ -66,6 +80,9 @@ const SidebarItem: FC<ISidebarType> = ({
</div>
<div className="relative hidden lg:flex items-center rounded-full cursor-pointer hover:bg-neutral-800 hover:bg-opacity-70 gap-4 p-4">
<Icon size={28} color="#fff" />
{alert ? (
<BsDot size={70} className="text-sky-500 absolute -top-4 left-0" />
) : null}
<span className="text-white text-lg hidden lg:block">{label}</span>
</div>
</div>
Expand Down
30 changes: 15 additions & 15 deletions components/modals/RegisterModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -95,22 +95,22 @@ const RegisterModal = () => {

useEffect(() => {
const fetchData = async () => {
try {
const { data } = await axios.get(`/api/register/${username}`);

const isUsernameExist = data.some(
(user: { username: string }) => user.username === username
);

if (data && username === data) {
setUsernameError(true);
} else {
setUsernameError(false);
}
} catch (err: any) {
console.error("Data fetch error", err);
}
if (registerModal.isOpen) {
try {
const { data } = await axios.get(`/api/register/${username}`);

const isUsernameExist = data.some(
(user: { username: string }) => user.username === username
);

if (data && username === data) {
setUsernameError(true);
} else {
setUsernameError(false);
}
} catch (err: any) {
console.error("Data fetch error", err);
}
window.history.pushState(null, "", "/register");
} else {
window.history.pushState(null, "", "/");
Expand Down
53 changes: 53 additions & 0 deletions components/notifications/NotificationFeed.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { Fragment, useEffect } from "react";

import { formatDistanceToNowStrict } from "date-fns";
import { BsTwitter } from "react-icons/bs";

import useCurrentUser from "@/hooks/useCurrentUser";
import useNotifications from "@/hooks/useNotifications";

const NotificationFeed = () => {
const { data: currentUser, mutate: mutateCurrentUser } = useCurrentUser();
const { data: notifications = [] } = useNotifications(currentUser?.id);

useEffect(() => {
mutateCurrentUser();
}, [mutateCurrentUser]);

return (
<>
{Array.isArray(notifications) &&
notifications.map((notification: Record<string, any>) => {
return (
<Fragment key={notification.id}>
<div
key={notification.id}
className="flex items-center px-4 py-3 border-b border-gray-200 dark:border-gray-800 hover:bg-gray-100 dark:hover:bg-gray-800"
>
<BsTwitter className="w-6 h-6 mr-4 text-blue-500" />
<div className="flex flex-col flex-1">
<span className="text-sm text-gray-500 dark:text-gray-400">
<span className="text-gray-600 dark:text-gray-300">
{notification.body}
</span>
</span>
<span className="text-xs text-gray-500 dark:text-gray-400">
{formatDistanceToNowStrict(
new Date(notification.createdAt)
)}
</span>
</div>
</div>
{Array.isArray(notifications) && notification.length === 0 && (
<div className="flex items-center justify-center h-full text-gray-500 dark:text-gray-400">
<span className="text-3xl">No notifications</span>
</div>
)}
</Fragment>
);
})}
</>
);
};

export default NotificationFeed;
4 changes: 2 additions & 2 deletions components/posts/PostFeed.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ const PostFeed: FC<IPostFeedProps> = ({ data }) => {
);
const closePostEdit = (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
const target = e.target as HTMLElement;
const attributeValue = target.getAttribute("editPost-data");
const attributeValue = target.getAttribute("editpost-data");
if (attributeValue === "editPost") return;
setEditPost(false);
};
Expand Down Expand Up @@ -185,7 +185,7 @@ const PostFeed: FC<IPostFeedProps> = ({ data }) => {
className={`absolute w-72 right-0 top-0 text-custom-white bg-custom-black z-50 ${
editPost ? "block shadow-customSecondary rounded-lg" : "hidden"
}`}
editPost-data="editPost"
editpost-data="editPost"
>
{isLoggedIn && data?.user?.username === isLoggedIn?.username && (
<>
Expand Down
3 changes: 0 additions & 3 deletions components/shared/BasicDatePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,6 @@ const BasicDatePicker: FC<IDatepickerProps> = ({
onChange = () => {},
defaultValue = null,
}) => {
/*
TODO:: @HD
console.log("hd", defaultValue ? dayjs(defaultValue) : null); */
return (
<LocalizationProvider dateAdapter={AdapterDayjs}>
<DatePicker
Expand Down
21 changes: 16 additions & 5 deletions hooks/useLikes.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import { useCallback, useMemo } from "react";

import axios from "axios";
import toast from "react-hot-toast";

import useCurrentUser from "./useCurrentUser";
import usePost from "./usePost";
import useLoginModal from "./useLoginModal";
import axios from "axios";
import usePost from "./usePost";
import usePosts from "./usePosts";
import toast from "react-hot-toast";

const useLikes = ({ postId, userId }: { postId: string; userId: string }) => {
const { data: currentUser } = useCurrentUser();
const { data: currentUser, mutate: mutateUser } = useCurrentUser();
const { data: fetchedPost, mutate: mutatePost } = usePost(postId);
const { mutate: mutatePosts } = usePosts();
const loginModal = useLoginModal();
Expand Down Expand Up @@ -35,13 +37,22 @@ const useLikes = ({ postId, userId }: { postId: string; userId: string }) => {
await request();
mutatePost();
mutatePosts();
mutateUser();

toast.success("Success");
} catch (error: any) {
console.log(error);
toast.error("Failed");
}
}, [currentUser, hasLiked, loginModal, mutatePost, mutatePosts, postId]);
}, [
currentUser,
hasLiked,
loginModal,
mutatePost,
mutatePosts,
postId,
mutateUser,
]);

return {
hasLiked,
Expand Down
17 changes: 17 additions & 0 deletions hooks/useNotifications.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import useSWR from "swr";

import fetcher from "@/libs/fetcher";

const useNotifications = (userId?: string) => {
const url = userId ? `/api/notifications/${userId}` : null;
const { data, error, mutate, isLoading } = useSWR(url, fetcher);

return {
data,
isLoading,
error,
mutate,
};
};

export default useNotifications;
4 changes: 2 additions & 2 deletions hooks/usePost.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import useSWR from "swr";

import fetcher from "@/libs/fetcher";

const usePost = (postId: string) => {
const usePost = (postId?: string) => {
const { data, error, isLoading, mutate, isValidating } = useSWR(
`/api/posts/${postId}`,
postId ? `/api/posts/${postId}` : null,
fetcher
);

Expand Down
28 changes: 28 additions & 0 deletions pages/api/comments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,34 @@ export default async function handler(
},
});

try {
const post = await prisma.post.findUnique({
where: {
id: postId,
},
});

if (post?.userId) {
await prisma.notification.create({
data: {
body: "Someone replied your post",
userId: post.userId,
},
});

await prisma.user.update({
where: {
id: post.userId,
},
data: {
hasNotification: true,
},
});
}
} catch (error: any) {
console.log(error);
}

return res.status(200).json(comment);
} catch (error: any) {
console.log(error);
Expand Down
20 changes: 20 additions & 0 deletions pages/api/follow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,26 @@ export default async function handler(

if (req.method === "POST") {
updatingFollowingIds.push(user.id);

try {
await prisma.notification.create({
data: {
body: "Someone followed you",
userId: user.id,
},
});

await prisma.user.update({
where: {
id: user.id,
},
data: {
hasNotification: true,
},
});
} catch (error: any) {
console.log(error);
}
}

if (req.method === "DELETE") {
Expand Down
Loading

0 comments on commit 833898a

Please sign in to comment.