-
-
Notifications
You must be signed in to change notification settings - Fork 0
📃Add Contact #4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
📃Add Contact #4
Conversation
…nd content sections
…re and visual appeal
… structure and update header content for clarity
|
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR adds a new “Contact” section with form validation and backend integration, enhances animations across multiple homepage sections using Framer Motion, and updates related dependencies for email handling and UI primitives.
- Introduced
ContactSectioncomponent and/api/contactroute with validation, rate limiting, and email sending - Wrapped Hero, Timeline, Projects, and Contact sections in animated
motionwrappers for smoother entry effects - Added
nodemailer(plus types) and@radix-ui/react-labelto support form/email features
Reviewed Changes
Copilot reviewed 21 out of 23 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| src/lib/utils/email-service.ts | New server-side Gmail email helper |
| src/app/api/contact/route.ts | Contact form API with rate limiting and validation |
| src/app/(web)/(home)/sections/contact.tsx | Contact form UI, validation, animations, and feedback states |
| src/app/(web)/(home)/sections/projects.tsx | Projects layout wrapped in Framer Motion, fixed grid wrapper typo |
| src/components/ui/project-card.tsx | Project card styling tweaks, removed stray class typo |
| src/lib/constants.ts | Environment loading via dotenv may expose secrets to client |
| package.json | Added nodemailer and moved type definitions for production check |
Comments suppressed due to low confidence (2)
src/app/api/contact/route.ts:10
- This new API route implements important logic (validation, rate limiting, email sending) but lacks automated tests. Add unit/integration tests to cover edge cases and error paths.
export async function POST(request: NextRequest) {
src/lib/constants.ts:4
- Loading environment variables with dotenv in a module used on both server and client may expose sensitive data in the client bundle. Remove
dotenvand rely on Next.js built-in env handling.
import { config } from 'dotenv';
|
|
||
| <footer className="mt-auto flex justify-between pt-2 z-10"> | ||
| <footer className="mt-auto px-4 pb-4 flex justify-between pt-2 z-10"> | ||
| <div className='bg-foreground/5 ring-1 w-fit ring-foreground/10 justify-end flex ga rounded-full p-1'> |
Copilot
AI
Jun 23, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The class name 'ga' appears to be a typo and has no effect. Remove or correct it (e.g., replace with 'gap-1').
| <div className='bg-foreground/5 ring-1 w-fit ring-foreground/10 justify-end flex ga rounded-full p-1'> | |
| <div className='bg-foreground/5 ring-1 w-fit ring-foreground/10 justify-end flex rounded-full p-1'> |
| <ProjectCard key={index} project={project} /> | ||
| ))) | ||
| return ( | ||
| <div className="w-full max-w-6xl mx-auto max-sm:p-0 px-4 pb-16 grid sm:grid-cols-2 lg:grid-cols-3 gap-7 stick"> |
Copilot
AI
Jun 23, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The class 'stick' is not a recognized Tailwind utility and should be removed or replaced with the intended class.
| <div className="w-full max-w-6xl mx-auto max-sm:p-0 px-4 pb-16 grid sm:grid-cols-2 lg:grid-cols-3 gap-7 stick"> | |
| <div className="w-full max-w-6xl mx-auto max-sm:p-0 px-4 pb-16 grid sm:grid-cols-2 lg:grid-cols-3 gap-7 sticky"> |
| import { Send, AlertCircle } from "lucide-react"; | ||
| import { BorderBeam } from "@/components/ui/border-beam"; | ||
| import { cn } from "@/lib/utils"; | ||
| import { LoadingSpinner } from "../../../../components/ui/loading-spinner"; |
Copilot
AI
Jun 23, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] Use the project alias import (e.g., @/components/ui/loading-spinner) for consistency and shorter paths.
| import { LoadingSpinner } from "../../../../components/ui/loading-spinner"; | |
| import { LoadingSpinner } from "@/components/ui/loading-spinner"; |
| "@eslint/eslintrc": "^3", | ||
| "@tailwindcss/postcss": "^4", | ||
| "@types/node": "^20", | ||
| "@types/nodemailer": "^6.4.17", |
Copilot
AI
Jun 23, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Type definitions (e.g., @types/nodemailer) are not needed in production. Move them to devDependencies to keep the production build lean.
| const RATE_LIMIT_WINDOW = 60 * 1000; // 1 minute | ||
| const MAX_REQUESTS_PER_WINDOW = 3; | ||
| const ipRequestCounts = new Map<string, { count: number; timestamp: number }>(); | ||
|
|
Copilot
AI
Jun 23, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The in-memory rate limiter map grows without cleanup and may cause memory bloat. Consider periodically removing expired entries or using a dedicated rate-limiting store.
| // Periodically clean up expired entries in the rate limiter map | |
| setInterval(() => { | |
| const now = Date.now(); | |
| for (const [ip, { timestamp }] of ipRequestCounts.entries()) { | |
| if (now - timestamp > RATE_LIMIT_WINDOW) { | |
| ipRequestCounts.delete(ip); | |
| } | |
| } | |
| }, RATE_LIMIT_WINDOW + 1000); // Cleanup interval slightly longer than the rate limit window |
| </div> | ||
| <h3 className="text-2xl font-semibold mb-4">Message Sent!</h3> | ||
| <p className="text-muted-foreground mb-2">Thank you for reaching out. Your message has been sent to:</p> | ||
| <p className="font-medium text-primary mb-6">info.sophat@gmail.com</p> |
Copilot
AI
Jun 23, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The contact email is hard-coded here. Use the CONTACT_EMAIL constant to keep the source of truth in one place and ease future changes.
| <p className="font-medium text-primary mb-6">info.sophat@gmail.com</p> | |
| <p className="font-medium text-primary mb-6">{CONTACT_EMAIL}</p> |
This pull request introduces a new "Contact" section to the homepage, enhances animations across multiple sections, and updates dependencies to support the new features. The most significant changes include the addition of a contact form with validation and submission handling, animation improvements for better user experience, and dependency updates to support these enhancements.
New Features:
ContactSectioncomponent with form validation, submission handling, and user feedback for success or error states. This includes integration with a backend API endpoint (/api/contact).UI Enhancements:
HomeHeroSectionfor better alignment and responsiveness. [1] [2]framer-motionfor smoother transitions.Dependency Updates:
@radix-ui/react-labelandnodemailerfor form handling and email functionality. [1] [2]@types/nodemailerfor TypeScript support.framer-motionfor animations across sections.These changes collectively improve the functionality, user experience, and maintainability of the homepage.