Skip to content

Feature import user cv#132

Merged
badarouzia merged 19 commits into
stagingfrom
feature-import-user-cv
Jun 26, 2026
Merged

Feature import user cv#132
badarouzia merged 19 commits into
stagingfrom
feature-import-user-cv

Conversation

@badarouzia

@badarouzia badarouzia commented May 12, 2026

Copy link
Copy Markdown
Collaborator

What type of PR is this? (check all applicable)

  • ✨ Feature
  • 🛑 Bug
  • ⚠️ Anomaly
  • 📝 Doc
  • 🎨 Style
  • 🧑‍💻 Refactor
  • 🛠️ Setup
  • 🏗️ Build
  • 🔥 Perfs
  • ✅ Test
  • 🔁 CI
  • ⏩ Revert

Description

This Pull Request introduces the Compatibility Analysis module. This feature allows users to bridge the gap between their current profile and a specific job offer by leveraging AI to extract skills and generate a tailored learning journey.

Features and Workflow

The module follows a structured three-step process as seen in the implemented UI:

Document and Data Intake

  • CV Upload: Drag-and-drop support for PDF and DOCX files with size validation.
  • Job Link Integration: Automated scraping of job descriptions via URL.
  • Deadline Tracking: A priority-based calendar system that calculates application urgency (Overdue, Today, or Days Left).

AI Processing

  • Visual progress feedback during Key Skills Extraction.
  • Matching logic between user experience and recruiter expectations.

Personalized Outcome

  • Confirmation screen displaying validated skills and optimized paths.
  • Direct CTA to Start My Training, leading the user to their customized curriculum.

Technical Changes

  • Component Architecture: Created CVAnalysisPage as a stateful orchestrator for UploaderCard, AIProcessingOverlay, and AnalysisResultCard.
  • Iconography: Migrated all hardcoded assets to the centralized iconMap system using react-icons.
  • State Management: Implemented hooks to handle file binary state, URL validation, and date calculations for the deadline urgency logic.
  • Styling: Built a responsive, clean grid layout using modern CSS-in-JS, ensuring a Premium AI feel.

Closes EpitechPromo2027/G-EIP-600-NAN-6-1-eip-tugdual.de-reviers#


Closes EpitechPromo2027/G-EIP-600-NAN-6-1-eip-tugdual.de-reviers#

Workspace

  • 🖥️ Web
  • 🛠️ Server
  • 🔁 CI
  • 🤖 Ai
  • 📱 App

Screenshots

Screenshot from 2026-05-10 08-54-29 Screenshot from 2026-05-12 11-14-48 Screenshot from 2026-05-12 11-15-11 Screenshot from 2026-05-12 11-15-17

@railway-app

railway-app Bot commented May 12, 2026

Copy link
Copy Markdown

This PR was not deployed automatically as @badarouzia does not have access to the Railway project.

In order to get automatic PR deploys, please add @badarouzia to your workspace on Railway.

@vercel

vercel Bot commented May 12, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
talk-up-ai-dev Ready Ready Preview, Comment Jun 21, 2026 7:16am

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR implements a new CV Compatibility Analysis flow in the web app, adding a 3-step UI (upload → “AI processing” overlay → results) and introducing supporting UI atoms/molecules/organisms plus tests.

Changes:

  • Reworked /cv-analysis route into a stateful orchestration page for upload, processing overlay, and result display.
  • Added new CV-import UI components (UploaderCard, AIProcessingOverlay, AnalysisResultCard) plus supporting atoms/molecules and Vitest tests.
  • Performed minor formatting/normalization updates in shared styles and a JSON data file.

Reviewed changes

Copilot reviewed 13 out of 15 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
web/src/styles/tailwind.css Normalizes hex color casing for CSS variables.
web/src/styles/scrollbar.css Re-indents scrollbar CSS (no functional change).
web/src/styles/calendar.css Re-formats calendar override CSS (no functional change).
web/src/routes/cv-analysis.tsx New CV analysis workflow page and orchestration logic.
web/src/components/organisms/cv-import/UploaderCard.tsx Drag-and-drop CV upload UI + deadline input/urgency display.
web/src/components/organisms/cv-import/Uploadercard.spec.tsx Adds tests for UploaderCard behavior (upload + deadline).
web/src/components/organisms/cv-import/AnalysisResultCard.tsx Results/CTA card shown after analysis completion.
web/src/components/organisms/cv-import/Analysisresultcard.spec.tsx Adds tests for AnalysisResultCard behavior.
web/src/components/organisms/cv-import/AIProcessingOverlay.tsx Simulated analysis overlay with progress + rotating status messages.
web/src/components/molecules/cv-import/Stepper.tsx Stepper molecule for the multi-step flow.
web/src/components/molecules/cv-import/AnalysisStatus.tsx Spinner + status message molecule used by the overlay.
web/src/components/molecules/convincing-banner/reviews.json Re-indents JSON content (no semantic change).
web/src/components/atoms/cv-import/StepIndicator.tsx Atom for individual step display.
web/src/components/atoms/cv-import/ProgressBar.tsx Progress bar atom used by the overlay.
web/src/components/atoms/cv-import/FileBadge.tsx File extension badge atom used in the uploader UI.
Comments suppressed due to low confidence (4)

