Scheduling

BookingSummary

What was booked: the place and picture, dates in and out with the nights counted, guests, price lines, total and status.

#schedule#commerce#price#checkout#card#no-js

Demo

Preview
A bright living room

River flat with a terrace

Lisbon, AlfamaBooking QX-48213Confirmed
Check-in
· 15:00
4 nights
Check-out
· 11:00
Guests
2 adults, 1 child
Change the booking
Edit dates or guests
4 nights × €95
€380.00
Cleaning
€40.00
Weekly discount
−€38.00
Tourist tax€2 a night for each adult
€16.00
Total
€398.00

Free cancellation until 1 November.

Pottery course

Awaiting payment
Starts
1 session
Ends
Guests
1 guest
1 session
$45.00
Total
$45.00

Get it

It needs theme.qwe, as every component does; or take the whole kit, quillo-ui.qwe. Each component brings its own styles to the pages that show it.

$ curl -O https://quillolang.org/components/ui/theme.qwe$ curl -O https://quillolang.org/components/ui/booking_summary.qwe
main.qwe
import ui/theme.qwe use theme_cssuse ui/booking_summary.qweroute GET / = <html><head><style>{theme_css}</style></head><body class="ui-root">...</body></html>

Example

The code of the preview above.

demos/booking_summary.qwe
view BookingSummaryDemo() =    <div.demo-row style="align-items: flex-start">        <div style="flex: 1 1 320px; max-width: 400px">            <BookingSummary id="booking-summary-demo-stay" title="River flat with a terrace" place="Lisbon, Alfama"                            image="https://picsum.photos/seed/flat/200/160" image_alt="A bright living room"                            check_in="2026-11-05" check_out="2026-11-09" times={{ in: "15:00", out: "11:00" }}                            guests="2 adults, 1 child" status="Confirmed" reference="QX-48213" edit_href="#booking_summary"                            lines={[{ label: "4 nights × €95", amount: "€380.00" }, { label: "Cleaning", amount: "€40.00" },                                    { label: "Weekly discount", amount: "−€38.00", tone: "success" },                                    { label: "Tourist tax", amount: "€16.00", hint: "€2 a night for each adult" }]}                            total="€398.00" note="Free cancellation until 1 November."/>        </div>        <div style="flex: 1 1 280px; max-width: 360px">            <BookingSummary id="booking-summary-demo-class" title="Pottery course" check_in="2026-11-02" check_out="2026-11-03"                            in_label="Starts" out_label="Ends" nights_label="session" guests={1} status="Awaiting payment"                            status_tone="warning" lines={[{ label: "1 session", amount: "$45.00" }]} total="$45.00"/>        </div>    </div>

Source

