This repository has been archived on 2026-08-11. You can view files and clone it, but cannot push or open issues or pull requests.
Gishen-B2B/src/types/index.ts
kirukib 1f30f00da6 Finalize portal polish: profile, avatars, ID cards, and list UX.
Ship leftover Yimaru login/personas, sidebar sections, filter modal, chart/stat clip fixes, and matching feature docs so the polish work is fully committed.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-06 21:57:07 +03:00

257 lines
5.4 KiB
TypeScript

export type Role = "SUPER_USER" | "HR_ADMIN" | "FINANCE" | "MEMBER";
export type LocaleCode = "en" | "am";
export type OrgStatus =
| "pending_activation"
| "active"
| "suspended"
| "closed";
export type MemberStatus = "invited" | "active" | "inactive" | "offboarded";
export type PrescriptionStatus =
| "submitted"
| "under_review"
| "approved"
| "queried"
| "rejected";
export type MigrationDataset =
| "departments"
| "packages"
| "members"
| "overrides"
| "dependants"
| "verification_ids"
| "full_onboarding";
export type MigrationJobStatus =
| "draft"
| "validating"
| "preview"
| "committing"
| "completed"
| "failed"
| "rolled_back";
export type ApprovalStatus = "pending" | "approved" | "flagged" | "rejected";
export type ContactChannel = "email" | "phone";
export interface SessionUser {
id: string;
email: string;
name: string;
roles: Role[];
activeRole: Role;
orgId: string;
memberId?: string;
locale: LocaleCode;
avatarInitials: string;
/** Optional profile photo; demos use deterministic DiceBear URLs */
avatarUrl?: string;
}
export interface Organisation {
id: string;
legalName: string;
tradeName: string;
tin: string;
status: OrgStatus;
billingEmail: string;
billingPhone: string;
approxHeadcount: number;
creditLimitEtb: number | null;
creditUsedEtb: number;
paymentTermsDays: number | null;
priceListCode: string | null;
contractStart: string | null;
contractEnd: string | null;
joinCode: string;
allowedEmailDomains: string[];
verificationMethod: "member_id" | "qr" | "phone_otp" | "none";
maxDependantsPerMember: number;
createdAt: string;
}
export interface OrgRegistrationRequest {
id: string;
contactName: string;
organisationName: string;
channel: ContactChannel;
email?: string;
phone?: string;
notes?: string;
status: "new" | "in_progress" | "converted" | "closed";
createdAt: string;
}
export interface Department {
id: string;
orgId: string;
name: string;
siteName: string;
parentId: string | null;
subLimitEtb: number | null;
spendEtb: number;
memberCount: number;
}
export interface BenefitPackage {
id: string;
orgId: string;
code: string;
name: string;
monthlyAllowanceEtb: number;
copayPercent: number;
categories: string[];
exclusions: string[];
perks: string[];
annualCapEtb: number | null;
active: boolean;
memberCount: number;
}
export interface MemberOverride {
memberId: string;
monthlyAllowanceEtb?: number;
copayPercent?: number;
categories?: string[];
notes?: string;
}
export interface Dependant {
id: string;
memberId: string;
name: string;
relationship: "spouse" | "child" | "parent" | "other";
dateOfBirth: string;
status: MemberStatus;
}
export interface Member {
id: string;
orgId: string;
customerId: string;
employeeId: string;
name: string;
email: string;
phone: string;
departmentId: string;
packageId: string;
status: MemberStatus;
startDate: string;
allowanceRemainingEtb: number;
allowanceTotalEtb: number;
override?: MemberOverride;
dependants: Dependant[];
verificationId?: string;
/** Pharmacy ID card number shown on printable badge (e.g. GSH-1001) */
cardId?: string;
/** Optional profile photo; demos use deterministic DiceBear URLs */
avatarUrl?: string;
/** Clinical fields — withheld from HR_ADMIN / FINANCE */
hasActiveRx?: boolean;
lastRxStatus?: PrescriptionStatus;
}
export interface SpendRow {
id: string;
orgId: string;
memberId: string;
memberName: string;
departmentId: string;
departmentName: string;
category: string;
amountEtb: number;
coveredEtb: number;
memberPaidEtb: number;
orderRef: string;
occurredAt: string;
/** Never expose Rx line items to HR/Finance */
clinicalSummaryWithheld: true;
}
export interface Statement {
id: string;
orgId: string;
period: string;
totalSpendEtb: number;
coveredEtb: number;
creditUsedEtb: number;
status: "draft" | "issued" | "paid";
issuedAt: string | null;
}
export interface ApprovalRequest {
id: string;
orgId: string;
memberName: string;
departmentName: string;
amountEtb: number;
thresholdEtb: number;
reason: string;
status: ApprovalStatus;
createdAt: string;
}
export interface MemberOrder {
id: string;
memberId: string;
placedAt: string;
status: "placed" | "processing" | "delivered" | "cancelled";
totalEtb: number;
coveredEtb: number;
memberPaidEtb: number;
itemCount: number;
}
export interface Prescription {
id: string;
memberId: string;
status: PrescriptionStatus;
submittedAt: string;
updatedAt: string;
pageCount: number;
daysOfSupply?: number;
pharmacistNote?: string;
/** File names only in mock — real blobs go to storage */
fileNames: string[];
}
export interface LoyaltySummary {
points: number;
tier: string;
note: string;
}
export interface MigrationJob {
id: string;
orgId: string;
dataset: MigrationDataset;
status: MigrationJobStatus;
fileName: string;
createdBy: string;
createdAt: string;
rowCount: number;
createCount: number;
updateCount: number;
skipCount: number;
errorCount: number;
errors: { row: number; field: string; message: string }[];
}
export interface Paginated<T> {
data: T[];
page: number;
pageSize: number;
total: number;
}
export interface ApiError {
code: string;
message: string;
details?: Record<string, unknown>;
}