diff --git a/env b/env index 8bf5180..f8d6860 100644 --- a/env +++ b/env @@ -13,3 +13,4 @@ S3_ACCESS_KEY_ID=97394cd503ae9973efa25168ed980e51 S3_SECRET_ACCESS_KEY=9b4e412850582aab32ffdadbe23bb7ea972b39aaf79c34da0c19d3fcafe11dd0 S3_REGION=ap-southeast-1 S3_ENDPOINT=https://jswmbraeandqttpcdfmj.supabase.co/storage/v1/s3 +NEXT_PUBLIC_PAYLOAD_URL=http://localhost:3000 diff --git a/package-lock.json b/package-lock.json index 29daaa1..b876761 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "@payloadcms/db-postgres": "^3.20.0", "@payloadcms/next": "^3.20.0", "@payloadcms/payload-cloud": "^3.20.0", + "@payloadcms/plugin-form-builder": "^3.20.0", "@payloadcms/richtext-lexical": "^3.20.0", "@payloadcms/storage-s3": "^3.20.0", "@popperjs/core": "2.11.8", @@ -25,6 +26,7 @@ "photoswipe": "^5.4.4", "react": "^19.0.0", "react-dom": "^19.0.0", + "react-hook-form": "^7.54.2", "react-modal-video": "^2.0.2", "react-photoswipe-gallery": "^3.0.1", "rellax": "^1.12.1", @@ -3369,6 +3371,21 @@ "payload": "3.20.0" } }, + "node_modules/@payloadcms/plugin-form-builder": { + "version": "3.20.0", + "resolved": "https://registry.npmjs.org/@payloadcms/plugin-form-builder/-/plugin-form-builder-3.20.0.tgz", + "integrity": "sha512-te29bejvFeH2xw4HtE9JA5DDZycKPuLZOPTGnoShwj+DeqZn5k3SfzewLam1fxPqxHHJhNzTO273lkPsCSxlPg==", + "license": "MIT", + "dependencies": { + "@payloadcms/ui": "3.20.0", + "escape-html": "^1.0.3" + }, + "peerDependencies": { + "payload": "3.20.0", + "react": "^19.0.0 || ^19.0.0-rc-65a56d0e-20241020", + "react-dom": "^19.0.0 || ^19.0.0-rc-65a56d0e-20241020" + } + }, "node_modules/@payloadcms/richtext-lexical": { "version": "3.20.0", "resolved": "https://registry.npmjs.org/@payloadcms/richtext-lexical/-/richtext-lexical-3.20.0.tgz", @@ -10532,6 +10549,22 @@ "react": ">=16.13.1" } }, + "node_modules/react-hook-form": { + "version": "7.54.2", + "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.54.2.tgz", + "integrity": "sha512-eHpAUgUjWbZocoQYUHposymRb4ZP6d0uwUnooL2uOybA9/3tPUvoAKqEWK1WaSiTxxOfTpffNZP7QwlnM3/gEg==", + "license": "MIT", + "engines": { + "node": ">=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/react-hook-form" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17 || ^18 || ^19" + } + }, "node_modules/react-image-crop": { "version": "10.1.8", "resolved": "https://registry.npmjs.org/react-image-crop/-/react-image-crop-10.1.8.tgz", diff --git a/package.json b/package.json index 5da2985..7d973bc 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "@payloadcms/db-postgres": "^3.20.0", "@payloadcms/next": "^3.20.0", "@payloadcms/payload-cloud": "^3.20.0", + "@payloadcms/plugin-form-builder": "^3.20.0", "@payloadcms/richtext-lexical": "^3.20.0", "@payloadcms/storage-s3": "^3.20.0", "@popperjs/core": "2.11.8", @@ -30,6 +31,7 @@ "photoswipe": "^5.4.4", "react": "^19.0.0", "react-dom": "^19.0.0", + "react-hook-form": "^7.54.2", "react-modal-video": "^2.0.2", "react-photoswipe-gallery": "^3.0.1", "rellax": "^1.12.1", diff --git a/public/assets/css/style.css b/public/assets/css/style.css index 1a190d5..3902096 100644 --- a/public/assets/css/style.css +++ b/public/assets/css/style.css @@ -2494,9 +2494,9 @@ textarea:-webkit-autofill:focus { color: var(--color-dark-mode-gray-1) !important; } -.form-control { +/* .form-control { border-radius: 0; -} +} */ /* * Input underline diff --git a/src/app/(main)/contact/page.tsx b/src/app/(main)/contact/page.tsx index 0d2de48..12c61f8 100644 --- a/src/app/(main)/contact/page.tsx +++ b/src/app/(main)/contact/page.tsx @@ -1,4 +1,5 @@ import Contact from "@/components/Contacts/Contact"; +import { fetchForm } from "@/services/payload/form"; import Image from "next/image"; export const metadata = { @@ -6,7 +7,9 @@ export const metadata = { description: "Contact - Cochise Oncology", }; -export default function SlickContactPageDark() { +export default async function SlickContactPageDark() { + const formRes = await fetchForm(1); + return ( <>
- +
); diff --git a/src/app/(main)/layout.tsx b/src/app/(main)/layout.tsx index 2f3a5da..29b9325 100644 --- a/src/app/(main)/layout.tsx +++ b/src/app/(main)/layout.tsx @@ -4,13 +4,13 @@ import { useEffect } from "react"; import { init_wow } from "@/utils/initWow"; import { parallaxMouseMovement, parallaxScroll } from "@/utils/parallax"; import { headerChangeOnScroll } from "@/utils/changeHeaderOnScroll"; +import "@/app/globals.css"; import "swiper/css"; import "jarallax/dist/jarallax.min.css"; import "swiper/css/effect-fade"; import "react-modal-video/css/modal-video.css"; import "photoswipe/dist/photoswipe.css"; import "tippy.js/dist/tippy.css"; - import "@public/assets/css/styles.css"; import Image from "next/image"; import Header from "@/components/Header"; diff --git a/src/app/(payload)/admin/importMap.js b/src/app/(payload)/admin/importMap.js index 79944a8..2172f9e 100644 --- a/src/app/(payload)/admin/importMap.js +++ b/src/app/(payload)/admin/importMap.js @@ -20,6 +20,7 @@ import { StrikethroughFeatureClient as StrikethroughFeatureClient_e70f5e05f09f93 import { UnderlineFeatureClient as UnderlineFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client' import { BoldFeatureClient as BoldFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client' import { ItalicFeatureClient as ItalicFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client' +import { FixedToolbarFeatureClient as FixedToolbarFeatureClient_e70f5e05f09f93e00b997edb1ef0c864 } from '@payloadcms/richtext-lexical/client' import { default as default_382980007b1adf7b8e8832707f1169fb } from '@/components/Logo/AdminLogo' export const importMap = { @@ -45,5 +46,6 @@ export const importMap = { "@payloadcms/richtext-lexical/client#UnderlineFeatureClient": UnderlineFeatureClient_e70f5e05f09f93e00b997edb1ef0c864, "@payloadcms/richtext-lexical/client#BoldFeatureClient": BoldFeatureClient_e70f5e05f09f93e00b997edb1ef0c864, "@payloadcms/richtext-lexical/client#ItalicFeatureClient": ItalicFeatureClient_e70f5e05f09f93e00b997edb1ef0c864, + "@payloadcms/richtext-lexical/client#FixedToolbarFeatureClient": FixedToolbarFeatureClient_e70f5e05f09f93e00b997edb1ef0c864, "/components/Logo/AdminLogo#default": default_382980007b1adf7b8e8832707f1169fb } diff --git a/src/blocks/Form.ts b/src/blocks/Form.ts new file mode 100644 index 0000000..dc687b6 --- /dev/null +++ b/src/blocks/Form.ts @@ -0,0 +1,33 @@ +import type { Block } from "payload"; + +export const FormBlock: Block = { + slug: "formBlock", + fields: [ + { + name: "form", + type: "relationship", + relationTo: "forms", + required: true, + }, + { + name: "enableIntro", + type: "checkbox", + label: "Enable Intro Content", + }, + { + name: "introContent", + type: "richText", + admin: { + condition: (_, { enableIntro }) => Boolean(enableIntro), + }, + label: "Intro Content", + }, + ], + graphQL: { + singularName: "FormBlock", + }, + labels: { + plural: "Form Blocks", + singular: "Form Block", + }, +}; diff --git a/src/components/Blocks/Form/Button/index.tsx b/src/components/Blocks/Form/Button/index.tsx new file mode 100644 index 0000000..5fe2734 --- /dev/null +++ b/src/components/Blocks/Form/Button/index.tsx @@ -0,0 +1,54 @@ +import type { ElementType } from "react"; + +import Link from "next/link"; +import React from "react"; + +export type Props = { + appearance?: "default" | "primary" | "secondary"; + className?: string; + el?: "a" | "button" | "link"; + form?: string; + href?: string; + label?: string; + newTab?: boolean | null; + onClick?: () => void; +}; + +export const Button: React.FC = ({ + className: classNameFromProps, + el = "button", + form, + href, + label, + newTab, +}) => { + const newTabProps = newTab ? { rel: "noopener noreferrer", target: "_blank" } : {}; + const Element: ElementType = el; + const className = [classNameFromProps].filter(Boolean).join(" "); + + const elementProps = { + ...newTabProps, + className, + form, + href, + }; + + const content = ( +
+ {label} +
+ ); + + return ( + + + {(el === "link" || el === "a") && ( + + {content} + + )} + {el === "button" && content} + + + ); +}; diff --git a/src/components/Blocks/Form/Checkbox/index.tsx b/src/components/Blocks/Form/Checkbox/index.tsx new file mode 100644 index 0000000..91a6e7d --- /dev/null +++ b/src/components/Blocks/Form/Checkbox/index.tsx @@ -0,0 +1,38 @@ +import type { CheckboxField } from "@payloadcms/plugin-form-builder/types"; +import type { FieldErrorsImpl, FieldValues, UseFormRegister } from "react-hook-form"; + +import React from "react"; + +import { Error } from "../Error"; +import { Width } from "../Width"; + +export const Checkbox: React.FC< + { + errors: Partial< + FieldErrorsImpl<{ + [x: string]: any; + }> + >; + getValues: any; + register: UseFormRegister; + setValue: any; + } & CheckboxField +> = ({ name, errors, label, register, required: requiredFromProps, width }) => { + return ( + +
+
+ + +
+ {requiredFromProps && errors[name] && } +
+
+ ); +}; diff --git a/src/components/Blocks/Form/Country/index.module.scss b/src/components/Blocks/Form/Country/index.module.scss new file mode 100644 index 0000000..1f5f6ac --- /dev/null +++ b/src/components/Blocks/Form/Country/index.module.scss @@ -0,0 +1,123 @@ +@use '../shared.scss'; + +.select { + position: relative; + margin-bottom: var(--base); +} + +.label { + margin-bottom: 10px; + display: block; +} + +.reactSelect { + display: flex; + + :global { + div.rs__control { + @include shared.formInput; + height: auto; + } + + .rs__input-container { + color: var(--color-black); + } + + .rs__value-container { + padding: 0; + > * { + margin-top: 0; + margin-bottom: 0; + padding-top: 0; + padding-bottom: 0; + } + } + + .rs__single-value { + color: var(--color-black); + } + + .rs__indicators { + position: absolute; + top: calc(var(--base) * 0.9); + right: calc(var(--base) * 0.9); + .arrow { + transform: rotate(90deg); + } + } + + .rs__indicator { + padding: 0px 4px; + cursor: pointer; + + svg path { + fill: var(--color-dark-gray); + } + + &:hover { + svg path { + fill: var(--color-dark-gray); + } + } + } + + .rs__indicator-separator { + display: none; + } + + .rs__menu { + color: var(--color-black); + background-color: var(--color-white); + z-index: 2; + border-radius: 0; + box-shadow: 0 4px 11px hsl(0deg 0% 0% / 10%); + } + + .rs__menu-list { + padding: calc(var(--base) / 4) 0; + } + + .rs__group-heading { + margin-bottom: calc(var(--base) / 2); + } + + .rs__option { + font-size: 1rem; + padding: calc(var(--base) / 2) var(--base); + + &--is-focused { + background-color: var(--color-light-gray); + color: var(--color-black); + } + + &--is-selected { + background-color: var(--color-light-gray); + color: var(--color-black); + } + } + + .rs__multi-value { + padding: 0; + background: var(--color-light-gray); + } + + .rs__multi-value__label { + max-width: 150px; + color: var(--color-black); + padding: calc(var(--base) / 8) calc(var(--base) / 4); + } + + .rs__multi-value__remove { + cursor: pointer; + + &:hover { + color: var(--color-black); + background: var(--color-light-gray); + } + } + + .rs__clear-indicator { + cursor: pointer; + } + } +} diff --git a/src/components/Blocks/Form/Country/index.tsx b/src/components/Blocks/Form/Country/index.tsx new file mode 100644 index 0000000..206b120 --- /dev/null +++ b/src/components/Blocks/Form/Country/index.tsx @@ -0,0 +1,50 @@ +import type { CountryField } from '@payloadcms/plugin-form-builder/types' +import type { Control, FieldErrorsImpl, FieldValues } from 'react-hook-form' + +import React from 'react' +import { Controller } from 'react-hook-form' +import ReactSelect from 'react-select' + +import { Error } from '../Error' +import { Width } from '../Width' +import classes from './index.module.scss' +import { countryOptions } from './options' + +export const Country: React.FC< + { + control: Control + errors: Partial< + FieldErrorsImpl<{ + [x: string]: any + }> + > + } & CountryField +> = ({ name, control, errors, label, required, width }) => { + return ( + +
+ + ( + onChange(val ? val.value : '')} + options={countryOptions} + value={countryOptions.find((c) => c.value === value)} + /> + )} + rules={{ required }} + /> + {required && errors[name] && } +
+
+ ) +} diff --git a/src/components/Blocks/Form/Country/options.ts b/src/components/Blocks/Form/Country/options.ts new file mode 100644 index 0000000..f952c1d --- /dev/null +++ b/src/components/Blocks/Form/Country/options.ts @@ -0,0 +1,982 @@ +export const countryOptions = [ + { + label: 'Afghanistan', + value: 'AF', + }, + { + label: 'Ă…land Islands', + value: 'AX', + }, + { + label: 'Albania', + value: 'AL', + }, + { + label: 'Algeria', + value: 'DZ', + }, + { + label: 'American Samoa', + value: 'AS', + }, + { + label: 'Andorra', + value: 'AD', + }, + { + label: 'Angola', + value: 'AO', + }, + { + label: 'Anguilla', + value: 'AI', + }, + { + label: 'Antarctica', + value: 'AQ', + }, + { + label: 'Antigua and Barbuda', + value: 'AG', + }, + { + label: 'Argentina', + value: 'AR', + }, + { + label: 'Armenia', + value: 'AM', + }, + { + label: 'Aruba', + value: 'AW', + }, + { + label: 'Australia', + value: 'AU', + }, + { + label: 'Austria', + value: 'AT', + }, + { + label: 'Azerbaijan', + value: 'AZ', + }, + { + label: 'Bahamas', + value: 'BS', + }, + { + label: 'Bahrain', + value: 'BH', + }, + { + label: 'Bangladesh', + value: 'BD', + }, + { + label: 'Barbados', + value: 'BB', + }, + { + label: 'Belarus', + value: 'BY', + }, + { + label: 'Belgium', + value: 'BE', + }, + { + label: 'Belize', + value: 'BZ', + }, + { + label: 'Benin', + value: 'BJ', + }, + { + label: 'Bermuda', + value: 'BM', + }, + { + label: 'Bhutan', + value: 'BT', + }, + { + label: 'Bolivia', + value: 'BO', + }, + { + label: 'Bosnia and Herzegovina', + value: 'BA', + }, + { + label: 'Botswana', + value: 'BW', + }, + { + label: 'Bouvet Island', + value: 'BV', + }, + { + label: 'Brazil', + value: 'BR', + }, + { + label: 'British Indian Ocean Territory', + value: 'IO', + }, + { + label: 'Brunei Darussalam', + value: 'BN', + }, + { + label: 'Bulgaria', + value: 'BG', + }, + { + label: 'Burkina Faso', + value: 'BF', + }, + { + label: 'Burundi', + value: 'BI', + }, + { + label: 'Cambodia', + value: 'KH', + }, + { + label: 'Cameroon', + value: 'CM', + }, + { + label: 'Canada', + value: 'CA', + }, + { + label: 'Cape Verde', + value: 'CV', + }, + { + label: 'Cayman Islands', + value: 'KY', + }, + { + label: 'Central African Republic', + value: 'CF', + }, + { + label: 'Chad', + value: 'TD', + }, + { + label: 'Chile', + value: 'CL', + }, + { + label: 'China', + value: 'CN', + }, + { + label: 'Christmas Island', + value: 'CX', + }, + { + label: 'Cocos (Keeling) Islands', + value: 'CC', + }, + { + label: 'Colombia', + value: 'CO', + }, + { + label: 'Comoros', + value: 'KM', + }, + { + label: 'Congo', + value: 'CG', + }, + { + label: 'Congo, The Democratic Republic of the', + value: 'CD', + }, + { + label: 'Cook Islands', + value: 'CK', + }, + { + label: 'Costa Rica', + value: 'CR', + }, + { + label: "Cote D'Ivoire", + value: 'CI', + }, + { + label: 'Croatia', + value: 'HR', + }, + { + label: 'Cuba', + value: 'CU', + }, + { + label: 'Cyprus', + value: 'CY', + }, + { + label: 'Czech Republic', + value: 'CZ', + }, + { + label: 'Denmark', + value: 'DK', + }, + { + label: 'Djibouti', + value: 'DJ', + }, + { + label: 'Dominica', + value: 'DM', + }, + { + label: 'Dominican Republic', + value: 'DO', + }, + { + label: 'Ecuador', + value: 'EC', + }, + { + label: 'Egypt', + value: 'EG', + }, + { + label: 'El Salvador', + value: 'SV', + }, + { + label: 'Equatorial Guinea', + value: 'GQ', + }, + { + label: 'Eritrea', + value: 'ER', + }, + { + label: 'Estonia', + value: 'EE', + }, + { + label: 'Ethiopia', + value: 'ET', + }, + { + label: 'Falkland Islands (Malvinas)', + value: 'FK', + }, + { + label: 'Faroe Islands', + value: 'FO', + }, + { + label: 'Fiji', + value: 'FJ', + }, + { + label: 'Finland', + value: 'FI', + }, + { + label: 'France', + value: 'FR', + }, + { + label: 'French Guiana', + value: 'GF', + }, + { + label: 'French Polynesia', + value: 'PF', + }, + { + label: 'French Southern Territories', + value: 'TF', + }, + { + label: 'Gabon', + value: 'GA', + }, + { + label: 'Gambia', + value: 'GM', + }, + { + label: 'Georgia', + value: 'GE', + }, + { + label: 'Germany', + value: 'DE', + }, + { + label: 'Ghana', + value: 'GH', + }, + { + label: 'Gibraltar', + value: 'GI', + }, + { + label: 'Greece', + value: 'GR', + }, + { + label: 'Greenland', + value: 'GL', + }, + { + label: 'Grenada', + value: 'GD', + }, + { + label: 'Guadeloupe', + value: 'GP', + }, + { + label: 'Guam', + value: 'GU', + }, + { + label: 'Guatemala', + value: 'GT', + }, + { + label: 'Guernsey', + value: 'GG', + }, + { + label: 'Guinea', + value: 'GN', + }, + { + label: 'Guinea-Bissau', + value: 'GW', + }, + { + label: 'Guyana', + value: 'GY', + }, + { + label: 'Haiti', + value: 'HT', + }, + { + label: 'Heard Island and Mcdonald Islands', + value: 'HM', + }, + { + label: 'Holy See (Vatican City State)', + value: 'VA', + }, + { + label: 'Honduras', + value: 'HN', + }, + { + label: 'Hong Kong', + value: 'HK', + }, + { + label: 'Hungary', + value: 'HU', + }, + { + label: 'Iceland', + value: 'IS', + }, + { + label: 'India', + value: 'IN', + }, + { + label: 'Indonesia', + value: 'ID', + }, + { + label: 'Iran, Islamic Republic Of', + value: 'IR', + }, + { + label: 'Iraq', + value: 'IQ', + }, + { + label: 'Ireland', + value: 'IE', + }, + { + label: 'Isle of Man', + value: 'IM', + }, + { + label: 'Israel', + value: 'IL', + }, + { + label: 'Italy', + value: 'IT', + }, + { + label: 'Jamaica', + value: 'JM', + }, + { + label: 'Japan', + value: 'JP', + }, + { + label: 'Jersey', + value: 'JE', + }, + { + label: 'Jordan', + value: 'JO', + }, + { + label: 'Kazakhstan', + value: 'KZ', + }, + { + label: 'Kenya', + value: 'KE', + }, + { + label: 'Kiribati', + value: 'KI', + }, + { + label: "Democratic People's Republic of Korea", + value: 'KP', + }, + { + label: 'Korea, Republic of', + value: 'KR', + }, + { + label: 'Kosovo', + value: 'XK', + }, + { + label: 'Kuwait', + value: 'KW', + }, + { + label: 'Kyrgyzstan', + value: 'KG', + }, + { + label: "Lao People's Democratic Republic", + value: 'LA', + }, + { + label: 'Latvia', + value: 'LV', + }, + { + label: 'Lebanon', + value: 'LB', + }, + { + label: 'Lesotho', + value: 'LS', + }, + { + label: 'Liberia', + value: 'LR', + }, + { + label: 'Libyan Arab Jamahiriya', + value: 'LY', + }, + { + label: 'Liechtenstein', + value: 'LI', + }, + { + label: 'Lithuania', + value: 'LT', + }, + { + label: 'Luxembourg', + value: 'LU', + }, + { + label: 'Macao', + value: 'MO', + }, + { + label: 'Macedonia, The Former Yugoslav Republic of', + value: 'MK', + }, + { + label: 'Madagascar', + value: 'MG', + }, + { + label: 'Malawi', + value: 'MW', + }, + { + label: 'Malaysia', + value: 'MY', + }, + { + label: 'Maldives', + value: 'MV', + }, + { + label: 'Mali', + value: 'ML', + }, + { + label: 'Malta', + value: 'MT', + }, + { + label: 'Marshall Islands', + value: 'MH', + }, + { + label: 'Martinique', + value: 'MQ', + }, + { + label: 'Mauritania', + value: 'MR', + }, + { + label: 'Mauritius', + value: 'MU', + }, + { + label: 'Mayotte', + value: 'YT', + }, + { + label: 'Mexico', + value: 'MX', + }, + { + label: 'Micronesia, Federated States of', + value: 'FM', + }, + { + label: 'Moldova, Republic of', + value: 'MD', + }, + { + label: 'Monaco', + value: 'MC', + }, + { + label: 'Mongolia', + value: 'MN', + }, + { + label: 'Montenegro', + value: 'ME', + }, + { + label: 'Montserrat', + value: 'MS', + }, + { + label: 'Morocco', + value: 'MA', + }, + { + label: 'Mozambique', + value: 'MZ', + }, + { + label: 'Myanmar', + value: 'MM', + }, + { + label: 'Namibia', + value: 'NA', + }, + { + label: 'Nauru', + value: 'NR', + }, + { + label: 'Nepal', + value: 'NP', + }, + { + label: 'Netherlands', + value: 'NL', + }, + { + label: 'Netherlands Antilles', + value: 'AN', + }, + { + label: 'New Caledonia', + value: 'NC', + }, + { + label: 'New Zealand', + value: 'NZ', + }, + { + label: 'Nicaragua', + value: 'NI', + }, + { + label: 'Niger', + value: 'NE', + }, + { + label: 'Nigeria', + value: 'NG', + }, + { + label: 'Niue', + value: 'NU', + }, + { + label: 'Norfolk Island', + value: 'NF', + }, + { + label: 'Northern Mariana Islands', + value: 'MP', + }, + { + label: 'Norway', + value: 'NO', + }, + { + label: 'Oman', + value: 'OM', + }, + { + label: 'Pakistan', + value: 'PK', + }, + { + label: 'Palau', + value: 'PW', + }, + { + label: 'Palestinian Territory, Occupied', + value: 'PS', + }, + { + label: 'Panama', + value: 'PA', + }, + { + label: 'Papua New Guinea', + value: 'PG', + }, + { + label: 'Paraguay', + value: 'PY', + }, + { + label: 'Peru', + value: 'PE', + }, + { + label: 'Philippines', + value: 'PH', + }, + { + label: 'Pitcairn', + value: 'PN', + }, + { + label: 'Poland', + value: 'PL', + }, + { + label: 'Portugal', + value: 'PT', + }, + { + label: 'Puerto Rico', + value: 'PR', + }, + { + label: 'Qatar', + value: 'QA', + }, + { + label: 'Reunion', + value: 'RE', + }, + { + label: 'Romania', + value: 'RO', + }, + { + label: 'Russian Federation', + value: 'RU', + }, + { + label: 'Rwanda', + value: 'RW', + }, + { + label: 'Saint Helena', + value: 'SH', + }, + { + label: 'Saint Kitts and Nevis', + value: 'KN', + }, + { + label: 'Saint Lucia', + value: 'LC', + }, + { + label: 'Saint Pierre and Miquelon', + value: 'PM', + }, + { + label: 'Saint Vincent and the Grenadines', + value: 'VC', + }, + { + label: 'Samoa', + value: 'WS', + }, + { + label: 'San Marino', + value: 'SM', + }, + { + label: 'Sao Tome and Principe', + value: 'ST', + }, + { + label: 'Saudi Arabia', + value: 'SA', + }, + { + label: 'Senegal', + value: 'SN', + }, + { + label: 'Serbia', + value: 'RS', + }, + { + label: 'Seychelles', + value: 'SC', + }, + { + label: 'Sierra Leone', + value: 'SL', + }, + { + label: 'Singapore', + value: 'SG', + }, + { + label: 'Slovakia', + value: 'SK', + }, + { + label: 'Slovenia', + value: 'SI', + }, + { + label: 'Solomon Islands', + value: 'SB', + }, + { + label: 'Somalia', + value: 'SO', + }, + { + label: 'South Africa', + value: 'ZA', + }, + { + label: 'South Georgia and the South Sandwich Islands', + value: 'GS', + }, + { + label: 'Spain', + value: 'ES', + }, + { + label: 'Sri Lanka', + value: 'LK', + }, + { + label: 'Sudan', + value: 'SD', + }, + { + label: 'Suriname', + value: 'SR', + }, + { + label: 'Svalbard and Jan Mayen', + value: 'SJ', + }, + { + label: 'Swaziland', + value: 'SZ', + }, + { + label: 'Sweden', + value: 'SE', + }, + { + label: 'Switzerland', + value: 'CH', + }, + { + label: 'Syrian Arab Republic', + value: 'SY', + }, + { + label: 'Taiwan', + value: 'TW', + }, + { + label: 'Tajikistan', + value: 'TJ', + }, + { + label: 'Tanzania, United Republic of', + value: 'TZ', + }, + { + label: 'Thailand', + value: 'TH', + }, + { + label: 'Timor-Leste', + value: 'TL', + }, + { + label: 'Togo', + value: 'TG', + }, + { + label: 'Tokelau', + value: 'TK', + }, + { + label: 'Tonga', + value: 'TO', + }, + { + label: 'Trinidad and Tobago', + value: 'TT', + }, + { + label: 'Tunisia', + value: 'TN', + }, + { + label: 'Turkey', + value: 'TR', + }, + { + label: 'Turkmenistan', + value: 'TM', + }, + { + label: 'Turks and Caicos Islands', + value: 'TC', + }, + { + label: 'Tuvalu', + value: 'TV', + }, + { + label: 'Uganda', + value: 'UG', + }, + { + label: 'Ukraine', + value: 'UA', + }, + { + label: 'United Arab Emirates', + value: 'AE', + }, + { + label: 'United Kingdom', + value: 'GB', + }, + { + label: 'United States', + value: 'US', + }, + { + label: 'United States Minor Outlying Islands', + value: 'UM', + }, + { + label: 'Uruguay', + value: 'UY', + }, + { + label: 'Uzbekistan', + value: 'UZ', + }, + { + label: 'Vanuatu', + value: 'VU', + }, + { + label: 'Venezuela', + value: 'VE', + }, + { + label: 'Viet Nam', + value: 'VN', + }, + { + label: 'Virgin Islands, British', + value: 'VG', + }, + { + label: 'Virgin Islands, U.S.', + value: 'VI', + }, + { + label: 'Wallis and Futuna', + value: 'WF', + }, + { + label: 'Western Sahara', + value: 'EH', + }, + { + label: 'Yemen', + value: 'YE', + }, + { + label: 'Zambia', + value: 'ZM', + }, + { + label: 'Zimbabwe', + value: 'ZW', + }, +] diff --git a/src/components/Blocks/Form/Email/index.tsx b/src/components/Blocks/Form/Email/index.tsx new file mode 100644 index 0000000..34fa4dd --- /dev/null +++ b/src/components/Blocks/Form/Email/index.tsx @@ -0,0 +1,33 @@ +import type { EmailField } from "@payloadcms/plugin-form-builder/types"; +import type { FieldErrorsImpl, FieldValues, UseFormRegister } from "react-hook-form"; + +import React from "react"; + +import { Error } from "../Error"; +import { Width } from "../Width"; + +export const Email: React.FC< + { + errors: Partial< + FieldErrorsImpl<{ + [x: string]: any; + }> + >; + register: UseFormRegister; + } & EmailField +> = ({ name, errors, label, register, required: requiredFromProps, width }) => { + return ( + +
+ + + {requiredFromProps && errors[name] && } +
+
+ ); +}; diff --git a/src/components/Blocks/Form/Error/index.module.scss b/src/components/Blocks/Form/Error/index.module.scss new file mode 100644 index 0000000..38792cc --- /dev/null +++ b/src/components/Blocks/Form/Error/index.module.scss @@ -0,0 +1,4 @@ +.error { + margin-top: 5px; + color: var(--color-red); +} diff --git a/src/components/Blocks/Form/Error/index.tsx b/src/components/Blocks/Form/Error/index.tsx new file mode 100644 index 0000000..e1d0980 --- /dev/null +++ b/src/components/Blocks/Form/Error/index.tsx @@ -0,0 +1,5 @@ +import * as React from "react"; + +export const Error: React.FC = () => { + return
This field is required
; +}; diff --git a/src/components/Blocks/Form/Gutter/index.module.scss b/src/components/Blocks/Form/Gutter/index.module.scss new file mode 100644 index 0000000..065eb85 --- /dev/null +++ b/src/components/Blocks/Form/Gutter/index.module.scss @@ -0,0 +1,7 @@ +.gutterLeft { + padding-left: var(--gutter-h); +} + +.gutterRight { + padding-right: var(--gutter-h); +} diff --git a/src/components/Blocks/Form/Gutter/index.tsx b/src/components/Blocks/Form/Gutter/index.tsx new file mode 100644 index 0000000..1156d8c --- /dev/null +++ b/src/components/Blocks/Form/Gutter/index.tsx @@ -0,0 +1,26 @@ +import React from 'react' + +import classes from './index.module.scss' + +type Props = { + children: React.ReactNode + className?: string + left?: boolean + ref?: React.Ref + right?: boolean +} + +export const Gutter: React.FC }> = (props) => { + const { children, className, left = true, right = true, ref } = props + + return ( +
+ {children} +
+ ) +} diff --git a/src/components/Blocks/Form/Link/index.tsx b/src/components/Blocks/Form/Link/index.tsx new file mode 100644 index 0000000..ab255a2 --- /dev/null +++ b/src/components/Blocks/Form/Link/index.tsx @@ -0,0 +1,72 @@ +import Link from "next/link"; +import React from "react"; + +// @ts-ignore +import type { Page } from "@/payload-types"; + +import { Button } from "../Button"; + +export type CMSLinkType = { + appearance?: "default" | "primary" | "secondary"; + children?: React.ReactNode; + className?: string; + label?: string; + newTab?: boolean | null; + reference?: { + relationTo: "pages"; + value: number | Page | string; + } | null; + type?: "custom" | "reference" | null; + url?: null | string; +}; + +export const CMSLink: React.FC = ({ + type, + appearance, + children, + className, + label, + newTab, + reference, + url, +}) => { + const href = + type === "reference" && typeof reference?.value === "object" && reference.value.slug + ? `${reference?.relationTo !== "pages" ? `/${reference?.relationTo}` : ""}/${reference.value.slug}` + : url; + + if (!href) { + return null; + } + + if (!appearance) { + const newTabProps = newTab ? { rel: "noopener noreferrer", target: "_blank" } : {}; + + if (type === "custom") { + return ( + + {label && label} + {children ? <>{children} : null} + + ); + } + + if (href) { + return ( + + {label && label} + {children ? <>{children} : null} + + ); + } + } + + const buttonProps = { + appearance, + href, + label, + newTab, + }; + + return