Blog creation and filling dialog completed #1
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "enshi",
|
"name": "enshi",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.1.7",
|
"version": "0.1.8",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
|
|||||||
@ -13,7 +13,7 @@ const router = createBrowserRouter(routes);
|
|||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
return (
|
return (
|
||||||
<Theme className="h-fit" accentColor="indigo" grayColor="slate" appearance="dark">
|
<Theme className="h-fit" accentColor="sky" grayColor="slate" appearance="dark">
|
||||||
<ToastProvider>
|
<ToastProvider>
|
||||||
<QueryClientProvider client={queryClient}>
|
<QueryClientProvider client={queryClient}>
|
||||||
<RouterProvider router={router} />
|
<RouterProvider router={router} />
|
||||||
|
|||||||
@ -1,7 +1,10 @@
|
|||||||
import { DoubleArrowDownIcon, DoubleArrowUpIcon } from "@radix-ui/react-icons";
|
import { DoubleArrowDownIcon, DoubleArrowUpIcon } from "@radix-ui/react-icons";
|
||||||
import { IconButton } from "@radix-ui/themes";
|
import { IconButton } from "@radix-ui/themes";
|
||||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||||
|
import { useAtomValue } from "jotai";
|
||||||
import { axiosLocalhost } from "../../../api/axios/axios";
|
import { axiosLocalhost } from "../../../api/axios/axios";
|
||||||
|
import { userAtom } from "../../../AtomStore/AtomStore";
|
||||||
|
import useToast from "../../../hooks/useToast";
|
||||||
|
|
||||||
export const UPVOTE = true;
|
export const UPVOTE = true;
|
||||||
export const DOWNVOTE = false;
|
export const DOWNVOTE = false;
|
||||||
@ -14,6 +17,9 @@ type TVoteButton = {
|
|||||||
export default function VoteButton(props: TVoteButton) {
|
export default function VoteButton(props: TVoteButton) {
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
|
const user = useAtomValue(userAtom);
|
||||||
|
const createToast = useToast();
|
||||||
|
|
||||||
const { data } = useQuery({
|
const { data } = useQuery({
|
||||||
queryKey: [props.vote + "voteCheck"],
|
queryKey: [props.vote + "voteCheck"],
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
@ -57,7 +63,13 @@ export default function VoteButton(props: TVoteButton) {
|
|||||||
<IconButton
|
<IconButton
|
||||||
variant={data ? "solid" : "outline"}
|
variant={data ? "solid" : "outline"}
|
||||||
size={"1"}
|
size={"1"}
|
||||||
onClick={() => voteMutation.mutate()}
|
onClick={() => {
|
||||||
|
if(!user) {
|
||||||
|
createToast({title: "Please log in to vote", description: "You need to be logged in to vote on a post."});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
voteMutation.mutate();
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{props.vote ? <DoubleArrowUpIcon /> : <DoubleArrowDownIcon />}
|
{props.vote ? <DoubleArrowUpIcon /> : <DoubleArrowDownIcon />}
|
||||||
</IconButton>
|
</IconButton>
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import { Button, Card, Flex, Select, Text, Theme } from "@radix-ui/themes";
|
|||||||
import { useMutation, useQuery } from "@tanstack/react-query";
|
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||||
import { useAtomValue } from "jotai";
|
import { useAtomValue } from "jotai";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate, useParams } from "react-router-dom";
|
||||||
import { Blog } from "../../../@types/BlogTypes";
|
import { Blog } from "../../../@types/BlogTypes";
|
||||||
import { axiosLocalhost } from "../../../api/axios/axios";
|
import { axiosLocalhost } from "../../../api/axios/axios";
|
||||||
import { userAtom } from "../../../AtomStore/AtomStore";
|
import { userAtom } from "../../../AtomStore/AtomStore";
|
||||||
@ -17,9 +17,12 @@ export default function AddPostToBlogDialog() {
|
|||||||
const user = useAtomValue(userAtom);
|
const user = useAtomValue(userAtom);
|
||||||
const [selectedBlog, setSelectedBlog] = useState<string>("");
|
const [selectedBlog, setSelectedBlog] = useState<string>("");
|
||||||
|
|
||||||
const createToast = useToast()
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
|
|
||||||
const { data } = useQuery({
|
const params = useParams();
|
||||||
|
const createToast = useToast();
|
||||||
|
|
||||||
|
const { data, refetch } = useQuery({
|
||||||
queryKey: ["userBlogs"],
|
queryKey: ["userBlogs"],
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
const response = await axiosLocalhost.get("/user/blogs", {
|
const response = await axiosLocalhost.get("/user/blogs", {
|
||||||
@ -30,20 +33,30 @@ export default function AddPostToBlogDialog() {
|
|||||||
|
|
||||||
return temp as Blog[];
|
return temp as Blog[];
|
||||||
},
|
},
|
||||||
|
enabled: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
const addMutation = useMutation({
|
const addMutation = useMutation({
|
||||||
mutationKey: ["addPostToBlog"],
|
mutationKey: ["addPostToBlog"],
|
||||||
mutationFn: async () => {
|
mutationFn: async () => {
|
||||||
|
const response = await axiosLocalhost.put(
|
||||||
|
`posts/${params["postId"]}/blogs/${selectedBlog}`
|
||||||
|
);
|
||||||
|
return response.data;
|
||||||
},
|
},
|
||||||
onError: (error) => {
|
onError: (error) => {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
createToast({title: "Error!", description: "Post have not been added"})
|
createToast({
|
||||||
|
title: "Error!",
|
||||||
|
description: "Post have not been added",
|
||||||
|
});
|
||||||
},
|
},
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
console.log("Post added successfully");
|
console.log("Post added successfully");
|
||||||
createToast({title: "Success!", description: "Post added successfully"})
|
createToast({
|
||||||
|
title: "Success!",
|
||||||
|
description: "Post added successfully",
|
||||||
|
});
|
||||||
},
|
},
|
||||||
onSettled: () => {
|
onSettled: () => {
|
||||||
console.log("Add mutation is settled");
|
console.log("Add mutation is settled");
|
||||||
@ -56,7 +69,15 @@ export default function AddPostToBlogDialog() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog.Root>
|
<Dialog.Root
|
||||||
|
open={isOpen}
|
||||||
|
onOpenChange={(e) => {
|
||||||
|
setIsOpen(e);
|
||||||
|
if (e) {
|
||||||
|
refetch();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
<Dialog.Trigger asChild>
|
<Dialog.Trigger asChild>
|
||||||
<Button variant="surface" className="h-5">
|
<Button variant="surface" className="h-5">
|
||||||
<Text>Add to blog</Text>
|
<Text>Add to blog</Text>
|
||||||
@ -64,9 +85,9 @@ export default function AddPostToBlogDialog() {
|
|||||||
</Dialog.Trigger>
|
</Dialog.Trigger>
|
||||||
<Dialog.Portal>
|
<Dialog.Portal>
|
||||||
<Dialog.Overlay className="fixed inset-0 bg-black/40 data-[state=open]:animate-overlayShow" />
|
<Dialog.Overlay className="fixed inset-0 bg-black/40 data-[state=open]:animate-overlayShow" />
|
||||||
<Dialog.Content className="fixed left-1/2 top-1/2 max-h-[85vh] w-[90vw] max-w-[600px] -translate-x-1/2 -translate-y-1/2 rounded-md p-[25px] shadow-[hsl(206_22%_7%_/_35%)_0px_10px_38px_-10px,_hsl(206_22%_7%_/_20%)_0px_10px_20px_-15px] focus:outline-none data-[state=open]:animate-contentShow">
|
<Dialog.Content className="fixed left-1/2 top-1/2 max-h-[85vh] w-[90vw] max-w-[600px] -translate-x-1/2 -translate-y-1/2 rounded-md shadow-[hsl(206_22%_7%_/_35%)_0px_10px_38px_-10px,_hsl(206_22%_7%_/_20%)_0px_10px_20px_-15px] focus:outline-none data-[state=open]:animate-contentShow">
|
||||||
<Theme>
|
<Theme panelBackground="solid">
|
||||||
<Card>
|
<Card className="p-5">
|
||||||
<Dialog.Title className="m-0 text-[17px] font-medium text-mauve12">
|
<Dialog.Title className="m-0 text-[17px] font-medium text-mauve12">
|
||||||
<Text size={"4"}>Add this post to blog</Text>
|
<Text size={"4"}>Add this post to blog</Text>
|
||||||
</Dialog.Title>
|
</Dialog.Title>
|
||||||
@ -75,9 +96,9 @@ export default function AddPostToBlogDialog() {
|
|||||||
<Text>{`Add post to `}</Text>
|
<Text>{`Add post to `}</Text>
|
||||||
<Select.Root
|
<Select.Root
|
||||||
value={selectedBlog}
|
value={selectedBlog}
|
||||||
onValueChange={(e) =>
|
onValueChange={(e) => {
|
||||||
setSelectedBlog(e)
|
setSelectedBlog(e);
|
||||||
}
|
}}
|
||||||
>
|
>
|
||||||
<Select.Trigger className="w-40 cursor-pointer" />
|
<Select.Trigger className="w-40 cursor-pointer" />
|
||||||
<Select.Content>
|
<Select.Content>
|
||||||
@ -98,15 +119,25 @@ export default function AddPostToBlogDialog() {
|
|||||||
</Flex>
|
</Flex>
|
||||||
</Dialog.Description>
|
</Dialog.Description>
|
||||||
|
|
||||||
<div className="mt-[25px] flex justify-end">
|
<Flex
|
||||||
<Dialog.Close asChild>
|
className="items-center justify-between"
|
||||||
<Button
|
>
|
||||||
className="cursor-pointer"
|
{selectedBlog ? <div/> : <Text color="gray">* Please select a blog to attach the post to.</Text>}
|
||||||
>
|
|
||||||
<Text>Confirm</Text>
|
<div className="flex flex-col justify-center">
|
||||||
</Button>
|
<Dialog.Close asChild>
|
||||||
</Dialog.Close>
|
<Button
|
||||||
</div>
|
className="cursor-pointer"
|
||||||
|
onClick={() => {
|
||||||
|
addMutation.mutate();
|
||||||
|
}}
|
||||||
|
disabled={!selectedBlog}
|
||||||
|
>
|
||||||
|
<Text>Confirm</Text>
|
||||||
|
</Button>
|
||||||
|
</Dialog.Close>
|
||||||
|
</div>
|
||||||
|
</Flex>
|
||||||
<Dialog.Close asChild>
|
<Dialog.Close asChild>
|
||||||
<button
|
<button
|
||||||
className="absolute right-2.5 top-2.5 inline-flex size-[25px] appearance-none items-center justify-center rounded-full text-violet11 hover:bg-violet4 focus:shadow-[0_0_0_2px] focus:shadow-violet7 focus:outline-none"
|
className="absolute right-2.5 top-2.5 inline-flex size-[25px] appearance-none items-center justify-center rounded-full text-violet11 hover:bg-violet4 focus:shadow-[0_0_0_2px] focus:shadow-violet7 focus:outline-none"
|
||||||
|
|||||||
@ -10,7 +10,8 @@ export default function AuthPageWrapper(props: React.PropsWithChildren) {
|
|||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
if (!user) {
|
if (!user) {
|
||||||
navigate("/login");
|
navigate("/login", { replace: true });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container size={"4"} className="mt-4">
|
<Container size={"4"} className="mt-4">
|
||||||
<Text size={"7"}>{t("errors.unauthorized")}</Text>
|
<Text size={"7"}>{t("errors.unauthorized")}</Text>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user