web/src/routes/cv-analysis.tsx:16

  • /cv-analysis is marked as requiresAuth: true in routes.config.ts, but this route no longer applies beforeLoad: createAuthGuard('/cv-analysis'). This makes the page accessible without the configured auth check. Re-add the auth guard (or update the route config if it’s intended to be public) so routing behavior matches the central config.
export const Route = createFileRoute('/cv-analysis')({
  component: CVAnalysisPage,
});

web/src/routes/cv-analysis.tsx:45

  • URL validation is currently jobUrl.trim().startsWith('http'), which can treat invalid strings as valid (e.g. httpxyz) and is duplicated in multiple places. Consider centralizing this into a single boolean (e.g. isJobUrlValid) and validating via new URL(jobUrl) with an allowed protocol list (http:/https:).
  const handleStartAnalysis = () => {
    if (cvFile && jobUrl.trim().startsWith('http')) {
      setIsAnalyzing(true);
    }
  };

web/src/routes/cv-analysis.tsx:85

  • onStartCourse currently logs to the console. Since this is a user-facing CTA, it should trigger real navigation/action (e.g. router.navigate to the generated curriculum route) or be removed until implemented; leaving console.log here can easily ship to production.
        <AnalysisResultCard
          onRetry={handleReset}
          onStartCourse={() => console.log('Navigating to course path...')}
        />

web/src/components/organisms/cv-import/UploaderCard.tsx:168

  • The UI states “Max size: 5 MB”, but there is no size/type validation before calling onFileSelect (both for drop and input). Add client-side checks (size limit + allowed MIME/types) and provide user feedback when the file is rejected, otherwise users can select larger/unsupported files despite the UI hint.
          <input
            id="cv-input"
            type="file"
            hidden
            accept=".pdf,.doc,.docx"
            onChange={(e) =>
              e.target.files?.[0] && onFileSelect(e.target.files[0])
            }

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread web/src/routes/cv-analysis.tsx Outdated
Comment thread web/src/components/organisms/cv-import-uploader-card/index.tsx
Comment thread web/src/components/organisms/cv-import-uploader-card/index.spec.tsx
Comment thread web/src/components/organisms/cv-import/AIProcessingOverlay.tsx Outdated
Comment thread web/src/components/organisms/cv-import/AIProcessingOverlay.tsx Outdated
Comment thread web/src/components/organisms/cv-import/AnalysisResultCard.tsx Outdated
Comment thread web/src/components/organisms/cv-import/AnalysisResultCard.tsx Outdated
Comment thread web/src/components/organisms/cv-import-uploader-card/index.spec.tsx
Comment thread web/src/components/organisms/cv-import/Analysisresultcard.spec.tsx Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 13 out of 15 changed files in this pull request and generated 11 comments.

Comments suppressed due to low confidence (8)

web/src/routes/cv-analysis.tsx:16

  • The route definition no longer applies beforeLoad: createAuthGuard(...). This makes /cv-analysis accessible without authentication and could expose CV-related UI to unauthenticated users. Re-add the auth guard (or explicitly document/handle why this route must be public).
export const Route = createFileRoute('/cv-analysis')({
  component: CVAnalysisPage,
});

web/src/routes/cv-analysis.tsx:85

  • onStartCourse currently just logs to the console. This leaves the primary CTA non-functional in production builds and makes it easy to miss navigation wiring. Consider using TanStack Router navigation (or pass a real callback from a parent) instead of console.log.
        <AnalysisResultCard
          onRetry={handleReset}
          onStartCourse={() => console.log('Navigating to course path...')}
        />

web/src/routes/cv-analysis.tsx:133

  • The job-offer URL <input> has no associated <label> or aria-label, so screen readers will only announce it generically (placeholder text is not a reliable accessible name). Add a visible label or at least an aria-label/aria-labelledby.
                  <input
                    type="url"
                    style={urlInputStyle}
                    placeholder="Paste LinkedIn, WTTJ link..."
                    value={jobUrl}
                    onChange={(e) => setJobUrl(e.target.value)}
                  />

