Skip to main content

Frontend Fixes & Enhancements — 8 April 2026

This document covers all bug fixes, UI improvements, and new features implemented on 8 April 2026 across 32 files.


1. Kanban Card Blur on Drag

Problem: Clicking/dragging a job card in the Jobs Kanban board caused the card to appear visually blurred.

Root cause: backdrop-blur-sm on the SelectBox component created a GPU compositing layer that produced rendering artifacts when combined with the drag state's opacity-50 + rotate + scale transitions.

Fix:

  • Removed backdrop-blur-sm from SelectBox (opaque bg-gray-50 background made it invisible anyway)
  • Narrowed transition-all to transition-[opacity,transform,border] on KanbanJobCardAdapter to prevent unintended property transitions

Files: components/ux/TWResponsiveCard/blocks/header/SelectBox.tsx, components/ux/KanbanJobCardAdapter.tsx


2. Due Date Past Date Validation

Problem: The system accepted past dates when editing a job's due date (e.g., setting due date to yesterday).

Fix: Added minDate prop to the TWDatepicker component:

  • Calendar days before minDate are greyed out and unclickable
  • Validation on confirm button prevents setting dates before minimum
  • Manual text input is also validated
  • Applied minDate={today} to the job form's Due Date field

Files: components/ux/TWDatepicker.tsx, components/jobs/JobRequirementsForm.tsx


3. Candidate "Applied" Date Showing N/A

Problem: The candidate card in the job pipeline Kanban showed "N/A" for the Applied date.

Root cause: The card config used source: "applied" but useJobCandidates provides the field as matchDate.

Fix: Changed source: "applied" to source: "matchDate" in the candidate card config.

File: components/ux/TWResponsiveCard/cardBuilder/configs/candidateConfig.ts


4. Company Logo Showing "?" Instead of Initials

Problem: When a company had no logo image, a purple circle with "?" appeared instead of the company name initials.

Root cause: resolveAvatarUrl() was called without the name parameter. When no image URL exists and no name is provided, the function falls back to ? in the generated avatar URL.

Fix: Added the company/user name as the second argument to resolveAvatarUrl() across all affected pages:

  • Job detail page (company logo, contact avatar, talent picker modal)
  • Visitor job page
  • Jobseeker application page
  • Jobseeker job detail page

Files: app/company/jobs/[jobId]/page.tsx, app/(visitor)/jobs/[jobId]/page.tsx, app/jobseeker/application/page.tsx, app/jobseeker/jobs/[jobId]/page.tsx


Problem: Match scores on the Recommended tab showed values like 5113, 4961, 5000 instead of 51, 50, 50.

Root cause: The backend returns scores as 0–100, but the hook multiplied by 100 again (score * 100).

Fix: Removed the erroneous * 100 multiplication in useRecommendedTalents.

File: lib/hooks/jobs/useRecommendedTalents.ts


6. Score Widget on Candidates List Page

Problem: The /company/resume/candidates page had no match score displayed on candidate cards.

Fix:

  • Added async score fetching using GET_USER_JOB_MATCH_SCORE per candidate (same pattern as the pipeline view)
  • Added score and jobId fields to CandidateRow type and builders
  • Added score widget to the resume candidate card profile block config
  • Scores load from Apollo cache first (cache-first policy) and don't block page rendering

Files: app/company/resume/candidates/page.tsx, components/ux/TWResponsiveCard/cardBuilder/configs/resumeCandidateConfig.ts, lib/utils/candidates/candidateRowBuilder.ts


7. "Due in -8 days" Overdue Display

Problem: The job detail page header showed "Due in -8 days" for overdue jobs.

Fix: Contextual display:

  • Negative days: "Overdue by X days" (red text)
  • Zero days: "Due today"
  • 1-7 days: amber warning color
  • 8+ days: default color

File: app/company/jobs/[jobId]/page.tsx


Problem: Recommended talent cards showed irrelevant information (status selector, "Handled by" name on every card, "Talent Pool Match" tag, edit/delete menu) and looked flat.

Changes:

  • Removed: Empty header block (eliminated blank space at top), status selector (NEW badge was wrong), edit/delete/download menu, "Handled by" info, "Applied" date, "Talent Pool Match" tag
  • Added: "Add as Candidate" footer button wired to addTalentAsCandidate mutation, email (clickable mailto), phone (clickable tel), top 5 skills from CV
  • Added addCandidate action to the action configs registry

