Skip to content

fix: redesign contact page as multi-section premium component layout#186

Open
Shivangi1515 wants to merge 5 commits into
kunalverma2512:mainfrom
Shivangi1515:fix/redesign-Contactpage
Open

fix: redesign contact page as multi-section premium component layout#186
Shivangi1515 wants to merge 5 commits into
kunalverma2512:mainfrom
Shivangi1515:fix/redesign-Contactpage

Conversation

@Shivangi1515

@Shivangi1515 Shivangi1515 commented Jun 12, 2026

Copy link
Copy Markdown

📌 Pull Request Summary

🔗 Related Issue

Closes #183


📝 Description

Completely redesigned the Contact page into a multi-section, component-driven, premium communication hub that matches the quality of the rest of the CodeLens product. The new layout offers contextual information, multiple contact channels, a smart dynamic form, project trust signals, and a delightful success state.

Changes Made

  • Replaced the single-form Contact page with a 6-component modular architecture under frontend/src/components/contact/
  • Added ContactHero.jsx — left-aligned hero with heading, welcome subtext, and animated green availability badge ("Usually replies within 24 hours")
  • Added ContactChannelCards.jsx — 4 premium cards (Email, GitHub Issues, GitHub Discussions, Discord) with thin borders, subtle hover lift, and external links
  • Added ContactForm.jsx — dynamic category selector (Bug Report, Feature Request, Partnership, General) that progressively discloses relevant fields, real-time email validation with green checkmark, character counters, auto-growing textarea, accessible labels, and loading state on submit
  • Added ContactSidebar.jsx — sticky sidebar with availability signal, timezone (IST / UTC+5:30), live GitHub API stats (stars, forks, open issues) with loading skeleton and error handling, plus a builder card
  • Added ContactFAQ.jsx — accessible accordion with 5 developer-focused questions, smooth CSS expand/collapse, chevron rotation, and single-open behavior
  • Added ContactSuccessState.jsx — animated checkmark via framer-motion, submitted category, estimated response time, and action buttons (Dashboard, GitHub Issues, Send Another Message)
  • Rewrote Contact.jsx to only import and compose the 6 components — zero UI logic in the page file

Motivation

The previous Contact page was a minimal single-form layout with no contextual information, no alternative contact channels, and no visual hierarchy. It did not reflect the quality of the rest of CodeLens and failed to communicate trust, response expectations, or developer-preferred support channels. This redesign brings the page up to the same premium standard as the rest of the product.


🚀 Type of Change

Select all that apply:

  • Bug Fix
  • New Feature
  • Enhancement
  • Documentation Update
  • Refactoring
  • Performance Improvement
  • DevOps / Tooling
  • Other

🧪 Testing

Verification

  • Tested Locally
  • Existing Tests Passed
  • New Tests Added
  • No Testing Required

Test Details

  • Build (npm run build) passes with zero errors
  • Lint (eslint) passes with zero errors
  • Dev server runs without console warnings or errors
  • Responsive at 375px, 768px, 1024px, 1280px, and 1600px verified
  • All form categories switch fields correctly
  • GitHub API stats load with skeleton and handle errors gracefully
  • FAQ accordion expands/collapses smoothly
  • Success state replaces form after simulated submission

📸 Screenshots / Demo (If Applicable)

Screenshot 2026-06-12 142412 Screenshot 2026-06-12 142808 Screenshot 2026-06-12 142454

✅ Checklist

  • I have read and followed the contribution guidelines.
  • I have self-reviewed my changes.
  • My changes are limited to the scope of this issue.
  • Documentation has been updated where necessary.
  • No unnecessary files or unrelated changes have been included.
  • The related issue has been linked correctly.
  • All applicable testing and validation steps have been completed.

📚 Additional Notes

  • Tailwind CSS only — no CSS files, CSS modules, styled-components, or inline styles
  • Single accent color (green/emerald) used for: active category, availability dot, submit button, success checkmark, and focus rings
  • Black & white makes up ~98% of the interface
  • Respects prefers-reduced-motion throughout
  • Fully keyboard accessible with ARIA labels and visible focus rings

Summary by CodeRabbit

  • New Features
    • Updated Contact hero with a “reply within 24 hours” status indicator
    • New category-based contact form with required-field + email validation, character counts, and success screen with navigation and reset options
    • Added a FAQ accordion for common questions
    • Added contact channel cards linking to Email, GitHub Issues, and Feature Requests
    • Added a Contact sidebar with availability/timezone and GitHub repository stats (loading/error states included)
  • Refactor
    • Reorganized the Contact page into separate sections and refreshed the page title/description

@vercel

vercel Bot commented Jun 12, 2026

Copy link
Copy Markdown

@Shivangi1515 is attempting to deploy a commit to the Kunal Verma's projects Team on Vercel.

A member of the Team first needs to authorize it.

@github-actions

Copy link
Copy Markdown

🚀 PR Received Successfully

Hello @Shivangi1515,

Thank you for taking the initiative to contribute to this project.

Please ensure that your PR follows all project guidelines properly before requesting review.

⚠️ Important Instructions

  • Maintain proper code quality and structure
  • Do not make unnecessary changes/files
  • Ensure responsiveness across devices
  • Follow existing project conventions strictly
  • Attach screenshots/videos for UI-related changes
  • Resolve merge conflicts before requesting review
  • Avoid AI-generated low quality PRs or copied implementations

📌 Mandatory for GSSoC'26 Participants

Joining the community group and announcement channel is compulsory for all contributors participating through GSSoC'26.

Failure to follow contribution guidelines may lead to PR rejection.

We appreciate your effort and wish you a great open-source journey ahead. ✨

@coderabbitai

coderabbitai Bot commented Jun 12, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@Shivangi1515, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 43 minutes and 11 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more credits in the billing tab to continue.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 04d2df20-f88b-4e39-973c-9dd6fe125996

📥 Commits

Reviewing files that changed from the base of the PR and between 594a99c and 739e279.

📒 Files selected for processing (1)
  • frontend/src/components/contact/ContactForm.jsx
📝 Walkthrough

Walkthrough

Refactors the Contact page into six focused components (Hero, ChannelCards, Form, Sidebar, FAQ, SuccessState). Implements category-driven form schemas and validation, GitHub repo stats fetching with caching and error handling, accessible FAQ accordion, and an animated post-submit success state; the page composes these components.

Changes

Contact Page Component-Driven Architecture

