Dealer_Onboard_Frontend/src/lib/statusProgressTheme.ts

232 lines
8.5 KiB
TypeScript

/**
* Unified status & progress colors across the app.
* Uses CSS classes from globals.css (amber) — NOT Tailwind bg-amber-* (remapped to re-red globally).
*
* - In progress / active: amber via .bg-status-progress / .bg-status-workflow-*
* - Completed / success: green
* - Rejected / revoked: re-red
*
* Primary buttons / brand UI: use bg-re-red (never amber).
*/
const TERMINAL_NEGATIVE = ['Rejected', 'Revoked', 'Withdrawn'] as const;
export type StatusProgressVariant = 'inProgress' | 'success' | 'negative' | 'neutral';
export function isStatusTerminalNegative(
status: string | null | undefined,
currentStage?: string | null | undefined
): boolean {
const s = String(status || '');
const stage = String(currentStage || '');
return TERMINAL_NEGATIVE.some((label) => s.includes(label) || stage === label);
}
export function isStatusTerminalSuccess(
status: string | null | undefined,
currentStage?: string | null | undefined
): boolean {
const s = String(status || '');
const stage = String(currentStage || '');
return (
s === 'Completed' ||
stage === 'Completed' ||
s === 'Settled' ||
s === 'Onboarded' ||
s === 'Verified' ||
s === 'Closed'
);
}
export function resolveStatusProgressVariant(
status: string | null | undefined,
currentStage?: string | null | undefined
): StatusProgressVariant {
if (isStatusTerminalSuccess(status, currentStage)) return 'success';
if (isStatusTerminalNegative(status, currentStage)) return 'negative';
return 'inProgress';
}
/** Semantic class sets — status/progress uses globals.css amber tokens */
export const STATUS_PROGRESS_THEME = {
inProgress: {
bar: 'bg-status-progress',
barBadge: 'bg-status-progress hover:bg-status-progress-hover text-white border-transparent',
badge: 'bg-status-progress-soft text-status-progress-strong border-status-progress',
badgeSolid: 'bg-status-progress hover:bg-status-progress-hover text-white border-transparent',
text: 'text-status-progress-muted',
textStrong: 'text-status-progress-strong',
icon: 'text-status-progress',
workflowIcon: 'bg-status-workflow-icon',
workflowPanel: 'bg-status-workflow-panel -ml-4 pl-4 pr-4 py-3 rounded-lg border border-status-workflow-panel',
workflowTitle: 'text-status-progress-strong',
workflowSubtitle: 'text-status-progress-muted',
workflowStageBadge: 'bg-status-workflow-badge border',
panel: 'bg-status-workflow-panel -ml-4 pl-4 pr-4 py-3 rounded-lg border border-status-workflow-panel',
title: 'text-status-progress-strong',
subtitle: 'text-status-progress-muted',
stageBadge: 'bg-status-workflow-badge border',
progress: 'bg-status-progress',
workflowActive: 'bg-status-workflow-active',
},
success: {
bar: 'bg-green-600',
barBadge: 'bg-green-600 hover:bg-green-700 text-white border-transparent',
badge: 'bg-green-100 text-green-800 border-green-200',
badgeSolid: 'bg-green-600 hover:bg-green-700 text-white border-transparent',
text: 'text-green-700',
textStrong: 'text-green-900',
icon: 'text-green-600',
workflowIcon: 'bg-green-100 text-green-600',
workflowPanel: 'bg-green-50 border border-green-200',
workflowTitle: 'text-green-900',
workflowSubtitle: 'text-green-700',
workflowStageBadge: 'bg-green-100 text-green-700 border-green-300',
panel: 'bg-green-50 border border-green-200',
title: 'text-green-900',
subtitle: 'text-green-700',
stageBadge: 'bg-green-100 text-green-700 border-green-300',
progress: 'bg-green-600',
workflowActive: 'bg-green-600 border-green-600',
},
negative: {
bar: 'bg-re-red',
barBadge: 'bg-re-red hover:bg-re-red-hover text-white border-transparent',
badge: 'bg-red-50 text-re-red border-red-200',
badgeSolid: 'bg-re-red hover:bg-re-red-hover text-white border-transparent',
text: 'text-re-red-hover',
textStrong: 'text-red-900',
icon: 'text-re-red',
workflowIcon: 'bg-red-100 text-re-red',
workflowPanel: 'bg-red-50 border border-red-200',
workflowTitle: 'text-red-900',
workflowSubtitle: 'text-re-red-hover',
workflowStageBadge: 'bg-red-50 text-re-red border-red-200',
panel: 'bg-red-50 border border-red-200',
title: 'text-red-900',
subtitle: 'text-re-red-hover',
stageBadge: 'bg-red-50 text-re-red border-red-200',
progress: 'bg-re-red',
workflowActive: 'bg-re-red border-re-red',
},
neutral: {
bar: 'bg-slate-300',
barBadge: 'bg-slate-500 text-white border-transparent',
badge: 'bg-slate-100 text-slate-700 border-slate-200',
badgeSolid: 'bg-slate-600 hover:bg-slate-700 text-white border-transparent',
text: 'text-slate-600',
textStrong: 'text-slate-900',
icon: 'text-slate-500',
workflowIcon: 'bg-slate-100 text-slate-400',
workflowPanel: '',
workflowTitle: 'text-slate-900',
workflowSubtitle: 'text-slate-600',
workflowStageBadge: 'bg-slate-100 text-slate-500 border-slate-300',
panel: '',
title: 'text-slate-900',
subtitle: 'text-slate-600',
stageBadge: 'bg-slate-100 text-slate-500 border-slate-300',
progress: 'bg-slate-300',
workflowActive: 'bg-slate-400 border-slate-400',
},
} as const;
function themeFor(status: string | null | undefined, currentStage?: string | null | undefined) {
return STATUS_PROGRESS_THEME[resolveStatusProgressVariant(status, currentStage)];
}
export function getStatusProgressBarClass(
status: string | null | undefined,
currentStage?: string | null | undefined
): string {
return themeFor(status, currentStage).bar;
}
export function getStatusProgressBadgeSolidClass(
status: string | null | undefined,
currentStage?: string | null | undefined
): string {
return themeFor(status, currentStage).barBadge;
}
export function getStatusProgressBadgeClass(
status: string | null | undefined,
currentStage?: string | null | undefined
): string {
return themeFor(status, currentStage).badge;
}
export function getWorkflowActiveStageTheme() {
return STATUS_PROGRESS_THEME.inProgress;
}
/** Progress bar / badge from completion % (EOR checklist, sub-trackers, etc.) */
export function getPercentProgressBarClass(percent: number): string {
if (percent >= 100) return STATUS_PROGRESS_THEME.success.bar;
return STATUS_PROGRESS_THEME.inProgress.bar;
}
export function getPercentProgressBadgeSolidClass(percent: number): string {
if (percent >= 100) return STATUS_PROGRESS_THEME.success.barBadge;
return STATUS_PROGRESS_THEME.inProgress.barBadge;
}
export function getStatusLabelBadgeClass(status: string | null | undefined): string {
const s = String(status || '');
const upper = s.toUpperCase();
if (s.includes('Rejected') || upper.includes('DOCUMENT_REJECTED')) {
return STATUS_PROGRESS_THEME.negative.badge;
}
if (s === 'Verified' || s === 'Completed' || upper.includes('DOCUMENT_VERIFIED')) {
return STATUS_PROGRESS_THEME.success.badge;
}
if (s.includes('Pending') || s.includes('Review') || s === 'In Progress') {
return STATUS_PROGRESS_THEME.inProgress.badge;
}
return STATUS_PROGRESS_THEME.neutral.badge;
}
/** Request status on listing/detail header — re-red while active (not amber). */
export function getRequestStatusBadgeClass(
status: string | null | undefined,
currentStage?: string | null | undefined
): string {
if (isStatusTerminalSuccess(status, currentStage)) {
return STATUS_PROGRESS_THEME.success.badge;
}
if (isStatusTerminalNegative(status, currentStage)) {
return STATUS_PROGRESS_THEME.negative.badge;
}
return STATUS_PROGRESS_THEME.negative.badge;
}
/** Solid request status pill (detail header). */
export function getRequestStatusBadgeSolidClass(
status: string | null | undefined,
currentStage?: string | null | undefined
): string {
if (isStatusTerminalSuccess(status, currentStage)) {
return STATUS_PROGRESS_THEME.success.badgeSolid;
}
if (isStatusTerminalNegative(status, currentStage)) {
return STATUS_PROGRESS_THEME.negative.badgeSolid;
}
return STATUS_PROGRESS_THEME.negative.badgeSolid;
}
/** Current stage chip (e.g. ASM Review) — brand re-red, not amber/yellow. */
export function getCurrentStageBadgeClass(
stage: string | null | undefined,
requestStatus?: string | null | undefined
): string {
const s = String(stage || '');
const status = String(requestStatus || '');
if (isStatusTerminalNegative(status, s) || /rejected|revoked/i.test(s)) {
return STATUS_PROGRESS_THEME.negative.badge;
}
if (s === 'Completed' || status === 'Completed' || s === 'Closed') {
return STATUS_PROGRESS_THEME.success.badge;
}
return STATUS_PROGRESS_THEME.negative.badge;
}