mirror of
https://dev.azure.com/globalhealthx/EMR/_git/helix-engage
synced 2026-04-12 02:38:15 +00:00
feat: add shared StatusBadge, SourceTag, AgeIndicator components and format utilities
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
24
src/components/shared/age-indicator.tsx
Normal file
24
src/components/shared/age-indicator.tsx
Normal file
@@ -0,0 +1,24 @@
|
||||
import { cx } from '@/utils/cx';
|
||||
import { daysAgoFromNow, getAgeBracket } from '@/lib/format';
|
||||
|
||||
const ageBracketColorMap = {
|
||||
fresh: 'text-success-primary',
|
||||
warm: 'text-warning-primary',
|
||||
cold: 'text-error-primary',
|
||||
};
|
||||
|
||||
interface AgeIndicatorProps {
|
||||
dateStr: string;
|
||||
}
|
||||
|
||||
export const AgeIndicator = ({ dateStr }: AgeIndicatorProps) => {
|
||||
const days = daysAgoFromNow(dateStr);
|
||||
const bracket = getAgeBracket(days);
|
||||
const colorClass = ageBracketColorMap[bracket];
|
||||
|
||||
return (
|
||||
<span className={cx('text-sm font-semibold', colorClass)}>
|
||||
{days}d
|
||||
</span>
|
||||
);
|
||||
};
|
||||
45
src/components/shared/source-tag.tsx
Normal file
45
src/components/shared/source-tag.tsx
Normal file
@@ -0,0 +1,45 @@
|
||||
import { Badge } from '@/components/base/badges/badges';
|
||||
import type { LeadSource } from '@/types/entities';
|
||||
|
||||
type SourceColor = 'blue' | 'pink' | 'success' | 'blue-light' | 'gray' | 'purple' | 'orange' | 'warning';
|
||||
|
||||
const sourceColorMap: Record<LeadSource, SourceColor> = {
|
||||
FACEBOOK_AD: 'blue',
|
||||
INSTAGRAM: 'pink',
|
||||
GOOGLE_AD: 'success',
|
||||
GOOGLE_MY_BUSINESS: 'blue-light',
|
||||
WHATSAPP: 'success',
|
||||
WEBSITE: 'gray',
|
||||
REFERRAL: 'purple',
|
||||
WALK_IN: 'orange',
|
||||
PHONE: 'warning',
|
||||
OTHER: 'gray',
|
||||
};
|
||||
|
||||
const sourceLabelMap: Record<LeadSource, string> = {
|
||||
FACEBOOK_AD: 'Facebook',
|
||||
INSTAGRAM: 'Instagram',
|
||||
GOOGLE_AD: 'Google',
|
||||
GOOGLE_MY_BUSINESS: 'GMB',
|
||||
WHATSAPP: 'WhatsApp',
|
||||
WEBSITE: 'Website',
|
||||
REFERRAL: 'Referral',
|
||||
WALK_IN: 'Walk-in',
|
||||
PHONE: 'Phone',
|
||||
OTHER: 'Other',
|
||||
};
|
||||
|
||||
interface SourceTagProps {
|
||||
source: LeadSource;
|
||||
size?: 'sm' | 'md';
|
||||
}
|
||||
|
||||
export const SourceTag = ({ source, size = 'sm' }: SourceTagProps) => {
|
||||
const color = sourceColorMap[source];
|
||||
const label = sourceLabelMap[source];
|
||||
return (
|
||||
<Badge size={size} type="pill-color" color={color}>
|
||||
{label}
|
||||
</Badge>
|
||||
);
|
||||
};
|
||||
54
src/components/shared/status-badge.tsx
Normal file
54
src/components/shared/status-badge.tsx
Normal file
@@ -0,0 +1,54 @@
|
||||
import { BadgeWithDot } from '@/components/base/badges/badges';
|
||||
import type { CampaignStatus, LeadStatus } from '@/types/entities';
|
||||
|
||||
const toTitleCase = (str: string): string =>
|
||||
str
|
||||
.toLowerCase()
|
||||
.replace(/_/g, ' ')
|
||||
.replace(/\b\w/g, (c) => c.toUpperCase());
|
||||
|
||||
type LeadStatusColor = 'blue' | 'brand' | 'success' | 'warning' | 'purple' | 'error' | 'gray';
|
||||
type CampaignStatusColor = 'gray' | 'success' | 'warning' | 'blue';
|
||||
|
||||
const leadStatusColorMap: Record<LeadStatus, LeadStatusColor> = {
|
||||
NEW: 'blue',
|
||||
CONTACTED: 'brand',
|
||||
QUALIFIED: 'success',
|
||||
NURTURING: 'warning',
|
||||
APPOINTMENT_SET: 'purple',
|
||||
CONVERTED: 'success',
|
||||
LOST: 'error',
|
||||
};
|
||||
|
||||
const campaignStatusColorMap: Record<CampaignStatus, CampaignStatusColor> = {
|
||||
DRAFT: 'gray',
|
||||
ACTIVE: 'success',
|
||||
PAUSED: 'warning',
|
||||
COMPLETED: 'blue',
|
||||
};
|
||||
|
||||
interface LeadStatusBadgeProps {
|
||||
status: LeadStatus;
|
||||
}
|
||||
|
||||
export const LeadStatusBadge = ({ status }: LeadStatusBadgeProps) => {
|
||||
const color = leadStatusColorMap[status];
|
||||
return (
|
||||
<BadgeWithDot size="sm" type="pill-color" color={color}>
|
||||
{toTitleCase(status)}
|
||||
</BadgeWithDot>
|
||||
);
|
||||
};
|
||||
|
||||
interface CampaignStatusBadgeProps {
|
||||
status: CampaignStatus;
|
||||
}
|
||||
|
||||
export const CampaignStatusBadge = ({ status }: CampaignStatusBadgeProps) => {
|
||||
const color = campaignStatusColorMap[status];
|
||||
return (
|
||||
<BadgeWithDot size="sm" type="pill-color" color={color}>
|
||||
{toTitleCase(status)}
|
||||
</BadgeWithDot>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user