Skip to content

Conversation

@GaneshPatil7517
Copy link

@GaneshPatil7517 GaneshPatil7517 commented Oct 2, 2025

This PR adds a new DynamicForm component that fetches questions from Google Forms via Google Apps Script and allows users to submit responses dynamically.

Changes Made
Added DynamicForm.js component.
Updated App.js to include a new route /dynamic-form.
Integrated Google Apps Script endpoint to fetch questions.
Basic UI for rendering text, paragraph, multiple choice, checkbox, and dropdown questions.

Testing
Verified that form questions are fetched correctly from the Apps Script endpoint.
Responses can be submitted successfully (will be stored in Google Form/Sheet).
Application runs at http://localhost:3000/#/dynamic-form.

Closes #.

Summary by CodeRabbit

  • New Features

    • Dynamic form that automatically loads the latest questions from an online source.
    • Renders appropriate field types: short answer, paragraph, multiple choice, checkboxes, and dropdowns.
    • Real-time answer tracking and streamlined submission with an on-screen confirmation.
  • Changes

    • Simplified experience: replaced multi-page navigation with a single, focused form view.
    • The app now updates questions on load to ensure users always see the most current form content.

@coderabbitai
Copy link

coderabbitai bot commented Oct 2, 2025

Walkthrough

Introduces a DynamicForm React component that fetches questions from a Google Apps Script endpoint, renders inputs based on question types, tracks responses, and handles submit. App.js is updated to remove routing UI and export DynamicForm as default. A new DynamicForm.js file is added exporting the same component.

Changes

Cohort / File(s) Summary
Dynamic form implementation
eduaid_web/src/DynamicForm.js
New component that fetches questions on mount, renders TEXT, PARAGRAPH_TEXT, CHECKBOX, LIST, MULTIPLE_CHOICE fields, manages responses via unified handleChange, and handles submit with preventDefault, logging answers and alerting. Default export: DynamicForm.
App shell update
eduaid_web/src/App.js
Replaces prior router-based App with DynamicForm usage; adds fetching/rendering logic, local state for questions/responses, and submit handler. Changes default export from App to DynamicForm.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant DF as DynamicForm (React)
  participant GAS as Google Apps Script API
  participant State as Local State

  rect rgb(240,248,255)
  note right of DF: On mount
  DF->>GAS: GET /questions
  GAS-->>DF: JSON questions
  DF->>State: setQuestions(list)
  end

  User->>DF: Input/select changes
  DF->>State: handleChange(id, value)<br/>• CHECKBOX: merge selections

  User->>DF: Submit form
  DF->>DF: preventDefault()
  DF->>State: read responses
  DF-->>User: Alert "Form submitted"
  note over DF: Logs responses to console
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related issues

Poem

Thump-thump goes my paw on the key,
Forms bloom like clover under a tree.
Checkboxes hop, radios align,
Text fields nibble a carrot vine.
From scripts we fetch, then swiftly submit—
A bunny-approved UI, every bit! 🥕🐇

Pre-merge checks and finishing touches

❌ 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%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title references the addition of a dynamic Google Form feature, which aligns with the main change of introducing the DynamicForm component fetching questions from a Google Apps Script endpoint, but it uses a branch-style “Feature/” prefix rather than a clear declarative phrasing.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Caution

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

⚠️ Outside diff range comments (1)
eduaid_web/src/App.js (1)

1-108: Architectural concern: App.js exports DynamicForm.

This file is named App.js but exports a component named DynamicForm, and there's a duplicate implementation in DynamicForm.js. This creates confusion about which file is the canonical source.

This version has some improvements over DynamicForm.js (label wrapping, textarea sizing), but maintaining two nearly identical implementations will lead to inconsistencies.

Recommendation:

  1. Consolidate to a single implementation (prefer this App.js version due to better UX)
  2. Remove DynamicForm.js
  3. Consider renaming the component in this file to App if it's meant to be the main app component, or create a proper App wrapper that imports DynamicForm from a separate file

Alternatively, if you want DynamicForm as a reusable component:

  1. Keep DynamicForm.js as the canonical implementation (merge improvements from App.js)
  2. Update App.js to import and use it:
import React from 'react';
import DynamicForm from './DynamicForm';

function App() {
  return <DynamicForm />;
}

export default App;
♻️ Duplicate comments (2)
eduaid_web/src/App.js (2)

8-15: Add loading state and improve error handling.

Same issue as flagged in DynamicForm.js: no loading indicator and errors only logged without user feedback.

Refer to the comment on DynamicForm.js lines 12-20 for the suggested implementation with loading and error states.