Layer / File(s) Summary
Hero and Channel Cards
frontend/src/components/contact/ContactHero.jsx, frontend/src/components/contact/ContactChannelCards.jsx
ContactHero renders heading, description, and an animated green response-time indicator badge. ContactChannelCards defines a channels array (Email, GitHub Issues, Feature Request) and maps it to responsive Tailwind grid of linked anchor cards with icons and target="_blank" behavior.
Form schema and input components
frontend/src/components/contact/ContactForm.jsx (lines 1–176)
Adds category-driven form configuration (email regex, per-category default values, field labels, input types, max lengths). Implements AutoTextarea component with dynamic height resizing and TextInput component with conditional email validity checkmark.
Form validation helpers and state handlers
frontend/src/components/contact/ContactForm.jsx (lines 78–243)
Validation helper functions (validateEmail, per-field validation messages, overall form validity checks). Form state initialization and handlers: category selection, field values and errors tracking, touched field management, change/blur validation, and submit prevention when form is invalid.
Form UI rendering and animations
frontend/src/components/contact/ContactForm.jsx (lines 244–379)
Renders category selector buttons, dynamically maps form fields to AutoTextarea or TextInput based on configuration, computes and displays per-field error/success states with inline error messages and textarea character counts. Animates transition between form and success state using AnimatePresence and framer-motion.
Success state and post-submit actions
frontend/src/components/contact/ContactSuccessState.jsx
Maps submitted category to estimated RESPONSE_TIME, renders Framer Motion animated success checkmark, displays "Message sent!" heading with category confirmation. Provides post-submit actions: navigate to /dashboard, open GitHub issues link, and "Send Another Message" button wired to onReset.
Sidebar: static cards and GitHub stats
frontend/src/components/contact/ContactSidebar.jsx
Composes Availability and Timezone cards (static IST/UTC+5:30), GitHubStats component (fetches hardcoded repo data from GitHub REST API with module-level Map cache using 5-minute TTL, checks X-RateLimit-Remaining header, handles errors, and shows loading skeletons), and Builder card with author details.
FAQ accordion
frontend/src/components/contact/ContactFAQ.jsx
Defines FAQS constant with question/answer pairs. Implements accessible accordion with openIndex state, memoized toggle callback, stable aria-controls/aria-labelledby ids, aria-expanded and aria-hidden attributes, and animated expand/collapse behavior via conditional CSS classes.
Contact page composition
frontend/src/pages/Contact.jsx
Imports all six subcomponents and composes them into a multi-section layout with separate form and sidebar blocks, followed by FAQ. Updates document <title> and description <meta> content. Removes previous inline hero/channel/form markup and local submit handler.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant ContactForm
  participant FormValidation
  participant ContactSuccessState
  participant GitHubStatsAPI
  
  User->>ContactForm: Select category & fill fields
  ContactForm->>FormValidation: Validate on change/blur
  FormValidation-->>ContactForm: Return errors & touched state
  User->>ContactForm: Submit (enabled when valid)
  ContactForm->>ContactForm: Prevent default, show alert
  ContactForm->>ContactSuccessState: AnimatePresence → success UI
  ContactSuccessState->>User: Display category & response time
  User->>ContactSuccessState: Click "Send Another Message"
  ContactSuccessState-->>ContactForm: onReset callback
  Note over GitHubStatsAPI: GitHubStats runs on mount, fetches repo stats with cache/TTL
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • kunalverma2512/CodeLens#153: Introduced the initial /contact page and route that this PR refactors into component-driven architecture.
  • kunalverma2512/CodeLens#50: Adds client-side email validation logic and submission-blocking with inline error handling, similar patterns applied to ContactForm in this PR.

Suggested labels

UI/UX, responsive, quality:exceptional, type:accessibility, type:refactor

Suggested reviewers

  • kunalverma2512

Poem

🐰 A rabbit hops through code so bright,
Cards and FAQs arranged just right.
A sidebar counts the stars we see,
A form that folds to victory—
Send another message—pure delight! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: a redesign of the contact page into a multi-section, component-driven premium layout.
Description check ✅ Passed The PR description comprehensively covers objectives, changes, motivation, testing, and includes all required template sections with detailed information and screenshots.
Linked Issues check ✅ Passed All six required components (ContactHero, ContactChannelCards, ContactForm, ContactSidebar, ContactFAQ, ContactSuccessState) are implemented with their specified behaviors, and Contact.jsx was refactored to only compose components.
Out of Scope Changes check ✅ Passed All changes are within scope: six new contact components, Contact.jsx refactoring, and removal of previous inline markup and handlers. No unrelated modifications detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (8)
frontend/src/components/contact/ContactForm.jsx (4)

117-127: ⚡ Quick win

Remove unused ref.

The ref is created and attached to the textarea but never read or accessed. Line 119 uses e.target directly to manipulate the element's height, making the ref unnecessary.

