diff --git a/addons/mcs_appointment_booking/__manifest__.py b/addons/mcs_appointment_booking/__manifest__.py index e31f401..ff7a6db 100644 --- a/addons/mcs_appointment_booking/__manifest__.py +++ b/addons/mcs_appointment_booking/__manifest__.py @@ -16,6 +16,7 @@ ], "assets": { "web.assets_frontend": [ + "mcs_appointment_booking/static/src/js/appointment_booking.js", "mcs_appointment_booking/static/src/scss/appointment_booking.scss", ], }, diff --git a/addons/mcs_appointment_booking/static/src/js/appointment_booking.js b/addons/mcs_appointment_booking/static/src/js/appointment_booking.js new file mode 100644 index 0000000..dd6a64a --- /dev/null +++ b/addons/mcs_appointment_booking/static/src/js/appointment_booking.js @@ -0,0 +1,28 @@ +(function () { + "use strict"; + + function initAppointmentBooking(root) { + const startInput = root.querySelector(".js-mcs-start"); + const stopInput = root.querySelector(".js-mcs-stop"); + const selectedLabel = root.querySelector(".js-mcs-selected-slot"); + const buttons = root.querySelectorAll(".mcs-appt-time"); + + if (!startInput || !stopInput || !selectedLabel || !buttons.length) { + return; + } + + buttons.forEach((button) => { + button.addEventListener("click", () => { + buttons.forEach((item) => item.classList.remove("active")); + button.classList.add("active"); + startInput.value = button.dataset.start || ""; + stopInput.value = button.dataset.stop || ""; + selectedLabel.textContent = button.dataset.label || button.textContent.trim(); + }); + }); + } + + document.addEventListener("DOMContentLoaded", () => { + document.querySelectorAll(".mcs-appointment").forEach(initAppointmentBooking); + }); +})(); diff --git a/addons/mcs_appointment_booking/static/src/scss/appointment_booking.scss b/addons/mcs_appointment_booking/static/src/scss/appointment_booking.scss index 39c0fa0..8afb207 100644 --- a/addons/mcs_appointment_booking/static/src/scss/appointment_booking.scss +++ b/addons/mcs_appointment_booking/static/src/scss/appointment_booking.scss @@ -22,9 +22,9 @@ .mcs-appt-shell { display: grid; - grid-template-columns: minmax(280px, 380px) minmax(0, 1fr); + grid-template-columns: minmax(260px, 340px) minmax(0, 1fr); gap: 0; - max-width: 1180px; + max-width: 1240px; margin: 0 auto; overflow: hidden; border: 1px solid var(--mcs-appt-line); @@ -34,13 +34,13 @@ } .mcs-appt-info { - padding: 34px; + padding: 30px; background: var(--mcs-appt-navy); color: #ffffff; h1 { margin: 18px 0 18px; - font-size: clamp(2rem, 5vw, 3.45rem); + font-size: clamp(2rem, 4vw, 3rem); line-height: 1.04; font-weight: 820; } @@ -89,7 +89,7 @@ .mcs-appt-booking { min-width: 0; - padding: 32px; + padding: 28px; } .mcs-appt-section-head { @@ -121,15 +121,16 @@ .mcs-appt-date-strip { display: grid; - grid-template-columns: repeat(auto-fill, minmax(82px, 1fr)); - gap: 10px; + grid-template-columns: repeat(7, minmax(0, 1fr)); + gap: 8px; + max-width: 560px; } .mcs-appt-date { display: grid; - min-height: 82px; + min-height: 66px; place-items: center; - padding: 10px; + padding: 8px 6px; border: 1px solid var(--mcs-appt-line); border-radius: 10px; background: #ffffff; @@ -146,7 +147,7 @@ span { color: var(--mcs-appt-ink); - font-size: 1.35rem; + font-size: 1.18rem; line-height: 1; font-weight: 850; } @@ -181,65 +182,69 @@ background: var(--mcs-appt-soft); } -.mcs-appt-slot-list { +.mcs-appt-workspace { display: grid; - gap: 10px; + grid-template-columns: minmax(0, 1fr) minmax(300px, 360px); + gap: 20px; + margin-top: 28px; + align-items: start; } -.mcs-appt-slot { - input[type="radio"] { - position: absolute; - opacity: 0; - pointer-events: none; +.mcs-appt-times, +.mcs-appt-details { + min-width: 0; +} + +.mcs-appt-selected-day { + margin: -8px 0 14px; + color: var(--mcs-appt-muted); + font-weight: 750; +} + +.mcs-appt-slot-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(128px, 1fr)); + gap: 9px; + max-height: 540px; + overflow-y: auto; + padding-right: 4px; +} + +.mcs-appt-time { + display: grid; + gap: 2px; + min-height: 66px; + border: 1px solid var(--mcs-appt-line); + border-radius: 10px; + padding: 10px; + background: #ffffff; + color: var(--mcs-appt-ink); + text-align: left; + transition: border-color 160ms ease-out, background 160ms ease-out, box-shadow 160ms ease-out, transform 160ms ease-out; + + span { + font-weight: 850; } - label { - display: flex; - align-items: center; - justify-content: space-between; - gap: 12px; - min-height: 56px; - padding: 12px 14px; - border: 1px solid var(--mcs-appt-line); - border-radius: 10px; - background: #ffffff; - color: var(--mcs-appt-ink); - cursor: pointer; - transition: border-color 160ms ease-out, background 160ms ease-out, transform 160ms ease-out; - - span { - font-size: 1.05rem; - font-weight: 850; - } - - small { - color: var(--mcs-appt-teal); - font-weight: 800; - } + small { + color: var(--mcs-appt-muted); + font-weight: 800; } - label:active { - transform: scale(0.99); - } - - input[type="radio"]:checked + label { + &.active { border-color: var(--mcs-appt-blue); background: #eef4ff; + box-shadow: inset 0 0 0 1px rgba(28, 78, 216, 0.15); } - input[type="radio"]:checked ~ .mcs-appt-form { - display: grid; + &:active { + transform: scale(0.98); } } .mcs-appt-form { - display: none; + display: grid; gap: 16px; - margin-top: 10px; - padding: 18px; - border: 1px solid #cbd8f7; - border-radius: 12px; - background: #f8fbff; } .mcs-appt-form-grid { @@ -292,6 +297,37 @@ } } +.mcs-appt-details { + position: sticky; + top: 96px; + padding: 18px; + border: 1px solid #cbd8f7; + border-radius: 14px; + background: #f8fbff; +} + +.mcs-appt-selected-slot { + display: grid; + gap: 4px; + margin-bottom: 16px; + padding: 12px; + border: 1px solid var(--mcs-appt-line); + border-radius: 10px; + background: #ffffff; + + small { + color: var(--mcs-appt-muted); + font-size: 0.76rem; + font-weight: 900; + text-transform: uppercase; + letter-spacing: 0.08em; + } + + strong { + font-size: 1.05rem; + } +} + @media (max-width: 900px) { .mcs-appt-shell { grid-template-columns: 1fr; @@ -301,6 +337,14 @@ .mcs-appt-booking { padding: 24px; } + + .mcs-appt-workspace { + grid-template-columns: 1fr; + } + + .mcs-appt-details { + position: static; + } } @media (max-width: 560px) { @@ -308,11 +352,14 @@ padding: 18px 12px 42px; } - .mcs-appt-date-strip, .mcs-appt-form-grid { grid-template-columns: 1fr; } + .mcs-appt-date-strip { + grid-template-columns: repeat(4, minmax(0, 1fr)); + } + .mcs-appt-section-head { align-items: flex-start; flex-direction: column; diff --git a/addons/mcs_appointment_booking/views/appointment_templates.xml b/addons/mcs_appointment_booking/views/appointment_templates.xml index b740468..556140e 100644 --- a/addons/mcs_appointment_booking/views/appointment_templates.xml +++ b/addons/mcs_appointment_booking/views/appointment_templates.xml @@ -66,41 +66,59 @@ -
- Step 2 -

Choose a time on

-
+
+
+
+ Step 2 +

Available times

+
+

-

- No free slots are available on this day. -
- -
- -
- - -
- - - -
- - - -