Appointment type selector

This commit is contained in:
Philip Peterson 2026-06-03 02:13:06 -07:00
parent c073984e82
commit 50f14afcd1
4 changed files with 92 additions and 6 deletions

View file

@ -13,7 +13,8 @@
} }
#riverside-calendar { #riverside-calendar {
max-width: 480px; --cal-row-h: 3.75rem;
max-width: 340px;
font-size: 0.9rem; font-size: 0.9rem;
flex-shrink: 0; flex-shrink: 0;
} }
@ -67,7 +68,7 @@
#riverside-calendar .fc-toolbar-title { #riverside-calendar .fc-toolbar-title {
font-family: Georgia, 'Times New Roman', serif; font-family: Georgia, 'Times New Roman', serif;
font-size: 1.35rem; font-size: 1.5rem;
font-weight: normal; font-weight: normal;
color: #111; color: #111;
} }
@ -115,13 +116,19 @@
/* ── Day cells ── */ /* ── Day cells ── */
#riverside-calendar .fc-daygrid-day-frame { #riverside-calendar .fc-daygrid-day-frame {
min-height: 3rem !important; min-height: calc(var(--cal-row-h) - 0.5rem) !important;
display: flex; display: flex;
flex-direction: row;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
padding: 0; padding: 0;
} }
#riverside-calendar .fc-daygrid-day-events,
#riverside-calendar .fc-daygrid-day-bg {
display: none !important;
}
#riverside-calendar .fc-daygrid-day-top { #riverside-calendar .fc-daygrid-day-top {
flex-direction: row; flex-direction: row;
justify-content: center; justify-content: center;
@ -145,7 +152,7 @@
/* Days with available slots — teal outline circle */ /* Days with available slots — teal outline circle */
#riverside-calendar .fc-daygrid-day.has-availability .fc-daygrid-day-number { #riverside-calendar .fc-daygrid-day.has-availability .fc-daygrid-day-number {
border: 2px solid #306f8e; border: 1px solid #306f8e;
color: #111; color: #111;
cursor: pointer; cursor: pointer;
} }
@ -157,7 +164,7 @@
/* Selected day — filled teal circle */ /* Selected day — filled teal circle */
#riverside-calendar .fc-daygrid-day.is-selected .fc-daygrid-day-number { #riverside-calendar .fc-daygrid-day.is-selected .fc-daygrid-day-number {
background: #306f8e; background: #306f8e;
border: 2px solid #306f8e; border: 1px solid #306f8e;
color: #fff !important; color: #fff !important;
} }
@ -172,6 +179,17 @@
background: none !important; background: none !important;
} }
/* Weekends — same appearance as any other non-available day */
#riverside-calendar .fc-day-sat,
#riverside-calendar .fc-day-sun {
background: none !important;
}
#riverside-calendar .fc-col-header-cell.fc-day-sat .fc-col-header-cell-cushion,
#riverside-calendar .fc-col-header-cell.fc-day-sun .fc-col-header-cell-cushion {
color: #9ca3af;
}
/* ── Hide all event bars, harnesses, and more-links ── */ /* ── Hide all event bars, harnesses, and more-links ── */
#riverside-calendar .fc-event, #riverside-calendar .fc-event,
#riverside-calendar .fc-daygrid-event-harness, #riverside-calendar .fc-daygrid-event-harness,
@ -183,6 +201,6 @@
/* ── Daygrid body rows — give them breathing room ── */ /* ── Daygrid body rows — give them breathing room ── */
#riverside-calendar .fc-daygrid-body tr { #riverside-calendar .fc-daygrid-body tr {
height: 3.5rem; height: var(--cal-row-h);
} }

View file

@ -0,0 +1,66 @@
import { h, render } from "https://esm.sh/preact@10";
import { useState } from "https://esm.sh/preact@10/hooks";
import { html } from "https://esm.sh/htm@3/preact";
const TYPES = [
{ id: "diagnostic", label: "Diagnostic Assessment", duration: "60 MINS" },
{ id: "sports", label: "Sports Rehabilitation", duration: "60 MINS" },
{ id: "surgical", label: "Surgery Rehabilitation", duration: "60 MINS" },
{ id: "neuro", label: "Neurological Therapy", duration: "60 MINS" },
];
const CHECK = html`<svg width="14" height="11" viewBox="0 0 14 11" fill="none" xmlns="http://www.w3.org/2000/svg">
<polyline points="1,5.5 5,9.5 13,1" stroke="white" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"/>
</svg>`;
function ApptType() {
const [selected, setSelected] = useState("diagnostic");
return html`
<div>
<p class="text-xs tracking-widest uppercase text-[#306f8e] font-semibold mb-5">Select Appointment Type</p>
<div class="grid grid-cols-1 sm:grid-cols-2 gap-3">
${TYPES.map(function (t) {
var active = selected === t.id;
return html`
<button
key=${t.id}
onClick=${function () { setSelected(t.id); }}
style="text-align:left; cursor:pointer;"
class=${
"flex items-center gap-4 p-4 w-full rounded-xl border transition-colors " +
(active ? "bg-[#306f8e] border-[#306f8e]" : "bg-white border-[#b8d4dc] hover:border-[#306f8e]")
}
>
<div class=${
"w-8 h-8 rounded-full shrink-0 flex items-center justify-center border " +
(active ? "border-white/60" : "border-[#b8d4dc]")
}>
${active ? CHECK : null}
</div>
<div>
<p class=${"font-serif text-[1.0625rem] font-normal leading-snug " + (active ? "text-white" : "text-gray-900")}>
${t.label}
</p>
<p class=${"text-[0.6875rem] tracking-widest font-semibold mt-0.5 " + (active ? "text-white/70" : "text-[#306f8e]")}>
${t.duration}
</p>
</div>
</button>
`;
})}
</div>
</div>
`;
}
class RptApptType extends HTMLElement {
connectedCallback() {
render(html`<${ApptType} />`, this);
}
disconnectedCallback() {
render(null, this);
}
}
customElements.define("rpt-appt-type", RptApptType);

View file

@ -8,6 +8,7 @@ app:
js/components/rpt-carousel.js: { attributes: { type: module } } js/components/rpt-carousel.js: { attributes: { type: module } }
js/components/rpt-testimonials.js: { attributes: { type: module } } js/components/rpt-testimonials.js: { attributes: { type: module } }
js/components/rpt-faq.js: { attributes: { type: module } } js/components/rpt-faq.js: { attributes: { type: module } }
js/components/rpt-appt-type.js: { attributes: { type: module } }
schedule: schedule:
css: css:
theme: theme:

View file

@ -118,6 +118,7 @@
<section class="py-24 px-6 bg-white"> <section class="py-24 px-6 bg-white">
<div class="max-w-[900px] mx-auto"> <div class="max-w-[900px] mx-auto">
<h2 class="text-[clamp(2.5rem,5vw,4rem)] font-serif font-light text-gray-800 mb-10 text-center">Book An Appointment</h2> <h2 class="text-[clamp(2.5rem,5vw,4rem)] font-serif font-light text-gray-800 mb-10 text-center">Book An Appointment</h2>
<rpt-appt-type class="block mb-10"></rpt-appt-type>
<div class="riverside-booking-wrap"> <div class="riverside-booking-wrap">
<div id="riverside-calendar"></div> <div id="riverside-calendar"></div>
<div id="riverside-slots-wrap" hidden> <div id="riverside-slots-wrap" hidden>