Compare commits

..

No commits in common. "2d6fead452ea9ee6294fb13dafc466365344d0b0" and "2a89f75ac6733b7e22d5d78dd98226df3620b72b" have entirely different histories.

2 changed files with 38 additions and 33 deletions
public/images/tags
src/components/posts

Binary file not shown.

Before

(image error) Size: 40 KiB

After

(image error) Size: 48 KiB

View file

@ -2,7 +2,7 @@
import { Button } from "@nextui-org/react"; import { Button } from "@nextui-org/react";
import { PostType } from "@/types/PostType"; import { PostType } from "@/types/PostType";
import { Heart } from "lucide-react"; import { Heart, LoaderCircle } from "lucide-react";
import { toast } from "react-toastify"; import { toast } from "react-toastify";
import { getCookie } from "@/helpers/cookie"; import { getCookie } from "@/helpers/cookie";
import { redirect } from "next/navigation"; import { redirect } from "next/navigation";
@ -11,6 +11,7 @@ import { useTheme } from "next-themes";
export default function LikeButton({ post }: { post: PostType }) { export default function LikeButton({ post }: { post: PostType }) {
const [likes, setLikes] = useState<number>(post.likes.length); const [likes, setLikes] = useState<number>(post.likes.length);
const [loading, setLoading] = useState<boolean>(false);
const [liked, setLiked] = useState<boolean>(false); const [liked, setLiked] = useState<boolean>(false);
const { theme } = useTheme(); const { theme } = useTheme();
const [reduceMotion, setReduceMotion] = useState<boolean>(false); const [reduceMotion, setReduceMotion] = useState<boolean>(false);
@ -42,10 +43,11 @@ export default function LikeButton({ post }: { post: PostType }) {
: "", : "",
}} }}
onPress={async () => { onPress={async () => {
if (!getCookie("token")) { if (loading || liked) {
redirect("/login"); return;
} }
setLoading(true);
const response = await fetch( const response = await fetch(
process.env.NEXT_PUBLIC_MODE === "PROD" process.env.NEXT_PUBLIC_MODE === "PROD"
? "https://d2jam.com/api/v1/like" ? "https://d2jam.com/api/v1/like"
@ -64,46 +66,49 @@ export default function LikeButton({ post }: { post: PostType }) {
} }
); );
post.hasLiked = !post.hasLiked;
if (post.hasLiked) {
setLiked(true);
setTimeout(() => setLiked(false), 1000);
setLikes(likes + 1);
} else {
setLiked(false);
setLikes(likes - 1);
}
if (!response.ok) { if (!response.ok) {
setLoading(false);
if (response.status == 401) { if (response.status == 401) {
redirect("/login"); redirect("/login");
} else { } else {
post.hasLiked = !post.hasLiked;
toast.error("An error occurred"); toast.error("An error occurred");
return; return;
} }
} else {
const data = await response.json();
setLikes(parseInt(data.likes));
post.hasLiked = data.action === "like";
setLoading(false);
setLiked(data.action === "like");
setTimeout(() => setLiked(false), 1000);
} }
}} }}
> >
<div className="flex gap-2 items-center" style={{ position: "relative" }}> {loading ? (
<Heart size={16} /> <LoaderCircle className="animate-spin" size={16} />
<Heart ) : (
size={16} <div
className={ className="flex gap-2 items-center"
liked && !reduceMotion style={{ position: "relative" }}
? "animate-ping absolute top-0 left-0" >
: "absolute top-0 left-0" <Heart size={16} />
} <Heart
style={{ size={16}
position: "absolute", className={
top: "0", liked && !reduceMotion
left: "0", ? "animate-ping absolute top-0 left-0"
zIndex: "10", : "absolute top-0 left-0"
}} }
/> style={{
<p>{likes}</p> position: "absolute",
</div> top: "0",
left: "0",
zIndex: "10",
}}
/>
<p>{likes}</p>
</div>
)}
</Button> </Button>
); );
} }