21-25: Implement actual form submission and validation.

Same issue as DynamicForm.js: the form only logs responses without submitting to backend or validating required fields.

Refer to the comment on DynamicForm.js lines 28-32 for implementation guidance.

🧹 Nitpick comments (7)
eduaid_web/src/DynamicForm.js (5)

46-51: Consider using controlled inputs.

The input is uncontrolled (no value prop), which makes it harder to reset the form or pre-populate values.

Apply this pattern for all inputs:

  {q.type === "TEXT" && (
    <input
      type="text"
+     value={answers[q.id] || ""}
      onChange={(e) => handleChange(q.id, e.target.value)}
+     placeholder="Enter your answer"
    />
  )}

53-57: Add sizing attributes and make controlled.

The textarea lacks sizing attributes and is uncontrolled.

  {q.type === "PARAGRAPH_TEXT" && (
    <textarea
+     rows="4"
+     cols="50"
+     value={answers[q.id] || ""}
      onChange={(e) => handleChange(q.id, e.target.value)}
+     placeholder="Enter your answer"
    ></textarea>
  )}

72-92: Make checkboxes controlled with checked prop.

The checkbox logic correctly manages array state, but checkboxes should be controlled to reflect the current state.

  {q.type === "CHECKBOX" &&
    q.choices?.map((choice, i) => (
      <div key={i}>
        <input
          type="checkbox"
          value={choice}
+         checked={(answers[q.id] || []).includes(choice)}
          onChange={(e) => {
            const selected = answers[q.id] || [];
            if (e.target.checked) {
              handleChange(q.id, [...selected, choice]);
            } else {
              handleChange(
                q.id,
                selected.filter((c) => c !== choice)
              );
            }
          }}
        />
        {choice}
      </div>
    ))}

94-103: Make dropdown controlled with value prop.

The dropdown should be controlled to reflect the current state.

  {q.type === "LIST" && (
    <select
+     value={answers[q.id] || ""}
      onChange={(e) => handleChange(q.id, e.target.value)}
    >
      <option value="">Select</option>
      {q.choices?.map((choice, i) => (
        <option key={i} value={choice}>
          {choice}
        </option>
      ))}
    </select>
  )}

1-114: Eliminate duplicate DynamicForm component
src/DynamicForm.js and src/App.js both define the same DynamicForm (state, fetch logic and handlers). Consolidate into one source of truth—import it where needed or remove the extra file.

eduaid_web/src/App.js (2)

45-51: Good use of sizing attributes, but make controlled.

The textarea correctly includes sizing attributes, which is better than the DynamicForm.js version.

Consider making it controlled:

  {q.type === "PARAGRAPH_TEXT" && (
    <textarea
      rows="4"
      cols="40"
+     value={responses[q.id] || ""}
      onChange={(e) => handleChange(q.id, e.target.value)}
+     placeholder="Enter your answer"
    />
  )}

53-73: Better UX with label wrapping, but make controlled.

Good improvement over DynamicForm.js by wrapping in labels for better clickable area.

Make controlled with checked prop:

  <input
    type="checkbox"
    value={choice}
