- Introduced a new Privileges module, including routes for creating, editing, and viewing privileges. - Implemented a detailed permissions matrix for managing actions (view, create, update, delete, import) associated with each privilege. - Added validation schema for privilege creation and editing. - Developed UI components for displaying and managing privilege details and permissions. - Integrated language support for English and Indonesian in the privileges module. - Created unit tests for the privileges remote data service and transformer to ensure functionality. This commit enhances the application by providing a comprehensive privileges management system, improving user role management and permissions handling.
287 lines
10 KiB
TypeScript
287 lines
10 KiB
TypeScript
import React from 'react';
|
|
import { Badge, BadgeProps } from '@mantine/core';
|
|
import {
|
|
CheckCircle2,
|
|
XCircle,
|
|
Clock,
|
|
Edit2,
|
|
Loader2,
|
|
Package,
|
|
AlertCircle,
|
|
RotateCcw,
|
|
Check,
|
|
CreditCard,
|
|
Send,
|
|
Users,
|
|
} from 'lucide-react';
|
|
|
|
export enum STATUS_DATA {
|
|
DRAFT = 'draft',
|
|
|
|
ACTIVE = 'active',
|
|
ACTIVATED = 'activated',
|
|
|
|
INACTIVE = 'inactive',
|
|
DEACTIVATED = 'deactivated',
|
|
ARCHIVED = 'archived',
|
|
|
|
REQUEST = 'request',
|
|
REQUESTING = 'requesting',
|
|
REQUESTED = 'requested',
|
|
|
|
APPROVAL = 'approval',
|
|
APPROVED = 'approved',
|
|
|
|
OPEN = 'open',
|
|
OPENED = 'opened',
|
|
|
|
PENDING = 'pending',
|
|
|
|
WAIT = 'wait',
|
|
WAITING = 'waiting',
|
|
WAITING_LIST = 'waiting-list',
|
|
|
|
PROCESS = 'process',
|
|
PROCESSING = 'processing',
|
|
IN_PROCESS = 'in-process',
|
|
PROCESSED = 'processed',
|
|
|
|
CLOSE = 'close',
|
|
CLOSED = 'closed',
|
|
|
|
CANCEL = 'cancel',
|
|
CANCELLED = 'cancelled',
|
|
|
|
COMPLETE = 'complete',
|
|
COMPLETED = 'completed',
|
|
|
|
TODO = 'todo',
|
|
DONE = 'done',
|
|
PARTIAL_DONE = 'partial-done',
|
|
|
|
ON_HOLD = 'on-hold',
|
|
|
|
SHIPMENT = 'shipment',
|
|
SHIPPING = 'shipping',
|
|
SHIPPED = 'shipped',
|
|
|
|
EXPIRED = 'expired',
|
|
|
|
REFUND = 'refund',
|
|
REFUNDED = 'refunded',
|
|
PARTIAL_REFUND = 'partial-refund',
|
|
PARTIALLY_REFUNDED = 'partially-refunded',
|
|
REFUND_PROCESSING = 'refund-processing',
|
|
REFUND_PROCESS = 'refund-process',
|
|
CANCEL_REFUNDED = 'cancel-refunded',
|
|
|
|
TRANSFERRED = 'transferred',
|
|
|
|
SETTLEMENT = 'settlement',
|
|
SETTLED = 'settled',
|
|
SETTLED_FREE = 'settled-free',
|
|
|
|
REJECTION = 'rejection',
|
|
REJECTED = 'rejected',
|
|
|
|
PAYMENT = 'payment',
|
|
PAID = 'paid',
|
|
|
|
ISSUE = 'issue',
|
|
PROBLEM = 'problem',
|
|
RESOLVED = 'resolved',
|
|
|
|
CHECKOUT = 'checkout',
|
|
INVOICE = 'invoice',
|
|
INVOICED = 'invoiced',
|
|
|
|
JOINED = 'joined',
|
|
INVITED = 'invited',
|
|
|
|
PRESENT = 'present',
|
|
}
|
|
|
|
export enum STATUS_COLOR {
|
|
// DRAFT = '#6A6725',
|
|
DRAFT = '#B6B6B6',
|
|
TODO = '#CCCF77',
|
|
|
|
// INACTIVE = '#6A252A',
|
|
// DEACTIVATED = '#792A2C',
|
|
INACTIVE = '#BC1913',
|
|
DEACTIVATED = '#BC1913',
|
|
CLOSE = '#883230',
|
|
CLOSED = '#973C35',
|
|
|
|
// ACTIVE = '#518F00',
|
|
// ACTIVATED = '#539B01',
|
|
ACTIVE = '#54B304',
|
|
ACTIVATED = '#54B304',
|
|
APPROVED = '#54A702',
|
|
PROCESSED = '#54B304',
|
|
COMPLETED = '#54BE05',
|
|
COMPLETE = '#53CA07',
|
|
DONE = '#51D509',
|
|
SHIPPED = '#4EE00B',
|
|
REFUNDED = '#4BEB0D',
|
|
SETTLED = '#4BF114',
|
|
PAID = '#4DF022',
|
|
INVOICED = '#51EF30',
|
|
RESOLVED = '#56EF3D',
|
|
JOINED = '#5CEF4B',
|
|
PRESENT = '#62EE58',
|
|
|
|
REQUEST = '#00758F',
|
|
REQUESTING = '#017A9D',
|
|
REQUESTED = '#037FAB',
|
|
OPEN = '#0482B8',
|
|
OPENED = '#0685C6',
|
|
PROCESS = '#0886D3',
|
|
PROCESSING = '#0B86E0',
|
|
IN_PROCESS = '#0D86ED',
|
|
SHIPMENT = '#1985F0',
|
|
SHIPPING = '#2985F0',
|
|
TRANSFERRED = '#3986EF',
|
|
PAYMENT = '#4988EF',
|
|
INVOICE = '#588BEE',
|
|
|
|
APPROVAL = '#8F4500',
|
|
PENDING = '#9D5301',
|
|
WAIT = '#AB6103',
|
|
WAITING = '#B87104',
|
|
WAITING_LIST = '#C68106',
|
|
PARTIAL_DONE = '#D39308',
|
|
ON_HOLD = '#E0A50B',
|
|
REFUND = '#EDB70D',
|
|
REFUND_PROCESSING = '#F0C519',
|
|
REFUND_PROCESS = '#F0C519',
|
|
PARTIAL_REFUND = '#F0D029',
|
|
PARTIALLY_REFUNDED = '#EFD939',
|
|
SETTLEMENT = '#EFE149',
|
|
INVITED = '#EEE858',
|
|
|
|
CANCEL = '#7C1217',
|
|
CANCELLED = '#991B1A',
|
|
REJECTION = '#B52B24',
|
|
REJECTED = '#CF3D2E',
|
|
ISSUE = '#D3614F',
|
|
PROBLEM = '#D78270',
|
|
|
|
EXPIRED = '#8F0005',
|
|
CANCEL_REFUNDED = '#BC1913',
|
|
|
|
CHECKOUT = '#FF7B00',
|
|
SETTLED_FREE = '#3D6E93',
|
|
}
|
|
|
|
export type StatusBadgeConfigCallback = (status: string) => Partial<BadgeProps>;
|
|
|
|
export interface StatusBadgeProps extends Omit<BadgeProps, 'color' | 'leftSection'> {
|
|
/** The status string or STATUS_DATA enum value */
|
|
status: STATUS_DATA | string;
|
|
/** Optional custom label, overrides default status string */
|
|
label?: string;
|
|
/** Callback to provide custom badge props (color, icon) for a specific status */
|
|
getCustomConfig?: StatusBadgeConfigCallback;
|
|
/** Overrides default and custom color */
|
|
color?: string;
|
|
/** Overrides default and custom leftSection icon */
|
|
leftSection?: React.ReactNode;
|
|
}
|
|
|
|
const ICON_SIZE = 12;
|
|
const STROKE_WIDTH = 2.5;
|
|
|
|
const getIcon = (IconCmp: any) => <IconCmp size={ICON_SIZE} strokeWidth={STROKE_WIDTH} />;
|
|
|
|
export const DEFAULT_STATUS_MAP: Record<string, BadgeProps> = {
|
|
[STATUS_DATA.DRAFT]: { color: STATUS_COLOR.DRAFT, leftSection: getIcon(Edit2) },
|
|
[STATUS_DATA.TODO]: { color: STATUS_COLOR.TODO, leftSection: getIcon(Clock) },
|
|
|
|
[STATUS_DATA.INACTIVE]: { color: STATUS_COLOR.INACTIVE, leftSection: getIcon(XCircle) },
|
|
[STATUS_DATA.ARCHIVED]: { color: STATUS_COLOR.INACTIVE, leftSection: getIcon(XCircle) },
|
|
[STATUS_DATA.DEACTIVATED]: { color: STATUS_COLOR.DEACTIVATED, leftSection: getIcon(XCircle) },
|
|
[STATUS_DATA.CLOSE]: { color: STATUS_COLOR.CLOSE, leftSection: getIcon(XCircle) },
|
|
[STATUS_DATA.CLOSED]: { color: STATUS_COLOR.CLOSED, leftSection: getIcon(XCircle) },
|
|
|
|
[STATUS_DATA.ACTIVE]: { color: STATUS_COLOR.ACTIVE, leftSection: getIcon(CheckCircle2) },
|
|
[STATUS_DATA.ACTIVATED]: { color: STATUS_COLOR.ACTIVATED, leftSection: getIcon(CheckCircle2) },
|
|
[STATUS_DATA.APPROVED]: { color: STATUS_COLOR.APPROVED, leftSection: getIcon(CheckCircle2) },
|
|
[STATUS_DATA.PROCESSED]: { color: STATUS_COLOR.PROCESSED, leftSection: getIcon(Check) },
|
|
[STATUS_DATA.COMPLETED]: { color: STATUS_COLOR.COMPLETED, leftSection: getIcon(CheckCircle2) },
|
|
[STATUS_DATA.COMPLETE]: { color: STATUS_COLOR.COMPLETE, leftSection: getIcon(CheckCircle2) },
|
|
[STATUS_DATA.DONE]: { color: STATUS_COLOR.DONE, leftSection: getIcon(CheckCircle2) },
|
|
[STATUS_DATA.SHIPPED]: { color: STATUS_COLOR.SHIPPED, leftSection: getIcon(Check) },
|
|
[STATUS_DATA.REFUNDED]: { color: STATUS_COLOR.REFUNDED, leftSection: getIcon(RotateCcw) },
|
|
[STATUS_DATA.SETTLED]: { color: STATUS_COLOR.SETTLED, leftSection: getIcon(CheckCircle2) },
|
|
[STATUS_DATA.PAID]: { color: STATUS_COLOR.PAID, leftSection: getIcon(CreditCard) },
|
|
[STATUS_DATA.INVOICED]: { color: STATUS_COLOR.INVOICED, leftSection: getIcon(CreditCard) },
|
|
[STATUS_DATA.RESOLVED]: { color: STATUS_COLOR.RESOLVED, leftSection: getIcon(CheckCircle2) },
|
|
[STATUS_DATA.JOINED]: { color: STATUS_COLOR.JOINED, leftSection: getIcon(Users) },
|
|
[STATUS_DATA.PRESENT]: { color: STATUS_COLOR.PRESENT, leftSection: getIcon(Users) },
|
|
|
|
[STATUS_DATA.REQUEST]: { color: STATUS_COLOR.REQUEST, leftSection: getIcon(Send) },
|
|
[STATUS_DATA.REQUESTING]: { color: STATUS_COLOR.REQUESTING, leftSection: getIcon(Send) },
|
|
[STATUS_DATA.REQUESTED]: { color: STATUS_COLOR.REQUESTED, leftSection: getIcon(Send) },
|
|
[STATUS_DATA.OPEN]: { color: STATUS_COLOR.OPEN, leftSection: getIcon(CheckCircle2) },
|
|
[STATUS_DATA.OPENED]: { color: STATUS_COLOR.OPENED, leftSection: getIcon(CheckCircle2) },
|
|
[STATUS_DATA.PROCESS]: { color: STATUS_COLOR.PROCESS, leftSection: getIcon(Loader2) },
|
|
[STATUS_DATA.PROCESSING]: { color: STATUS_COLOR.PROCESSING, leftSection: getIcon(Loader2) },
|
|
[STATUS_DATA.IN_PROCESS]: { color: STATUS_COLOR.IN_PROCESS, leftSection: getIcon(Loader2) },
|
|
[STATUS_DATA.SHIPMENT]: { color: STATUS_COLOR.SHIPMENT, leftSection: getIcon(Package) },
|
|
[STATUS_DATA.SHIPPING]: { color: STATUS_COLOR.SHIPPING, leftSection: getIcon(Package) },
|
|
[STATUS_DATA.TRANSFERRED]: { color: STATUS_COLOR.TRANSFERRED, leftSection: getIcon(Send) },
|
|
[STATUS_DATA.PAYMENT]: { color: STATUS_COLOR.PAYMENT, leftSection: getIcon(CreditCard) },
|
|
[STATUS_DATA.INVOICE]: { color: STATUS_COLOR.INVOICE, leftSection: getIcon(CreditCard) },
|
|
|
|
[STATUS_DATA.APPROVAL]: { color: STATUS_COLOR.APPROVAL, leftSection: getIcon(CheckCircle2) },
|
|
[STATUS_DATA.PENDING]: { color: STATUS_COLOR.PENDING, leftSection: getIcon(Clock) },
|
|
[STATUS_DATA.WAIT]: { color: STATUS_COLOR.WAIT, leftSection: getIcon(Clock) },
|
|
[STATUS_DATA.WAITING]: { color: STATUS_COLOR.WAITING, leftSection: getIcon(Clock) },
|
|
[STATUS_DATA.WAITING_LIST]: { color: STATUS_COLOR.WAITING_LIST, leftSection: getIcon(Clock) },
|
|
[STATUS_DATA.PARTIAL_DONE]: { color: STATUS_COLOR.PARTIAL_DONE, leftSection: getIcon(Clock) },
|
|
[STATUS_DATA.ON_HOLD]: { color: STATUS_COLOR.ON_HOLD, leftSection: getIcon(Clock) },
|
|
[STATUS_DATA.REFUND]: { color: STATUS_COLOR.REFUND, leftSection: getIcon(RotateCcw) },
|
|
[STATUS_DATA.REFUND_PROCESSING]: { color: STATUS_COLOR.REFUND_PROCESSING, leftSection: getIcon(Loader2) },
|
|
[STATUS_DATA.REFUND_PROCESS]: { color: STATUS_COLOR.REFUND_PROCESS, leftSection: getIcon(Loader2) },
|
|
[STATUS_DATA.PARTIAL_REFUND]: { color: STATUS_COLOR.PARTIAL_REFUND, leftSection: getIcon(RotateCcw) },
|
|
[STATUS_DATA.PARTIALLY_REFUNDED]: { color: STATUS_COLOR.PARTIALLY_REFUNDED, leftSection: getIcon(RotateCcw) },
|
|
[STATUS_DATA.SETTLEMENT]: { color: STATUS_COLOR.SETTLEMENT, leftSection: getIcon(CheckCircle2) },
|
|
[STATUS_DATA.INVITED]: { color: STATUS_COLOR.INVITED, leftSection: getIcon(Users) },
|
|
|
|
[STATUS_DATA.CANCEL]: { color: STATUS_COLOR.CANCEL, leftSection: getIcon(XCircle) },
|
|
[STATUS_DATA.CANCELLED]: { color: STATUS_COLOR.CANCELLED, leftSection: getIcon(XCircle) },
|
|
[STATUS_DATA.REJECTION]: { color: STATUS_COLOR.REJECTION, leftSection: getIcon(XCircle) },
|
|
[STATUS_DATA.REJECTED]: { color: STATUS_COLOR.REJECTED, leftSection: getIcon(XCircle) },
|
|
[STATUS_DATA.ISSUE]: { color: STATUS_COLOR.ISSUE, leftSection: getIcon(AlertCircle) },
|
|
[STATUS_DATA.PROBLEM]: { color: STATUS_COLOR.PROBLEM, leftSection: getIcon(AlertCircle) },
|
|
|
|
[STATUS_DATA.EXPIRED]: { color: STATUS_COLOR.EXPIRED, leftSection: getIcon(AlertCircle) },
|
|
[STATUS_DATA.CANCEL_REFUNDED]: { color: STATUS_COLOR.CANCEL_REFUNDED, leftSection: getIcon(XCircle) },
|
|
|
|
[STATUS_DATA.CHECKOUT]: { color: STATUS_COLOR.CHECKOUT, leftSection: getIcon(CreditCard) },
|
|
[STATUS_DATA.SETTLED_FREE]: { color: STATUS_COLOR.SETTLED_FREE, leftSection: getIcon(CheckCircle2) },
|
|
};
|
|
|
|
export function StatusBadge({ status, label, getCustomConfig, color, ...rest }: StatusBadgeProps) {
|
|
if (!status) return null;
|
|
|
|
const normalizedStatus = status?.toLowerCase() || '';
|
|
const defaultConfig = DEFAULT_STATUS_MAP[normalizedStatus] || { color: 'gray' };
|
|
const customConfig = getCustomConfig ? getCustomConfig(normalizedStatus) : {};
|
|
|
|
return (
|
|
<Badge
|
|
size="sm"
|
|
radius="sm"
|
|
fw={600}
|
|
style={{ textTransform: 'capitalize' }}
|
|
variant={customConfig.variant ? customConfig.variant : 'light'}
|
|
color={color || customConfig.color || defaultConfig.color}
|
|
{...rest}
|
|
>
|
|
{label || (status ? status.replace(/-/g, ' ') : 'Unknown')}
|
|
</Badge>
|
|
);
|
|
}
|