Files: components/ux/TWResponsiveCard/cardBuilder/configs/recommendedTalentsConfig.ts, lib/hooks/jobs/useRecommendedTalents.ts, components/ux/TWResponsiveCard/cardBuilder/actions/actionConfigs.tsx, app/company/jobs/[jobId]/page.tsx


9. Dropzone MIME Type Warnings

Problem: Browser console showed warnings: Skipped ".csv" because it is not a valid MIME type for every file extension in the accept prop.

Root cause: The Dropzone component passed file extensions (.pdf, .csv) directly as keys to react-dropzone's accept prop, which expects MIME types.

Fix: Added an EXT_TO_MIME mapping and parseAccept() function that converts extensions to proper MIME types (e.g., .pdfapplication/pdf, .csvtext/csv).

File: components/reusable/Dropzone.tsx


10. Agent Document Upload — 0 Bytes Size

Problem: Uploaded agent documents showed "0 B" file size.

Root cause: file.size was logged but never included in the uploadAgentDocument mutation input.

Fix: Added sizeBytes: file.size to the mutation input object.

File: lib/hooks/useAgentDocuments.ts


11. Document Card — Upload Date Display

Problem: No way to see when a document was uploaded.

Fix: Added formatted upload date with calendar icon next to the file size on each document card.

Note: "Uploaded by" is not available — the backend's AgentDocument type doesn't expose an uploadedBy field. The uploadedById is sent during upload but not returned on queries. This requires a backend change.

File: components/company/ai-agent/DocumentCard.tsx


12. Book Interview Modal — End Time Fix

Problem: The end time field was a static read-only display (<div>) that didn't align with the "From" dropdown and couldn't be changed by the user. Duration was fixed and didn't update.

Fix:

  • Replaced static <div> with an editable TWSelect dropdown (proper alignment)
  • End time options filtered to only show times after the selected start time
  • Bidirectional sync: changing duration updates end time, changing end time updates duration

File: app/company/resume/candidates/_components/modals/BookInterviewModal.tsx


13. Save as Draft Job Posting

Problem: "Save as Draft" button created jobs with status "NEW" instead of "DRAFT".

Root cause: handleSaveAsDraft called buildJobInput with { publishedOnline: false } but didn't override the status, which defaulted to "NEW".

Fix: Added status: "DRAFT" to the overrides: buildJobInput(resolvedSkills, { publishedOnline: false, status: "DRAFT" }).

File: components/reusable/jobs/CreateJob.tsx


14. Draft Status in Kanban Board

Problem: Draft jobs had no dedicated column in the Kanban board — they were mapped to "New".

Fix:

  • Added DRAFT to PipelineItemStatus union type
  • Added DRAFT to DEFAULT_PIPELINE_STATUSES (first position, before NEW)
  • Fixed status mapping: DRAFT → DRAFT (was DRAFT → NEW)
  • Added Draft column to KanbanBoard default columns
  • Added Draft option to card status selector dropdowns
  • Added EditIcon for Draft column visibility filter on jobs page

Files: lib/types/kanban.ts, lib/types/pipeline.ts, lib/utils/pipeline.ts, components/ux/KanbanBoard.tsx, components/ux/KanbanJobCardAdapter.tsx, app/company/jobs/page.tsx


15. Inline Edit Duplication Bug (Critical Fix)

Problem: Inline editing any field (title, location, year, etc.) on certifications, experiences, or education cards on the talent view page (/company/resume/talents/[id]) caused the edited item to be duplicated — both the old and new version appeared.

Root cause: The useInlineResumeEdit hook's edit handlers (handleCertificateEdit, handleExperienceEdit, handleEducationEdit) replaced the array item with the updated object from the card's onEdit callback. But the card component types (Certificate, Experience, Education from lib/types/qualifications.ts) don't include _structuredId. So the replacement item lost its _structuredId.

When saveStructuredCv ran its diff to determine which mutations to call, items without _structuredId were treated as new items → ADD mutation was called instead of UPDATE → backend created a new record while keeping the old one → duplication.

Fix: All three edit handlers in useInlineResumeEdit.ts now preserve _structuredId from the original array item before replacing with the updated data:

const original = certificates[index] as Record<string, unknown> | undefined
const structuredId = original?._structuredId
certificates[index] = structuredId
? { ...updated, _structuredId: structuredId } as Certificate
: updated

File: app/company/resume/candidates/_components/utils/useInlineResumeEdit.ts


