39950-vm/frontend/src/helpers/legalAiFormatting.ts
Flatlogic Bot 97439eda85 2
2026-05-11 12:32:55 +00:00

172 lines
4.2 KiB
TypeScript

import { humanize } from './humanize';
export const useCaseStatusMeta = {
draft: {
label: 'Draft',
className: 'bg-slate-100 text-slate-700 border-slate-200',
},
submitted: {
label: 'Submitted',
className: 'bg-blue-100 text-blue-700 border-blue-200',
},
risk_review: {
label: 'GC review',
className: 'bg-amber-100 text-amber-800 border-amber-200',
},
security_review: {
label: 'Security review',
className: 'bg-indigo-100 text-indigo-700 border-indigo-200',
},
ethics_review: {
label: 'Ethics review',
className: 'bg-violet-100 text-violet-700 border-violet-200',
},
approved: {
label: 'Approved',
className: 'bg-emerald-100 text-emerald-700 border-emerald-200',
},
rejected: {
label: 'Rejected',
className: 'bg-rose-100 text-rose-700 border-rose-200',
},
needs_changes: {
label: 'Needs changes',
className: 'bg-orange-100 text-orange-700 border-orange-200',
},
retired: {
label: 'Retired',
className: 'bg-slate-100 text-slate-600 border-slate-200',
},
};
export const riskLevelMeta = {
low: {
label: 'Low',
className: 'bg-emerald-100 text-emerald-700 border-emerald-200',
},
medium: {
label: 'Medium',
className: 'bg-amber-100 text-amber-800 border-amber-200',
},
high: {
label: 'High',
className: 'bg-orange-100 text-orange-700 border-orange-200',
},
critical: {
label: 'Critical',
className: 'bg-rose-100 text-rose-700 border-rose-200',
},
};
export const approvalStepMeta = {
partner: {
label: 'Partner / governance lead',
description: 'Business sponsor confirms value and ownership.',
},
general_counsel: {
label: 'General counsel',
description: 'Legal leadership confirms risk posture and client impact.',
},
it_security: {
label: 'IT / security',
description: 'Security posture, retention, SSO, and controls are validated.',
},
ethics_risk: {
label: 'Ethics / risk',
description: 'Human review and professional responsibility safeguards are confirmed.',
},
};
export function getBadgeClasses(className = 'bg-slate-100 text-slate-700 border-slate-200') {
return `inline-flex items-center rounded-full border px-2.5 py-1 text-xs font-semibold ${className}`;
}
export function getStatusBadge(value?: string | null) {
if (!value) {
return {
label: 'Not set',
className: getBadgeClasses(),
};
}
const meta = useCaseStatusMeta[value as keyof typeof useCaseStatusMeta] || {
label: humanize(value),
className: 'bg-slate-100 text-slate-700 border-slate-200',
};
return {
label: meta.label,
className: getBadgeClasses(meta.className),
};
}
export function getRiskBadge(value?: string | null) {
if (!value) {
return {
label: 'Risk pending',
className: getBadgeClasses('bg-slate-100 text-slate-700 border-slate-200'),
};
}
const meta = riskLevelMeta[value as keyof typeof riskLevelMeta] || {
label: humanize(value),
className: 'bg-slate-100 text-slate-700 border-slate-200',
};
return {
label: meta.label,
className: getBadgeClasses(meta.className),
};
}
export function getDecisionBadge(value?: string | null) {
if (!value || value === 'pending') {
return {
label: 'Pending',
className: getBadgeClasses('bg-slate-100 text-slate-700 border-slate-200'),
};
}
if (value === 'approved') {
return {
label: 'Approved',
className: getBadgeClasses('bg-emerald-100 text-emerald-700 border-emerald-200'),
};
}
if (value === 'rejected') {
return {
label: 'Rejected',
className: getBadgeClasses('bg-rose-100 text-rose-700 border-rose-200'),
};
}
if (value === 'needs_changes') {
return {
label: 'Needs changes',
className: getBadgeClasses('bg-orange-100 text-orange-700 border-orange-200'),
};
}
return {
label: humanize(value),
className: getBadgeClasses(),
};
}
export function formatNumber(value?: number | string | null) {
if (value === null || value === undefined || value === '') {
return '—';
}
const numericValue = Number(value);
if (Number.isNaN(numericValue)) {
return '—';
}
return new Intl.NumberFormat('en-US', {
maximumFractionDigits: 1,
}).format(numericValue);
}