diff --git a/public/android-chrome-192x192.png b/public/android-chrome-192x192.png index f459fcc..259c25b 100644 Binary files a/public/android-chrome-192x192.png and b/public/android-chrome-192x192.png differ diff --git a/public/android-chrome-512x512.png b/public/android-chrome-512x512.png index f71def1..c3b263c 100644 Binary files a/public/android-chrome-512x512.png and b/public/android-chrome-512x512.png differ diff --git a/public/apple-touch-icon.png b/public/apple-touch-icon.png index affa9a8..2c404f7 100644 Binary files a/public/apple-touch-icon.png and b/public/apple-touch-icon.png differ diff --git a/public/favicon-16x16.png b/public/favicon-16x16.png index d5a15e3..144930e 100644 Binary files a/public/favicon-16x16.png and b/public/favicon-16x16.png differ diff --git a/public/favicon-32x32.png b/public/favicon-32x32.png index 9624341..61593e5 100644 Binary files a/public/favicon-32x32.png and b/public/favicon-32x32.png differ diff --git a/public/favicon.ico b/public/favicon.ico index ccad1ed..84ecbe4 100644 Binary files a/public/favicon.ico and b/public/favicon.ico differ diff --git a/public/favicon.png b/public/favicon.png deleted file mode 100644 index f4e9174..0000000 Binary files a/public/favicon.png and /dev/null differ diff --git a/public/favicon.svg b/public/favicon.svg index 5f41f7a..97366bb 100644 --- a/public/favicon.svg +++ b/public/favicon.svg @@ -1 +1,3 @@ - \ No newline at end of file + + + \ No newline at end of file diff --git a/public/logo.png b/public/logo.png new file mode 100644 index 0000000..9ed040f Binary files /dev/null and b/public/logo.png differ diff --git a/public/og-image.png b/public/og-image.png index 1922960..72e6710 100644 Binary files a/public/og-image.png and b/public/og-image.png differ diff --git a/public/twitter-image.png b/public/twitter-image.png index 1922960..2dc827d 100644 Binary files a/public/twitter-image.png and b/public/twitter-image.png differ diff --git a/src/assets/images/connect1.svg b/src/assets/images/connect1.svg deleted file mode 100644 index 8e955f7..0000000 --- a/src/assets/images/connect1.svg +++ /dev/null @@ -1,208 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/assets/images/hero-alt.webp b/src/assets/images/hero-alt.webp deleted file mode 100644 index ffed4df..0000000 Binary files a/src/assets/images/hero-alt.webp and /dev/null differ diff --git a/src/assets/images/hero-illustration.svg b/src/assets/images/hero-illustration.svg deleted file mode 100644 index 11b36c9..0000000 --- a/src/assets/images/hero-illustration.svg +++ /dev/null @@ -1,570 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/assets/images/hero-illustration.webp b/src/assets/images/hero-illustration.webp deleted file mode 100644 index c365f75..0000000 Binary files a/src/assets/images/hero-illustration.webp and /dev/null differ diff --git a/src/assets/images/hero-pattern.svg b/src/assets/images/hero-pattern.svg deleted file mode 100644 index a3c197f..0000000 --- a/src/assets/images/hero-pattern.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/assets/images/icons/apps.svg b/src/assets/images/icons/apps.svg deleted file mode 100644 index dd727b2..0000000 --- a/src/assets/images/icons/apps.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/src/assets/images/icons/aws.svg b/src/assets/images/icons/aws.svg deleted file mode 100644 index ecfcfc0..0000000 --- a/src/assets/images/icons/aws.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/src/assets/images/icons/blocks.svg b/src/assets/images/icons/blocks.svg deleted file mode 100644 index 0b9f565..0000000 --- a/src/assets/images/icons/blocks.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - blocks-group-solid-alerted - - - \ No newline at end of file diff --git a/src/assets/images/icons/bootstrap.svg b/src/assets/images/icons/bootstrap.svg deleted file mode 100644 index 5ae64c2..0000000 --- a/src/assets/images/icons/bootstrap.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/src/assets/images/icons/code.svg b/src/assets/images/icons/code.svg deleted file mode 100644 index a23b419..0000000 --- a/src/assets/images/icons/code.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - - code [#1115] - Created with Sketch. - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/assets/images/icons/codeigniter.svg b/src/assets/images/icons/codeigniter.svg deleted file mode 100644 index 9f0e1e4..0000000 --- a/src/assets/images/icons/codeigniter.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/assets/images/icons/css.svg b/src/assets/images/icons/css.svg deleted file mode 100644 index 4bf1f2d..0000000 --- a/src/assets/images/icons/css.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/assets/images/icons/express.svg b/src/assets/images/icons/express.svg deleted file mode 100644 index f18858c..0000000 --- a/src/assets/images/icons/express.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/assets/images/icons/figma.svg b/src/assets/images/icons/figma.svg deleted file mode 100644 index f8c0d63..0000000 --- a/src/assets/images/icons/figma.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/assets/images/icons/git.svg b/src/assets/images/icons/git.svg deleted file mode 100644 index 72fd36d..0000000 --- a/src/assets/images/icons/git.svg +++ /dev/null @@ -1,2 +0,0 @@ - - \ No newline at end of file diff --git a/src/assets/images/icons/github.svg b/src/assets/images/icons/github.svg deleted file mode 100644 index 1dd4671..0000000 --- a/src/assets/images/icons/github.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - github - \ No newline at end of file diff --git a/src/assets/images/icons/go.svg b/src/assets/images/icons/go.svg deleted file mode 100644 index 026829c..0000000 --- a/src/assets/images/icons/go.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/src/assets/images/icons/html.svg b/src/assets/images/icons/html.svg deleted file mode 100644 index ac51933..0000000 --- a/src/assets/images/icons/html.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/assets/images/icons/javascript.svg b/src/assets/images/icons/javascript.svg deleted file mode 100644 index 7f38585..0000000 --- a/src/assets/images/icons/javascript.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/assets/images/icons/mysql.svg b/src/assets/images/icons/mysql.svg deleted file mode 100644 index ea328cf..0000000 --- a/src/assets/images/icons/mysql.svg +++ /dev/null @@ -1,25 +0,0 @@ - - - - - databases-and-servers/databases/mysql - Created with Sketch. - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/assets/images/icons/nestjs.svg b/src/assets/images/icons/nestjs.svg deleted file mode 100644 index 005df8a..0000000 --- a/src/assets/images/icons/nestjs.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/assets/images/icons/nextjs.svg b/src/assets/images/icons/nextjs.svg deleted file mode 100644 index b3e04e2..0000000 --- a/src/assets/images/icons/nextjs.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/src/assets/images/icons/nodejs.svg b/src/assets/images/icons/nodejs.svg deleted file mode 100644 index 3e77c25..0000000 --- a/src/assets/images/icons/nodejs.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/assets/images/icons/photoshop.svg b/src/assets/images/icons/photoshop.svg deleted file mode 100644 index 3222aac..0000000 --- a/src/assets/images/icons/photoshop.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/assets/images/icons/php.svg b/src/assets/images/icons/php.svg deleted file mode 100644 index c080af5..0000000 --- a/src/assets/images/icons/php.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/src/assets/images/icons/python.svg b/src/assets/images/icons/python.svg deleted file mode 100644 index 3a4e654..0000000 --- a/src/assets/images/icons/python.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/assets/images/icons/react.svg b/src/assets/images/icons/react.svg deleted file mode 100644 index 905ed98..0000000 --- a/src/assets/images/icons/react.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/assets/images/icons/redux.svg b/src/assets/images/icons/redux.svg deleted file mode 100644 index 3f1378a..0000000 --- a/src/assets/images/icons/redux.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/assets/images/icons/sass.svg b/src/assets/images/icons/sass.svg deleted file mode 100644 index 26b98f9..0000000 --- a/src/assets/images/icons/sass.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/assets/images/icons/tailwindcss.svg b/src/assets/images/icons/tailwindcss.svg deleted file mode 100644 index 4b23707..0000000 --- a/src/assets/images/icons/tailwindcss.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/assets/images/icons/tools.svg b/src/assets/images/icons/tools.svg deleted file mode 100644 index 5a06b1d..0000000 --- a/src/assets/images/icons/tools.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/assets/images/icons/typescript.svg b/src/assets/images/icons/typescript.svg deleted file mode 100644 index b04ab30..0000000 --- a/src/assets/images/icons/typescript.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/assets/images/icons/vscode.svg b/src/assets/images/icons/vscode.svg deleted file mode 100644 index 392a9df..0000000 --- a/src/assets/images/icons/vscode.svg +++ /dev/null @@ -1 +0,0 @@ -file_type_vscode2 \ No newline at end of file diff --git a/src/assets/images/logo.png b/src/assets/images/logo.png new file mode 100644 index 0000000..9ed040f Binary files /dev/null and b/src/assets/images/logo.png differ diff --git a/src/assets/images/logo.svg b/src/assets/images/logo.svg index de93e3b..97489e4 100644 --- a/src/assets/images/logo.svg +++ b/src/assets/images/logo.svg @@ -1 +1,49 @@ - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/images/message_send.svg b/src/assets/images/message_send.svg deleted file mode 100644 index de6b86e..0000000 --- a/src/assets/images/message_send.svg +++ /dev/null @@ -1,236 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/assets/images/og-image.png b/src/assets/images/og-image.png new file mode 100644 index 0000000..41177c4 Binary files /dev/null and b/src/assets/images/og-image.png differ diff --git a/src/assets/images/portfolio/featured-project/vaultdrive-dashboard-3.webp b/src/assets/images/portfolio/featured-project/vaultdrive-dashboard-3.webp deleted file mode 100644 index fed99f8..0000000 Binary files a/src/assets/images/portfolio/featured-project/vaultdrive-dashboard-3.webp and /dev/null differ diff --git a/src/components/sections/Contact.tsx b/src/components/sections/Contact.tsx index 6c55f0d..604ec66 100644 --- a/src/components/sections/Contact.tsx +++ b/src/components/sections/Contact.tsx @@ -2,60 +2,141 @@ import emailjs from '@emailjs/browser'; import { faGithub, faLinkedin } from '@fortawesome/free-brands-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { ArrowUpRight, Loader2, Mail, MapPin, Send } from 'lucide-react'; -import { ChangeEvent, FormEvent, useMemo, useRef, useState } from 'react'; +import { + ChangeEvent, + SubmitEventHandler, + useEffect, + useMemo, + useRef, + useState, +} from 'react'; import validator from 'validator'; import workspaceImage from '#assets/images/portfolio/workspace-placeholder.png'; +import { SOCIALS_USERNAME } from '#config/social.ts'; import { Button } from '../ui/Button'; import { Reveal } from '../ui/Reveal'; import { Section } from '../ui/Section'; +type ContactFormInputs = { + name: string; + email: string; + message: string; +}; + +type ContactFormErrors = Record; + +type EmailJsCredentials = { + serviceId?: string; + templateId?: string; + publicKey?: string; +}; + +type SubmissionStatus = 'idle' | 'loading' | 'completed' | 'rejected'; + +const INITIAL_CONTACT_FORM_INPUTS: ContactFormInputs = { + name: '', + email: '', + message: '', +}; + +const STATUS_RESET_DELAY_MS = 5000; +const SUBMITTED_AT_LOCALE = 'en-IN'; + +const getEmailJsCredentials = (): EmailJsCredentials => ({ + serviceId: import.meta.env.VITE_EMAILJS_SERVICE_ID, + templateId: import.meta.env.VITE_EMAILJS_TEMPLATE_ID, + publicKey: import.meta.env.VITE_EMAILJS_PUBLIC_KEY, +}); + +const hasEmailJsCredentials = ( + credentials: EmailJsCredentials, +): credentials is Required => + Boolean( + credentials.serviceId && credentials.templateId && credentials.publicKey, + ); + +const validateContactForm = (inputs: ContactFormInputs): ContactFormErrors => ({ + name: inputs.name.trim().length < 2, + email: !validator.isEmail(inputs.email), + message: inputs.message.trim().length < 20, +}); + export function Contact() { - const initial = { name: '', email: '', message: '' }; - const [inputs, setInputs] = useState(initial); - const [status, setStatus] = useState< - 'idle' | 'loading' | 'completed' | 'rejected' - >('idle'); + const emailJsCredentials = useMemo(getEmailJsCredentials, []); const formRef = useRef(null); - const errors = useMemo( - () => ({ - name: inputs.name.trim().length < 2, - email: !validator.isEmail(inputs.email), - message: inputs.message.trim().length < 20, - }), - [inputs], + const [formInputs, setFormInputs] = useState( + INITIAL_CONTACT_FORM_INPUTS, + ); + const [status, setStatus] = useState('idle'); + + useEffect(() => { + if (status !== 'completed' && status !== 'rejected') return; + + const resetStatusTimer = window.setTimeout(() => { + setStatus('idle'); + }, STATUS_RESET_DELAY_MS); + + return () => window.clearTimeout(resetStatusTimer); + }, [status]); + + const formErrors = useMemo( + () => validateContactForm(formInputs), + [formInputs], ); - const invalid = errors.name || errors.email || errors.message; + const isFormInvalid = + formErrors.name || formErrors.email || formErrors.message; - const onChange = (e: ChangeEvent) => - setInputs(v => ({ ...v, [e.target.name]: e.target.value })); + const handleInputChange = ( + event: ChangeEvent, + ) => { + const { name, value } = event.target; + + setFormInputs(currentInputs => ({ + ...currentInputs, + [name]: value, + })); + }; + + const handleSubmit: SubmitEventHandler = async event => { + event.preventDefault(); + + if (isFormInvalid || !formRef.current) return; - const onSubmit = async (e: FormEvent) => { - e.preventDefault(); - if (invalid || !formRef.current) return; setStatus('loading'); + + if (!hasEmailJsCredentials(emailJsCredentials)) { + setStatus('rejected'); + return; + } + try { - const res = await emailjs.sendForm( - 'service_qdjdol9', - 'template_lobv7nq', + const response = await emailjs.sendForm( + emailJsCredentials.serviceId, + emailJsCredentials.templateId, formRef.current, - 'G0MWsjYi9pbxnAwfJ', + emailJsCredentials.publicKey, ); - if (res.status === 200) { - setInputs(initial); + + if (response.status === 200) { + setFormInputs(INITIAL_CONTACT_FORM_INPUTS); setStatus('completed'); - } else setStatus('rejected'); - } catch { + return; + } + + setStatus('rejected'); + } catch (error) { + console.error(error); setStatus('rejected'); } }; return (
-
+

Contact @@ -78,6 +159,7 @@ export function Contact() { alt="Workspace" className="aspect-video w-full object-cover" /> +

@@ -91,9 +173,8 @@ export function Contact() {
- frontendfixer@email.com + {SOCIALS_USERNAME.email}
-
India ยท Remote Worldwide @@ -102,14 +183,14 @@ export function Contact() {
@@ -121,37 +202,52 @@ export function Contact() { -
+ + + + +