update position page design

This commit is contained in:
2026-08-13 21:41:14 +05:30
parent 6340962907
commit 1c653264b5
124 changed files with 5746 additions and 596 deletions

View File

@@ -8,7 +8,9 @@ import { cn } from '@/lib/utils';
import {
Avatar, Badge, Button, EmptyState, ProgressBar, StatusBadge, toast,
} from '@/components/ds';
import { useApplications, useInterviews, useJobPostings } from '@/lib/krowHooks';
import { useApplications, useCourses, useInterviews, useJobPostings, useWorkerProfiles } from '@/lib/krowHooks';
import { VerifiedSkills } from '@/components/krow/VerifiedSkills';
import { usePageSkills } from '@/lib/skills/usePageSkills';
import {
ALL_DIMENSIONS, SCORE_GROUPS, activityTimeline, careerScore, careerTier,
communicationLabel, endorsements, marketValue, nextPromotion, recommendationVerdict,
@@ -685,8 +687,12 @@ function Endorsements({ candidate }) {
}
/** Experience: history, availability, credentials and the applied position. */
function Experience({ candidate, job, interview }) {
function Experience({ candidate, job, interview, workerProfiles = [], courses = [], positions = [] }) {
const c = candidate;
/* What Forge has attached to the Candidates page. Nothing here names a skill —
a path authored tomorrow with `pages: candidates` appears without this
component changing. */
const pageSkills = usePageSkills('candidates');
return (
<div className="space-y-8">
@@ -738,6 +744,27 @@ function Experience({ candidate, job, interview }) {
)}
</section>
{/* Verified capability first, self-reported skills after it. Both belong
on the page — but one is backed by evidence Owliver graded, and the
order should say which.
Which skills appear is the Forge definitions' decision: only paths
attached to `candidates` are surfaced here, and when none are, the
heading goes with them rather than sitting over an empty panel. */}
{pageSkills.skills.length > 0 && (
<section>
<SectionLabel meta={`${pageSkills.skills.length} attached`}>Verified skills</SectionLabel>
<VerifiedSkills
pageId="candidates"
email={c.email}
profiles={workerProfiles}
courses={courses}
positions={positions}
customSources={pageSkills.customSources}
/>
</section>
)}
<SkillsAndCerts candidate={c} />
<section>
@@ -835,6 +862,11 @@ export default function CandidateProfile() {
const { data: applications = [], isLoading } = useApplications();
const { data: postings = [] } = useJobPostings();
const { data: interviews = [] } = useInterviews();
/* The workforce and the training library, for the verified-skill panel: a
candidate's real capability lives on the worker profile behind the
application, not on the application itself. */
const { data: workerProfiles = [] } = useWorkerProfiles();
const { data: courses = [] } = useCourses();
const candidate = useMemo(() => applications.find((a) => a.id === id), [applications, id]);
const job = useMemo(
@@ -946,7 +978,14 @@ export default function CandidateProfile() {
{tab === 'reputation' && <Reputation candidate={candidate} />}
{tab === 'experience' && (
<Experience candidate={candidate} job={job} interview={interview} />
<Experience
candidate={candidate}
job={job}
interview={interview}
workerProfiles={workerProfiles}
courses={courses}
positions={postings}
/>
)}
{tab === 'endorsements' && <Endorsements candidate={candidate} />}
{tab === 'activity' && <Activity candidate={candidate} interview={interview} />}