update position page design
This commit is contained in:
56
src/lib/skills/usePageSkills.js
Normal file
56
src/lib/skills/usePageSkills.js
Normal file
@@ -0,0 +1,56 @@
|
||||
import { useMemo } from 'react';
|
||||
import { usePreferences } from '@/lib/krowHooks';
|
||||
import {
|
||||
isSkillOnPage, pageDefinitionForSkillId, skillStatesForPage, workforceSkillsForPage,
|
||||
} from './pageSkills';
|
||||
|
||||
/**
|
||||
* A page's skill attachments, resolved once.
|
||||
*
|
||||
* Every consuming page needs the same two things before it can ask anything
|
||||
* else: the account's custom definitions (a skill added in Settings is as real
|
||||
* as one on disk) and the ids it has switched off. Reading those in one hook
|
||||
* means no page can forget either, and none has to know where they are stored.
|
||||
*
|
||||
* The hook is deliberately thin — it resolves attachment and hands back the
|
||||
* helpers already bound to this page. The rules themselves stay in
|
||||
* `pageSkills.js`, which is what keeps them testable without React.
|
||||
*
|
||||
* Usage is always the same shape:
|
||||
*
|
||||
* const { skills, statesFor } = usePageSkills('profile');
|
||||
* if (!skills.length) return null; // nothing attached: no section
|
||||
*
|
||||
* `attaches(skillId)` is the gate for a contextual addition to something that
|
||||
* already exists — a training prompt beside a position requirement, say — where
|
||||
* the page is not listing skills but is about to mention one.
|
||||
*/
|
||||
export function usePageSkills(pageId) {
|
||||
const preferences = usePreferences();
|
||||
|
||||
/* `usePreferences` rebuilds its object on every read, so the arrays inside it
|
||||
are new identities each render. Keying the memo on their content is what
|
||||
stops every consumer from recomputing — and re-rendering — continuously. */
|
||||
const customKey = JSON.stringify(preferences.customSkills || []);
|
||||
const disabledKey = JSON.stringify(preferences.disabledSkills || []);
|
||||
|
||||
return useMemo(() => {
|
||||
const customSources = JSON.parse(customKey);
|
||||
const disabled = JSON.parse(disabledKey);
|
||||
const options = { customSources, disabled };
|
||||
const skills = workforceSkillsForPage(pageId, options);
|
||||
|
||||
return {
|
||||
/** The definitions attached here. Empty means render nothing. */
|
||||
skills,
|
||||
/** True when this page may surface that capability at all. */
|
||||
attaches: (skillId) => isSkillOnPage(skillId, pageId, options),
|
||||
/** The definition behind a capability, but only if attached here. */
|
||||
definitionFor: (skillId) => pageDefinitionForSkillId(skillId, pageId, options),
|
||||
/** Each attached definition paired with one person's state in it. */
|
||||
statesFor: (courses, profile) => skillStatesForPage(pageId, courses, profile, options),
|
||||
/** Passed through to components that resolve attachment themselves. */
|
||||
customSources,
|
||||
};
|
||||
}, [pageId, customKey, disabledKey]);
|
||||
}
|
||||
Reference in New Issue
Block a user