ui/booking_summary.qwe
// BookingSummary: what was booked, for a checkout's side or a confirmation: the place// (with a picture), the dates in and out with the nights between, the guests, the price// line by line and the total, a status, and a note (the cancellation terms).////   <BookingSummary title="River flat" place="Lisbon, Alfama" image="/img/flat.jpg"//                   check_in="2026-11-05" check_out="2026-11-09" guests="2 adults, 1 child" status="Confirmed"//                   lines={[{ label: "4 nights × €95", amount: "€380.00" }, { label: "Cleaning", amount: "€40.00" },//                           { label: "Weekly discount", amount: "−€38.00", tone: "success" }]}//                   total="€382.00" note="Free cancellation until 1 November." edit_href="/booking/edit"/>//// title: what was booked; place: where; image: a picture (image_alt). check_in,// check_out: "YYYY-MM-DD", shown as "Thu 5 Nov 2026", with the nights between them// counted (nights_label: what a night is called, "night"; "session" for a class).// in_label ("Check-in"), out_label ("Check-out"). times: the hours, under the dates// ({ in: "15:00", out: "11:00" }). guests: text ("2 adults") or a number ("2 guests").// lines: a list of { label, amount, tone? ("success", "muted", "danger"), hint? }, the// amounts already written in their currency. total; total_label ("Total"). status: a// badge ("Confirmed"); status_tone: "success" (default), "warning", "danger", "info".// reference: the booking's code, shown and selectable. note: a small line at the end.// edit_href: an Edit link by the dates.import ui/theme.qwe use ui_clslet booking_summary_css = css`.ui-booking-summary { display: grid; gap: 14px; min-width: 0; padding: 16px; border: 1px solid var(--ui-border); border-radius: var(--ui-radius); background: var(--ui-surface); font: 14px/1.45 var(--ui-font); color: var(--ui-fg); --t: var(--ui-success); --ts: var(--ui-success-soft); }.ui-booking-summary-warning { --t: var(--ui-warning); --ts: var(--ui-warning-soft); }.ui-booking-summary-danger { --t: var(--ui-danger); --ts: var(--ui-danger-soft); }.ui-booking-summary-info { --t: var(--ui-info); --ts: var(--ui-info-soft); }.ui-booking-summary-head { display: flex; gap: 12px; align-items: flex-start; }.ui-booking-summary-head img { flex: none; width: 88px; height: 72px; border-radius: var(--ui-radius-sm); object-fit: cover; background: var(--ui-subtle); }.ui-booking-summary-what { display: grid; gap: 2px; min-width: 0; flex: 1; }.ui-booking-summary-title { margin: 0; font-size: 16px; font-weight: 650; line-height: 1.3; }.ui-booking-summary-place { color: var(--ui-muted); font-size: 13px; }.ui-booking-summary-status { justify-self: start; margin-top: 4px; padding: 2px 8px; border-radius: 999px; background: var(--ts); color: var(--t); font-size: 12px; font-weight: 600; }.ui-booking-summary-ref { color: var(--ui-muted); font-size: 12px; }.ui-booking-summary-ref code { font: 600 12px/1 var(--ui-mono); color: var(--ui-fg); user-select: all; }.ui-booking-summary-dates { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 8px; margin: 0; padding: 12px; border-radius: var(--ui-radius-sm); background: var(--ui-subtle); }.ui-booking-summary-dates div { display: grid; gap: 1px; min-width: 0; }.ui-booking-summary-dates div:last-child { text-align: right; }.ui-booking-summary-dates dt { color: var(--ui-muted); font-size: 12px; }.ui-booking-summary-dates dd { margin: 0; font-weight: 600; }.ui-booking-summary-dates small { color: var(--ui-muted); font-size: 12px; font-weight: 400; }.ui-booking-summary-nights { padding: 2px 8px; border: 1px solid var(--ui-border); border-radius: 999px; background: var(--ui-surface); color: var(--ui-muted); font-size: 12px; white-space: nowrap; }.ui-booking-summary-row { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }.ui-booking-summary-row dt { color: var(--ui-muted); }.ui-booking-summary-row dd { margin: 0; font-weight: 500; }.ui-booking-summary-facts { display: grid; gap: 6px; margin: 0; }.ui-booking-summary-edit { color: var(--ui-accent); font-size: 13px; text-decoration: none; }.ui-booking-summary-edit:hover { text-decoration: underline; }.ui-booking-summary-edit:focus-visible { outline: none; border-radius: 3px; box-shadow: var(--ui-focus); }.ui-booking-summary-lines { display: grid; gap: 6px; margin: 0; padding-top: 12px; border-top: 1px solid var(--ui-border); }.ui-booking-summary-line { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; }.ui-booking-summary-line dd { margin: 0; font-variant-numeric: tabular-nums; white-space: nowrap; }.ui-booking-summary-hint { display: block; color: var(--ui-muted); font-size: 12px; }.ui-booking-summary-success dt, .ui-booking-summary-success dd { color: var(--ui-success); }.ui-booking-summary-muted dt, .ui-booking-summary-muted dd { color: var(--ui-muted); }.ui-booking-summary-danger-line dt, .ui-booking-summary-danger-line dd { color: var(--ui-danger); }.ui-booking-summary-total { padding-top: 8px; border-top: 1px solid var(--ui-border); font-size: 16px; font-weight: 700; }.ui-booking-summary-note { margin: 0; color: var(--ui-muted); font-size: 12px; }`view BookingSummary(title: str, check_in: str, check_out: str, place: str? = null, image: str? = null, image_alt: str = "",                    guests = null, lines: list = [], total: str? = null, total_label: str = "Total", status: str? = null,                    status_tone: str = "success", reference: str? = null, note: str? = null, edit_href: str? = null,                    times: map? = null, in_label: str = "Check-in", out_label: str = "Check-out", nights_label: str = "night",                    id: str? = null, class: str? = null) {    style global booking_summary_css    let n = date.days_between(check_in, check_out)    let who = guests == null ? null : (type_of(guests) == "int" ? `${guests} ${guests == 1 ? "guest" : "guests"}` : str(guests))    <section class={ui_cls(["ui-booking-summary", status_tone != "success" && `ui-booking-summary-${status_tone}`, class])} id={id}             aria-label={`Booking: ${title}`}>        <div.ui-booking-summary-head>            {image != null && <img src={image} alt={image_alt} loading="lazy"/>}            <div.ui-booking-summary-what>                <h3.ui-booking-summary-title>{title}</h3>                {place != null && <span.ui-booking-summary-place>{place}</span>}                {reference != null && <span.ui-booking-summary-ref>Booking <code>{reference}</code></span>}                {status != null && <span.ui-booking-summary-status>{status}</span>}            </div>        </div>        <dl.ui-booking-summary-dates>            <div>                <dt>{in_label}</dt>                <dd><time datetime={check_in}>{date.format(check_in, "ddd D MMM YYYY")}</time>{times != null && times.in != null && <small> · {times.in}</small>}</dd>            </div>            <span.ui-booking-summary-nights>{n} {n == 1 ? nights_label : `${nights_label}s`}</span>            <div>                <dt>{out_label}</dt>                <dd><time datetime={check_out}>{date.format(check_out, "ddd D MMM YYYY")}</time>{times != null && times.out != null && <small> · {times.out}</small>}</dd>            </div>        </dl>        {(who != null || edit_href != null) && <dl.ui-booking-summary-facts>            {who != null && <div.ui-booking-summary-row><dt>Guests</dt><dd>{who}</dd></div>}            {edit_href != null && <div.ui-booking-summary-row><dt><span.ui-sr>Change the booking</span></dt><dd><a.ui-booking-summary-edit href={edit_href}>Edit dates or guests</a></dd></div>}        </dl>}        {(len(lines) > 0 || total != null) && <dl.ui-booking-summary-lines>            {for l in lines => <div key={l.label} class={ui_cls(["ui-booking-summary-line",                    l.tone == "success" && "ui-booking-summary-success", l.tone == "muted" && "ui-booking-summary-muted",                    l.tone == "danger" && "ui-booking-summary-danger-line"])}>                <dt>{l.label}{l.hint != null && <span.ui-booking-summary-hint>{l.hint}</span>}</dt>                <dd>{l.amount}</dd>            </div>}            {total != null && <div.ui-booking-summary-line.ui-booking-summary-total><dt>{total_label}</dt><dd>{total}</dd></div>}        </dl>}        {note != null && <p.ui-booking-summary-note>{note}</p>}    </section>}
Thread
67Useful? Like it, or add to its thread below.

Thread 0 posts

On BookingSummary: questions, tips, corrections, and code that uses it.

No posts yet. The first one opens the thread.