web/src/routes/cv-analysis.tsx:174

  • This file uses many hardcoded colors and large inline style objects (e.g. pageContainer, jobCard, button colors) rather than the existing Tailwind + design-token approach used across routes. This makes theming and future design updates harder. Consider translating these styles to Tailwind classes and/or CSS variables (e.g. var(--color-...)).
/** @type {React.CSSProperties} Layout for the main page container */
const pageContainer: React.CSSProperties = {
  backgroundColor: '#F8FAFC',
  minHeight: '100vh',
  padding: '60px 20px',
  fontFamily: 'Inter, system-ui, sans-serif',
};

web/src/routes/cv-analysis.tsx:170

  • This file references React.CSSProperties but does not import React (or CSSProperties) for the React type namespace. In this codebase, other files import React when using React.* types (e.g. web/src/types/events.ts:1). Import type { CSSProperties } from react (or import React from 'react') to avoid TS/lint issues.
/** @type {React.CSSProperties} Layout for the main page container */
const pageContainer: React.CSSProperties = {
  backgroundColor: '#F8FAFC',

web/src/components/organisms/cv-import/AIProcessingOverlay.tsx:80

  • User-facing title text contains spelling/grammar errors: “Analys TalkUp.AI in processe”. This will be visible during the analysis overlay; please correct it (e.g., “TalkUp.AI analysis in progress”).
    <div style={overlayStyle}>
      <div style={contentBox}>
        <h2 style={{ marginBottom: '24px' }}>Analys TalkUp.AI in processe</h2>

        <AnalysisStatus message={currentMessage} />

web/src/components/organisms/cv-import/AIProcessingOverlay.tsx:103

  • This file uses React.CSSProperties for style objects but does not import React (or CSSProperties). To match existing code patterns and avoid TS/lint issues, import type { CSSProperties } from react (or import React) and use that type instead of relying on a global React namespace.
/** @type {React.CSSProperties} Styles for the full-screen background */
const overlayStyle: React.CSSProperties = {
  position: 'fixed',
  top: 0,

web/src/components/organisms/cv-import/UploaderCard.tsx:169

  • The file input onChange forwards the selected file directly to onFileSelect without enforcing the advertised constraints (5MB max, allowed types). Add the same size/type validation here as for drag/drop to prevent unsupported uploads via the file picker.
          <input
            id="cv-input"
            type="file"
            hidden
            accept=".pdf,.doc,.docx"
            onChange={(e) =>
              e.target.files?.[0] && onFileSelect(e.target.files[0])
            }
          />

Comment thread web/src/routes/cv-analysis.tsx Outdated
Comment thread web/src/components/organisms/cv-import-uploader-card/index.tsx
Comment thread web/src/components/organisms/cv-import/AIProcessingOverlay.tsx Outdated
Comment thread web/src/components/atoms/cv-import/StepIndicator.tsx Outdated
Comment thread web/src/components/molecules/cv-import/Stepper.tsx Outdated
Comment thread web/src/components/atoms/cv-import/ProgressBar.tsx Outdated
Comment thread web/src/components/organisms/cv-import/AnalysisResultCard.tsx Outdated
Comment thread web/src/components/organisms/cv-import/AnalysisResultCard.tsx Outdated
Comment thread web/src/components/organisms/cv-import/Analysisresultcard.spec.tsx Outdated
Comment thread web/src/components/organisms/cv-import-uploader-card/index.spec.tsx

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 13 out of 15 changed files in this pull request and generated 8 comments.

Comments suppressed due to low confidence (1)

web/src/components/organisms/cv-import/UploaderCard.tsx:168

  • The file input onChange accepts and forwards any selected file without enforcing the advertised constraints (max size 5MB, PDF/DOC/DOCX). Implement the same validation here as for drag/drop and display an error message when the file is too large or unsupported.
          <input
            id="cv-input"
            type="file"
            hidden
            accept=".pdf,.doc,.docx"
            onChange={(e) =>
              e.target.files?.[0] && onFileSelect(e.target.files[0])
            }

Comment thread web/src/routes/cv-analysis.tsx
Comment thread web/src/routes/cv-analysis.tsx Outdated
Comment thread web/src/routes/cv-analysis.tsx
Comment thread web/src/components/organisms/cv-import-uploader-card/index.tsx
Comment thread web/src/components/organisms/cv-import/UploaderCard.tsx Outdated
Comment thread web/src/components/organisms/cv-import/Uploadercard.spec.tsx Outdated
Comment thread web/src/components/organisms/cv-import/AIProcessingOverlay.tsx Outdated
Comment thread web/src/components/organisms/cv-import/AIProcessingOverlay.tsx Outdated

@BhuvanArn BhuvanArn left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Review — request changes

CI is green but this isn't mergeable as-is. One security blocker, plus systemic design-system violations and a couple of non-functional UI dead-ends. Sorted by severity below; inline comments mark the specific spots.

🔴 Blockers

  1. Auth guard removed — route now public. web/src/routes/cv-analysis.tsx deletes beforeLoad: createAuthGuard('/cv-analysis'). This page handles user CVs (PII) and was protected; every other authed route keeps the guard. Restore it. (No inline anchor — the line was deleted in this PR.)
  2. Feature ignores the design system. Entire feature is inline React.CSSProperties with hardcoded hex (#2B70C9, #64748B, #F8FAFC, #1D9E75…). The design we implemented since the beginning of the project require semantic tokens (bg-accent, text-text, border-border…) and Tailwind utilities (text-h*, text-body-*). Zero dark-mode support : fixed white/slate backgrounds break the .dark class. Needs rework to tokens + Tailwind, not inline styles.

🟠 Major

  1. AI processing is simulated, not real. AIProcessingOverlay runs a setInterval 0→100% timer with no API call; AnalysisResultCard shows static "Analysis Complete!" / "Skills Validated". No CV parsing, no scraping, no backend, no server changes — so "import user CV" stores/sends nothing. If this is an intentional UI-first stub, label it as such in code + PR description.
  2. console.log as default behavior. Default onStartCourse and the route both console.log(...). "Start My Training" CTA is a dead end. (oxlint no-console is set to warn, so it doesn't fail CI — that's why this slipped through.)
  3. URL validation is .startsWith('http'). If this URL ever reaches a server-side scraper it's an SSRF surface. Validate with URL() + an https: protocol allowlist, and never let a raw user URL drive a server-side fetch without allowlisting.

🟡 Minor

  • File naming breaks kebab-case convention (Analysisresultcard.spec.tsx…); repo norm is kebab-case-dir/index.tsx.
  • File-type check accepts on MIME OR extension (||); extension is trivially spoofed — real validation belongs server-side.
  • Hover via JS (onMouseOver/Out hex swap) instead of CSS :hover/:focus; tests even assert the JS hex, which is brittle.
  • French error strings in an otherwise-English UI.
  • Missing a11y: the processing overlay is a fixed full-screen modal with no role="dialog"/aria-modal/focus management/aria-live; the job-URL input has no label.
  • reviews.json / calendar.css / scrollbar.css diffs are CRLF→LF churn only; tailwind.css change is hex-lowercasing only. Revert to keep the diff focused.
  • Emoji in the button label ("Start My Training 🚀") — not in the design system.

✅ Good

  • Atomic structure (atoms/molecules/organisms) is correct.
  • Solid test coverage on UploaderCard + AnalysisResultCard (deadline urgency, drag/drop, validation paths).
  • Thorough JSDoc; label htmlFor/id on the file input; timer/interval cleanup in useEffect.

Fixes for all of the above are being pushed to this branch; I'll pin each comment to the fixing commit.

Comment thread web/src/routes/cv-analysis.tsx Outdated
Comment thread web/src/routes/cv-analysis.tsx Outdated
Comment thread web/src/routes/cv-analysis.tsx Outdated
Comment thread web/src/routes/cv-analysis.tsx Outdated
Comment thread web/src/components/organisms/cv-import/AnalysisResultCard.tsx Outdated
Comment thread web/src/components/organisms/cv-import/AnalysisResultCard.tsx Outdated
Comment thread web/src/components/organisms/cv-import/UploaderCard.tsx Outdated
…, a11y

- restore createAuthGuard on /cv-analysis (route handles CV PII)
- rewrite cv-import feature to semantic tokens + Tailwind (dark-mode), drop inline hex
- add isAllowedJobUrl (URL parse + https allowlist) replacing startsWith('http')
- wire onStartCourse to real navigation, drop console.log dead-ends
- label simulated AI processing + static result card as UI-first stub
- restructure components to kebab-dir/index.tsx, rename specs
- english error strings, CSS hover, overlay/input a11y (role/aria/labels)
- revert EOL/hex churn files
@badarouzia badarouzia merged commit ec47981 into staging Jun 26, 2026
9 checks passed
@badarouzia badarouzia deleted the feature-import-user-cv branch June 26, 2026 05:45
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.

3 participants