From 01ace1b5964fba30fded253fe61c05d5bb27ae93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Gonz=C3=A1lez=20Mu=C3=B1oz?= Date: Wed, 15 Nov 2023 18:11:41 +0100 Subject: [PATCH 1/5] contact page: contact form --- frontend/.env.default | 2 + frontend/package.json | 5 +- frontend/src/components/.gitkeep | 0 frontend/src/components/footer.tsx | 2 +- frontend/src/components/header.tsx | 2 +- frontend/src/components/ui/form.tsx | 169 + frontend/src/components/ui/input.tsx | 2 +- frontend/src/components/ui/textarea.tsx | 23 + .../src/containers/contact-us/form/index.tsx | 180 + frontend/src/pages/api/contact-us.ts | 38 + frontend/src/pages/contact-us.tsx | 23 + frontend/src/pages/knowledge-hub/index.tsx | 2 +- .../src/types/generated/strapi.schemas.ts | 2916 ++++++++--------- frontend/yarn.lock | 60 +- 14 files changed, 1958 insertions(+), 1466 deletions(-) delete mode 100644 frontend/src/components/.gitkeep create mode 100644 frontend/src/components/ui/form.tsx create mode 100644 frontend/src/components/ui/textarea.tsx create mode 100644 frontend/src/containers/contact-us/form/index.tsx create mode 100644 frontend/src/pages/api/contact-us.ts create mode 100644 frontend/src/pages/contact-us.tsx diff --git a/frontend/.env.default b/frontend/.env.default index 4adb6dea..2bec459d 100644 --- a/frontend/.env.default +++ b/frontend/.env.default @@ -1,2 +1,4 @@ NEXT_PUBLIC_API_URL=http://0.0.0.0:1337/api NEXT_PUBLIC_MAPBOX_API_TOKEN= +SENDGRID_API_KEY= +SENDGRID_CONTACT_LIST_ID= diff --git a/frontend/package.json b/frontend/package.json index ac3e1126..fd6b88d2 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -19,6 +19,7 @@ "@deck.gl/json": "8.9.31", "@deck.gl/layers": "8.9.31", "@deck.gl/mapbox": "8.9.31", + "@hookform/resolvers": "3.3.2", "@loaders.gl/core": "^3.4.14", "@loaders.gl/kml": "^3.4.14", "@loaders.gl/loader-utils": "^3.4.14", @@ -36,6 +37,7 @@ "@radix-ui/react-switch": "^1.0.3", "@radix-ui/react-tabs": "^1.0.4", "@radix-ui/react-tooltip": "^1.0.6", + "@sendgrid/client": "7.7.0", "@tailwindcss/forms": "0.5.3", "@tailwindcss/line-clamp": "0.4.4", "@tailwindcss/typography": "0.5.9", @@ -67,7 +69,8 @@ "rooks": "7.14.1", "tailwind-merge": "^1.14.0", "tailwindcss": "3.2.7", - "tailwindcss-animate": "^1.0.7" + "tailwindcss-animate": "1.0.7", + "zod": "3.22.4" }, "devDependencies": { "@types/google.analytics": "0.0.42", diff --git a/frontend/src/components/.gitkeep b/frontend/src/components/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/frontend/src/components/footer.tsx b/frontend/src/components/footer.tsx index 3cfbe943..03e56602 100644 --- a/frontend/src/components/footer.tsx +++ b/frontend/src/components/footer.tsx @@ -2,7 +2,7 @@ import Link from 'next/link'; const navigation = [ { name: 'About', href: '/about' }, - { name: 'Contact', href: '/contact' }, + { name: 'Contact', href: '/contact-us' }, { name: 'Privacy Policy', href: '/privacy-policy' }, ]; diff --git a/frontend/src/components/header.tsx b/frontend/src/components/header.tsx index b24b73d9..843cfe3d 100644 --- a/frontend/src/components/header.tsx +++ b/frontend/src/components/header.tsx @@ -22,7 +22,7 @@ const navigation = [ // { name: 'Dashboard', href: '/dashboard', colorClassName: 'text-blue fill-blue' }, { name: 'Knowledge Hub', href: '/knowledge-hub', colorClassName: 'text-green fill-green' }, { name: 'About', href: '/about', colorClassName: 'text-black fill-black' }, - { name: 'Contact', href: '/contact', colorClassName: 'text-black fill-black' }, + { name: 'Contact', href: '/contact-us', colorClassName: 'text-black fill-black' }, ]; const Header: React.FC = () => ( diff --git a/frontend/src/components/ui/form.tsx b/frontend/src/components/ui/form.tsx new file mode 100644 index 00000000..bb1de689 --- /dev/null +++ b/frontend/src/components/ui/form.tsx @@ -0,0 +1,169 @@ +import * as React from 'react'; + +import { + Controller, + ControllerProps, + FieldPath, + FieldValues, + FormProvider, + useFormContext, +} from 'react-hook-form'; + +import * as LabelPrimitive from '@radix-ui/react-label'; +import { Slot } from '@radix-ui/react-slot'; + +import { Label } from '@/components/ui/label'; +import { cn } from '@/lib/classnames'; + +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>( + ({ className, ...props }, ref) => { + const id = React.useId(); + + return ( + +
+ + ); + } +); +FormItem.displayName = 'FormItem'; + +const FormLabel = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => { + const { formItemId } = useFormField(); + + return ( +