Skip to content

new jobs page to see all saved jobs with proper pagination.#20

Merged
afnanaghai4 merged 2 commits into
masterfrom
feature/jobs-integrated-page
Apr 15, 2026
Merged

new jobs page to see all saved jobs with proper pagination.#20
afnanaghai4 merged 2 commits into
masterfrom
feature/jobs-integrated-page

Conversation

@afnanaghai4

@afnanaghai4 afnanaghai4 commented Apr 15, 2026

Copy link
Copy Markdown
Owner

Release Notes

  • New Jobs Management Page: Added dedicated page to view all saved jobs with a clean, card-based layout
  • Pagination Support: Implemented pagination controls to browse through jobs with previous/next navigation and current page indicator
  • Job Display Cards: New job cards show job title, company name, job content (text or link), input type badge, and creation date
  • Improved Navigation: Updated dashboard quick actions menu item from "Submit Job Posting" to "Manage Jobs" for clearer action intent
  • Backend Pagination Logic: Enhanced job service to return pagination metadata (hasMore flag) enabling efficient client-side pagination
  • Type System Improvements: Consolidated job-related types into frontend/types/job.ts including new Job type and InputType enum moved from API layer
  • Updated API: Added getJobs() endpoint function to fetch paginated job lists with skip/take parameters
  • Removed Unused Types: Cleaned up unused authentication type definitions from type system

new commit changes:

  1. feat(backend): Add pagination improvements with deterministic ordering

    • Add totalCount query to job service
    • Implement jobId tie-breaker for deterministic ordering
    • Fixes pagination inconsistencies with duplicate timestamps
  2. feat(backend): Add totalPages calculation to jobs controller

    • Calculate totalPages from totalCount
    • Add type-safe null handling for query.take parameter
    • Returns complete pagination metadata to frontend
  3. feat(frontend): Update job API to return totalCount and totalPages

    • Update getJobs() return type
    • Align with new backend response structure
  4. feat(frontend): Implement race-safety with AbortController

    • Cancel stale requests when user navigates pages
    • Prevent data corruption from out-of-order responses
    • Handle unmount scenarios gracefully
  5. feat(frontend): Clear jobs state on empty and error responses

    • Prevent stale UI data after navigation
    • Improve user experience and data accuracy
  6. feat(frontend): Add callbacks to JobCard component

    • Add onView and onDelete optional props
    • Thread callbacks through JobsList to JobsPageContent
    • Prepares infrastructure for view/delete functionality
  7. feat(frontend): Improve accessibility and UX

    • Add aria-pressed attributes to job-input-toggle
    • Update dashboard-widgets copy to reflect new functionality
    • WCAG compliance improvement

@coderabbitai

coderabbitai Bot commented Apr 15, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@afnanaghai4 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 42 minutes and 37 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 42 minutes and 37 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, 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 have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 72e0be70-b38f-434b-b22f-473e08367bb1

📥 Commits

Reviewing files that changed from the base of the PR and between 73b41e2 and 2bf5f1f.

📒 Files selected for processing (8)
  • backend/src/jobs/job.controller.ts
  • backend/src/jobs/job.service.ts
  • frontend/components/dashboard/dashboard-widgets.tsx
  • frontend/components/job/job-card.tsx
  • frontend/components/job/job-input-toggle.tsx
  • frontend/components/job/jobs-list.tsx
  • frontend/components/job/jobs-page-content.tsx
  • frontend/lib/job-api.ts
📝 Walkthrough

Walkthrough

The pull request introduces pagination support to the jobs feature. The backend's JobService.getJobsByUserId method now returns a composite object containing both the jobs array and a hasMore boolean flag computed by fetching one extra record. The frontend migrated the InputType enum from the job-api module to a dedicated types file, created new job listing components with pagination controls, and added a getJobs API function to fetch paginated results.

Changes

Cohort / File(s) Summary
Backend Pagination
backend/src/jobs/job.service.ts, backend/src/jobs/job.controller.ts
Modified getJobsByUserId to return { jobs, hasMore } instead of raw Job[] array. Pagination logic now fetches take + 1 records, slices to take for response, and computes hasMore based on whether fetched count exceeds requested page size. Controller updated to destructure and return the composite object.
Frontend Type Consolidation
frontend/types/job.ts, frontend/types/auth.ts, frontend/lib/job-api.ts, frontend/components/job/job-form.tsx, frontend/components/job/job-input-toggle.tsx, frontend/components/job/job-result-preview.tsx
Moved InputType enum from job-api.ts to dedicated types/job.ts file as a string union type. Updated all imports across components to reference new location. Changed internal state initialization and comparisons from InputType.TEXT/InputType.LINK to string literals "TEXT"/"LINK". Removed unused auth types from auth.ts.
Frontend Job Listing Components
frontend/components/job/job-card.tsx, frontend/components/job/jobs-list.tsx, frontend/components/job/jobs-page-content.tsx
Added three new components: JobCard displays individual job details with badge color derived from inputType; JobsList renders loading state, empty state, or job grid with pagination controls; JobsPageContent manages pagination state, fetches jobs with getJobs() on mount/skip change, computes totalPages from hasMore flag, and wires navigation callbacks with clamping logic.
Frontend API & Page Updates
frontend/lib/job-api.ts, frontend/app/jobs/page.tsx, frontend/components/dashboard/dashboard-widgets.tsx
Added getJobs(skip, take) function to job-api that fetches paginated results from /jobs endpoint. Updated jobs/page.tsx to render new JobsPageContent component instead of JobForm. Changed dashboard widget label from "Submit Job Posting" to "Manage Jobs".

