Repository navigation
System redesign - #2
Merged
Merged
Conversation
…s for dashboard, jobs, applications, careers, and onboarding
…lored options and download functionality
There was a problem hiding this comment.
Pull request overview
This PR introduces a redesigned Windrush product flow and UI shell (sidebar + new pages), adds onboarding/status routing, and expands the backend to support job feed endpoints and PDF export for generated application documents.
Changes:
- Added an
AppShell+Sidebarlayout and new top-level pages for Dashboard, Jobs, Job Details, Careers, and Applications. - Implemented onboarding flow with onboarding completion tracking and root-page routing based on onboarding status.
- Added PDF generation/download endpoints and persisted additional application data (including tailored CV) in the tracker DB.
Reviewed changes
Copilot reviewed 20 out of 21 changed files in this pull request and generated 11 comments.
Show a summary per file
| File | Description |
|---|---|
| frontend/src/components/Sidebar.tsx | New sidebar navigation and logout control. |
| frontend/src/components/JobCard.tsx | New job card UI + navigation to job detail. |
| frontend/src/components/AppShell.tsx | Wraps app pages with sidebar except for auth/onboarding routes. |
| frontend/src/app/layout.tsx | Wraps all pages with AppShell. |
| frontend/src/app/page.tsx | Root now routes to login/dashboard/onboarding based on token + onboarding status. |
| frontend/src/app/onboarding/page.tsx | New 3-step onboarding (CV upload → credentials → persona confirm). |
| frontend/src/app/dashboard/page.tsx | New dashboard UI (stats, recent applications, skill risk summary). |
| frontend/src/app/jobs/page.tsx | New job feed UI (search, filter chips, sorting, results grid). |
| frontend/src/app/jobs/[id]/page.tsx | New job detail flow (analysis, tailored CV + letter generation, browser-agent apply, PDF export). |
| frontend/src/app/applications/page.tsx | New application tracker UI with status updates + notes. |
| frontend/src/app/careers/page.tsx | New careers page (skill exposure risk + roadmap generation). |
| frontend/src/app/profile/page.tsx | Adds “Application Credentials” section to persona profile UI. |
| frontend/src/app/app/page.tsx | Replaces legacy app flow with a redirect to /jobs. |
| api/requirements.txt | Adds PDF-related dependencies. |
| api/app/tracker.py | Adds onboarding flag + tailored CV persistence and default status changes. |
| api/app/pdf_generator.py | New PDF generator module (CV + cover letter). |
| api/app/models.py | Extends persona core info with job-board credential fields. |
| api/app/main.py | Adds onboarding endpoints, job feed endpoints, per-job SSE endpoints, and PDF endpoints; adjusts apply flow. |
| api/app/agent.py | Adds tailored CV tool and tweaks risk/fit scoring outputs. |
| api/app/browser_agent.py | Updates Groq adapter for browser-use integration. |
| .idea/workspace.xml | Adds IDE workspace changes. |
Files not reviewed (1)
- .idea/workspace.xml: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+66
to
+71
| const sorted = [...filtered].sort((a, b) => { | ||
| if (sort === "fit") return norm(b.exposure_score) - norm(a.exposure_score); | ||
| if (sort === "risk") return norm(a.exposure_score) - norm(b.exposure_score); | ||
| return 0; | ||
| }); | ||
|
|
Comment on lines
+99
to
+104
| // Load job from sessionStorage | ||
| useEffect(() => { | ||
| const raw = sessionStorage.getItem(`job_${decodedId}`); | ||
| if (raw) { | ||
| try { setJob(JSON.parse(raw) as Job); } catch {} | ||
| } |
Comment on lines
+164
to
+166
| } catch {} | ||
| setStreamingCv(false); | ||
| setAppStep("cv_done"); |
Comment on lines
+335
to
353
| user_confirmed = False | ||
| try: | ||
| async for chunk in run_apply( | ||
| current_user.id, job_id, job_url, cover_letter, risks, session_id, q, fq, | ||
| job_email=job_email, job_password=job_password, cv_path=cv_path, | ||
| job_email=effective_email, job_password=effective_password, cv_path=cv_path, | ||
| ): | ||
| # Detect successful completion from done event | ||
| try: | ||
| payload = json.loads(chunk.removeprefix("data: ").strip()) | ||
| if payload.get("type") == "done": | ||
| applied_successfully = True | ||
| user_confirmed = True | ||
| except Exception: | ||
| pass | ||
| yield chunk | ||
| finally: | ||
| _browser_queues.pop(session_id, None) | ||
| _browser_frames.pop(session_id, None) | ||
| if app_id and applied_successfully: | ||
| if app_id and user_confirmed: | ||
| tracker.update_status(app_id, "Applied") | ||
|
|
Comment on lines
437
to
443
| ): | ||
| status = body.get("status", "") | ||
| notes = body.get("notes") | ||
| # In a multi-user system, we should verify the app_id belongs to current_user.id | ||
| # but for now update_status is global. Let's fix tracker later if needed. | ||
| ok = tracker.update_status(app_id, status, notes) | ||
| if not ok: | ||
| raise HTTPException(status_code=400, detail=f"Invalid status: {status!r}") | ||
| return {"id": app_id, "status": status, "updated": True} |
Comment on lines
+226
to
+233
| <label className="text-xs text-zinc-400 uppercase tracking-widest">Master password</label> | ||
| <div className="relative"> | ||
| <input | ||
| type={showPassword ? "text" : "password"} | ||
| value={jobPassword} | ||
| onChange={(e) => setJobPassword(e.target.value)} | ||
| placeholder="••••••••" | ||
| className="w-full bg-zinc-950 border border-zinc-800 rounded-lg px-4 py-2.5 text-sm text-zinc-100 focus:outline-none focus:border-teal-500 transition-colors pr-12" |
Comment on lines
+310
to
+317
| <label className="text-xs text-zinc-500 uppercase">Master password</label> | ||
| <input | ||
| type="password" | ||
| className="w-full bg-zinc-950 border border-zinc-800 rounded p-2 text-sm focus:border-teal-500 outline-none" | ||
| value={persona.core_info.job_password ?? ""} | ||
| onChange={(e) => handleChange("core_info", "job_password", e.target.value)} | ||
| placeholder="••••••••" | ||
| /> |
| groq>=0.9 | ||
| langchain-groq>=0.2 | ||
| fpdf2>=2.7.9 | ||
| markdown>=3.5 |
Comment on lines
4
to
+10
| <option name="autoReloadType" value="SELECTIVE" /> | ||
| </component> | ||
| <component name="ChangeListManager"> | ||
| <list default="true" id="657acfba-7aae-4604-a67f-31eee75bbb05" name="Changes" comment="refactor agent.py to switch LLM backend between Ollama and Groq based on environment variable"> | ||
| <list default="true" id="657acfba-7aae-4604-a67f-31eee75bbb05" name="Changes" comment="feat: implement AppShell and Sidebar components for improved layout and navigation"> | ||
| <change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" /> | ||
| <change beforePath="$PROJECT_DIR$/api/app/main.py" beforeDir="false" afterPath="$PROJECT_DIR$/api/app/main.py" afterDir="false" /> | ||
| <change beforePath="$PROJECT_DIR$/api/requirements.txt" beforeDir="false" afterPath="$PROJECT_DIR$/api/requirements.txt" afterDir="false" /> | ||
| <change beforePath="$PROJECT_DIR$/frontend/src/app/app/page.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/frontend/src/app/app/page.tsx" afterDir="false" /> | ||
| <change beforePath="$PROJECT_DIR$/frontend/src/app/page.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/frontend/src/app/page.tsx" afterDir="false" /> | ||
| <change beforePath="$PROJECT_DIR$/frontend/src/components/BrowserView.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/frontend/src/components/BrowserView.tsx" afterDir="false" /> | ||
| <change beforePath="$PROJECT_DIR$/frontend/src/app/profile/page.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/frontend/src/app/profile/page.tsx" afterDir="false" /> |
Comment on lines
+618
to
+619
| except Exception as exc: | ||
| raise HTTPException(status_code=500, detail=str(exc)) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.