import { type HTMLAttributes } from 'react';
import { type VariantProps } from 'class-variance-authority';
import type { AppointmentState } from '../_shared/entity-card';
export { isSafeEntityUrl as isSafeAppointmentUrl } from '../_shared/is-safe-url';
/** Appointment delivery channel. */
export type AppointmentType = 'inPractice' | 'telehealth';
/** First-visit tri-state flag. */
export type AppointmentFirstVisit = 'yes' | 'no' | 'unknown';
/** Operator (clinician) summary — name + optional palette colour id. */
export interface AppointmentOperator {
/** Operator display name — drives the avatar initials + accessible name. */
name: string;
/** Numeric palette colour id, resolved to a kit token for the colour dot. */
colorId?: number | string;
}
/** Patient summary — identity + optional age driver. */
export interface AppointmentPatient {
/** Patient display name. */
name: string;
/** Optional avatar image URL. */
avatarUrl?: string;
/** ISO-8601 date of birth — when present, the card renders the age as a
* suffix on the name (e.g. "Carol Danvers · 45"). */
dobIso?: string;
}
/** One treatment line within the appointment. */
export interface AppointmentTreatment {
/** Localised care / treatment name. */
careName: string;
/** Optional tooth elements (e.g. FDI ids) the treatment targets. */
elements?: string[];
}
/** Booking-reason metadata captured at online-booking time. */
export interface AppointmentBookingReason {
/** Localised booking-reason description. */
description: string;
/** Expected duration in minutes. */
durationMin?: number;
/** Advance / deposit amount in cents (non-negative). */
advanceAmountCents?: number;
/** Localised specialty label. */
specialty?: string;
}
/** Money summary for the appointment. */
export interface AppointmentMoney {
/** Total billable amount in cents. When present, rendered as a
* TransactionChip. */
billableAmountCents?: number;
/** Outstanding unpaid amount in cents. When > 0, rendered as a warning
* TransactionChip so the front desk can flag it at a glance. */
unpaidAmountCents?: number;
}
/** Signing status for documents attached to the appointment. */
export interface AppointmentSigning {
/** How many documents require a signature. */
required: number;
/** How many have been completed so far. */
toComplete: number;
}
/** Boolean appointment flags surfaced as chips / indicators. */
export interface AppointmentFlags {
bookedOnline?: boolean;
noPatientAssigned?: boolean;
highlightedAnamnesis?: boolean;
billable?: boolean;
}
export interface AppointmentItem {
/** Stable appointment identifier. */
id: string;
/** ISO-8601 start instant. */
startIso: string;
/** Duration in minutes. */
durationMin: number;
/** Lifecycle state — drives the Badge variant + label. */
state: AppointmentState;
/** Delivery channel — drives the leading type glyph. */
type: AppointmentType;
/** First-visit flag. */
firstVisit?: AppointmentFirstVisit;
/** Assigned operator. */
operator?: AppointmentOperator;
/** Chair / room label — surfaced as a chip. */
chair?: string;
/**
* The care plan this appointment belongs to, when any — surfaced as a chip
* (`Care plan {number}`). `url` is the deep link the consumer may use for
* navigation; the chip itself is non-interactive so it never nests an anchor
* inside the row's own stretched link.
*/
carePlan?: {
number: string;
url?: string;
};
/** Patient identity. */
patient?: AppointmentPatient;
/** Treatment lines. */
treatments?: AppointmentTreatment[];
/** Online booking-reason metadata. */
bookingReason?: AppointmentBookingReason;
/** Boolean flags. */
flags?: AppointmentFlags;
/** Money summary — billable + unpaid amounts. */
money?: AppointmentMoney;
/** Whether this appointment is part of a recurring series. */
recurring?: boolean;
/** Signing status for attached documents. */
signing?: AppointmentSigning;
/** A note left by the patient at booking time. When present, a small
* message icon signals it. */
bookingNote?: string;
/** Optional deep link — when present (and safe) the row renders as an anchor. */
url?: string;
/**
* Settle the row visually without removing it from the list — a muted
* wash in place of the elevated surface, shadow dropped. Text keeps its
* normal foreground colour so contrast is unaffected; only the chrome
* dims. For a row already concluded (done / no-show) that a host still
* wants listed alongside what's still ahead.
*/
dimmed?: boolean;
/**
* Marks this as the NEXT appointment to start — a steady accent outline
* (a state, not a one-off address, so it never animates) plus a small
* "Next" label. The cue never rests on colour alone.
*/
next?: boolean;
}
declare const appointmentCardVariants: (props?: ({
size?: "sm" | "md" | null | undefined;
interactive?: boolean | null | undefined;
surface?: "elevated" | "flat" | null | undefined;
selected?: boolean | null | undefined;
dimmed?: boolean | null | undefined;
next?: boolean | null | undefined;
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
export interface AppointmentCardProps extends Omit, 'onClick' | 'title'>, VariantProps {
/** The appointment to render. */
item: AppointmentItem;
/** Visual density. */
size?: 'sm' | 'md';
/**
* `'flat'` (default) — chrome-less row for use inside a bordered
* `AppointmentTray`. `'elevated'` — each row carries its own card chrome
* (border + shadow), for placing rows directly on a rail (AppointmentTimeline).
*/
surface?: 'flat' | 'elevated';
/** BCP-47 locale override for the timestamp + currency. */
locale?: string;
/** ISO-4217 currency code for the advance-deposit chip. Defaults to `EUR`. */
currency?: string;
/**
* Show the patient identity (avatar + name as the row title). Default `true`.
* Set `false` in single-patient surfaces (e.g. a patient's own
* `AppointmentTimeline`) where repeating the name is redundant — the row then
* leads with the operator as its title, falling back to a generic label.
*/
showPatient?: boolean;
/** Fires when the row is activated. */
onActivate?: (item: AppointmentItem) => void;
/**
* Mark this row as the active/selected appointment — an info-tinted
* inline-start bar plus a soft wash, so the eye keeps its place in the
* list after a click. Renders `aria-current="true"` for assistive tech.
*/
selected?: boolean;
/**
* Withhold the lifecycle-state badge when the item's state is the
* default/expected one (`confirmed`) — it needs no announcement, and
* dropping it leaves the badge to states that actually ask for
* attention. Default `false` (today's behaviour: every state, including
* `confirmed`, shows its badge) so existing consumers are unaffected.
*/
hideDefaultStatus?: boolean;
}
export declare const AppointmentCard: import("react").ForwardRefExoticComponent>;
//# sourceMappingURL=appointment-card.d.ts.map