Skip to content

Commit

Permalink
feature(reservation): api and hook (#68)
Browse files Browse the repository at this point in the history
  • Loading branch information
huangfishburger authored May 17, 2024
1 parent c7bf848 commit a1ed1b9
Show file tree
Hide file tree
Showing 7 changed files with 276 additions and 177 deletions.
192 changes: 45 additions & 147 deletions src/app/reservation/[id]/page.tsx

Large diffs are not rendered by default.

65 changes: 49 additions & 16 deletions src/app/reservation/_components/reservation-card.tsx
Original file line number Diff line number Diff line change
@@ -1,40 +1,73 @@
"use client";

import { useState } from "react";

import { MinusCircle } from "lucide-react";

import { Button } from "@/components/ui/button";
import { Card } from "@/components/ui/card";

import ResStateDialog from "./resstate-dialog";

type ReservationCard = {
productId: number;
id: number;
name: string;
note: string;
price: number;
unit: number;
time: string;
quantity: number;
status: string;
};

export function ReservationCard({
id,
name,
note,
price,
unit,
time,
quantity,
status,
}: ReservationCard) {
const [finishDialogOpen, setFinishDialogOpen] = useState(false);
const [cancelDialogOpen, setCancelDialogOpen] = useState(false);

return (
<Card className="w-full cursor-pointer p-4">
<div className="flex flex-col gap-x-4">
<div className="flex flex-row items-center justify-between">
<Card
className="w-full cursor-pointer p-4"
onClick={() => setFinishDialogOpen(!finishDialogOpen)}
>
<div className="flex flex-row justify-between">
<div className="flex flex-col gap-x-4">
<div className="flex items-center gap-x-2 lg:gap-x-8">
<p className="text-lg font-bold lg:text-2xl">{name}</p>
<p className="text-md lg:text-lg">$ {price}</p>
</div>
<p className="text-md font-semibold lg:text-lg">{unit}</p>
</div>
<div className="text-md pt-2 font-normal text-muted-foreground lg:pt-4 lg:text-lg">
{note.slice(0, 20)}...
<div className="text-md pt-2 font-normal text-muted-foreground lg:pt-4 lg:text-lg">
{status}...
</div>
</div>
<div className="text-md pt-2 text-end font-normal lg:pt-4 lg:text-lg">
{time}
<div className="flex flex-row items-center gap-x-4">
<p className="text-md font-semibold lg:text-lg">{quantity}</p>
<Button
variant="ghost"
size="icon"
className="flex flex-col items-center justify-center"
onClick={() => setCancelDialogOpen(!cancelDialogOpen)}
>
<MinusCircle />
</Button>
</div>
</div>
<ResStateDialog
open={finishDialogOpen}
onOpenChange={setFinishDialogOpen}
type="finish"
id={id}
quantity={quantity}
/>
<ResStateDialog
open={cancelDialogOpen}
onOpenChange={setCancelDialogOpen}
type="cancel"
id={id}
quantity={quantity}
/>
</Card>
);
}
51 changes: 51 additions & 0 deletions src/app/reservation/_components/reservation-update.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
"use client";

import React from "react";
import { useState } from "react";

import { PlusCircle, MinusCircle } from "lucide-react";

import usePost from "@/hooks/use-post";

type ReservationUpdate = {
id: number;
postId: number;
name: string;
quantity: number;
description: string;
image: string;
};

export function ReservationUpdate({
id,
postId,
name,
quantity,
description,
image,
}: ReservationUpdate) {
const { updatePost } = usePost();
const [dishQuantity, setDishQuantity] = useState(quantity);

const handleDecreaseQuantity = () => {
if (dishQuantity !== undefined && dishQuantity > 0) {
updatePost(id, postId, name, dishQuantity - 1, description, image);
setDishQuantity(dishQuantity - 1);
}
};

const handleIncreaseQuantity = () => {
if (dishQuantity !== undefined) {
updatePost(id, postId, name, dishQuantity + 1, description, image);
setDishQuantity(dishQuantity + 1);
}
};

return (
<div className="flex flex-row items-center gap-x-2">
<MinusCircle onClick={handleDecreaseQuantity} />
<p className="text-xs lg:text-lg">{dishQuantity}</p>
<PlusCircle onClick={handleIncreaseQuantity} />
</div>
);
}
40 changes: 26 additions & 14 deletions src/app/reservation/_components/resstate-dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,32 @@ import {
DialogFooter,
DialogTitle,
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import useReservation from "@/hooks/use-reservation";

type ResStateDialogProps = {
open: boolean;
onOpenChange: (open: boolean) => void;
type: string;
id: number;
quantity: number;
};

export default function ResStateDialog({
open,
onOpenChange,
type,
id,
quantity,
}: ResStateDialogProps) {
const { finishRservation, cancelRservation } = useReservation();

const handleCancel = () => {
cancelRservation(id);
};
const handleFinish = () => {
finishRservation(id, quantity);
};

return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className="w-[80%] max-w-[400px] rounded">
Expand All @@ -29,27 +41,27 @@ export default function ResStateDialog({
<DialogTitle className="text-lg lg:text-xl">
Cancel Reservation?
</DialogTitle>
<div className="grid w-full max-w-sm items-center gap-2">
<Label htmlFor="number">數量</Label>
<Input
type="number"
className="rounded-md border border-gray-300 p-2"
required
placeholder="number"
/>
</div>
</div>
)}
{type === "finish" && (
<div>
<div className="flex flex-col items-center gap-y-4">
<DialogTitle className="text-center text-lg lg:text-xl">
Finish reservation?
</DialogTitle>
</div>
)}

<DialogFooter className="gap-2">
<Button className="block w-full" onClick={() => onOpenChange(!open)}>
<Button
className="block w-full"
onClick={() => {
onOpenChange(!open);
if (type === "cancel") {
handleCancel();
} else if (type === "finish") {
handleFinish();
}
}}
>
confirm
</Button>
</DialogFooter>
Expand Down
3 changes: 3 additions & 0 deletions src/components/supplier/post.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ export function Post({
}: {
post: SelectPost & { postDishes: SelectPostDish };
}) {
// const session = await getServerSession(authOptions);
// const isAuthor = post.userId === session?.user.id;

return (
<ImageCard href={`/post/${post.id}`} image={post.postDishes?.image}>
<div className="flex justify-between">
Expand Down
36 changes: 36 additions & 0 deletions src/hooks/use-post.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,45 @@ export default function usePost() {
setLoading(false);
};

const updatePost = async (
id: number,
postId: number,
name: string,
quantity: number,
description: string,
image: string,
) => {
setLoading(true);

try {
await handleFetch({
data: {
id,
postId,
name,
quantity,
description,
image,
},
method: "PUT",
url: `/api/posts/post-dishes`,
});

setLoading(false);
router.refresh();
} catch (error) {
console.error("Error updating post item quantity:", error);
}

toast("Post item has been updated.");
router.refresh();
setLoading(false);
};

return {
createPost,
createPostReservation,
updatePost,
loading,
};
}
66 changes: 66 additions & 0 deletions src/hooks/use-reservation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { useState } from "react";

import { useRouter } from "next/navigation";

import { toast } from "sonner";

import handleFetch from "./utils";

export default function useReservation() {
const [loading, setLoading] = useState(false);
const router = useRouter();

const finishRservation = async (id: number, quantity: number) => {
setLoading(true);

try {
await handleFetch({
data: {
id,
quantity,
status: "finished",
},
method: "PUT",
url: "/api/posts/post-reservations",
});

setLoading(false);
router.refresh();
} catch (error) {
console.error("Error updating reservation:", error);
}

toast("Reservation has finished.");
router.refresh();
setLoading(false);
};

const cancelRservation = async (id: number) => {
setLoading(true);

try {
await handleFetch({
data: {
id,
},
method: "DELETE",
url: "/api/posts/post-reservations",
});

setLoading(false);
router.refresh();
} catch (error) {
console.error("Error delete reservation:", error);
}

toast("Reservation has been deleted.");
router.refresh();
setLoading(false);
};

return {
finishRservation,
cancelRservation,
loading,
};
}

0 comments on commit a1ed1b9

Please sign in to comment.