Skip to content

Comments

Sprint3/frontend backend api integration 3.2#12

Open
1000jae wants to merge 10 commits intomainfrom
sprint3/frontend-backend-api-integration
Open

Sprint3/frontend backend api integration 3.2#12
1000jae wants to merge 10 commits intomainfrom
sprint3/frontend-backend-api-integration

Conversation

@1000jae
Copy link
Collaborator

@1000jae 1000jae commented Feb 20, 2026

🎉 New feature (Extends application, non-breaking feature)

PR Summary

This PR connects the frontend UI to the backend study pack generation endpoint. It enables the application to send user notes to the backend, receive a structured study pack response, and handle errors gracefully without crashing the page.

Overview

  • What feature/problem does this PR address?
    Previously, the frontend was not connected to the backend study generation endpoint. Users could not generate study packs directly from the UI.

  • What approach was taken?

    • Updated frontend/src/lib/api.ts to include a new generateStudyPack() function that wraps the POST request to the backend endpoint.
    • Updated frontend/src/app/page.tsx so that the page calls generateStudyPack() when the submit button is clicked.
    • Implemented basic UI for displaying the study pack summary and quiz questions, with interactive feedback showing if the selected option is correct.
    • Utilized Jest and React Testing Library (RTL) to test end-to-end connectivity, including handling of successful responses, backend failures, and invalid input, and making sure the page does not crash for bad inputs and backend failures.
  • Any important design decisions or trade-offs?

    • Updated backend/main.py to remove redundant duplicate request classes and ensure clean API responses so both /api/v1/generate and /generate-study-pack use GenerateRequest.
    • Basic UI implemented for study pack display to make sure frontend receives and able to display the study pack on the page.

Checklist

  • Added a clear description
  • Included evidence of Unit Testing
  • Updated documentation (if needed)

Unit Test Evidence

> frontend@0.1.0 test
> jest

 PASS  src/tests/api.test.ts
 PASS  src/tests/home.test.tsx
  ● Console

    console.log
      Study pack response: {
        summary: [
          'Plants use sunlight to produce food.',
          'Chlorophyll absorbs light energy.'
        ],
        quiz: [
          {
            question: 'What pigment absorbs light in photosynthesis?',
            options: [Array],
            answer: 'Chlorophyll'
          }
        ]
      }

      at handleSubmit (src/app/page.tsx:39:15)


Test Suites: 2 passed, 2 total
Tests:       17 passed, 17 total
Snapshots:   0 total
Time:        3.275 s
Ran all test suites.

Additional Notes

  • Backend errors are handled gracefully; frontend displays appropriate messages to the user.
  • Future improvements could include enhanced styling and advanced quiz interactions such as quiz regeneration button that refreshes the quiz section with new quizzes regarding the same notes.

How to Test

cd frontend

# Install
npm install --save-dev @testing-library/react @testing-library/jest-dom @testing-library/user-event
npm install --save-dev ts-jest @types/jest

# Run tests 
npm test

Jira Ticket