Sequence Diagram(s)

sequenceDiagram
    participant Client as JobsPageContent
    participant API as getJobs()
    participant Server as JobController
    participant DB as JobService/Database
    
    Client->>Client: Initialize state<br/>(page=1, pageSize=6)
    Client->>Client: Calculate skip = (page-1) × 6
    
    Client->>API: getJobs(skip, pageSize)
    API->>Server: GET /jobs?skip=X&take=6
    Server->>DB: getJobsByUserId(userId, skip, take)<br/>Fetch take+1 records
    DB-->>Server: Return 7 records
    Server->>Server: Slice to 6, compute hasMore
    Server-->>API: { jobs: [...], hasMore: boolean }
    API-->>Client: { jobs: [...], hasMore: boolean }
    
    Client->>Client: Derive totalPages<br/>= hasMore ? page+1 : page
    Client->>Client: Render JobsList<br/>with pagination controls
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • PR #18: Modifies jobs page and job-related frontend components with overlapping file changes (job-form, job-input-toggle, job-result-preview, job-api).
  • PR #17: Updates JobService and JobController in the same module, adding createJob functionality that complements the pagination changes.
  • PR #19: Adds GET /jobs endpoint and modifies JobController.getUserJobs/JobService.getJobsByUserId return types with hasMore support.
