From 687e8ee6868968d0b3609b50d747786f023a80c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cyril=20=C5=A0ebek?= Date: Sat, 8 Jun 2024 14:42:05 +0200 Subject: [PATCH] Added contact form (not working yet) TODO: backend for the contact form --- package.json | 7 +- pnpm-lock.yaml | 67 +++++++++++-- src/components/ContactForm.tsx | 145 ++++++++++++++++++++++++++++ src/components/Hero.astro | 14 ++- src/components/NavButton.jsx | 2 +- src/components/SinglePostCard.astro | 4 +- src/components/ui/button.jsx | 2 +- src/components/ui/dialog.jsx | 94 ++++++++++++++++++ src/components/ui/form.jsx | 133 +++++++++++++++++++++++++ src/components/ui/input.jsx | 19 ++++ src/components/ui/label.jsx | 16 +++ src/components/ui/textarea.jsx | 18 ++++ src/i18n/en.js | 22 +++++ 13 files changed, 524 insertions(+), 19 deletions(-) create mode 100644 src/components/ContactForm.tsx create mode 100644 src/components/ui/dialog.jsx create mode 100644 src/components/ui/form.jsx create mode 100644 src/components/ui/input.jsx create mode 100644 src/components/ui/label.jsx create mode 100644 src/components/ui/textarea.jsx diff --git a/package.json b/package.json index 671e9e6..72e65ea 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,10 @@ "@astrojs/rss": "^4.0.5", "@astrojs/sitemap": "^3.1.1", "@astrojs/tailwind": "^5.1.0", + "@hookform/resolvers": "^3.6.0", + "@radix-ui/react-dialog": "^1.0.5", "@radix-ui/react-dropdown-menu": "^2.0.6", + "@radix-ui/react-label": "^2.0.2", "@radix-ui/react-slot": "^1.0.2", "@radix-ui/react-tabs": "^1.0.4", "@types/react": "^18.2.74", @@ -29,12 +32,14 @@ "lucide-react": "^0.365.0", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-hook-form": "^7.51.5", "rehype-pretty-code": "^0.13.2", "rehype-slug": "^6.0.0", "tailwind-merge": "^2.2.2", "tailwindcss": "^3.4.1", "tailwindcss-animate": "^1.0.7", - "vaul": "^0.9.0" + "vaul": "^0.9.0", + "zod": "^3.23.8" }, "devDependencies": { "@tailwindcss/typography": "^0.5.13" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index be797b3..654a63d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -19,9 +19,18 @@ dependencies: '@astrojs/tailwind': specifier: ^5.1.0 version: 5.1.0(astro@4.5.6)(tailwindcss@3.4.1) + '@hookform/resolvers': + specifier: ^3.6.0 + version: 3.6.0(react-hook-form@7.51.5) + '@radix-ui/react-dialog': + specifier: ^1.0.5 + version: 1.0.5(@types/react-dom@18.2.24)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) '@radix-ui/react-dropdown-menu': specifier: ^2.0.6 version: 2.0.6(@types/react-dom@18.2.24)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-label': + specifier: ^2.0.2 + version: 2.0.2(@types/react-dom@18.2.24)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) '@radix-ui/react-slot': specifier: ^1.0.2 version: 1.0.2(@types/react@18.2.74)(react@18.2.0) @@ -58,6 +67,9 @@ dependencies: react-dom: specifier: ^18.2.0 version: 18.2.0(react@18.2.0) + react-hook-form: + specifier: ^7.51.5 + version: 7.51.5(react@18.2.0) rehype-pretty-code: specifier: ^0.13.2 version: 0.13.2(shiki@1.6.1) @@ -76,6 +88,9 @@ dependencies: vaul: specifier: ^0.9.0 version: 0.9.0(@types/react-dom@18.2.24)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) + zod: + specifier: ^3.23.8 + version: 3.23.8 devDependencies: '@tailwindcss/typography': @@ -230,7 +245,7 @@ packages: resolution: {integrity: sha512-qPgdBIcDUaea98mTtLfi5z9oXZpzSjEn/kes70/Ex8FOZZ+DIHVKRYOLOtvy8p+FTXr/9oc7BjmIbTYmYLLJVg==} dependencies: sitemap: 7.1.1 - zod: 3.22.4 + zod: 3.23.8 dev: false /@astrojs/tailwind@5.1.0(astro@4.5.6)(tailwindcss@3.4.1): @@ -753,6 +768,14 @@ packages: resolution: {integrity: sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q==} dev: false + /@hookform/resolvers@3.6.0(react-hook-form@7.51.5): + resolution: {integrity: sha512-UBcpyOX3+RR+dNnqBd0lchXpoL8p4xC21XP8H6Meb8uve5Br1GCnmg0PcBoKKqPKgGu9GHQ/oygcmPrQhetwqw==} + peerDependencies: + react-hook-form: ^7.0.0 + dependencies: + react-hook-form: 7.51.5(react@18.2.0) + dev: false + /@isaacs/cliui@8.0.2: resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} @@ -1074,6 +1097,27 @@ packages: react: 18.2.0 dev: false + /@radix-ui/react-label@2.0.2(@types/react-dom@18.2.24)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-N5ehvlM7qoTLx7nWPodsPYPgMzA5WM8zZChQg8nyFJKnDO5WHdba1vv5/H6IO5LtJMfD2Q3wh1qHFGNtK0w3bQ==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.24.4 + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.24)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0) + '@types/react': 18.2.74 + '@types/react-dom': 18.2.24 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /@radix-ui/react-menu@2.0.6(@types/react-dom@18.2.24)(@types/react@18.2.74)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-BVkFLS+bUC8HcImkRKPSiVumA1VPOOEC5WBMiT+QAVsPzW1FJzI9KnqgGxVDPBcql5xXrHkD3JOVoXWEXD8SYA==} peerDependencies: @@ -1783,8 +1827,8 @@ packages: vitefu: 0.2.5(vite@5.1.6) which-pm: 2.1.1 yargs-parser: 21.1.1 - zod: 3.22.4 - zod-to-json-schema: 3.22.4(zod@3.22.4) + zod: 3.23.8 + zod-to-json-schema: 3.22.4(zod@3.23.8) optionalDependencies: sharp: 0.32.6 transitivePeerDependencies: @@ -4178,6 +4222,15 @@ packages: scheduler: 0.23.0 dev: false + /react-hook-form@7.51.5(react@18.2.0): + resolution: {integrity: sha512-J2ILT5gWx1XUIJRETiA7M19iXHlG74+6O3KApzvqB/w8S5NQR7AbU8HVZrMALdmDgWpRPYiZJl0zx8Z4L2mP6Q==} + engines: {node: '>=12.22.0'} + peerDependencies: + react: ^16.8.0 || ^17 || ^18 + dependencies: + react: 18.2.0 + dev: false + /react-refresh@0.14.0: resolution: {integrity: sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==} engines: {node: '>=0.10.0'} @@ -5292,16 +5345,16 @@ packages: engines: {node: '>=12.20'} dev: false - /zod-to-json-schema@3.22.4(zod@3.22.4): + /zod-to-json-schema@3.22.4(zod@3.23.8): resolution: {integrity: sha512-2Ed5dJ+n/O3cU383xSY28cuVi0BCQhF8nYqWU5paEpl7fVdqdAmiLdqLyfblbNdfOFwFfi/mqU4O1pwc60iBhQ==} peerDependencies: zod: ^3.22.4 dependencies: - zod: 3.22.4 + zod: 3.23.8 dev: false - /zod@3.22.4: - resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==} + /zod@3.23.8: + resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==} dev: false /zwitch@2.0.4: diff --git a/src/components/ContactForm.tsx b/src/components/ContactForm.tsx new file mode 100644 index 0000000..62ae8d1 --- /dev/null +++ b/src/components/ContactForm.tsx @@ -0,0 +1,145 @@ +"use client"; + +import { useTranslations } from "../i18n/utils"; +import { Button } from "./ui/button"; +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, + DialogTrigger, +} from "./ui/dialog"; +import { + Form, + FormControl, + FormDescription, + FormField, + FormItem, + FormLabel, + FormMessage, +} from "./ui/form"; +import { Input } from "./ui/input"; +import { z } from "astro/zod"; +import { zodResolver } from "@hookform/resolvers/zod"; +import { useForm } from "react-hook-form"; +import { Textarea } from "./ui/textarea" + + +const formSchema = z.object({ + username: z.string().min(2), + email: z.string().email(), + message: z.string(), +}); + +export function ContactForm({ currentLocale }) { + const t = useTranslations(currentLocale); + + const form = useForm>({ + resolver: zodResolver(formSchema), + defaultValues: { + username: "", + email: "", + message: "", + /*datetime: "2020-01-01T00:00:00Z",*/ + }, + }); + + function onSubmit(values: z.infer) { + // Do something with the form values. + // ✅ This will be type-safe and validated. + console.log(values); + } + + return ( + + + + + + +

{t("contact").title}

+ {t("contact").description} +
+ +
+ + ( + + {t("contact").name} + + + + + {t("contact").nameDescription} + + + + )} + /> + + ( + + {t("contact").email} + + + + + {t("contact").emailDescription} + + + + )} + /> + + ( + + {t("contact").message} + +