+   checked={(responses[q.id] || []).includes(choice)}
    onChange={(e) => {
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5d6e4ad and 7cd8210.

📒 Files selected for processing (2)
  • eduaid_web/src/App.js (1 hunks)
  • eduaid_web/src/DynamicForm.js (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
eduaid_web/src/DynamicForm.js (1)
eduaid_web/src/App.js (3)
  • questions (4-4)
  • handleChange (17-19)
  • handleSubmit (21-25)
eduaid_web/src/App.js (1)
eduaid_web/src/DynamicForm.js (3)
  • questions (4-4)
  • handleChange (23-25)
  • handleSubmit (28-32)
🔇 Additional comments (3)
eduaid_web/src/DynamicForm.js (2)

23-25: LGTM!

The functional state update correctly merges the new answer with existing state.


59-70: LGTM, but be aware of XSS risk.

The radio button logic is correct. However, if choice values can contain user-generated HTML, there's a potential XSS risk since React renders text content safely by default, but this assumes the data source is trusted.

Verify that the Google Apps Script endpoint sanitizes choice values and doesn't return user-generated content that could contain malicious scripts.

eduaid_web/src/App.js (1)

86-97: LGTM! Good UX with label wrapping.

The label wrapping provides better clickable area and improves accessibility compared to the DynamicForm.js version.

Comment on lines +9 to +11
fetch(
"https://script.google.com/macros/s/AKfycbxRamNfuS1b9yBXapdCs9gB3ScRhpxiRPbjTO0qrzeYel0BJEq4VyTGX3GnZ_-KIsZXkw/exec"
)
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Move the Google Apps Script URL to environment variables.

The script URL is hardcoded, which exposes the endpoint and makes environment-specific configuration difficult.

  useEffect(() => {
    fetch(
-      "https://script.google.com/macros/s/AKfycbxRamNfuS1b9yBXapdCs9gB3ScRhpxiRPbjTO0qrzeYel0BJEq4VyTGX3GnZ_-KIsZXkw/exec"
+      process.env.REACT_APP_GOOGLE_SCRIPT_URL
    )

Add to .env:

REACT_APP_GOOGLE_SCRIPT_URL=https://script.google.com/macros/s/AKfycbxRamNfuS1b9yBXapdCs9gB3ScRhpxiRPbjTO0qrzeYel0BJEq4VyTGX3GnZ_-KIsZXkw/exec
📝 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
fetch(
"https://script.google.com/macros/s/AKfycbxRamNfuS1b9yBXapdCs9gB3ScRhpxiRPbjTO0qrzeYel0BJEq4VyTGX3GnZ_-KIsZXkw/exec"
)
fetch(
process.env.REACT_APP_GOOGLE_SCRIPT_URL
)
🤖 Prompt for AI Agents
In eduaid_web/src/App.js around lines 9-11 the Google Apps Script URL is
hardcoded; move this value into an environment variable by adding
REACT_APP_GOOGLE_SCRIPT_URL=<the URL> to .env, then update the fetch call to
read from process.env.REACT_APP_GOOGLE_SCRIPT_URL (and add a clear runtime error
or fallback if the env var is missing) so the endpoint is configurable per
environment and no secrets/URLs are hardcoded in source.

Comment on lines +7 to +9
// 👉 Replace this with your deployed Google Apps Script URL
const GOOGLE_SCRIPT_URL =
"https://script.google.com/macros/s/AKfycbxRamNfuS1b9yBXapdCs9gB3ScRhpxiRPbjTO0qrzeYel0BJEq4VyTGX3GnZ_-KIsZXkw/exec";
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Move the Google Apps Script URL to environment variables.

Hardcoding the script URL exposes the endpoint publicly and makes it difficult to maintain across environments (dev, staging, prod).

Move to an environment variable:

-  // 👉 Replace this with your deployed Google Apps Script URL
-  const GOOGLE_SCRIPT_URL =
-    "https://script.google.com/macros/s/AKfycbxRamNfuS1b9yBXapdCs9gB3ScRhpxiRPbjTO0qrzeYel0BJEq4VyTGX3GnZ_-KIsZXkw/exec";
+  const GOOGLE_SCRIPT_URL = process.env.REACT_APP_GOOGLE_SCRIPT_URL;

Then add to .env:

REACT_APP_GOOGLE_SCRIPT_URL=https://script.google.com/macros/s/AKfycbxRamNfuS1b9yBXapdCs9gB3ScRhpxiRPbjTO0qrzeYel0BJEq4VyTGX3GnZ_-KIsZXkw/exec
📝 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
// 👉 Replace this with your deployed Google Apps Script URL
const GOOGLE_SCRIPT_URL =
"https://script.google.com/macros/s/AKfycbxRamNfuS1b9yBXapdCs9gB3ScRhpxiRPbjTO0qrzeYel0BJEq4VyTGX3GnZ_-KIsZXkw/exec";
const GOOGLE_SCRIPT_URL = process.env.REACT_APP_GOOGLE_SCRIPT_URL;
🤖 Prompt for AI Agents
In eduaid_web/src/DynamicForm.js around lines 7 to 9 the Google Apps Script URL
is hardcoded; replace it with an environment variable reference
(process.env.REACT_APP_GOOGLE_SCRIPT_URL) and remove the literal string, update
.env with REACT_APP_GOOGLE_SCRIPT_URL=<your-script-url>, and add a safe fallback
or throw a clear error if the env var is missing so builds fail fast in
non-configured environments.

Comment on lines +12 to +20
useEffect(() => {
fetch(GOOGLE_SCRIPT_URL)
.then((res) => res.json())
.then((data) => {
console.log("Fetched form data:", data);
setQuestions(data);
})
.catch((err) => console.error("Error fetching form data:", err));
}, []);
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Add loading state and improve error handling.

The component doesn't indicate when data is being fetched, and errors are only logged without user feedback.

Apply this diff:

 function DynamicForm() {
   const [questions, setQuestions] = useState([]);
   const [answers, setAnswers] = useState({});
+  const [loading, setLoading] = useState(true);
+  const [error, setError] = useState(null);

   const GOOGLE_SCRIPT_URL =
     "https://script.google.com/macros/s/AKfycbxRamNfuS1b9yBXapdCs9gB3ScRhpxiRPbjTO0qrzeYel0BJEq4VyTGX3GnZ_-KIsZXkw/exec";

   useEffect(() => {
+    setLoading(true);
     fetch(GOOGLE_SCRIPT_URL)
       .then((res) => res.json())
       .then((data) => {
         console.log("Fetched form data:", data);
         setQuestions(data);
+        setLoading(false);
       })
-      .catch((err) => console.error("Error fetching form data:", err));
+      .catch((err) => {
+        console.error("Error fetching form data:", err);
+        setError("Failed to load form. Please try again later.");
+        setLoading(false);
+      });
   }, []);

Then update the render logic to show loading/error states:

  if (loading) return <div>Loading form...</div>;
  if (error) return <div style={{ color: "red" }}>{error}</div>;
🤖 Prompt for AI Agents
In eduaid_web/src/DynamicForm.js around lines 12 to 20, the component fetch
logic lacks a loading state and user-visible error handling; update the
component to add local state variables (loading and error), set loading=true
before fetch, set loading=false and setQuestions(data) on success, and set
loading=false and setError with a user-friendly message on catch; then update
the render to return a loading placeholder when loading is true and an error
message styled in red when error is set (i.e., if (loading) return <div>Loading
form...</div>; if (error) return <div style={{ color: "red" }}>{error}</div>;).

Comment on lines +28 to +32
const handleSubmit = (e) => {
e.preventDefault();
console.log("Submitted answers:", answers);
alert("Form submitted! Check console for answers.");
};
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Implement actual form submission and validation.

The form currently only logs responses locally without submitting them to the Google Apps Script endpoint or validating required fields.

Consider implementing:

  1. POST request to submit responses to the backend
  2. Validation for required fields
  3. Better user feedback (e.g., success message, loading spinner)

Example:

  const handleSubmit = (e) => {
    e.preventDefault();
+    
+    // Validate required fields
+    const requiredQuestions = questions.filter(q => q.required);
+    const missingAnswers = requiredQuestions.filter(q => !answers[q.id]);
+    if (missingAnswers.length > 0) {
+      alert("Please answer all required questions.");
+      return;
+    }
+    
+    // Submit to backend
+    setLoading(true);
+    fetch(GOOGLE_SCRIPT_URL, {
+      method: 'POST',
+      headers: { 'Content-Type': 'application/json' },
+      body: JSON.stringify(answers)
+    })
+      .then(res => res.json())
+      .then(data => {
+        alert("Form submitted successfully!");
+        console.log("Submitted answers:", answers);
+        setLoading(false);
+      })
+      .catch(err => {
+        alert("Failed to submit form. Please try again.");
+        console.error("Submission error:", err);
+        setLoading(false);
+      });
-    console.log("Submitted answers:", answers);
-    alert("Form submitted! Check console for answers.");
  };
📝 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 handleSubmit = (e) => {
e.preventDefault();
console.log("Submitted answers:", answers);
alert("Form submitted! Check console for answers.");
};
const handleSubmit = (e) => {
e.preventDefault();
// Validate required fields
const requiredQuestions = questions.filter(q => q.required);
const missingAnswers = requiredQuestions.filter(q => !answers[q.id]);
if (missingAnswers.length > 0) {
alert("Please answer all required questions.");
return;
}
// Submit to backend
setLoading(true);
fetch(GOOGLE_SCRIPT_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(answers)
})
.then(res => res.json())
.then(data => {
alert("Form submitted successfully!");
console.log("Submitted answers:", answers);
setLoading(false);
})
.catch(err => {
alert("Failed to submit form. Please try again.");
console.error("Submission error:", err);
setLoading(false);
});
};
🤖 Prompt for AI Agents
In eduaid_web/src/DynamicForm.js around lines 28 to 32, the form submit handler
only logs answers and shows an alert; replace it with real submission and
validation: validate required fields before sending, show inline validation
errors, set a loading state to disable the submit button and display a spinner
while submitting, send a POST (fetch/axios) to the Google Apps Script endpoint
with the answers as JSON and appropriate headers, await the response and handle
non-2xx responses as errors, show a success message on completion and clear or
preserve form per UX decision, and catch/network errors to show a user-friendly
error message and re-enable the form. Ensure to prevent multiple submissions and
include minimal retry/backoff or instructive error text for failed submissions.

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