🚥 Pre-merge checks | ✅ 2 | ❌ 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 (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main objective of the pull request—implementing a new jobs page with pagination functionality to display all saved jobs.

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


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.

@codecov

codecov Bot commented Apr 15, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 0% with 7 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
backend/src/jobs/job.service.ts 0.00% 4 Missing ⚠️
backend/src/jobs/job.controller.ts 0.00% 3 Missing ⚠️

📢 Thoughts on this report? Let us know!

@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: 5

Caution

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

⚠️ Outside diff range comments (2)
frontend/components/dashboard/dashboard-widgets.tsx (1)

21-29: ⚠️ Potential issue | 🟡 Minor

Update the helper copy to match the new CTA.

The button now says “Manage Jobs”, but the text above it still describes creating/analyzing a new posting. That mismatch is likely to confuse users on the dashboard.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/components/dashboard/dashboard-widgets.tsx` around lines 21 - 29,
The helper copy above the CTA is out of sync: update the paragraph text in the
dashboard-widgets component (the <p> element shown in dashboard-widgets.tsx that
currently reads "Analyze a new job posting to get recommendations.") so it
aligns with the CTA "Manage Jobs" (the Link with href="/jobs" and link text
"Manage Jobs"); replace it with a short line like "View and manage your job
postings" or similar copy that clearly references managing or viewing jobs.
frontend/components/job/job-input-toggle.tsx (1)

17-31: ⚠️ Potential issue | 🟡 Minor

Expose the selected toggle state to assistive tech.

These buttons act like a toggle, but the active state is only visual right now. Adding aria-pressed will make the current selection understandable to screen readers.

Accessibility fix
         <button
           type="button"
+          aria-pressed={isText}
           onClick={() => onChange("TEXT")}
           className={`rounded-lg px-4 py-2 text-sm font-medium transition ${
             isText
               ? "bg-white shadow text-black"
               : "text-gray-600 hover:text-black"
@@
         <button
           type="button"
+          aria-pressed={isLink}
           onClick={() => onChange("LINK")}
           className={`rounded-lg px-4 py-2 text-sm font-medium transition ${
             isLink
               ? "bg-white shadow text-black"
               : "text-gray-600 hover:text-black"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/components/job/job-input-toggle.tsx` around lines 17 - 31, The
toggle buttons (Paste Text and Link) only convey state visually; update the
button elements (the one using isText and the one calling onChange("LINK")) to
include an aria-pressed attribute that reflects the active state (for the TEXT
button use aria-pressed={isText} and for the LINK button use
aria-pressed={!isText} or an explicit isLink boolean), so screen readers can
announce which option is selected; ensure the attribute is present on both
buttons that call onChange and ties to the same isText state.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@backend/src/jobs/job.controller.ts`:
- Around line 52-61: The response currently returns only hasMore; update the
controller method that calls this.jobService.getJobsByUserId to include a
totalCount (or totalPages) in the returned payload so the frontend can render
numbered pagination. Modify the jobService.getJobsByUserId (or add a companion
method like jobService.countJobsByUserId) to return totalCount alongside
result.jobs and result.hasMore, then change the controller return object to
include totalCount (or compute totalPages from totalCount and query.take) and
update the TypeScript return type accordingly.

In `@backend/src/jobs/job.service.ts`:
- Around line 29-33: The pagination sorting is currently non-deterministic
because jobRepository.find orders only by createdAt; update the order clause
used by jobRepository.find to include a unique tie-breaker such as the primary
key (e.g., id) in a deterministic direction (for example order: { createdAt:
'DESC', id: 'DESC' }) so offset pagination with skip/take (take + 1) will not
duplicate or skip rows when createdAt values are identical.

In `@frontend/components/job/job-card.tsx`:
- Around line 27-33: The "View" and "Delete" buttons in the JobCard component
are interactive but currently no-ops; update the component (JobCard) to accept
optional callback props (e.g., onView: (id: string) => void, onDelete: (id:
string) => void) and wire the "View" button to call props.onView(job.id) and the
"Delete" button to call props.onDelete(job.id) (with proper null-checks), or if
you prefer not to implement callbacks yet, render these buttons with disabled
styling/disabled attribute and remove onclick behavior; ensure to update the
component's props interface and all callers to pass handlers or accept the
disabled state.

In `@frontend/components/job/jobs-page-content.tsx`:
- Around line 26-30: The empty/error fetch branches do not clear previous
results, so add a call to clear the jobs state (e.g., setJobs([])) before
returning in both the "if (!jobs || jobs.length === 0) { ... }" branch and the
error/empty path around lines 42-46; keep the existing setTotalPages(1) and
setIsLoading(false) but ensure setJobs([]) is invoked prior to return so stale
job entries are not rendered after an empty response or failed request.
- Around line 19-49: The fetchJobs useEffect is vulnerable to out-of-order
responses overwriting state; make it race-safe by tracking the latest request
and ignoring stale responses: add a fetchRequestId ref (e.g.,
fetchRequestId.current) or an AbortController per invocation inside the
useEffect, increment/replace it before calling getJobs, capture the id or signal
in the async fetchJobs, and only call setJobs, setTotalPages, and setIsLoading
if the captured id matches the current fetchRequestId (or the signal is not
aborted). Keep the existing getJobs, fetchJobs, and state setters but gate state
updates behind this check and ensure cleanup in the effect returns
abort/invalidates the request to prevent updates after unmount.

---

Outside diff comments:
In `@frontend/components/dashboard/dashboard-widgets.tsx`:
- Around line 21-29: The helper copy above the CTA is out of sync: update the
paragraph text in the dashboard-widgets component (the <p> element shown in
dashboard-widgets.tsx that currently reads "Analyze a new job posting to get
recommendations.") so it aligns with the CTA "Manage Jobs" (the Link with
href="/jobs" and link text "Manage Jobs"); replace it with a short line like
"View and manage your job postings" or similar copy that clearly references
managing or viewing jobs.

In `@frontend/components/job/job-input-toggle.tsx`:
- Around line 17-31: The toggle buttons (Paste Text and Link) only convey state
visually; update the button elements (the one using isText and the one calling
onChange("LINK")) to include an aria-pressed attribute that reflects the active
state (for the TEXT button use aria-pressed={isText} and for the LINK button use
aria-pressed={!isText} or an explicit isLink boolean), so screen readers can
announce which option is selected; ensure the attribute is present on both
buttons that call onChange and ties to the same isText state.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 9d767c83-ef1b-4055-bc05-35631680f109

📥 Commits

Reviewing files that changed from the base of the PR and between 0ae3be7 and 73b41e2.

📒 Files selected for processing (14)
  • backend/src/jobs/job.controller.ts
  • backend/src/jobs/job.service.ts
  • frontend/app/jobs/page.tsx
  • frontend/components/dashboard/dashboard-widgets.tsx
  • frontend/components/job/job-card.tsx
  • frontend/components/job/job-form.tsx
  • frontend/components/job/job-input-toggle.tsx
  • frontend/components/job/job-list.tsx
  • frontend/components/job/job-result-preview.tsx
  • frontend/components/job/jobs-list.tsx
  • frontend/components/job/jobs-page-content.tsx
  • frontend/lib/job-api.ts
  • frontend/types/auth.ts
  • frontend/types/job.ts
💤 Files with no reviewable changes (1)
  • frontend/types/auth.ts

Comment thread backend/src/jobs/job.controller.ts Outdated
Comment thread backend/src/jobs/job.service.ts
Comment thread frontend/components/job/job-card.tsx
Comment thread frontend/components/job/jobs-page-content.tsx Outdated
Comment thread frontend/components/job/jobs-page-content.tsx Outdated
@afnanaghai4 afnanaghai4 merged commit f391199 into master Apr 15, 2026
3 of 4 checks passed
@afnanaghai4 afnanaghai4 deleted the feature/jobs-integrated-page branch May 12, 2026 00:29
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