From 6cf6660eedf9725d6c3eb03af5ad12e20b9fa8a5 Mon Sep 17 00:00:00 2001 From: Bochkovskyi Date: Wed, 7 Feb 2024 14:21:25 +0200 Subject: [PATCH 01/25] add react-hook-form and zod packages --- package-lock.json | 36 +++++++++++++++++++++++++++++++++++- package.json | 5 ++++- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5130b3c..fd98ee9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,7 @@ "name": "portfolio-site", "version": "0.1.0", "dependencies": { + "@hookform/resolvers": "^3.3.4", "class-variance-authority": "^0.7.0", "clsx": "^2.1.0", "gray-matter": "^4.0.3", @@ -16,8 +17,10 @@ "next-themes": "^0.2.1", "react": "^18", "react-dom": "^18", + "react-hook-form": "^7.50.1", "react-icons": "^5.0.1", - "tailwind-merge": "^2.2.1" + "tailwind-merge": "^2.2.1", + "zod": "^3.22.4" }, "devDependencies": { "@types/node": "^20", @@ -553,6 +556,14 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/@hookform/resolvers": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-3.3.4.tgz", + "integrity": "sha512-o5cgpGOuJYrd+iMKvkttOclgwRW86EsWJZZRC23prf0uU2i48Htq4PuT73AVb9ionFyZrwYEITuOFGF+BydEtQ==", + "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", @@ -5644,6 +5655,21 @@ "react": "^18.2.0" } }, + "node_modules/react-hook-form": { + "version": "7.50.1", + "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.50.1.tgz", + "integrity": "sha512-3PCY82oE0WgeOgUtIr3nYNNtNvqtJ7BZjsbxh6TnYNbXButaD5WpjOmTjdxZfheuHKR68qfeFnEDVYoSSFPMTQ==", + "engines": { + "node": ">=12.22.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/react-hook-form" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17 || ^18" + } + }, "node_modules/react-icons": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.0.1.tgz", @@ -6984,6 +7010,14 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/zod": { + "version": "3.22.4", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.4.tgz", + "integrity": "sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } } } } diff --git a/package.json b/package.json index 7d08caf..5009030 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "prepare": "husky install" }, "dependencies": { + "@hookform/resolvers": "^3.3.4", "class-variance-authority": "^0.7.0", "clsx": "^2.1.0", "gray-matter": "^4.0.3", @@ -23,8 +24,10 @@ "next-themes": "^0.2.1", "react": "^18", "react-dom": "^18", + "react-hook-form": "^7.50.1", "react-icons": "^5.0.1", - "tailwind-merge": "^2.2.1" + "tailwind-merge": "^2.2.1", + "zod": "^3.22.4" }, "devDependencies": { "@types/node": "^20", From bfd87de067da1377f7609d46bc7f92a63284a284 Mon Sep 17 00:00:00 2001 From: Bochkovskyi Date: Wed, 7 Feb 2024 16:53:14 +0200 Subject: [PATCH 02/25] add contact form zod utilities --- src/utils/index.ts | 1 + src/utils/zod.ts | 9 +++++++++ 2 files changed, 10 insertions(+) create mode 100644 src/utils/zod.ts diff --git a/src/utils/index.ts b/src/utils/index.ts index 12a0292..366ac67 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1,2 +1,3 @@ export * from './misc' export * from './constants' +export * from './zod' diff --git a/src/utils/zod.ts b/src/utils/zod.ts new file mode 100644 index 0000000..325b971 --- /dev/null +++ b/src/utils/zod.ts @@ -0,0 +1,9 @@ +import { z } from 'zod' + +export const ContactFormSchema = z.object({ + email: z.string().email('Email is invalid'), + message: z.string().min(5, 'Message is too short'), + name: z.string().min(2, 'Name is required'), +}) + +export type ContactFormInputs = z.infer From 5f327702934bd85da24e2ea8a3decf833c0a2c0d Mon Sep 17 00:00:00 2001 From: Bochkovskyi Date: Wed, 7 Feb 2024 16:53:45 +0200 Subject: [PATCH 03/25] replace button with link --- src/components/sections/hero/hero.tsx | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/components/sections/hero/hero.tsx b/src/components/sections/hero/hero.tsx index 7ede32d..6479f7c 100644 --- a/src/components/sections/hero/hero.tsx +++ b/src/components/sections/hero/hero.tsx @@ -1,8 +1,9 @@ -import Button from '@/components/ui/button' +import Button, { buttonVariants } from '@/components/ui/button' import Content from '@/components/ui/content' import Heading from '@/components/ui/heading' import Socials from '@/components/ui/socials/socials' import { cn } from '@/utils' +import Link from 'next/link' import { FC, HTMLAttributes } from 'react' import styles from './hero.module.css' @@ -29,9 +30,12 @@ const Hero: FC = ({ className, ...props }) => { elegant and responsive user interfaces.

- + + My Projects + Date: Wed, 7 Feb 2024 16:54:09 +0200 Subject: [PATCH 04/25] update styles --- src/components/sections/projects/projects.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/sections/projects/projects.tsx b/src/components/sections/projects/projects.tsx index c931403..c50a6b9 100644 --- a/src/components/sections/projects/projects.tsx +++ b/src/components/sections/projects/projects.tsx @@ -23,7 +23,7 @@ const Projects: FC = async ({ className, ...props }) => { explore other sections of the site.

) : ( -
+
{projects.map((project) => ( Date: Wed, 7 Feb 2024 16:54:47 +0200 Subject: [PATCH 05/25] update technologies mapping --- src/components/sections/projects/project-card.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/sections/projects/project-card.tsx b/src/components/sections/projects/project-card.tsx index 27c1563..85ae45d 100644 --- a/src/components/sections/projects/project-card.tsx +++ b/src/components/sections/projects/project-card.tsx @@ -39,10 +39,10 @@ const ProjectCard: FC = ({ /> {technologies && (
- {technologies.map((technology, index) => ( + {technologies.map((technology) => ( {technology} From 0d285c5898872d1dac8474a98d04f8ac2c51bfcd Mon Sep 17 00:00:00 2001 From: Bochkovskyi Date: Wed, 7 Feb 2024 16:55:24 +0200 Subject: [PATCH 06/25] add Input component --- src/components/ui/input.tsx | 76 +++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 src/components/ui/input.tsx diff --git a/src/components/ui/input.tsx b/src/components/ui/input.tsx new file mode 100644 index 0000000..f27caa1 --- /dev/null +++ b/src/components/ui/input.tsx @@ -0,0 +1,76 @@ +import { ContactFormInputs, cn } from '@/utils' +import { VariantProps, cva } from 'class-variance-authority' +import { FC, InputHTMLAttributes } from 'react' +import { Path, UseFormRegister } from 'react-hook-form' + +export const inputVariants = cva( + 'w-full transition-colors outline-none md:text-xl', + { + defaultVariants: { + customSize: 'default', + variant: 'default', + }, + variants: { + customSize: { + default: 'rounded-2xl px-4 py-3.5', + placeholder: 'rounded-2xl px-4 pb-2 pt-5', + }, + variant: { + default: + 'border border-neutral-400 bg-light dark:border-neutral-600 dark:bg-dark', + placeholder: + 'border border-neutral-400 bg-light dark:border-neutral-600 dark:bg-dark peer relative placeholder:opacity-0', + }, + }, + } +) + +export interface InputProps + extends InputHTMLAttributes, + VariantProps { + name: Path + register: UseFormRegister +} + +const Input: FC = ({ + className, + customSize, + name, + placeholder, + register, + required, + variant, + ...props +}) => { + return ( + <> + {placeholder ? ( +
+ + + {placeholder} + +
+ ) : ( + + )} + + ) +} + +export default Input From ed37705d1e574721afe2013370d96eb09de73d10 Mon Sep 17 00:00:00 2001 From: Bochkovskyi Date: Wed, 7 Feb 2024 16:55:45 +0200 Subject: [PATCH 07/25] add Textarea component --- src/components/ui/textarea.tsx | 56 ++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 src/components/ui/textarea.tsx diff --git a/src/components/ui/textarea.tsx b/src/components/ui/textarea.tsx new file mode 100644 index 0000000..7051c02 --- /dev/null +++ b/src/components/ui/textarea.tsx @@ -0,0 +1,56 @@ +import { inputVariants } from '@/components/ui/input' +import { ContactFormInputs, cn } from '@/utils' +import { VariantProps } from 'class-variance-authority' +import { FC, TextareaHTMLAttributes } from 'react' +import { Path, UseFormRegister } from 'react-hook-form' + +export interface TextareaProps + extends TextareaHTMLAttributes, + VariantProps { + name: Path + register: UseFormRegister +} + +const Textarea: FC = ({ + className, + customSize, + name, + placeholder, + register, + required, + variant, + ...props +}) => { + return ( + <> + {placeholder ? ( +
+