import type { GymPlan } from "@/lib/models/gym-plan" import type { PaymentStatus, SubscriptionSummary } from "@/lib/models/subscription" /** One weekly weigh-in (CusWeightLossProgress). */ export interface WeightProgressPoint { weeklyProgressId: string weight?: number | null recordedAt: string } /** A member's goal/measurements (CustomerTarget) with their weight history. */ export interface CustomerTarget { customerTargetId: string currentWeight?: number | null currentHeight?: number | null targetWeight?: number | null goal?: string | null timePeriod?: string | null weeklyProgresses?: WeightProgressPoint[] | null } /** Customer entity as serialized by the backend (camelCase of the EF model). */ export interface MemberProfile { cusId: string cusName?: string | null gender?: string | null /** Date of birth, "yyyy-MM-dd". Backend property is BoD. */ boD?: string | null primaryPH?: string | null secondaryPH?: string | null email?: string | null nic?: string | null address?: string | null fkUserId?: string isActive: boolean createdAt: string isLocked?: boolean lockReason?: string | null lockedAt?: string | null customerTargets?: CustomerTarget[] | null user?: { userId: string userName?: string | null email?: string | null phoneNumber?: string | null } | null } /** A workout/meal plan the member is assigned to. */ export interface FollowedPlan { planId: string name?: string | null isFollowing: boolean completedDate?: string | null } /** GET client/customers/{id}/full — the "More Info" aggregate. */ export interface MemberFullDetail { customer: MemberProfile subscriptions?: SubscriptionSummary[] workoutPlans: FollowedPlan[] mealPlans: FollowedPlan[] } /** POST client/customers/{id}/medical (password-gated). */ export interface MedicalDetails { bloodGroup?: string | null disabilities?: string | null } /** * Row shape of GET client/customers (MemberListRowDto): one row per member. * Group members each get a row pointing at their shared subscription. */ export interface MemberSubscription { subscriptionId: string fkCustomerPlanId: string fkCustomerId: string onboardDate: string /** Frozen at creation, never changes again -- use renewalDate for current status/listing. */ expiryDate?: string | null renewalDate?: string | null isActive: boolean createdAt: string customer?: MemberProfile | null isPrimary: boolean /** False when unassigned from the plan but still a member of the gym — re-assignable. */ isPlanAssigned?: boolean planName?: string | null /** "None" means this member was created without a plan yet — assign one to make them active. */ planScope?: "Individual" | "Group" | "None" memberCount?: number memberLimit?: number invoiceAmount?: number paidAmount?: number balance?: number paymentStatus?: PaymentStatus allowSplitPayments?: boolean fingerprintId?: number | null fingerprintName?: string | null accessProfileId?: number | null accessNumber?: string | null accessProvisionStatus?: "NotConfigured" | "NoDevice" | "Pending" | "Synced" | "Failed" actualAccessState?: "Unknown" | "Enabled" | "Disabled" | "Mixed" desiredAccessState?: "Enabled" | "Disabled" fingerprintCount?: number accessLastError?: string | null isLocked?: boolean lockReason?: string | null /** Face-photo enrolment on the gym's access terminals. */ hasFacePhoto?: boolean facePhotoStatus?: "None" | "Pending" | "Synced" | "Failed" facePhotoError?: string | null } /** GET client/customers/unlinked-fingerprints — a device enrollment not yet linked to a Customer. */ export interface UnlinkedFingerprint { id: string deviceUserId: number deviceEmployeeNo: string deviceReportedName?: string | null deviceUserType?: string | null fingerprintCount: number deviceId: string deviceName?: string | null discoveredAt: string } export interface AccessCommandStatus { accessProfileId: number accessNumber: string personType: "Customer" | "Staff" desiredAccessState: "Enabled" | "Disabled" provisionStatus: "NoDevice" | "Pending" | "Synced" | "Failed" actualAccessState: "Unknown" | "Enabled" | "Disabled" | "Mixed" fingerprintCount: number lastError?: string | null lastSyncedAt?: string | null deviceCount: number syncedDeviceCount: number } /** GET client/customers/{id} response. */ export interface MemberDetail { customer: MemberProfile plans: GymPlan[] subscriptions?: SubscriptionSummary[] } export interface MemberInput { fullname: string userName: string email: string mobileNumber: string gender: string /** "yyyy-MM-dd" */ birthday: string nic?: string customerPlanId?: string workoutPlanIds?: string[] mealPlanIds?: string[] /** ISO datetime. Only meaningful alongside customerPlanId. */ onboardDate?: string /** false bills the plan at Rs. 0.00 and skips the automatic payment link. */ chargePayment?: boolean discountType?: "Percentage" | "Flat" discountValue?: number /** Set true only on the resubmit after staff has confirmed linking an existing platform * customer to this gym (see CreateMemberResult.requiresConfirmation). */ confirmLink?: boolean }