♻️ Proposed cleanup
 function AutoTextarea({ value, onChange, onBlur, maxLength, id, name, required, placeholder, hasError, hasSuccess }) {
-  const ref = useRef(null);
   const handleInput = useCallback((e) => {
     const el = e.target;
     el.style.height = "auto";
     el.style.height = el.scrollHeight + "px";
     onChange(e);
   }, [onChange]);

   return (
     <textarea
-      ref={ref}
       id={id}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/components/contact/ContactForm.jsx` around lines 117 - 127, The
ref named "ref" is created with useRef and attached to the textarea but never
used; remove the unused ref declaration and its ref={ref} prop to clean up the
component, and ensure handleInput continues to use e.target for resizing (refer
to useRef(null), ref, handleInput, and the textarea JSX to locate and remove the
unused pieces).

244-247: ⚡ Quick win

Unnecessary useCallback wrapping.

currentMaxLength has no dependencies and only reads from the module-level FIELD_MAX_LENGTH constant. Wrapping it in useCallback adds no value since the function has no closure over component state.

♻️ Proposed simplification

Move to module scope:

+const getMaxLength = (fieldName) => FIELD_MAX_LENGTH[fieldName] || 2000;
+
 export default function ContactForm() {
   // ...
-  const currentMaxLength = useCallback(
-    (fieldName) => FIELD_MAX_LENGTH[fieldName] || 2000,
-    [],
-  );

Then use getMaxLength(name) instead of currentMaxLength(name) on line 290.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/components/contact/ContactForm.jsx` around lines 244 - 247,
Remove the unnecessary useCallback wrapper around currentMaxLength: extract a
pure helper function (e.g., getMaxLength(fieldName)) to module scope that
returns FIELD_MAX_LENGTH[fieldName] || 2000, delete the currentMaxLength hook,
and update all local references (calls to currentMaxLength(...) — e.g., where
it’s used around line 290) to call getMaxLength(...) instead.

2-3: ⚡ Quick win

Remove incorrect eslint-disable comment.

The eslint-disable-line no-unused-vars comment on line 2 claims framer-motion is unused, but both AnimatePresence (line 250) and motion (lines 252, 262) are actively used throughout the file. This comment is misleading and should be removed.

🧹 Proposed fix
-// eslint-disable-next-line no-unused-vars
-import { AnimatePresence, motion } from "framer-motion";
+import { AnimatePresence, motion } from "framer-motion";
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/components/contact/ContactForm.jsx` around lines 2 - 3, Remove
the incorrect eslint-disable comment that suppresses the no-unused-vars rule for
the framer-motion import; the file does use AnimatePresence and motion
(referenced in AnimatePresence and motion usage around the ContactForm
component), so delete the line "// eslint-disable-next-line no-unused-vars"
above the import of { AnimatePresence, motion } from "framer-motion" so ESLint
correctly reflects actual usage.

83-104: ⚡ Quick win

Simplify validator factory.

buildValidator is a factory function that takes no arguments and closes over no variables. The wrapper adds unnecessary indirection. Consider defining validateField directly at module scope.

♻️ Proposed simplification
-function buildValidator() {
-  return function validateField(name, value) {
+function validateField(name, value) {
     if (name === "email") {
       if (!value) return "Email is required";
       if (!validateEmail(value)) return "Invalid email address";
     }
     // ... rest of validation
     return null;
-  };
-}
+}

Then update line 187:

-  const validate = useMemo(() => buildValidator(), []);
+  const validate = validateField;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/components/contact/ContactForm.jsx` around lines 83 - 104, The
buildValidator wrapper is unnecessary because it takes no args or closed-over
state; replace it by defining validateField at module scope (move the inner
function out and remove buildValidator), then update all call sites that
currently invoke buildValidator() to call validateField directly (e.g., where
buildValidator() was used in ContactForm.jsx). Keep the exact validation logic
(email/name/company/platform/message/stepsToReproduce/expectedBehavior/actualBehavior/description/proposal
checks) intact when moving the function.
frontend/src/components/contact/ContactSuccessState.jsx (3)

82-99: 💤 Low value

Consider extracting GitHub URL to a constant.

The GitHub repository URL is hardcoded on line 83. For better maintainability, especially if this URL is used elsewhere (e.g., in ContactChannelCards), consider extracting it to a shared constant or configuration file.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/components/contact/ContactSuccessState.jsx` around lines 82 -
99, Extract the hardcoded GitHub URL used in the ContactSuccessState component
into a shared constant (e.g., GITHUB_REPO_URL) in a central config or constants
module and import it into ContactSuccessState.jsx; replace the href value on the
anchor element in the ContactSuccessState component with the imported constant
so other components (like ContactChannelCards) can reuse the same constant and
you avoid duplicated hardcoded URLs.

1-2: ⚡ Quick win

Remove incorrect eslint-disable comment.

The eslint-disable-line no-unused-vars comment claims motion is unused, but motion.div, motion.svg, and motion.path are used throughout the component (lines 18, 24, 38). This comment should be removed.

🧹 Proposed fix
-// eslint-disable-next-line no-unused-vars
-import { motion } from "framer-motion";
+import { motion } from "framer-motion";
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/components/contact/ContactSuccessState.jsx` around lines 1 - 2,
Remove the incorrect eslint-disable comment before the motion import in
ContactSuccessState.jsx: delete the line "// eslint-disable-next-line
no-unused-vars" that precedes "import { motion } from 'framer-motion'"; confirm
that the component continues to use motion via motion.div, motion.svg, and
motion.path so no eslint suppression is needed and no other unused-vars disables
are left in the file.

24-44: ⚡ Quick win

Remove redundant pathLength animation on svg element.

Lines 34-36 define a pathLength animation on the motion.svg element, but pathLength is a property of SVG path elements, not the svg container itself. The working animation is on the motion.path element (lines 40-42). The svg-level animation properties are ineffective and should be removed to avoid confusion.

♻️ Proposed cleanup
       <motion.svg
         width="24"
         height="24"
         viewBox="0 0 24 24"
         fill="none"
         stroke="currentColor"
         strokeWidth="3"
         strokeLinecap="round"
         strokeLinejoin="round"
         className="text-emerald-600"
-        initial={{ pathLength: 0 }}
-        animate={{ pathLength: 1 }}
-        transition={{ duration: 0.5, delay: 0.2, ease: "easeOut" }}
       >
         <motion.path
           d="M5 13l4 4L19 7"
           initial={{ pathLength: 0 }}
           animate={{ pathLength: 1 }}
           transition={{ duration: 0.5, delay: 0.2, ease: "easeOut" }}
         />
       </motion.svg>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/components/contact/ContactSuccessState.jsx` around lines 24 -
44, The motion.svg element in ContactSuccessState.jsx is incorrectly given
pathLength animation props (initial/animate transition using pathLength) which
are only effective on SVG path elements; remove the redundant
initial/animate/transition that reference pathLength from the motion.svg element
so the animation is only applied on the motion.path (d="M5 13l4 4L19 7") and
keep the existing animation props on motion.path; ensure only motion.path uses
initial={{ pathLength: 0 }} animate={{ pathLength: 1 }} transition={{ ... }} and
delete those same props from motion.svg to avoid confusion.
frontend/src/components/contact/ContactSidebar.jsx (1)

57-58: 💤 Low value

Optional: Log errors to aid debugging.

The empty catch block silently swallows errors, making it harder to diagnose issues during development (e.g., network failures, API changes, CORS problems).

🔍 Suggested enhancement
       } catch {
+        console.error('Failed to fetch GitHub stats:', error);
         if (!cancelled) setError(true);
       } finally {

Alternatively, integrate with an error tracking service (e.g., Sentry) for production error monitoring.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/components/contact/ContactSidebar.jsx` around lines 57 - 58, The
catch block in ContactSidebar.jsx currently swallows errors; change it to accept
the error (e.g., "catch (err)") and log the error (e.g., console.error or send
to your Sentry/logger) while preserving the existing cancelled check and
setError(true) call; update the catch surrounding the async logic that uses the
"cancelled" variable and "setError" so errors are visible in dev and optionally
forwarded to your monitoring service.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@frontend/src/components/contact/ContactChannelCards.jsx`:
- Line 26: The Discord card currently uses a placeholder href ("#") in the
ContactChannelCards component (and the Footer component has the same
placeholder); update the Discord link to the real invite URL or hide/disable the
Discord card until a valid invite is available by replacing the placeholder href
in the Discord card JSX (look for the Discord card render inside
ContactChannelCards.jsx and Footer.jsx) with the actual invite URL constant or
conditional rendering that omits the card when no DISCORD_INVITE is provided;
ensure you reference a single source (e.g., a DISCORD_INVITE env constant or
prop) so both components use the same real link or both hide when it's absent.

In `@frontend/src/components/contact/ContactSidebar.jsx`:
- Around line 45-68: ContactSidebar.jsx currently calls GitHub API directly
inside fetchStats which causes unauthenticated rate-limit failures and swallows
errors; change fetchStats to call a new server-side cached public endpoint (e.g.
GET /api/public/github-stats) or implement a short client TTL cache keyed by
repo (store timestamp + stats) before falling back to network, and update UI via
setStats/setError/setLoading accordingly; also surface a graceful "try again
later" message when X-RateLimit-Remaining is low or failed, and log the caught
error (e.g. console.error) instead of swallowing it so failures are visible for
debugging.

---

Nitpick comments:
In `@frontend/src/components/contact/ContactForm.jsx`:
- Around line 117-127: The ref named "ref" is created with useRef and attached
to the textarea but never used; remove the unused ref declaration and its
ref={ref} prop to clean up the component, and ensure handleInput continues to
use e.target for resizing (refer to useRef(null), ref, handleInput, and the
textarea JSX to locate and remove the unused pieces).
- Around line 244-247: Remove the unnecessary useCallback wrapper around
currentMaxLength: extract a pure helper function (e.g., getMaxLength(fieldName))
to module scope that returns FIELD_MAX_LENGTH[fieldName] || 2000, delete the
currentMaxLength hook, and update all local references (calls to
currentMaxLength(...) — e.g., where it’s used around line 290) to call
getMaxLength(...) instead.
- Around line 2-3: Remove the incorrect eslint-disable comment that suppresses
the no-unused-vars rule for the framer-motion import; the file does use
AnimatePresence and motion (referenced in AnimatePresence and motion usage
around the ContactForm component), so delete the line "//
eslint-disable-next-line no-unused-vars" above the import of { AnimatePresence,
motion } from "framer-motion" so ESLint correctly reflects actual usage.
- Around line 83-104: The buildValidator wrapper is unnecessary because it takes
no args or closed-over state; replace it by defining validateField at module
scope (move the inner function out and remove buildValidator), then update all
call sites that currently invoke buildValidator() to call validateField directly
(e.g., where buildValidator() was used in ContactForm.jsx). Keep the exact
validation logic
(email/name/company/platform/message/stepsToReproduce/expectedBehavior/actualBehavior/description/proposal
checks) intact when moving the function.

In `@frontend/src/components/contact/ContactSidebar.jsx`:
- Around line 57-58: The catch block in ContactSidebar.jsx currently swallows
errors; change it to accept the error (e.g., "catch (err)") and log the error
(e.g., console.error or send to your Sentry/logger) while preserving the
existing cancelled check and setError(true) call; update the catch surrounding
the async logic that uses the "cancelled" variable and "setError" so errors are
visible in dev and optionally forwarded to your monitoring service.

In `@frontend/src/components/contact/ContactSuccessState.jsx`:
- Around line 82-99: Extract the hardcoded GitHub URL used in the
ContactSuccessState component into a shared constant (e.g., GITHUB_REPO_URL) in
a central config or constants module and import it into ContactSuccessState.jsx;
replace the href value on the anchor element in the ContactSuccessState
component with the imported constant so other components (like
ContactChannelCards) can reuse the same constant and you avoid duplicated
hardcoded URLs.
- Around line 1-2: Remove the incorrect eslint-disable comment before the motion
import in ContactSuccessState.jsx: delete the line "// eslint-disable-next-line
no-unused-vars" that precedes "import { motion } from 'framer-motion'"; confirm
that the component continues to use motion via motion.div, motion.svg, and
motion.path so no eslint suppression is needed and no other unused-vars disables
are left in the file.
- Around line 24-44: The motion.svg element in ContactSuccessState.jsx is
incorrectly given pathLength animation props (initial/animate transition using
pathLength) which are only effective on SVG path elements; remove the redundant
initial/animate/transition that reference pathLength from the motion.svg element
so the animation is only applied on the motion.path (d="M5 13l4 4L19 7") and
keep the existing animation props on motion.path; ensure only motion.path uses
initial={{ pathLength: 0 }} animate={{ pathLength: 1 }} transition={{ ... }} and
delete those same props from motion.svg to avoid confusion.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3ee13742-b0b3-4f78-9e73-c90e7c23e2d2

📥 Commits

Reviewing files that changed from the base of the PR and between 58213ea and a6fd07c.

📒 Files selected for processing (7)
  • frontend/src/components/contact/ContactChannelCards.jsx
  • frontend/src/components/contact/ContactFAQ.jsx
  • frontend/src/components/contact/ContactForm.jsx
  • frontend/src/components/contact/ContactHero.jsx
  • frontend/src/components/contact/ContactSidebar.jsx
  • frontend/src/components/contact/ContactSuccessState.jsx
  • frontend/src/pages/Contact.jsx

Comment thread frontend/src/components/contact/ContactChannelCards.jsx Outdated
Comment thread frontend/src/components/contact/ContactSidebar.jsx
@kunalverma2512

kunalverma2512 commented Jun 12, 2026

Copy link
Copy Markdown
Owner

@Shivangi1515 Fantastic work

Still some more changes needed before final merge

  1. remove green colors (i.e use only black and white) from everywhere except that bullet dot
  2. for bullet dot - use some more darker shade of green but not too much darker
  3. remove rounded corners
  4. make every section height and width to 100% and make sure every section must be fully responsive
  5. Change the plan to not to go with sidebar and dettach from other components and shift it to downward with 100 % height and 100% width
  6. contact form should be the second section as we dont want that user must scroll a lot for getting that form
  7. wherever it is possible to have largest heading then go with more font size but make sure to make it resposnive when seen on different devises like phone,etc
  8. please make the content more confident , bold , attractive
  9. remove discord

@kunalverma2512

Copy link
Copy Markdown
Owner

@Shivangi1515 you can support this project by starring the repository

Also if you are working on what I said before then just write a ping message so as to know whether you started or not

@Shivangi1515

Shivangi1515 commented Jun 12, 2026 via email

Copy link
Copy Markdown
Author

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (4)
frontend/src/components/contact/ContactSuccessState.jsx (4)

18-45: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Respect prefers-reduced-motion for animations.

The PR objectives explicitly require "minimal motion respecting prefers-reduced-motion," but the scale and path-drawing animations run unconditionally. Users with motion sensitivity will experience the full animations.

[accessibility]

♿ Proposed fix to respect motion preferences
 export default function ContactSuccessState({ category, onReset }) {
   const navigate = useNavigate();
+  const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;

   return (
     <div className="flex flex-col items-start">
       <motion.div
-        initial={{ scale: 0 }}
-        animate={{ scale: 1 }}
-        transition={{ type: "spring", stiffness: 260, damping: 20 }}
+        initial={prefersReducedMotion ? { scale: 1 } : { scale: 0 }}
+        animate={{ scale: 1 }}
+        transition={prefersReducedMotion ? { duration: 0 } : { type: "spring", stiffness: 260, damping: 20 }}
         className="flex h-14 w-14 items-center justify-center bg-neutral-100 mb-6"
       >
         <motion.svg
           ...
-          initial={{ pathLength: 0 }}
-          animate={{ pathLength: 1 }}
-          transition={{ duration: 0.5, delay: 0.2, ease: "easeOut" }}
+          initial={prefersReducedMotion ? { pathLength: 1 } : { pathLength: 0 }}
+          animate={{ pathLength: 1 }}
+          transition={prefersReducedMotion ? { duration: 0 } : { duration: 0.5, delay: 0.2, ease: "easeOut" }}
         >
           <motion.path
             d="M5 13l4 4L19 7"
-            initial={{ pathLength: 0 }}
-            animate={{ pathLength: 1 }}
-            transition={{ duration: 0.5, delay: 0.2, ease: "easeOut" }}
+            initial={prefersReducedMotion ? { pathLength: 1 } : { pathLength: 0 }}
+            animate={{ pathLength: 1 }}
+            transition={prefersReducedMotion ? { duration: 0 } : { duration: 0.5, delay: 0.2, ease: "easeOut" }}
           />
         </motion.svg>
       </motion.div>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/components/contact/ContactSuccessState.jsx` around lines 18 -
45, The animations in ContactSuccessState.jsx (the motion.div, motion.svg and
motion.path elements) ignore users' prefers-reduced-motion; use Framer Motion's
useReducedMotion (or window.matchMedia) to detect reduced motion and, when true,
disable or short-circuit the animations by providing non-animating props (e.g.,
set initial/animate to the final state: scale: 1 and pathLength: 1, omit
transitions or set duration 0) for those symbols so the check occurs before
rendering and avoids running spring/path-draw animations for motion-sensitive
users.

65-67: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add fallback for undefined response time.

If an invalid category is passed (one not defined in RESPONSE_TIME), line 66 will render undefined. While the current form implementation passes valid categories, defensive coding suggests adding a fallback.

🛡️ Proposed fix to add fallback
           <p className="text-sm font-medium text-neutral-900">
-            {RESPONSE_TIME[category]}
+            {RESPONSE_TIME[category] || "We'll respond as soon as possible"}
           </p>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/components/contact/ContactSuccessState.jsx` around lines 65 -
67, The rendering of RESPONSE_TIME[category] in ContactSuccessState.jsx can
produce undefined for unknown categories; update the display to use a safe
fallback (e.g., 'N/A' or a localized fallback string) when
RESPONSE_TIME[category] is falsy/undefined. Locate the JSX that references
RESPONSE_TIME[category] (inside the <p> with className "text-sm font-medium
text-neutral-900") and replace the direct lookup with a fallback expression so
the UI never renders "undefined" for invalid category values.

24-44: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add accessible label to the success checkmark icon.

The animated checkmark SVG has no ARIA attributes, so screen reader users won't receive feedback that the message was successfully sent.

[accessibility]

♿ Proposed fix to add ARIA label
         <motion.svg
           width="24"
           height="24"
           viewBox="0 0 24 24"
           fill="none"
           stroke="currentColor"
           strokeWidth="3"
           strokeLinecap="round"
           strokeLinejoin="round"
           className="text-neutral-900"
+          role="img"
+          aria-label="Success"
           initial={{ pathLength: 0 }}
           animate={{ pathLength: 1 }}
           transition={{ duration: 0.5, delay: 0.2, ease: "easeOut" }}
         >
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/components/contact/ContactSuccessState.jsx` around lines 24 -
44, The animated checkmark SVG in ContactSuccessState.jsx (the motion.svg
element) lacks ARIA labeling; add an accessible name by giving the motion.svg a
role="img" and either an aria-label (e.g., "Message sent") or aria-labelledby
pointing to a <title> text node, and mark the decorative path (motion.path) as
aria-hidden="true" so screen readers read only the SVG label; update the
motion.svg attributes (role/aria-label or aria-labelledby) and add a <title>
element or aria-label accordingly while keeping motion.path aria-hidden.

1-2: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Remove the incorrect eslint-disable comment.

The motion import is actively used throughout the component (lines 18-44), so the no-unused-vars suppression is incorrect and should be removed.

🧹 Proposed fix
-// eslint-disable-next-line no-unused-vars
 import { motion } from "framer-motion";
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/components/contact/ContactSuccessState.jsx` around lines 1 - 2,
Remove the incorrect eslint suppression above the motion import: delete the
comment "// eslint-disable-next-line no-unused-vars" so the import line remains
"import { motion } from 'framer-motion';" (the component uses motion in
ContactSuccessState.jsx across the animated JSX). Ensure no other unused-vars
disable comments remain for that import and run lint to confirm.
♻️ Duplicate comments (1)
frontend/src/components/contact/ContactSidebar.jsx (1)

65-70: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Check HTTP status codes for rate-limit detection instead of relying on header value.

The current logic checks rateLimitRemaining === "0" after a failed response, but if the X-RateLimit-Remaining header is missing or null (edge case), the check fails silently and falls through to the generic error message. Checking res.status === 403 || res.status === 429 is more robust and doesn't depend on header presence.

🛡️ Proposed fix
-        if (!res.ok) {
-          if (rateLimitRemaining === "0") {
-            throw new Error("Rate limit exceeded. Please try again later.");
-          }
-          throw new Error(`GitHub API responded with ${res.status}`);
-        }
+        if (!res.ok) {
+          if (res.status === 403 || res.status === 429) {
+            throw new Error("Rate limit exceeded. Please try again later.");
+          }
+          throw new Error(`GitHub API responded with ${res.status}`);
+        }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/components/contact/ContactSidebar.jsx` around lines 65 - 70, The
error handling uses rateLimitRemaining to detect rate limits which can be
missing; update the failure branch in ContactSidebar.jsx (the block using res
and rateLimitRemaining) to check HTTP status codes instead: if res.status ===
403 || res.status === 429 then throw the "Rate limit exceeded. Please try again
later." error, otherwise throw the generic `GitHub API responded with
${res.status}` error; keep using rateLimitRemaining as supplemental information
if present but do not rely on it as the primary check.
🧹 Nitpick comments (3)
frontend/src/components/contact/ContactChannelCards.jsx (1)

32-51: 💤 Low value

Consider adding screen-reader indication for external links.

The channel cards open in new tabs (via target="_blank"), and the ArrowUpRight icon provides a visual cue. For screen-reader users, consider adding an aria-label that mentions the link opens externally.

♿ Optional enhancement for screen-reader users
              <a
                key={channel.title}
                href={channel.href}
                target="_blank"
                rel="noopener noreferrer"
+               aria-label={`${channel.title} (opens in new tab)`}
                className="group relative flex flex-col border border-neutral-200 bg-white p-5 shadow-sm transition-all duration-200 hover:-translate-y-0.5 hover:scale-[1.01] hover:shadow-md focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-neutral-900 focus-visible:ring-offset-2"
              >
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/components/contact/ContactChannelCards.jsx` around lines 32 -
51, Add an accessible label to the channel card anchor so screen readers know
the link opens in a new tab: update the anchor used in ContactChannelCards.jsx
(the <a> that uses channel.href and target="_blank") to include an aria-label
that composes channel.title plus a suffix like "opens in a new tab" (or
reference a visually-hidden text via aria-describedby); ensure the ArrowUpRight
visual cue is preserved and the rel attribute remains "noopener noreferrer".
frontend/src/components/contact/ContactSuccessState.jsx (2)

82-82: ⚡ Quick win

Consider making the GitHub repository URL configurable.

The GitHub Issues URL is hardcoded. If the repository is forked or the owner changes, this link will break. Consider moving it to a configuration constant or environment variable.

♻️ Suggested approach

Create a config file or add to an existing one:

// config/constants.js or similar
export const GITHUB_REPO = {
  owner: 'kunalverma2512',
  repo: 'CodeLens'
};
export const GITHUB_ISSUES_URL = `https://github.com/${GITHUB_REPO.owner}/${GITHUB_REPO.repo}/issues`;

Then import and use:

+import { GITHUB_ISSUES_URL } from '../../config/constants';

 <a
-  href="https://github.com/kunalverma2512/CodeLens/issues"
+  href={GITHUB_ISSUES_URL}
   target="_blank"
   rel="noopener noreferrer"
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/components/contact/ContactSuccessState.jsx` at line 82, The
hardcoded GitHub issues link in ContactSuccessState.jsx (the href
"https://github.com/kunalverma2512/CodeLens/issues") should be made
configurable: add a constant (e.g., GITHUB_ISSUES_URL) in a shared config module
(or read from an env var like REACT_APP_GITHUB_ISSUES_URL) and import it into
ContactSuccessState.jsx, then replace the literal href with that constant;
ensure the config exports GITHUB_REPO owner/repo or a full URL and add a
sensible default so forks or owner changes don’t break the link.

88-97: 💤 Low value

Consider using lucide-react's Github icon for consistency.

The component imports ArrowRight from lucide-react but uses an inline SVG for the GitHub icon. Using lucide-react's Github icon would improve consistency and reduce code.

♻️ Proposed refactor
-import { ArrowRight } from "lucide-react";
+import { ArrowRight, Github } from "lucide-react";

 <a
   ...
   className="inline-flex items-center gap-2 border border-neutral-200 bg-white px-5 py-2.5 text-sm font-medium text-neutral-700 shadow-sm transition-all duration-200 hover:border-neutral-300 hover:shadow-md focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-neutral-900 focus-visible:ring-offset-2"
 >
   Check GitHub Issues
-  <svg
-    width="16"
-    height="16"
-    viewBox="0 0 24 24"
-    fill="currentColor"
-    aria-hidden="true"
-    className="text-neutral-400"
-  >
-    <path d="M12 0C5.37 0 0 5.37 0 12c0 5.31 3.435 9.795 8.205 11.385.6.105.825-.255.825-.57 0-.285-.015-1.23-.015-2.235-3.015.555-3.795-.735-4.035-1.41-.135-.345-.72-1.41-1.23-1.695-.42-.225-1.02-.78-.015-.795.945-.015 1.62.87 1.845 1.23 1.08 1.815 2.805 1.305 3.495.99.105-.78.42-1.305.765-1.605-2.67-.3-5.46-1.335-5.46-5.925 0-1.305.465-2.385 1.23-3.225-.12-.3-.54-1.53.12-3.18 0 0 1.005-.315 3.3 1.23.96-.27 1.98-.405 3-.405s2.04.135 3 .405c2.295-1.56 3.3-1.23 3.3-1.23.66 1.65.24 2.88.12 3.18.765.84 1.23 1.905 1.23 3.225 0 4.605-2.805 5.625-5.475 5.925.435.375.81 1.095.81 2.22 0 1.605-.015 2.895-.015 3.3 0 .315.225.69.825.57A12.02 12.02 0 0 0 24 12c0-6.63-5.37-12-12-12z" />
-  </svg>
+  <Github className="h-4 w-4 text-neutral-400" />
 </a>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/components/contact/ContactSuccessState.jsx` around lines 88 -
97, The component is using an inline GitHub SVG instead of the lucide-react icon
already used for ArrowRight; import the Github icon from "lucide-react"
alongside ArrowRight, remove the inline <svg> markup in ContactSuccessState (the
GitHub icon block) and render the <Github /> component with the same
props/className (width/height, aria-hidden, className="text-neutral-400") so
visuals and accessibility remain identical.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@frontend/src/components/contact/ContactSidebar.jsx`:
- Around line 75-82: The code assumes GitHub fields exist when building
statsData in the ContactSidebar component; validate that `data` has numeric
`stargazers_count`, `forks_count`, and `open_issues_count` before using them (in
the block that sets `statsData`, updates `STATS_CACHE`, and calls `setStats`),
and provide safe fallbacks (e.g., 0 or null) so downstream code calling
`stats.stars.toLocaleString()` won't throw; update the cached object and
`setStats` with the normalized values and set a non-empty `setError` or leave it
unchanged only on fatal failures so UI can handle missing values gracefully.

---

Outside diff comments:
In `@frontend/src/components/contact/ContactSuccessState.jsx`:
- Around line 18-45: The animations in ContactSuccessState.jsx (the motion.div,
motion.svg and motion.path elements) ignore users' prefers-reduced-motion; use
Framer Motion's useReducedMotion (or window.matchMedia) to detect reduced motion
and, when true, disable or short-circuit the animations by providing
non-animating props (e.g., set initial/animate to the final state: scale: 1 and
pathLength: 1, omit transitions or set duration 0) for those symbols so the
check occurs before rendering and avoids running spring/path-draw animations for
motion-sensitive users.
- Around line 65-67: The rendering of RESPONSE_TIME[category] in
ContactSuccessState.jsx can produce undefined for unknown categories; update the
display to use a safe fallback (e.g., 'N/A' or a localized fallback string) when
RESPONSE_TIME[category] is falsy/undefined. Locate the JSX that references
RESPONSE_TIME[category] (inside the <p> with className "text-sm font-medium
text-neutral-900") and replace the direct lookup with a fallback expression so
the UI never renders "undefined" for invalid category values.
- Around line 24-44: The animated checkmark SVG in ContactSuccessState.jsx (the
motion.svg element) lacks ARIA labeling; add an accessible name by giving the
motion.svg a role="img" and either an aria-label (e.g., "Message sent") or
aria-labelledby pointing to a <title> text node, and mark the decorative path
(motion.path) as aria-hidden="true" so screen readers read only the SVG label;
update the motion.svg attributes (role/aria-label or aria-labelledby) and add a
<title> element or aria-label accordingly while keeping motion.path aria-hidden.
- Around line 1-2: Remove the incorrect eslint suppression above the motion
import: delete the comment "// eslint-disable-next-line no-unused-vars" so the
import line remains "import { motion } from 'framer-motion';" (the component
uses motion in ContactSuccessState.jsx across the animated JSX). Ensure no other
unused-vars disable comments remain for that import and run lint to confirm.

---

Duplicate comments:
In `@frontend/src/components/contact/ContactSidebar.jsx`:
- Around line 65-70: The error handling uses rateLimitRemaining to detect rate
limits which can be missing; update the failure branch in ContactSidebar.jsx
(the block using res and rateLimitRemaining) to check HTTP status codes instead:
if res.status === 403 || res.status === 429 then throw the "Rate limit exceeded.
Please try again later." error, otherwise throw the generic `GitHub API
responded with ${res.status}` error; keep using rateLimitRemaining as
supplemental information if present but do not rely on it as the primary check.

---

Nitpick comments:
In `@frontend/src/components/contact/ContactChannelCards.jsx`:
- Around line 32-51: Add an accessible label to the channel card anchor so
screen readers know the link opens in a new tab: update the anchor used in
ContactChannelCards.jsx (the <a> that uses channel.href and target="_blank") to
include an aria-label that composes channel.title plus a suffix like "opens in a
new tab" (or reference a visually-hidden text via aria-describedby); ensure the
ArrowUpRight visual cue is preserved and the rel attribute remains "noopener
noreferrer".

In `@frontend/src/components/contact/ContactSuccessState.jsx`:
- Line 82: The hardcoded GitHub issues link in ContactSuccessState.jsx (the href
"https://github.com/kunalverma2512/CodeLens/issues") should be made
configurable: add a constant (e.g., GITHUB_ISSUES_URL) in a shared config module
(or read from an env var like REACT_APP_GITHUB_ISSUES_URL) and import it into
ContactSuccessState.jsx, then replace the literal href with that constant;
ensure the config exports GITHUB_REPO owner/repo or a full URL and add a
sensible default so forks or owner changes don’t break the link.
- Around line 88-97: The component is using an inline GitHub SVG instead of the
lucide-react icon already used for ArrowRight; import the Github icon from
"lucide-react" alongside ArrowRight, remove the inline <svg> markup in
ContactSuccessState (the GitHub icon block) and render the <Github /> component
with the same props/className (width/height, aria-hidden,
className="text-neutral-400") so visuals and accessibility remain identical.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3a727a2a-6052-43bd-9805-994f47ebd3b1

📥 Commits

Reviewing files that changed from the base of the PR and between a6fd07c and ae70da5.

📒 Files selected for processing (7)
  • frontend/src/components/contact/ContactChannelCards.jsx
  • frontend/src/components/contact/ContactFAQ.jsx
  • frontend/src/components/contact/ContactForm.jsx
  • frontend/src/components/contact/ContactHero.jsx
  • frontend/src/components/contact/ContactSidebar.jsx
  • frontend/src/components/contact/ContactSuccessState.jsx
  • frontend/src/pages/Contact.jsx
🚧 Files skipped from review as they are similar to previous changes (2)
  • frontend/src/components/contact/ContactFAQ.jsx
  • frontend/src/components/contact/ContactForm.jsx

Comment on lines +75 to +82
const statsData = {
stars: data.stargazers_count,
forks: data.forks_count,
openIssues: data.open_issues_count,
};
STATS_CACHE.set(repo, { stats: statsData, timestamp: Date.now() });
setStats(statsData);
setError("");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Validate GitHub API response structure before accessing nested fields.

If the GitHub API response structure changes or returns unexpected data, accessing data.stargazers_count, data.forks_count, or data.open_issues_count without validation will cause a runtime crash when stats.stars.toLocaleString() is called at line 127.

🛡️ Proposed fix
         const data = await res.json();
 
         if (!cancelled) {
+          if (
+            typeof data.stargazers_count !== "number" ||
+            typeof data.forks_count !== "number" ||
+            typeof data.open_issues_count !== "number"
+          ) {
+            throw new Error("Invalid API response structure");
+          }
           const statsData = {
             stars: data.stargazers_count,
             forks: data.forks_count,
             openIssues: data.open_issues_count,
           };
           STATS_CACHE.set(repo, { stats: statsData, timestamp: Date.now() });
           setStats(statsData);
           setError("");
         }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const statsData = {
stars: data.stargazers_count,
forks: data.forks_count,
openIssues: data.open_issues_count,
};
STATS_CACHE.set(repo, { stats: statsData, timestamp: Date.now() });
setStats(statsData);
setError("");
const data = await res.json();
if (!cancelled) {
if (
typeof data.stargazers_count !== "number" ||
typeof data.forks_count !== "number" ||
typeof data.open_issues_count !== "number"
) {
throw new Error("Invalid API response structure");
}
const statsData = {
stars: data.stargazers_count,
forks: data.forks_count,
openIssues: data.open_issues_count,
};
STATS_CACHE.set(repo, { stats: statsData, timestamp: Date.now() });
setStats(statsData);
setError("");
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/components/contact/ContactSidebar.jsx` around lines 75 - 82, The
code assumes GitHub fields exist when building statsData in the ContactSidebar
component; validate that `data` has numeric `stargazers_count`, `forks_count`,
and `open_issues_count` before using them (in the block that sets `statsData`,
updates `STATS_CACHE`, and calls `setStats`), and provide safe fallbacks (e.g.,
0 or null) so downstream code calling `stats.stars.toLocaleString()` won't
throw; update the cached object and `setStats` with the normalized values and
set a non-empty `setError` or leave it unchanged only on fatal failures so UI
can handle missing values gracefully.

@kunalverma2512

Copy link
Copy Markdown
Owner

@Shivangi1515 make sure to provide a video for this PR work
you can make a video and upload on google drive and send its links here

@kunalverma2512

kunalverma2512 commented Jun 12, 2026

Copy link
Copy Markdown
Owner

@coderabbitai please completely check this PR that is the work done is compatible with nearby codes, files and folder and is it ready to merge ?

Repository owner deleted a comment from coderabbitai Bot Jun 12, 2026
@coderabbitai

coderabbitai Bot commented Jun 12, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
echo "=== Directory structure ==="
tree frontend/src/components/contact/ 2>/dev/null || find frontend/src/components/contact -type f | sort

echo ""
echo "=== Contact.jsx (page) ==="
cat frontend/src/pages/Contact.jsx

echo ""
echo "=== ContactHero.jsx ==="
cat frontend/src/components/contact/ContactHero.jsx

echo ""
echo "=== ContactChannelCards.jsx ==="
cat frontend/src/components/contact/ContactChannelCards.jsx

echo ""
echo "=== ContactForm.jsx ==="
cat frontend/src/components/contact/ContactForm.jsx

echo ""
echo "=== ContactSidebar.jsx ==="
cat frontend/src/components/contact/ContactSidebar.jsx

echo ""
echo "=== ContactFAQ.jsx ==="
cat frontend/src/components/contact/ContactFAQ.jsx

echo ""
echo "=== ContactSuccessState.jsx ==="
cat frontend/src/components/contact/ContactSuccessState.jsx

Length of output: 33161


🏁 Script executed:

#!/bin/bash
echo "=== Router / App entry to check Contact route wiring ==="
fd -e jsx -e js App frontend/src/ | head -5 | xargs cat 2>/dev/null || true
fd -e jsx -e js -e tsx router frontend/src/ | head -5 | xargs cat 2>/dev/null || true

echo ""
echo "=== Check for any existing router file ==="
fd "router" frontend/src --type f | xargs cat 2>/dev/null || true
fd "routes" frontend/src --type f | xargs cat 2>/dev/null || true

echo ""
echo "=== Check package.json for framer-motion dependency ==="
cat frontend/package.json 2>/dev/null | python3 -c "import sys,json; d=json.load(sys.stdin); deps={**d.get('dependencies',{}), **d.get('devDependencies',{})}; [print(k,v) for k,v in deps.items() if k in ['framer-motion','lucide-react','react','react-dom','react-router-dom']]"

echo ""
echo "=== Check for any existing Contact component to see what was replaced ==="
git log --oneline -10

echo ""
echo "=== Check for any other files that import from Contact ==="
rg -rn "from.*Contact" frontend/src/ --type jsx 2>/dev/null || rg -rn "from.*Contact" frontend/src/ 2>/dev/null | grep -v "node_modules"

echo ""
echo "=== Check for green color classes in components (should only be in availability dot) ==="
rg -n "green|emerald" frontend/src/components/contact/ 2>/dev/null

echo ""
echo "=== Check for rounded corners ==="
rg -n "rounded" frontend/src/components/contact/ 2>/dev/null

echo ""
echo "=== Check for Discord references ==="
rg -n -i "discord" frontend/src/components/contact/ 2>/dev/null

echo ""
echo "=== Check for sidebar layout in Contact.jsx ==="
grep -n "sidebar\|Sidebar\|grid\|flex\|w-full\|100%" frontend/src/pages/Contact.jsx 2>/dev/null

Length of output: 9834



@kunalverma2512 Here is a full compatibility and merge-readiness report for PR #186.


PR Description Images

The three screenshots in the PR description (hero section, form with sidebar, FAQ) appear to be from the earlier commit (a6fd07c), not the latest redesign commit (ae70da5). They still show the green "Send Message" and "General" buttons, the old sidebar alongside the form, and the Discord card — all of which have since been redesigned. @Shivangi1515 should update the screenshots (or provide the video you requested).


Reviewer's 9 Requests — Compliance Check

# Request Status
1 Remove green everywhere except bullet dot ✅ Only bg-emerald-500/600 on ping dots
2 Darker shade for bullet dot bg-emerald-600 (solid) + bg-emerald-500 (ping animation)
3 Remove rounded corners ✅ Only rounded-full remains, on circular dots (necessary for shape)
4 Every section full-width ✅ All sections use w-full with responsive padding
5 Detach sidebar → full-width section ContactSidebar is now its own section with a 1→2→4 column responsive grid
6 Form as second section ✅ Order: Hero → Form → ChannelCards → Sidebar → FAQ
7 Larger, responsive headings ✅ Hero uses text-4xl sm:text-5xl md:text-6xl lg:text-7xl xl:text-8xl
8 Confident, bold copy ✅ "we don't keep you waiting", "Found a bug? Report it and we'll squash it." etc.
9 Remove Discord ✅ No Discord references anywhere in the contact components

Code Compatibility

  • /contact route is properly wired in App.jsximport Contact from "./pages/Contact" and <Route path="/contact" element={<Contact />} />.
  • Contact.jsx contains only composition (no UI logic), as required.
  • ✅ All dependencies are present: framer-motion ^12.40.0, lucide-react ^1.17.0, react-router-dom ^7.13.2.
  • ContactForm correctly imports and uses ContactSuccessState as a sub-component.
  • ✅ Keyboard accessibility and ARIA attributes are in place (accordion, form labels, aria-expanded, aria-controls).
  • prefers-reduced-motion respected with motion-reduce:animate-none on ping animations.

Bugs That Must Be Fixed Before Merge

🔴 Bug: Raw HTML entities in JS string literals (ContactChannelCards.jsx)

The channel description values inside the JS channels array use &apos; — but these are plain JavaScript strings, not JSX. HTML entities are not decoded in JS strings, so users will see literal &apos; text on screen instead of apostrophes.

Affected lines in ContactChannelCards.jsx:

// ❌ Wrong — &apos; renders literally in JS strings
description: "Fire off an email and we&apos;ll get back to you — fast.",
description: "Found a bug? Report it and we&apos;ll squash it.",
// ✅ Fix — use real apostrophes (JS strings handle them fine)
description: "Fire off an email and we'll get back to you — fast.",
description: "Found a bug? Report it and we'll squash it.",

Minor Issues (Non-blocking)

  1. Simulated form submissionContactForm uses setTimeout to fake a send. There's no actual backend/email call. This is acceptable for a frontend-only PR, but should be noted.

  2. "Explore Dashboard" in ContactSuccessState navigates to /dashboard, which is a ProtectedRoute. Unauthenticated users who fill the form will be redirected to login — this is probably acceptable behavior but worth being aware of.

  3. Unnecessary eslint-disable-next-line no-unused-vars comments in ContactForm.jsx (line 2) and ContactSuccessState.jsx (line 1) — motion is actively used in the JSX of both files, so these comments are misleading and should be removed.

  4. Screenshots are outdated — the PR description images still show the pre-redesign UI. @Shivangi1515, please update with current screenshots or the Google Drive video link @kunalverma2512 requested.


Verdict

Not quite ready to merge yet. The HTML entity bug in ContactChannelCards.jsx is a visible rendering defect that must be fixed. Once that one-line fix is applied and updated screenshots/video are provided, the PR will be ready from a code perspective.

@kunalverma2512

Copy link
Copy Markdown
Owner

@Shivangi1515 Please see the coderabbitai comment for fixing remaining issues

@kunalverma2512

Copy link
Copy Markdown
Owner

@Shivangi1515 for form , just use alert when tapping on send for the form as it backend will be going to be written in future issues
and resolve rest issues mentioned by coderabbitai

@kunalverma2512

Copy link
Copy Markdown
Owner

update @Shivangi1515 ?

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
frontend/src/components/contact/ContactForm.jsx (1)

219-227: ⚡ Quick win

Consider removing the alert to avoid blocking the success animation.

The alert() call creates redundant messaging and interrupts the polished user experience. When the user submits, they see a blocking browser alert, must click OK, and only then see the animated success state. Since ContactSuccessState already provides comprehensive feedback—animated checkmark, "Message sent!" heading, submitted category, and estimated response time—the alert is unnecessary and degrades the flow.

Removing the alert and keeping only setSubmitted(true) would create a smoother, more modern experience where the success animation plays immediately.

✨ Suggested improvement
 const handleSubmit = useCallback(
   (e) => {
     e.preventDefault();
     if (!valid) return;
-    alert("Your message has been sent! We'll get back to you soon.");
     setSubmitted(true);
   },
   [valid],
 );
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/components/contact/ContactForm.jsx` around lines 219 - 227,
Remove the alert() call from the handleSubmit function in ContactForm.jsx to
allow the success animation to display immediately without blocking user
interaction. The alert creates redundant messaging since ContactSuccessState
already provides comprehensive visual feedback (animated checkmark, success
heading, etc.). Keep the setSubmitted(true) call which triggers the smooth
success animation—this single state change is sufficient to notify the user of
successful submission and will provide a more polished, modern user experience.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@frontend/src/components/contact/ContactForm.jsx`:
- Around line 219-227: Remove the alert() call from the handleSubmit function in
ContactForm.jsx to allow the success animation to display immediately without
blocking user interaction. The alert creates redundant messaging since
ContactSuccessState already provides comprehensive visual feedback (animated
checkmark, success heading, etc.). Keep the setSubmitted(true) call which
triggers the smooth success animation—this single state change is sufficient to
notify the user of successful submission and will provide a more polished,
modern user experience.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f7dcebb8-ad4c-4078-9ce7-485636e49bbc

📥 Commits

Reviewing files that changed from the base of the PR and between ae70da5 and 594a99c.

📒 Files selected for processing (3)
  • frontend/src/components/contact/ContactChannelCards.jsx
  • frontend/src/components/contact/ContactForm.jsx
  • frontend/src/components/contact/ContactSuccessState.jsx
💤 Files with no reviewable changes (1)
  • frontend/src/components/contact/ContactSuccessState.jsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • frontend/src/components/contact/ContactChannelCards.jsx

@kunalverma2512

Copy link
Copy Markdown
Owner

@Shivangi1515 Fantastic work

Still some more changes needed before final merge

  1. remove green colors (i.e use only black and white) from everywhere except that bullet dot
  2. for bullet dot - use some more darker shade of green but not too much darker
  3. remove rounded corners
  4. make every section height and width to 100% and make sure every section must be fully responsive
  5. Change the plan to not to go with sidebar and dettach from other components and shift it to downward with 100 % height and 100% width
  6. contact form should be the second section as we dont want that user must scroll a lot for getting that form
  7. wherever it is possible to have largest heading then go with more font size but make sure to make it resposnive when seen on different devises like phone,etc
  8. please make the content more confident , bold , attractive
  9. remove discord

@coderabbitai please check latest commits and tell whether @Shivangi1515 has resolved issues told by you previously and is things are implemented according to what I told in this comment ? i.e this comment

And finally tell is this ready to merge ?

@coderabbitai

coderabbitai Bot commented Jun 14, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
echo "=== Recent commits ==="
git log --oneline -10

echo ""
echo "=== ContactChannelCards.jsx (check HTML entities & Discord) ==="
cat frontend/src/components/contact/ContactChannelCards.jsx

echo ""
echo "=== ContactForm.jsx (check eslint-disable & setTimeout/alert) ==="
cat frontend/src/components/contact/ContactForm.jsx

echo ""
echo "=== ContactSuccessState.jsx (check eslint-disable) ==="
cat frontend/src/components/contact/ContactSuccessState.jsx

echo ""
echo "=== ContactHero.jsx ==="
cat frontend/src/components/contact/ContactHero.jsx

echo ""
echo "=== ContactSidebar.jsx (check green colors, rounded, full-width) ==="
cat frontend/src/components/contact/ContactSidebar.jsx

echo ""
echo "=== ContactFAQ.jsx (check rounded corners) ==="
cat frontend/src/components/contact/ContactFAQ.jsx

echo ""
echo "=== Contact.jsx (check section order) ==="
cat frontend/src/pages/Contact.jsx

echo ""
echo "=== Check for green/emerald classes ==="
rg -n "green|emerald" frontend/src/components/contact/

echo ""
echo "=== Check for rounded (non-full) ==="
rg -n "rounded-" frontend/src/components/contact/ | grep -v "rounded-full"

echo ""
echo "=== Check for Discord ==="
rg -ni "discord" frontend/src/components/contact/

echo ""
echo "=== Check for HTML entities ==="
rg -n "&apos;\|&amp;\|&quot;\|&lt;\|&gt;" frontend/src/components/contact/

echo ""
echo "=== Check for setTimeout ==="
rg -n "setTimeout" frontend/src/components/contact/

echo ""
echo "=== Check for alert ==="
rg -n "alert(" frontend/src/components/contact/

echo ""
echo "=== Check for eslint-disable comments ==="
rg -n "eslint-disable" frontend/src/components/contact/

Length of output: 35419



PR description images (all three): These screenshots are from an older commit — they still show the green "Send Message" button, green "General" pill tab, sidebar alongside the form, and "Discord Community" card. They do not reflect the current code.


@kunalverma2512 Here is the updated full status check against the latest commits (594a99c and 739e279).


Previously Flagged Bugs — All Fixed ✅

Bug Status
HTML entities (&apos;) in JS strings in ContactChannelCards.jsx ✅ Fixed — real apostrophes used: "we'll get back to you", "we'll squash it"
Unnecessary eslint-disable-next-line comments in ContactForm.jsx / ContactSuccessState.jsx ✅ Fixed — zero eslint-disable comments remain
setTimeout simulating submission ✅ Fixed — handleSubmit now calls setSubmitted(true) directly, triggering the animated ContactSuccessState

Note on the alert: Commit 594a99c added an alert(), then 739e279 removed it in favour of the animated success state. This is actually better UX than a bare browser alert — the user sees a clear animated confirmation. The intent of your feedback (give users feedback on submission) is satisfied.


Your 9 Reviewer Requirements — All Implemented ✅

# Requirement Status
1 Remove green everywhere except bullet dot emerald classes appear only on the two availability ping dots (Hero + Sidebar)
2 Darker shade for bullet dot bg-emerald-600 solid + bg-emerald-500 ping
3 Remove rounded corners ✅ Zero rounded-* classes on any card/button — only rounded-full on circular dots
4 Full-width, fully responsive sections ✅ All sections use w-full + responsive padding
5 Detach sidebar → own full-width section ContactSidebar is its own <section> with a grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 layout
6 Form as second section ✅ Order: Hero → Form → ChannelCards → Sidebar → FAQ
7 Larger responsive headings ✅ Hero: text-4xl → xl:text-8xl; FAQ: text-4xl → lg:text-6xl
8 Confident, bold, attractive copy ✅ "Reach out — we don't keep you waiting", "Drop us a line and we'll take it from there.", "Found a bug? Report it and we'll squash it."
9 Remove Discord ✅ Zero Discord references anywhere

Verdict

Ready to merge from a code perspective. All bugs fixed, all 9 requirements implemented, no regressions detected.

One remaining action for @Shivangi1515:

  • The PR description screenshots are still outdated. Please update them with current screenshots, or share the Google Drive video link you were asked for. That's the only thing left before @kunalverma2512 can approve.

🐇 (ᵔᴥᵔ) Looks clean — nice turnaround on the fixes!

@kunalverma2512

Copy link
Copy Markdown
Owner

@Shivangi1515 current screenshots in PR description are outdated and must be replaced by newer and all UIs you developed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Redesign: Contact Page — Multi-Section, Component-Driven Architecture

2 participants