Jira Ticket(s) - [SOC-16]```⁩

@1000jae 1000jae requested a review from Arhum2 February 20, 2026 02:53
@1000jae 1000jae self-assigned this Feb 20, 2026
Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

@Arhum2
Copy link
Contributor

Arhum2 commented Feb 20, 2026

@greptileai

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Feb 20, 2026

Greptile Summary

This PR successfully connects the frontend UI to the backend study pack generation endpoint, enabling end-to-end functionality for generating study materials from user notes.

Key Changes:

  • Consolidated duplicate backend request models (StudyPackRequestGenerateRequest) with proper validation constraints (10-10000 characters)
  • Added generateStudyPack() function in frontend/src/lib/api.ts to call the /generate-study-pack endpoint
  • Integrated study pack display in the UI with summary bullets and interactive quiz questions showing correct/incorrect feedback
  • Comprehensive test coverage for API requests, responses, error scenarios, and frontend resilience to backend failures

Issues Found:

  • Error handling in api.ts:66 assumes nested error.detail[0].msg structure and will crash if the backend returns a different error format (e.g., 500 errors return detail as a string, not an array)

Confidence Score: 3/5

  • This PR is mostly safe but has a critical error handling bug that will crash on server errors
  • Score reflects strong test coverage and solid architecture, but critical error handling bug in api.ts will cause crashes when backend returns 500 errors with string detail instead of validation errors with array detail
  • Pay close attention to frontend/src/lib/api.ts - the error handling needs fixing before merge

Important Files Changed

Filename Overview
backend/main.py Consolidated duplicate StudyPackRequest into GenerateRequest with validation constraints, improved error messaging
frontend/src/lib/api.ts Added generateStudyPack() function for /generate-study-pack endpoint, but error handling will crash on non-standard responses
frontend/src/app/page.tsx Integrated study pack generation with UI display, includes summary bullets and interactive quiz with answer feedback
frontend/src/tests/api.test.ts Comprehensive tests for generateStudyPack() covering requests, responses, and error scenarios with mocked fetch
frontend/src/tests/home.test.tsx Tests Home component resilience to backend failures, validates no crashes on various error scenarios

Sequence Diagram

sequenceDiagram
    participant User
    participant Frontend as Frontend (page.tsx)
    participant API as API Layer (api.ts)
    participant Backend as Backend (/generate-study-pack)
    participant Gemini as Gemini AI Service

    User->>Frontend: Enter notes and click "Generate study pack"
    Frontend->>Frontend: Validate input (not empty, not loading)
    Frontend->>Frontend: Clear previous study pack & errors
    Frontend->>Frontend: Set loading state
    Frontend->>API: generateStudyPack(notes)
    API->>Backend: POST /generate-study-pack {text}
    Backend->>Backend: Validate text (10-10000 chars)
    Backend->>Gemini: call_gemini(prompt)
    Gemini-->>Backend: JSON response with summary & quiz
    Backend->>Backend: clean_response() - Remove markdown
    Backend->>Backend: validate_data() - Verify structure
    Backend-->>API: GenerateResponse {summary, quiz}
    API-->>Frontend: Study pack data
    Frontend->>Frontend: Set studyPack state
    Frontend->>User: Display summary & interactive quiz

    Note over API,Backend: Error Handling
    Backend--xAPI: 422 Validation Error (detail[0].msg)
    Backend--xAPI: 500 Server Error (detail string)
    API--xFrontend: Throw Error with message
    Frontend->>Frontend: Set error message
    Frontend->>User: Display error alert
Loading

Last reviewed commit: e700b92

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

10 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

Comment on lines 64 to 67
const error = await response.json().catch(()=>({}));
throw new Error(
error.detail[0].msg || `Request failed with status ${response.status}`
);
Copy link
Contributor

Choose a reason for hiding this comment

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

accessing error.detail[0].msg will crash if the error response doesn't have this nested structure

Suggested change
const error = await response.json().catch(()=>({}));
throw new Error(
error.detail[0].msg || `Request failed with status ${response.status}`
);
const error = await response.json().catch(()=>({}));
const errorMessage = error.detail?.[0]?.msg || error.detail || `Request failed with status ${response.status}`;
throw new Error(errorMessage);

@1000jae
Copy link
Collaborator Author

1000jae commented Feb 20, 2026

@greptileai

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Feb 20, 2026

Greptile Summary

This PR connects the frontend to the /generate-study-pack backend endpoint, enabling users to submit notes and receive a structured study pack (summary + quiz). It adds a new generateStudyPack() API function, displays results with interactive quiz UI, and includes Jest/RTL tests for both the API layer and the page component.

  • Frontend-backend integration: New generateStudyPack() in api.ts calls /generate-study-pack with proper error handling; page.tsx wires it to the submit button and renders summary/quiz sections.
  • Backend consolidation: Removed duplicate StudyPackRequest class; both /api/v1/generate and /generate-study-pack now share GenerateRequest. This silently adds min 10 / max 10,000 character length constraints to /api/v1/generate — a breaking change for that endpoint.
  • Test bug in home.test.tsx: The "long text" test passes "q".repeat (function reference) instead of "q".repeat(10001) (string), so it does not actually test the intended long-input scenario.
  • Test coverage: Good coverage across API unit tests and component crash-resistance tests; backend tests updated to use GenerateRequest.

Confidence Score: 3/5

  • Functional but has a test bug and an unintended breaking change to the existing /api/v1/generate endpoint
  • Score of 3 reflects two concrete issues: (1) the "q".repeat test bug means the long-text crash-resistance scenario is not actually tested, and (2) merging length constraints into GenerateRequest silently breaks the /api/v1/generate endpoint for callers sending text outside the 10–10,000 character range. The core integration logic is sound and well-tested otherwise.
  • Pay close attention to backend/main.py (breaking validator change) and frontend/src/tests/home.test.tsx (test bug on line 89)

Important Files Changed

Filename Overview
backend/main.py Consolidated StudyPackRequest into GenerateRequest and added length constraints. This is a breaking change — the /api/v1/generate endpoint now enforces min/max text length that it did not before.
frontend/src/app/page.tsx Adds study pack display UI with quiz interaction. Has an unused correctAnswer variable and an unused generateStudyMaterials import. Functional logic is sound.
frontend/src/lib/api.ts Adds generateStudyPack function wrapping the POST to /generate-study-pack. Error handling correctly falls back through detail formats. Previous review flagged the error.detail[0].msg access pattern.
frontend/src/tests/api.test.ts Good test coverage for generateStudyPack including request validation, response parsing, and error scenarios. Tests are well-structured.
frontend/src/tests/home.test.tsx Bug on line 89: "q".repeat passes the function reference instead of calling it with (10001), so the "long text" test is not testing the intended scenario.
backend/tests/test_studypack_unit.py Renamed StudyPackRequest references to GenerateRequest. Comprehensive test coverage for validation, endpoint behavior, and edge cases.

Sequence Diagram

sequenceDiagram
    participant User
    participant PageTSX as page.tsx
    participant ApiTS as api.ts
    participant Backend as /generate-study-pack
    participant Gemini as GeminiService

    User->>PageTSX: Click "Generate study pack"
    PageTSX->>PageTSX: setLoading(true), clear errors
    PageTSX->>ApiTS: generateStudyPack(notes)
    ApiTS->>Backend: POST /generate-study-pack {text}
    Backend->>Backend: Validate GenerateRequest (empty, length)
    alt Validation fails
        Backend-->>ApiTS: 422 {detail: [{msg: "..."}]}
        ApiTS-->>PageTSX: throw Error(detail[0].msg)
        PageTSX-->>User: Show error alert
    else Validation passes
        Backend->>Gemini: call_gemini(prompt)
        alt Gemini unavailable
            Gemini-->>Backend: None
            Backend-->>ApiTS: 500 {detail: "Failed to generate..."}
            ApiTS-->>PageTSX: throw Error(detail)
            PageTSX-->>User: Show error alert
        else Gemini responds
            Gemini-->>Backend: JSON string
            Backend->>Backend: clean_response + validate_data
            Backend-->>ApiTS: 200 {summary[], quiz[]}
            ApiTS-->>PageTSX: GenerateResponse
            PageTSX->>PageTSX: setStudyPack(response)
            PageTSX-->>User: Render summary + quiz UI
        end
    end
Loading

Last reviewed commit: b428fa5

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

10 files reviewed, 3 comments

Edit Code Review Agent Settings | Greptile

render(<Home />);

fireEvent.change(screen.getByRole("textbox"), {
target: {value: "q".repeat}
Copy link
Contributor

Choose a reason for hiding this comment

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

"q".repeat passes the function, not a string

"q".repeat is a reference to the String.prototype.repeat function itself, not a call to it. The textarea value will be set to the string representation of the function (something like "function repeat() { [native code] }"), not a 10001-character string. This means the test is not actually testing the long-text scenario — it's setting a short unrelated string.

Suggested change
target: {value: "q".repeat}
target: {value: "q".repeat(10001)}

Comment on lines 44 to 53
@field_validator("text")
@classmethod
def text_length_constraint(cls, v: str) -> str:
stripped = v.strip()
# validate length
if len(stripped) < 10:
raise ValueError(f"text must not be less than 10 characters")
if len(stripped) > 10000:
raise ValueError("text must not be more than 10000 characters")
return v
Copy link
Contributor

Choose a reason for hiding this comment

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

Length constraints now apply to /api/v1/generate too

Before this PR, GenerateRequest only validated that text was non-empty. Adding text_length_constraint here means the /api/v1/generate endpoint now also enforces min 10 / max 10,000 character limits — a breaking change for any existing callers that send short notes (< 10 chars) or very long notes (> 10,000 chars).

If this is intentional, the docstring for /api/v1/generate (line 141) should document the new constraints. If unintentional, consider keeping the length validator only in a subclass or applying it selectively to the /generate-study-pack route.

const [showAnswer, setShowAnswer] = useState(false);

// correct answer if selected answer = answer to question
const correctAnswer = selectedAnswer === question.answer;
Copy link
Contributor

Choose a reason for hiding this comment

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

Unused variable correctAnswer

correctAnswer is assigned but never read. The component uses option === question.answer and option === selectedAnswer inline instead. This will trigger a lint warning and should be removed or used.

Suggested change
const correctAnswer = selectedAnswer === question.answer;

@1000jae
Copy link
Collaborator Author

1000jae commented Feb 20, 2026

@greptileai

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Feb 20, 2026

Greptile Summary

This PR successfully integrates the frontend with the /generate-study-pack backend endpoint, enabling users to generate study materials from their notes with comprehensive error handling.

Key changes:

  • Added generateStudyPack() API function with robust error extraction from nested validation responses
  • Integrated study pack generation into the home page with interactive quiz UI that shows correct/incorrect feedback
  • Refactored backend to consolidate duplicate StudyPackRequest class using inheritance from GenerateRequest
  • Added comprehensive test coverage for API connectivity, error scenarios, and UI resilience

Issues found:

  • Critical validation bug: StudyPackRequest child validator overrides parent's empty-text validation due to Pydantic v2 behavior
  • The previous thread comments about unused correctAnswer variable and .repeat function reference appear to have been addressed or are in different code paths

Confidence Score: 3/5

  • Safe to merge after fixing the validation bypass bug
  • The PR demonstrates solid engineering with comprehensive tests and proper error handling, but contains a critical logic bug where empty text can bypass validation in StudyPackRequest due to Pydantic validator inheritance behavior. The frontend integration is well-implemented with proper state management and user feedback.
  • Pay close attention to backend/main.py - the validator inheritance issue must be fixed before merge

Important Files Changed

Filename Overview
backend/main.py Refactored duplicate request classes, but child validator silently drops parent's empty-text validation
frontend/src/lib/api.ts Added generateStudyPack() function with proper error handling for nested validation errors
frontend/src/app/page.tsx Integrated generateStudyPack API call with UI components for displaying study pack results
frontend/src/tests/api.test.ts Comprehensive test coverage for generateStudyPack() including request format, response parsing, and error scenarios
frontend/src/tests/home.test.tsx Tests UI error handling and graceful degradation for all backend failure scenarios

Sequence Diagram

sequenceDiagram
    participant User
    participant Frontend as page.tsx
    participant API as api.ts
    participant Backend as /generate-study-pack
    participant Gemini as Gemini Service

    User->>Frontend: Enter notes & click Generate
    Frontend->>Frontend: Clear previous studyPack & errors
    Frontend->>API: generateStudyPack(notes)
    API->>Backend: POST /generate-study-pack {text}
    Backend->>Backend: Validate StudyPackRequest (10-10000 chars)
    alt Validation fails
        Backend-->>API: 422 {detail: [{msg}]}
        API-->>Frontend: throw Error(msg)
        Frontend->>Frontend: setErrorMessage(user-friendly)
        Frontend-->>User: Display error alert
    else Validation passes
        Backend->>Gemini: call_gemini(prompt)
        alt Gemini unavailable
            Gemini-->>Backend: null
            Backend-->>API: 500 {detail: "Gemini unavailable"}
            API-->>Frontend: throw Error
            Frontend-->>User: Display error alert
        else Gemini success
            Gemini-->>Backend: JSON response
            Backend->>Backend: clean_response & validate_data
            Backend-->>API: 200 {summary, quiz}
            API-->>Frontend: {summary, quiz}
            Frontend->>Frontend: setStudyPack(response)
            Frontend-->>User: Display summary & interactive quiz
        end
    end
Loading

Last reviewed commit: 55e5232

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

10 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

Comment on lines 45 to 59
class StudyPackRequest(GenerateRequest):
"""
Request body for POST /generate-study-pack
- text: The user's study notes to process
"""
@field_validator("text")
@classmethod
def text_length_constraint(cls, v: str) -> str:
stripped = v.strip()
# validate length
if len(stripped) < 10:
raise ValueError(f"text must not be less than 10 characters")
if len(stripped) > 10000:
raise ValueError("text must not be more than 10000 characters")
return v
Copy link
Contributor

Choose a reason for hiding this comment

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

Child validator overrides parent's empty check

In Pydantic v2, StudyPackRequest.text_length_constraint completely replaces GenerateRequest.text_must_not_be_empty instead of running both. Empty/whitespace text will pass through StudyPackRequest validation unchecked.

Suggested change
class StudyPackRequest(GenerateRequest):
"""
Request body for POST /generate-study-pack
- text: The user's study notes to process
"""
@field_validator("text")
@classmethod
def text_length_constraint(cls, v: str) -> str:
stripped = v.strip()
# validate length
if len(stripped) < 10:
raise ValueError(f"text must not be less than 10 characters")
if len(stripped) > 10000:
raise ValueError("text must not be more than 10000 characters")
return v
class StudyPackRequest(GenerateRequest):
"""
Request body for POST /generate-study-pack
- text: The user's study notes to process
"""
@field_validator("text")
@classmethod
def text_length_constraint(cls, v: str) -> str:
# Must re-check emptiness since child validators override parent
stripped = v.strip()
if not v or not stripped:
raise ValueError("text must not be empty")
# validate length
if len(stripped) < 10:
raise ValueError(f"text must not be less than 10 characters")
if len(stripped) > 10000:
raise ValueError("text must not be more than 10000 characters")
return v

@1000jae
Copy link
Collaborator Author

1000jae commented Feb 20, 2026

@greptileai

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Feb 20, 2026

Greptile Summary

This PR successfully integrates the frontend UI with the backend /generate-study-pack endpoint, enabling users to generate study packs from notes. The implementation includes comprehensive error handling, input validation (10-10,000 character limits), and extensive test coverage across both frontend and backend.

Major Changes:

  • Backend refactored GenerateRequest and StudyPackRequest classes to use inheritance with shared empty-text validation
  • Frontend added generateStudyPack() function with improved error message extraction from nested validation responses
  • UI components added to display study pack summaries and interactive quiz questions
  • Comprehensive test suites added: api.test.ts (API layer), home.test.tsx (component resilience), test_studypack_unit.py (backend validation)

Issues Found:

  • Previous review comments noted potential crashes in error handling (error.detail[0].msg access) and test issues ("q".repeat passes function reference instead of calling it) - these were already flagged
  • The validator inheritance pattern could potentially skip the empty-text check in Pydantic v2, though backend tests confirm it's working correctly

Confidence Score: 4/5

  • This PR is safe to merge with minor concerns about error handling edge cases that have already been flagged in previous review threads.
  • The implementation is well-tested with comprehensive unit and integration tests covering success paths, validation errors, and backend failures. Both frontend and backend have proper error handling. The score of 4 (rather than 5) reflects the previously identified issues with potential crashes in error.detail[0].msg access and the "q".repeat test bug, which should be addressed but don't block core functionality.
  • Pay attention to frontend/src/lib/api.ts (line 65) and frontend/src/tests/home.test.tsx (line 89) to address the previously flagged issues with error handling safety and test correctness.

Important Files Changed

Filename Overview
backend/main.py Refactored validation by extracting check_empty_text helper and made StudyPackRequest inherit from GenerateRequest. This adds 10-10000 character limits to the /generate-study-pack endpoint.
frontend/src/lib/api.ts Added new generateStudyPack() function that calls the /generate-study-pack endpoint with improved error handling that gracefully extracts validation messages from nested error structures.
frontend/src/app/page.tsx Integrated generateStudyPack() API call into submit handler and added UI components to display study pack summary and interactive quiz questions. Includes fallback preview for testing.
frontend/src/tests/api.test.ts Comprehensive test coverage for generateStudyPack() including request format, response validation, and error handling for network failures, validation errors, and backend failures.
frontend/src/tests/home.test.tsx End-to-end tests verifying the Home page doesn't crash on backend failures, validation errors, or after retry attempts. Tests use proper React Testing Library patterns.
backend/tests/test_studypack_unit.py Extensive backend test coverage for StudyPackRequest validation and /generate-study-pack endpoint, including boundary tests, error handling, and response format validation.

Sequence Diagram

sequenceDiagram
    participant User
    participant Frontend as page.tsx
    participant API as api.ts
    participant Backend as /generate-study-pack
    participant Gemini as Gemini API

    User->>Frontend: Enter notes & click submit
    Frontend->>Frontend: setStudyPack(null)<br/>setErrorMessage(null)<br/>setLoading(true)
    Frontend->>API: generateStudyPack(notes)
    API->>Backend: POST /generate-study-pack<br/>{text: notes}
    
    alt Validation fails (empty, <10, >10000 chars)
        Backend-->>API: 422 {detail: [{msg: "..."}]}
        API-->>Frontend: throw Error(detail[0].msg)
        Frontend->>Frontend: setErrorMessage()<br/>setLoading(false)
        Frontend-->>User: Display error message
    else Gemini unavailable
        Backend->>Gemini: Generate study pack
        Gemini-->>Backend: null
        Backend-->>API: 500 {detail: "Gemini unavailable..."}
        API-->>Frontend: throw Error(detail)
        Frontend->>Frontend: setErrorMessage()<br/>setLoading(false)
        Frontend-->>User: Display error message
    else Success
        Backend->>Gemini: Generate study pack
        Gemini-->>Backend: JSON response
        Backend->>Backend: clean_response()<br/>validate_data()
        Backend-->>API: 200 {summary: [...], quiz: [...]}
        API-->>Frontend: Return response
        Frontend->>Frontend: setStudyPack(response)<br/>setLoading(false)
        Frontend-->>User: Display summary & quiz
    end
Loading

Last reviewed commit: 641ba13

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.

2 participants