update owliver skill
This commit is contained in:
@@ -56,6 +56,26 @@ const FREE_TEXT = /^(?:other|another|custom|enter|enter .*|type .*|somewhere els
|
||||
* understood — which re-asks with `retry` rather than storing a guess.
|
||||
*/
|
||||
const FIELDS = {
|
||||
/**
|
||||
* The client this role is being staffed for.
|
||||
*
|
||||
* A "client" is not a record of its own in this product — it is the `company`
|
||||
* on the position, which is the field the Create Position form writes, the
|
||||
* Positions card leads with, and Hired History reports against. So the
|
||||
* conversation collects it into the same field rather than into a store of
|
||||
* its own, and asking Owliver to create a client starts here.
|
||||
*/
|
||||
company: {
|
||||
label: 'Company',
|
||||
settled: (draft) => Boolean(String(draft.company || '').trim()),
|
||||
retry: 'Type the client or company name — "Fairmont San Jose".',
|
||||
parse: (answer) => {
|
||||
const value = cleanPhrase(answer, 60);
|
||||
return value && value.length > 1 ? { company: titleCase(value) } : null;
|
||||
},
|
||||
summary: (draft) => (draft.company ? `Company: ${draft.company}` : null),
|
||||
},
|
||||
|
||||
role_category: {
|
||||
label: 'Role',
|
||||
settled: (draft) => Boolean(draft.title),
|
||||
@@ -233,10 +253,13 @@ function review(flow, steps) {
|
||||
doc: doc(
|
||||
text('Ready to create this position?'),
|
||||
list(summaryLines(flow, steps)),
|
||||
note('Nothing is saved until you choose Create position.')
|
||||
note('Nothing is saved until you choose one. Save as Draft keeps it unpublished — the same as the button on the form.')
|
||||
),
|
||||
/* The two the form offers, in the same words and the same order, so the
|
||||
conversation and the page commit a position the same two ways. */
|
||||
followUp: [
|
||||
{ label: 'Create position', prompt: 'Create position' },
|
||||
{ label: 'Save as Draft', prompt: 'Save as draft' },
|
||||
{ label: 'Publish Job Posting', prompt: 'Publish job posting' },
|
||||
{ label: 'Change details', prompt: 'Change details' },
|
||||
],
|
||||
};
|
||||
@@ -305,9 +328,15 @@ export function advancePositionFlow({ flow, answer, skill, roles = [] }) {
|
||||
|
||||
/* The confirmation step. "Create position" is the only path to a record. */
|
||||
if (flow.stage === 'review') {
|
||||
if (/^(?:create position|create|create it|yes|confirm|looks good|go ahead)$/i.test(said)) {
|
||||
/* Saving unpublished. The same write, with the status the form's own
|
||||
"Save as Draft" button sets — one create path, two statuses. */
|
||||
if (/^(?:save as draft|save draft|draft|save it as a draft)$/i.test(said)) {
|
||||
if (missingRequired(flow, steps).length) return review(flow, steps);
|
||||
return { flow: { ...flow, stage: 'creating' }, create: { draft: flow.draft } };
|
||||
return { flow: { ...flow, stage: 'creating' }, create: { draft: flow.draft, status: 'draft' } };
|
||||
}
|
||||
if (/^(?:create position|publish job posting|publish|create|create it|yes|confirm|looks good|go ahead)$/i.test(said)) {
|
||||
if (missingRequired(flow, steps).length) return review(flow, steps);
|
||||
return { flow: { ...flow, stage: 'creating' }, create: { draft: flow.draft, status: 'active' } };
|
||||
}
|
||||
if (/^(?:change|change details|edit|change something|no)$/i.test(said)) return changeMenu(flow, steps);
|
||||
|
||||
@@ -322,7 +351,7 @@ export function advancePositionFlow({ flow, answer, skill, roles = [] }) {
|
||||
doc: doc(
|
||||
text('I did not catch that. Ready to create this position?'),
|
||||
list(summaryLines(flow, steps)),
|
||||
note('Choose Create position, or tell me what to change.')
|
||||
note('Choose Save as Draft or Publish Job Posting, or tell me what to change.')
|
||||
),
|
||||
};
|
||||
}
|
||||
@@ -430,14 +459,19 @@ function applyStatement(flow, steps, said, roles) {
|
||||
|
||||
/** The position exists. Said plainly, with what was created. */
|
||||
export function positionCreatedReply(position) {
|
||||
const isDraft = position.status === 'draft';
|
||||
|
||||
return doc(
|
||||
text('Position created successfully.'),
|
||||
text(isDraft ? 'Saved as a draft.' : 'Position created successfully.'),
|
||||
list([
|
||||
position.company,
|
||||
position.title,
|
||||
position.location,
|
||||
payLabel(position),
|
||||
].filter(Boolean)),
|
||||
note('It is on the Positions list now — applications will start appearing against it.')
|
||||
note(isDraft
|
||||
? 'It is on the Positions list as a draft — nobody can apply until it is published, and it stays a draft until you publish it.'
|
||||
: 'It is on the Positions list now — applications will start appearing against it.')
|
||||
);
|
||||
}
|
||||
|
||||
@@ -449,7 +483,20 @@ export function positionFailedReply() {
|
||||
);
|
||||
}
|
||||
|
||||
/** What the panel offers after a position is created. */
|
||||
export const createdFollowUp = (position) => [
|
||||
{ label: 'View position', route: `/admin/positions/${position.id}` },
|
||||
];
|
||||
/**
|
||||
* What the panel offers after a position is created.
|
||||
*
|
||||
* A published role has an obvious next question — who can fill it — so it is
|
||||
* offered here rather than left to be typed. The chip carries the position's
|
||||
* own title and the wording the workforce engine already answers, so it is an
|
||||
* ordinary question resolved by the path that was already there: no handler,
|
||||
* no navigation, and the same answer as asking it by hand.
|
||||
*/
|
||||
export const createdFollowUp = (position) => (position.status === 'draft'
|
||||
/* A draft is unfinished, so the way on is the form that finishes it — the
|
||||
same route the Positions card's Continue uses. */
|
||||
? [{ label: 'Continue to save', route: `/admin/positions/new?draft=${encodeURIComponent(position.id)}` }]
|
||||
: [
|
||||
{ label: 'View position', route: `/admin/positions/${position.id}` },
|
||||
{ label: 'Match candidates', prompt: `Who matches ${position.title}?` },
|
||||
]);
|
||||
|
||||
Reference in New Issue
Block a user