16. Certification Location Not Preserved in CV Builder

Problem: Editing a certification's location through the CV builder / ProfileForm path dropped the location field.

Root cause: The converter functions cvBuilderCertToOnboarding and onboardingCertToCVBuilder in ProfileForm.tsx didn't include the location field — only title, year, and institute were mapped.

Fix: Added location to both converter functions.

File: components/cv/ProfileForm.tsx


17. Inline Edit Double-Fire Guard

Problem: Clicking the "Done" button while a text input was focused caused handleDone to fire twice — once from the input's onBlur and once from the button's onClick. This could cause state inconsistencies.

Fix: Added guard if (editingField === null) return at the top of handleDone and handleFieldDone in all three qualification card components. The second call is a no-op since the first already set editingField to null.

Files: components/reusable/qualifications/CertificateCard.tsx, EducationCard.tsx, ExperienceCard.tsx


18. TWSelect defaultOpen Prop

Problem: Location fields in qualification cards required two clicks — one to enter edit mode (swap text for dropdown), another to open the dropdown.

Fix: Added defaultOpen prop to TWSelect and TWLocationAutocomplete. When defaultOpen is true, the dropdown opens automatically after mount via requestAnimationFrame (delayed to avoid the original mousedown triggering click-outside). Location fields in qualification cards changed from fixed w-64 to flex-1 min-w-0 for proper width.

Note: defaultOpen is currently not applied to the qualification cards (reverted to avoid interaction issues). The prop is available for future use.

Files: components/ux/TWSelect.tsx, components/ux/TWLocationAutocomplete.tsx, components/reusable/qualifications/CertificateCard.tsx, EducationCard.tsx, ExperienceCard.tsx


Files Changed Summary

#FileChanges
1components/ux/TWResponsiveCard/blocks/header/SelectBox.tsxRemove backdrop-blur-sm
2components/ux/KanbanJobCardAdapter.tsxNarrow transitions, add DRAFT status
3components/ux/TWDatepicker.tsxAdd minDate prop with calendar/input validation
4components/jobs/JobRequirementsForm.tsxApply minDate to due date field
5components/ux/TWResponsiveCard/cardBuilder/configs/candidateConfig.tsFix applied date field mapping
6components/ux/TWResponsiveCard/cardBuilder/configs/resumeCandidateConfig.tsAdd score widget
7components/ux/TWResponsiveCard/cardBuilder/configs/recommendedTalentsConfig.tsFull card overhaul
8components/ux/TWResponsiveCard/cardBuilder/actions/actionConfigs.tsxAdd addCandidate action
9components/reusable/Dropzone.tsxFix MIME type mapping
10components/reusable/jobs/CreateJob.tsxFix draft status
11components/company/ai-agent/DocumentCard.tsxAdd upload date
12components/ux/KanbanBoard.tsxAdd Draft column
13app/company/jobs/page.tsxAdd Draft icon/label
14app/company/jobs/[jobId]/page.tsxFix avatars, overdue display, recommended grid
15app/company/resume/candidates/page.tsxAdd score fetching
16app/company/resume/candidates/_components/modals/BookInterviewModal.tsxFix end time
17app/(visitor)/jobs/[jobId]/page.tsxFix company logo avatar
18app/jobseeker/application/page.tsxFix company logo avatar
19app/jobseeker/jobs/[jobId]/page.tsxFix company logo avatar
20lib/hooks/jobs/useRecommendedTalents.tsFix score, add email/phone/skills
21lib/hooks/useAgentDocuments.tsAdd sizeBytes to mutation
22lib/utils/candidates/candidateRowBuilder.tsAdd score/jobId fields
23lib/utils/pipeline.tsFix DRAFT mapping
24lib/types/kanban.tsAdd DRAFT to type
25lib/types/pipeline.tsAdd DRAFT to defaults
26app/company/resume/candidates/_components/utils/useInlineResumeEdit.tsPreserve _structuredId on inline edit
27components/cv/ProfileForm.tsxAdd location to cert converters
28components/reusable/qualifications/CertificateCard.tsxGuard double-fire, flex location
29components/reusable/qualifications/EducationCard.tsxGuard double-fire, flex location
30components/reusable/qualifications/ExperienceCard.tsxGuard double-fire, flex location
31components/ux/TWSelect.tsxAdd defaultOpen prop
32components/ux/TWLocationAutocomplete.tsxPass defaultOpen to TWSelect