From a2cd4e1b561f43170469610ad4465ecd0217da5f Mon Sep 17 00:00:00 2001
From: DevMirza <53424436+Zaid-maker@users.noreply.github.com>
Date: Tue, 2 Jul 2024 17:09:17 +0000
Subject: [PATCH 1/7] empty
From 5b644251ffd45b47360c78b477f87dbafbe1f4d2 Mon Sep 17 00:00:00 2001
From: DevMirza <53424436+Zaid-maker@users.noreply.github.com>
Date: Tue, 2 Jul 2024 17:27:11 +0000
Subject: [PATCH 2/7] add creatEvent
---
app/(root)/events/create/page.tsx | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
create mode 100644 app/(root)/events/create/page.tsx
diff --git a/app/(root)/events/create/page.tsx b/app/(root)/events/create/page.tsx
new file mode 100644
index 0000000..a6a9482
--- /dev/null
+++ b/app/(root)/events/create/page.tsx
@@ -0,0 +1,25 @@
+import { auth } from "@clerk/nextjs";
+import React from "react";
+
+const CreateEvent = () => {
+ const { sessionClaims } = auth();
+
+ const userId = sessionClaims?.userId as string;
+
+ return (
+ <>
+
+
+
+ {/* */}
+ EventForm
+
+ >
+ );
+};
+
+export default CreateEvent;
From 7103d732eae11acd08c97d4858f0f932b38390a7 Mon Sep 17 00:00:00 2001
From: DevMirza <53424436+Zaid-maker@users.noreply.github.com>
Date: Tue, 2 Jul 2024 17:30:44 +0000
Subject: [PATCH 3/7] add EventForm component
---
app/(root)/events/create/page.tsx | 4 ++--
components/shared/EventForm.tsx | 17 +++++++++++++++++
2 files changed, 19 insertions(+), 2 deletions(-)
create mode 100644 components/shared/EventForm.tsx
diff --git a/app/(root)/events/create/page.tsx b/app/(root)/events/create/page.tsx
index a6a9482..688b327 100644
--- a/app/(root)/events/create/page.tsx
+++ b/app/(root)/events/create/page.tsx
@@ -1,3 +1,4 @@
+import EventForm from "@/components/shared/EventForm";
import { auth } from "@clerk/nextjs";
import React from "react";
@@ -15,8 +16,7 @@ const CreateEvent = () => {
- {/* */}
- EventForm
+
>
);
diff --git a/components/shared/EventForm.tsx b/components/shared/EventForm.tsx
new file mode 100644
index 0000000..68f4bd5
--- /dev/null
+++ b/components/shared/EventForm.tsx
@@ -0,0 +1,17 @@
+"use client";
+
+import { IEvent } from "@/lib/database/models/event.model";
+import React from "react";
+
+type EventFormProps = {
+ userId: string;
+ type: "Create" | "Update";
+ event?: IEvent;
+ eventId?: string;
+};
+
+const EventForm = ({}: EventFormProps) => {
+ return EventForm
;
+};
+
+export default EventForm;
From aaca12352cd1b3b85fd577837ad3a2df224c4268 Mon Sep 17 00:00:00 2001
From: DevMirza <53424436+Zaid-maker@users.noreply.github.com>
Date: Tue, 2 Jul 2024 17:40:28 +0000
Subject: [PATCH 4/7] UpdateEvent page
---
app/(root)/events/create/[id]/update/page.tsx | 37 +++++++++++++++++++
components/shared/EventForm.tsx | 4 +-
2 files changed, 39 insertions(+), 2 deletions(-)
create mode 100644 app/(root)/events/create/[id]/update/page.tsx
diff --git a/app/(root)/events/create/[id]/update/page.tsx b/app/(root)/events/create/[id]/update/page.tsx
new file mode 100644
index 0000000..a36d3de
--- /dev/null
+++ b/app/(root)/events/create/[id]/update/page.tsx
@@ -0,0 +1,37 @@
+import EventForm from "@/components/shared/EventForm";
+import { getEventById } from "@/lib/actions/event.actions";
+import { auth } from "@clerk/nextjs";
+
+type UpdateEventProps = {
+ params: {
+ id: string;
+ };
+};
+
+const UpdateEvent = async ({ params: { id } }: UpdateEventProps) => {
+ const { sessionClaims } = auth();
+
+ const userId = sessionClaims?.userId as string;
+ const event = await getEventById(id);
+
+ return (
+ <>
+
+
+
+
+
+ >
+ );
+};
+
+export default UpdateEvent;
diff --git a/components/shared/EventForm.tsx b/components/shared/EventForm.tsx
index 68f4bd5..455e419 100644
--- a/components/shared/EventForm.tsx
+++ b/components/shared/EventForm.tsx
@@ -10,8 +10,8 @@ type EventFormProps = {
eventId?: string;
};
-const EventForm = ({}: EventFormProps) => {
- return EventForm
;
+const EventForm = ({ type }: EventFormProps) => {
+ return EventForm {type}
;
};
export default EventForm;
From 868e09f96ea79e0aed5d1e81a1cf427042fc66b4 Mon Sep 17 00:00:00 2001
From: DevMirza <53424436+Zaid-maker@users.noreply.github.com>
Date: Tue, 2 Jul 2024 17:44:49 +0000
Subject: [PATCH 5/7] fix
---
app/(root)/events/[id]/page.tsx | 7 +++++++
app/(root)/events/{create => }/[id]/update/page.tsx | 0
2 files changed, 7 insertions(+)
create mode 100644 app/(root)/events/[id]/page.tsx
rename app/(root)/events/{create => }/[id]/update/page.tsx (100%)
diff --git a/app/(root)/events/[id]/page.tsx b/app/(root)/events/[id]/page.tsx
new file mode 100644
index 0000000..012915b
--- /dev/null
+++ b/app/(root)/events/[id]/page.tsx
@@ -0,0 +1,7 @@
+import React from "react";
+
+const EventDetails = () => {
+ return EventDetails
;
+};
+
+export default EventDetails;
diff --git a/app/(root)/events/create/[id]/update/page.tsx b/app/(root)/events/[id]/update/page.tsx
similarity index 100%
rename from app/(root)/events/create/[id]/update/page.tsx
rename to app/(root)/events/[id]/update/page.tsx
From ec3ec66d040a532d7986ca98c5edf0ab232411eb Mon Sep 17 00:00:00 2001
From: DevMirza <53424436+Zaid-maker@users.noreply.github.com>
Date: Wed, 3 Jul 2024 09:17:48 +0000
Subject: [PATCH 6/7] add form component
---
components/ui/form.tsx | 177 ++++++++++++++++++++++++++++++++++++++++
components/ui/label.tsx | 26 ++++++
package-lock.json | 59 +++++++++++++-
package.json | 6 +-
4 files changed, 266 insertions(+), 2 deletions(-)
create mode 100644 components/ui/form.tsx
create mode 100644 components/ui/label.tsx
diff --git a/components/ui/form.tsx b/components/ui/form.tsx
new file mode 100644
index 0000000..497718a
--- /dev/null
+++ b/components/ui/form.tsx
@@ -0,0 +1,177 @@
+import * as React from "react";
+import * as LabelPrimitive from "@radix-ui/react-label";
+import { Slot } from "@radix-ui/react-slot";
+import {
+ Controller,
+ ControllerProps,
+ FieldPath,
+ FieldValues,
+ FormProvider,
+ useFormContext,
+} from "react-hook-form";
+
+import { cn } from "@/lib/utils";
+import { Label } from "@/components/ui/label";
+
+const Form = FormProvider;
+
+type FormFieldContextValue<
+ TFieldValues extends FieldValues = FieldValues,
+ TName extends FieldPath = FieldPath,
+> = {
+ name: TName;
+};
+
+const FormFieldContext = React.createContext(
+ {} as FormFieldContextValue,
+);
+
+const FormField = <
+ TFieldValues extends FieldValues = FieldValues,
+ TName extends FieldPath = FieldPath,
+>({
+ ...props
+}: ControllerProps) => {
+ return (
+
+
+
+ );
+};
+
+const useFormField = () => {
+ const fieldContext = React.useContext(FormFieldContext);
+ const itemContext = React.useContext(FormItemContext);
+ const { getFieldState, formState } = useFormContext();
+
+ const fieldState = getFieldState(fieldContext.name, formState);
+
+ if (!fieldContext) {
+ throw new Error("useFormField should be used within ");
+ }
+
+ const { id } = itemContext;
+
+ return {
+ id,
+ name: fieldContext.name,
+ formItemId: `${id}-form-item`,
+ formDescriptionId: `${id}-form-item-description`,
+ formMessageId: `${id}-form-item-message`,
+ ...fieldState,
+ };
+};
+
+type FormItemContextValue = {
+ id: string;
+};
+
+const FormItemContext = React.createContext(
+ {} as FormItemContextValue,
+);
+
+const FormItem = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => {
+ const id = React.useId();
+
+ return (
+
+
+
+ );
+});
+FormItem.displayName = "FormItem";
+
+const FormLabel = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => {
+ const { error, formItemId } = useFormField();
+
+ return (
+
+ );
+});
+FormLabel.displayName = "FormLabel";
+
+const FormControl = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ ...props }, ref) => {
+ const { error, formItemId, formDescriptionId, formMessageId } =
+ useFormField();
+
+ return (
+
+ );
+});
+FormControl.displayName = "FormControl";
+
+const FormDescription = React.forwardRef<
+ HTMLParagraphElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => {
+ const { formDescriptionId } = useFormField();
+
+ return (
+
+ );
+});
+FormDescription.displayName = "FormDescription";
+
+const FormMessage = React.forwardRef<
+ HTMLParagraphElement,
+ React.HTMLAttributes
+>(({ className, children, ...props }, ref) => {
+ const { error, formMessageId } = useFormField();
+ const body = error ? String(error?.message) : children;
+
+ if (!body) {
+ return null;
+ }
+
+ return (
+
+ {body}
+
+ );
+});
+FormMessage.displayName = "FormMessage";
+
+export {
+ useFormField,
+ Form,
+ FormItem,
+ FormLabel,
+ FormControl,
+ FormDescription,
+ FormMessage,
+ FormField,
+};
diff --git a/components/ui/label.tsx b/components/ui/label.tsx
new file mode 100644
index 0000000..84f8b0c
--- /dev/null
+++ b/components/ui/label.tsx
@@ -0,0 +1,26 @@
+"use client";
+
+import * as React from "react";
+import * as LabelPrimitive from "@radix-ui/react-label";
+import { cva, type VariantProps } from "class-variance-authority";
+
+import { cn } from "@/lib/utils";
+
+const labelVariants = cva(
+ "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
+);
+
+const Label = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef &
+ VariantProps
+>(({ className, ...props }, ref) => (
+
+));
+Label.displayName = LabelPrimitive.Root.displayName;
+
+export { Label };
diff --git a/package-lock.json b/package-lock.json
index 235011e..0cc6c85 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9,7 +9,9 @@
"version": "0.1.0",
"dependencies": {
"@clerk/nextjs": "^4.27.5",
+ "@hookform/resolvers": "^3.7.0",
"@radix-ui/react-dialog": "^1.1.1",
+ "@radix-ui/react-label": "^2.1.0",
"@radix-ui/react-select": "^2.1.1",
"@radix-ui/react-separator": "^1.1.0",
"@radix-ui/react-slot": "^1.1.0",
@@ -23,11 +25,13 @@
"query-string": "^9.0.0",
"react": "^18",
"react-dom": "^18",
+ "react-hook-form": "^7.52.1",
"stripe": "^14.8.0",
"svix": "^1.24.0",
"tailwind-merge": "^2.3.0",
"tailwindcss-animate": "^1.0.7",
- "uploadthing": "^6.13.2"
+ "uploadthing": "^6.13.2",
+ "zod": "^3.23.8"
},
"devDependencies": {
"@types/node": "^20",
@@ -310,6 +314,14 @@
"resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.4.tgz",
"integrity": "sha512-dWO2pw8hhi+WrXq1YJy2yCuWoL20PddgGaqTgVe4cOS9Q6qklXCiA1tJEqX6BEwRNSCP84/afac9hd4MS+zEUA=="
},
+ "node_modules/@hookform/resolvers": {
+ "version": "3.7.0",
+ "resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-3.7.0.tgz",
+ "integrity": "sha512-42p5X18noBV3xqOpTlf2V5qJZwzNgO4eLzHzmKGh/w7z4+4XqRw5AsESVkqE+qwAuRRlg2QG12EVEjPkrRIbeg==",
+ "peerDependencies": {
+ "react-hook-form": "^7.0.0"
+ }
+ },
"node_modules/@humanwhocodes/config-array": {
"version": "0.11.14",
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz",
@@ -878,6 +890,28 @@
}
}
},
+ "node_modules/@radix-ui/react-label": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.0.tgz",
+ "integrity": "sha512-peLblDlFw/ngk3UWq0VnYaOLy6agTZZ+MUO/WhVfm14vJGML+xH4FAl2XQGLqdefjNb7ApRg6Yn7U42ZhmYXdw==",
+ "dependencies": {
+ "@radix-ui/react-primitive": "2.0.0"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
"node_modules/@radix-ui/react-popper": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.0.tgz",
@@ -5213,6 +5247,21 @@
"react": "^18.3.1"
}
},
+ "node_modules/react-hook-form": {
+ "version": "7.52.1",
+ "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.52.1.tgz",
+ "integrity": "sha512-uNKIhaoICJ5KQALYZ4TOaOLElyM+xipord+Ha3crEFhTntdLvWZqVY49Wqd/0GiVCA/f9NjemLeiNPjG7Hpurg==",
+ "engines": {
+ "node": ">=12.22.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/react-hook-form"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17 || ^18 || ^19"
+ }
+ },
"node_modules/react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
@@ -6654,6 +6703,14 @@
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
+ },
+ "node_modules/zod": {
+ "version": "3.23.8",
+ "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz",
+ "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==",
+ "funding": {
+ "url": "https://github.com/sponsors/colinhacks"
+ }
}
}
}
diff --git a/package.json b/package.json
index 914385e..15f8c72 100644
--- a/package.json
+++ b/package.json
@@ -10,7 +10,9 @@
},
"dependencies": {
"@clerk/nextjs": "^4.27.5",
+ "@hookform/resolvers": "^3.7.0",
"@radix-ui/react-dialog": "^1.1.1",
+ "@radix-ui/react-label": "^2.1.0",
"@radix-ui/react-select": "^2.1.1",
"@radix-ui/react-separator": "^1.1.0",
"@radix-ui/react-slot": "^1.1.0",
@@ -24,11 +26,13 @@
"query-string": "^9.0.0",
"react": "^18",
"react-dom": "^18",
+ "react-hook-form": "^7.52.1",
"stripe": "^14.8.0",
"svix": "^1.24.0",
"tailwind-merge": "^2.3.0",
"tailwindcss-animate": "^1.0.7",
- "uploadthing": "^6.13.2"
+ "uploadthing": "^6.13.2",
+ "zod": "^3.23.8"
},
"devDependencies": {
"@types/node": "^20",
From d8ba205795fb12b88fb61790dc982adb0609c377 Mon Sep 17 00:00:00 2001
From: DevMirza <53424436+Zaid-maker@users.noreply.github.com>
Date: Wed, 3 Jul 2024 09:22:03 +0000
Subject: [PATCH 7/7] backbone of setting up FOrm
---
components/shared/EventForm.tsx | 61 ++++++++++++++++++++++++++++++++-
1 file changed, 60 insertions(+), 1 deletion(-)
diff --git a/components/shared/EventForm.tsx b/components/shared/EventForm.tsx
index 455e419..fe5db33 100644
--- a/components/shared/EventForm.tsx
+++ b/components/shared/EventForm.tsx
@@ -1,5 +1,27 @@
"use client";
+import { zodResolver } from "@hookform/resolvers/zod";
+import { useForm } from "react-hook-form";
+import { z } from "zod";
+
+import { Button } from "@/components/ui/button";
+import {
+ Form,
+ FormControl,
+ FormDescription,
+ FormField,
+ FormItem,
+ FormLabel,
+ FormMessage,
+} from "@/components/ui/form";
+import { Input } from "@/components/ui/input";
+
+const formSchema = z.object({
+ username: z.string().min(2, {
+ message: "Username must be at least 2 characters.",
+ }),
+});
+
import { IEvent } from "@/lib/database/models/event.model";
import React from "react";
@@ -11,7 +33,44 @@ type EventFormProps = {
};
const EventForm = ({ type }: EventFormProps) => {
- return EventForm {type}
;
+ // 1. Define your form.
+ const form = useForm>({
+ resolver: zodResolver(formSchema),
+ defaultValues: {
+ username: "",
+ },
+ });
+
+ // 2. Define a submit handler.
+ function onSubmit(values: z.infer) {
+ // Do something with the form values.
+ // ✅ This will be type-safe and validated.
+ console.log(values);
+ }
+
+ return (
+
+
+ );
};
export default EventForm;