mq-schedule
Multi-step appointment scheduling. Walks the patient through choosing a professional, slot, profile and payment, emitting events the host reacts to.
<mq-schedule> is a self-contained scheduling wizard. It handles two top-level flows — schedule (new appointment) and reschedule (modify an existing one) — through a small declarative set of steps: choose professional → slot → complete profile → confirm → pay → done.
It is routing-agnostic: it never navigates on its own. It emits semantic events (appointment-created, back) and the host decides what to do — show its own confirmation screen, route elsewhere, or mount the standalone success screen. The component assumes an already-exchanged access token; it performs no token exchange.
Dependencies
<mq-schedule> does not wrap the generic providers — mount them yourself as ancestors:
<mq-theme-provider>— design tokens / theming.<mq-query-client-provider>— the TanStack Query client the wizard's data fetching relies on.
Inside <mq-router> these are already provided by the host, so the auth attributes below are omitted there.
Installation
npm install @mediquo/web-componentsimport "@mediquo/web-components/mq-schedule";
import "@mediquo/web-components/mq-theme-provider";
import "@mediquo/web-components/mq-query-client-provider";Usage
HTML
<mq-theme-provider theme="mediquo">
<mq-query-client-provider>
<mq-schedule
env="production"
api-key="<your-api-key>"
token="<already-exchanged-access-token>"
locale="es_ES"
timezone="Europe/Madrid"
default-specialty="ginecologia"
></mq-schedule>
</mq-query-client-provider>
</mq-theme-provider>React / Next.js
"use client";
import { useEffect, useRef } from "react";
export function Schedule({ apiKey, token }) {
const ref = useRef<HTMLElement>(null);
useEffect(() => {
import("@mediquo/web-components/mq-schedule");
import("@mediquo/web-components/mq-theme-provider");
import("@mediquo/web-components/mq-query-client-provider");
}, []);
useEffect(() => {
const el = ref.current;
if (!el) return;
const onCreated = (e: Event) => {
const { appointmentId } = (e as CustomEvent).detail;
// route to confirmation / show success screen
};
const onBack = () => {
// user left the wizard — route away / close
};
el.addEventListener("appointment-created", onCreated);
el.addEventListener("back", onBack);
return () => {
el.removeEventListener("appointment-created", onCreated);
el.removeEventListener("back", onBack);
};
}, []);
return (
/* @ts-expect-error — custom element */
<mq-theme-provider theme="mediquo">
{/* @ts-expect-error — custom element */}
<mq-query-client-provider>
{/* @ts-expect-error — custom element */}
<mq-schedule
ref={ref}
env="production"
api-key={apiKey}
token={token}
locale="es_ES"
timezone="Europe/Madrid"
/>
</mq-query-client-provider>
</mq-theme-provider>
);
}Attributes & properties
| Name | Type | Required | Description |
|---|---|---|---|
api-key | string | Standalone | API key for the Mediquo platform. Omitted inside mq-router (the host configures the http client). |
token | string | Standalone | Already-exchanged access token. No token exchange happens inside the component. |
kind | "schedule" | "reschedule" | No | Top-level flow. Defaults to "schedule". |
appointment-id | string | When reschedule | Appointment to modify. Required when kind="reschedule". |
default-specialty | string | No | Pre-selects a specialty. Accepts a public slug ("ginecologia") or a raw backend code. |
default-service | string | No | Pre-selects a service. Accepts a public slug ("videoconsulta") or a raw backend code. |
default-professional-hash | string | No | Pre-selects a professional and starts the wizard at the slot picker. |
requires-payment | boolean | No | If false, the payment step is skipped. Defaults to true; always false for reschedule. |
show-mediquo-branding | boolean | No | Toggles the Mediquo logo in the layout header. Defaults to true. |
locale | string | No | Locale code: es_ES, en_US, pt_PT, de_DE, ca_ES. Defaults to the host/build locale. |
env | string | No | Backend environment: "development" or "production". Applied once at mount. |
timezone | string | No | IANA timezone used to render slot times (e.g. "Europe/Madrid"). Not part of the patient profile, so the host supplies it; defaults to the browser's resolved timezone. |
Events
All events bubble and cross shadow boundaries (composed: true).
| Event | Detail | Description |
|---|---|---|
appointment-created | { appointmentId: string } | The appointment was booked (or payment succeeded). |
back | — | The user navigated back past the first step. The host decides where to go. |
const schedule = document.querySelector("mq-schedule");
schedule.addEventListener("appointment-created", (e) => {
// route to confirmation — e.detail.appointmentId
});
schedule.addEventListener("back", () => {
// user left the wizard backwards — route away / close
});Patient identity
The wizard needs minimal patient data (name for the header, timezone for slot times, hash for analytics). It reads name and hash from the patient profile API automatically; only timezone must be supplied by the host (via the attribute above), defaulting to the browser timezone. No login-token wiring is required.
The post-booking success screen (
<mq-schedule-success>) is a separate element controlled by its own route — it is not part of this wizard.
Interactive playground
Documentation pages show usage only. For a full-page, interactive demo with sidebar → Devtools (dialog: API key, token, locale, theme, and an optional professional hash), open the standalone demo route on this site:
/web-components/mq-schedule/demoThe demo emits appointment-created and back as toasts so you can see the host-side callbacks fire.