Source identity
| Field | Recorded value |
|---|---|
| Source type | GitHub source |
| Original record | Janady13/missionmatch / frontend/src/tools/recruitmatch/statusUi.ts |
| Date | Not specified in source |
| Repository | Janady13/missionmatch |
| Revision | 720d47fae476b0d38477ae4401697d372b1ea2bc |
| Branch | feature/opportunity-to-outcome |
| Path or archive member | frontend/src/tools/recruitmatch/statusUi.ts |
| Original SHA-256 | 38513387e43aeacaf4e06f9f9afb8584441b1e70033b6b59c755cec9995012c9 |
| Git blob SHA | 0392449bd5045eb6987f7905aa2ccb6fb4df5c12 |
| Reading-copy SHA-256 | 38513387e43aeacaf4e06f9f9afb8584441b1e70033b6b59c755cec9995012c9 |
Every recorded occurrence
These 2 records contain identical original source bytes. Their paths and revisions remain part of the archive.
| Original record | Branch or archive | Revision / identifier | Original location |
|---|---|---|---|
| Janady13/missionmatch / frontend/src/tools/recruitmatch/statusUi.ts | feature/opportunity-to-outcome | 720d47fae476b0d38477ae4401697d372b1ea2bc | Open original |
| Janady13/missionmatch / frontend/src/tools/recruitmatch/statusUi.ts | feature/aioe-upgrade | 2178e7298d0e5d9af83afa12402fd587f0ba6ed8 | Open original |
Recovered source transcript
Download complete source text ↓99 lines · 3.5 KB
import type { RRequisition } from '../../lib/types'
// The transition graph, mirrored from internal/modules/recruiting/requisition_status.go.
//
// Duplicated deliberately, and kept honest by the server rather than by discipline: the buttons offered
// here are only a convenience, and the server refuses anything illegal regardless of what was clicked.
// Showing a recruiter a button that always fails is worse than showing fewer buttons.
export const REQ_TRANSITIONS: Record<string, string[]> = {
draft: ['open', 'cancelled'],
open: ['on_hold', 'filled', 'closed', 'cancelled'],
on_hold: ['open', 'filled', 'closed', 'cancelled'],
filled: ['open', 'closed'],
closed: ['open'],
cancelled: ['open'],
}
export const STATUS_LABEL: Record<string, string> = {
draft: 'Draft',
open: 'Open',
on_hold: 'On hold',
filled: 'Filled',
closed: 'Closed',
cancelled: 'Cancelled',
}
// The verb, not the noun. A button that says "On hold" reads as a label; one that says "Put on hold"
// reads as the action it performs.
export const STATUS_ACTION: Record<string, string> = {
draft: 'Return to draft',
open: 'Reopen',
on_hold: 'Put on hold',
filled: 'Mark filled',
closed: 'Close',
cancelled: 'Cancel',
}
export function statusColor(status: string): string {
switch (status) {
case 'open':
return 'var(--color-ok)'
case 'on_hold':
return 'var(--color-warn)'
case 'filled':
return 'var(--color-blue-soft)'
case 'draft':
return 'var(--color-faint)'
default:
return 'var(--color-muted)'
}
}
export const PRIORITY_LABEL: Record<string, string> = {
low: 'Low',
normal: 'Normal',
high: 'High',
critical: 'Critical',
}
export function priorityColor(p: string): string {
switch (p) {
case 'critical':
return 'var(--color-risk)'
case 'high':
return 'var(--color-warn)'
default:
return 'var(--color-faint)'
}
}
// A rate range, rendered from the decimal strings the API sends.
//
// The string is sliced, never parsed to a number. Number() would round a value that was stored exactly,
// and the whole point of carrying money as a decimal string is that it survives the trip unchanged.
//
// Always two decimal places. numeric(12,4) sends 168.5000, and trimming trailing zeros renders that as
// "$168.5", which reads as a typo rather than as money. Extra precision beyond cents is kept if it is
// really there, because a rate carrying four places is a rate someone entered that way on purpose.
export function rateRange(min?: string, max?: string, suffix = '/hr'): string {
const fmt = (v: string) => {
const [whole, frac = ''] = v.split('.')
const trimmed = frac.replace(/0+$/, '')
return '$' + whole + '.' + (trimmed.length <= 2 ? trimmed.padEnd(2, '0') : trimmed)
}
if (min && max) return `${fmt(min)} to ${fmt(max)}${suffix}`
if (min) return `from ${fmt(min)}${suffix}`
if (max) return `up to ${fmt(max)}${suffix}`
return ''
}
// How a job order's target date should read. Absent is not the same as zero, and a passed target must
// say so plainly rather than showing a negative number.
export function targetText(r: RRequisition): { text: string; urgent: boolean } | null {
if (r.days_to_target === undefined || r.days_to_target === null) return null
const d = r.days_to_target
if (d < 0) return { text: `${Math.abs(d)} day${Math.abs(d) === 1 ? '' : 's'} past target`, urgent: true }
if (d === 0) return { text: 'Target is today', urgent: true }
return { text: `${d} day${d === 1 ? '' : 's'} to target`, urgent: d <= 7 }
}