Skip to content

Commit

Permalink
feat: add AddStoreDishDialog
Browse files Browse the repository at this point in the history
  • Loading branch information
guan404ming committed May 25, 2024
1 parent 78de114 commit 01f210a
Show file tree
Hide file tree
Showing 5 changed files with 228 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,7 @@ import { UploadButton } from "@/lib/uploadthing";

import LocationPicker from "./location-picker";

type DialogProps = {
type: string;
};

export default function AddDialog({ type }: DialogProps) {
export default function AddPostDialog() {
const [open, setOpen] = useState<boolean>(false);
const [url, setUrl] = useState<string>("");
const [location, setLocation] = useState<{ lat: number; lng: number } | null>(
Expand Down Expand Up @@ -89,7 +85,7 @@ export default function AddDialog({ type }: DialogProps) {
<DialogContent className="h-[80%] w-[80%] max-w-[400px] overflow-scroll rounded">
<DialogHeader>
<DialogTitle className="flex justify-start text-lg lg:text-xl">
Add {type}
Add Post
</DialogTitle>
</DialogHeader>

Expand Down
199 changes: 199 additions & 0 deletions src/app/my/_components/add-store-dish.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
"use client";

import { useState } from "react";
import { useForm } from "react-hook-form";

import Image from "next/image";

import { zodResolver } from "@hookform/resolvers/zod";
import { PlusCircle } from "lucide-react";
import { z } from "zod";

import { Button } from "@/components/ui/button";
import {
Dialog,
DialogContent,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog";
import {
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import { Textarea } from "@/components/ui/textarea";
import useStore from "@/hooks/use-store";
import { UploadButton } from "@/lib/uploadthing";

type DialogProps = {
storeId: number;
};

export default function AddStoreDishDialog({ storeId }: DialogProps) {
const [open, setOpen] = useState<boolean>(false);
const [url, setUrl] = useState<string>("");
const { createStoreDish } = useStore();

const formSchema = z.object({
name: z.string().min(1),
description: z.string().optional(),
quantity: z.number().min(1).max(10000),
price: z.number().min(1).max(10000),
});

const form = useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema),
defaultValues: {
name: "",
description: "",
quantity: 0,
price: 0,
},
});

function onSubmit(values: z.infer<typeof formSchema>) {
console.log(values, storeId, url);
if (!url) return;
createStoreDish({
...values,
image: url,
storeId,
});
setOpen(false);
}

return (
<Dialog open={open} onOpenChange={setOpen}>
<DialogTrigger asChild>
<Button size={"icon"} variant={"ghost"}>
<PlusCircle className="h-5 w-5 cursor-pointer" />
</Button>
</DialogTrigger>
<DialogContent className="h-[80%] w-[80%] max-w-[400px] overflow-scroll rounded">
<DialogHeader>
<DialogTitle className="flex justify-start text-lg lg:text-xl">
Add Store Dish
</DialogTitle>
</DialogHeader>

<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-8">
<FormField
control={form.control}
name="name"
render={({ field }) => (
<FormItem>
<FormLabel>Dish Name*</FormLabel>
<FormControl>
<Input
placeholder="Enter the name of the dish"
{...field}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>

<FormField
control={form.control}
name="description"
render={({ field }) => (
<FormItem>
<FormLabel>Dish Description*</FormLabel>
<FormControl>
<Textarea
placeholder="Enter a brief description of your post"
{...field}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>

<FormField
control={form.control}
name="quantity"
render={({ field }) => (
<FormItem>
<FormLabel>Dish Quantity*</FormLabel>
<FormControl>
<Input
placeholder="quantity"
type="number"
{...field}
onChange={(value) =>
field.onChange(value.target.valueAsNumber)
}
min={0}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>

<FormField
control={form.control}
name="price"
render={({ field }) => (
<FormItem>
<FormLabel>Dish Price*</FormLabel>
<FormControl>
<Input
placeholder="price"
type="number"
{...field}
onChange={(value) =>
field.onChange(value.target.valueAsNumber)
}
min={0}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>

<div className="grid w-full max-w-sm items-center gap-2">
<FormLabel htmlFor="description" className="mb-4">
Dish Image*
</FormLabel>
<UploadButton
className="w-full text-black"
endpoint="imageUploader"
appearance={{ button: "w-full text-black bg-white border" }}
onClientUploadComplete={(res) => {
console.log("Files: ", res);
setUrl(res[0].url);
}}
onUploadError={(error: Error) => {
console.log(`ERROR! ${error.message}`);
}}
/>
{url && (
<Image
src={url}
alt={""}
width={100}
height={100}
className="aspect-auto w-full border object-cover"
/>
)}
</div>

<Button type="submit" className="mt-4 w-full">
Submit
</Button>
</form>
</Form>
</DialogContent>
</Dialog>
);
}
4 changes: 2 additions & 2 deletions src/app/my/posts/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { getServerSession } from "next-auth/next";

import AddDialog from "../_components/add-dialog";
import AddPostDialog from "../_components/add-post-dialog";
import { eq } from "drizzle-orm";

import UnauthorizedPage from "@/app/unauthorized";
Expand All @@ -27,7 +27,7 @@ export default async function MyReservationsPage() {
<>
<div className="flex items-center justify-between">
<h1 className="text-xl font-semibold">My Posts</h1>
<AddDialog type="Post"></AddDialog>
<AddPostDialog />
</div>

<GridContainer>
Expand Down
7 changes: 6 additions & 1 deletion src/app/my/stores/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { getServerSession } from "next-auth/next";

import AddStoreDishDialog from "../_components/add-store-dish";
import { eq } from "drizzle-orm";

import UnauthorizedPage from "@/app/unauthorized";
Expand All @@ -26,7 +27,11 @@ export default async function MyStoresPage() {

return (
<>
<h1 className="text-xl font-semibold">My Store Dishes</h1>
<div className="flex items-center justify-between">
<h1 className="text-xl font-semibold">My Store Dishes</h1>
<AddStoreDishDialog storeId={store.id} />
</div>

<GridContainer>
{store.storeDishes.map((storeDish, index) => (
<StoreDish storeDish={storeDish} key={index} isAuthor isCounter />
Expand Down
19 changes: 19 additions & 0 deletions src/hooks/use-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,24 @@ export default function useStore() {
router.refresh();
};

const createStoreDish = async ({
quantity,
storeId,
name,
price,
description,
image,
}: InsertStoreDish) => {
await handleFetch({
data: { quantity, storeId, name, price, description, image },
method: "POST",
url: "/api/stores/store-dishes",
successMessage: "Store dish has been created.",
setLoading,
});
router.refresh();
};

const updateStoreDish = async ({
id,
quantity,
Expand Down Expand Up @@ -137,6 +155,7 @@ export default function useStore() {
finishStoreReservation,
deleteStoreReservation,
createStoreReservation,
createStoreDish,
updateStoreDish,
saveStore,
unsaveStore,
Expand Down

0 comments on commit 01f210a

Please sign in to comment.