Skip to content

Conversation

@pphatdev
Copy link
Owner

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:

  • Contact Section: Added a fully functional ContactSection component 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:

  • Hero Section: Adjusted layout and styling in HomeHeroSection for better alignment and responsiveness. [1] [2]
  • Projects Section: Improved layout and added animations using framer-motion for smoother transitions.
  • Timeline Section: Enhanced the "Work Experience" section with animations and updated layout for consistency with other sections. [1] [2]

Dependency Updates:

  • Added @radix-ui/react-label and nodemailer for form handling and email functionality. [1] [2]
  • Added @types/nodemailer for TypeScript support.
  • Incorporated framer-motion for animations across sections.

These changes collectively improve the functionality, user experience, and maintainability of the homepage.

pphatdev added 27 commits June 24, 2025 00:58
… structure and update header content for clarity
@pphatdev pphatdev requested a review from Copilot June 23, 2025 18:57
@pphatdev pphatdev self-assigned this Jun 23, 2025
@vercel
Copy link

vercel bot commented Jun 23, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
v4 ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jun 23, 2025 6:57pm

@pphatdev pphatdev merged commit 9767bb6 into master Jun 23, 2025
3 checks passed
Copy link
Contributor

Copilot AI left a 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 ContactSection component and /api/contact route with validation, rate limiting, and email sending
  • Wrapped Hero, Timeline, Projects, and Contact sections in animated motion wrappers for smoother entry effects
  • Added nodemailer (plus types) and @radix-ui/react-label to 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 dotenv and 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'>
Copy link

Copilot AI Jun 23, 2025

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').

Suggested change
<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'>

Copilot uses AI. Check for mistakes.
<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">
Copy link

Copilot AI Jun 23, 2025

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.

Suggested change
<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">

Copilot uses AI. Check for mistakes.
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";
Copy link

Copilot AI Jun 23, 2025

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.

Suggested change
import { LoadingSpinner } from "../../../../components/ui/loading-spinner";
import { LoadingSpinner } from "@/components/ui/loading-spinner";

Copilot uses AI. Check for mistakes.
"@eslint/eslintrc": "^3",
"@tailwindcss/postcss": "^4",
"@types/node": "^20",
"@types/nodemailer": "^6.4.17",
Copy link

Copilot AI Jun 23, 2025

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.

Copilot uses AI. Check for mistakes.
const RATE_LIMIT_WINDOW = 60 * 1000; // 1 minute
const MAX_REQUESTS_PER_WINDOW = 3;
const ipRequestCounts = new Map<string, { count: number; timestamp: number }>();

Copy link

Copilot AI Jun 23, 2025

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.

Suggested change
// 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

Copilot uses AI. Check for mistakes.
</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>
Copy link

Copilot AI Jun 23, 2025

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.

Suggested change
<p className="font-medium text-primary mb-6">info.sophat@gmail.com</p>
<p className="font-medium text-primary mb-6">{CONTACT_EMAIL}</p>

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant