Files
nobat724_front/components/appointment/Container.js
T
hamedandClaude Opus 5 51c21938eb feat(booking): give the booking flow a dark palette derived from its own colours
components/appointment/ had every colour hard-coded, so the flow rendered
identically in either theme even after the wiring was fixed. It now reads from
CSS custom properties.

These are not new colours. The :root values are byte-for-byte the hex codes
that were already in the components — twenty-one files, mapped one to one — so
light mode is unchanged. The dark values are derived from those same colours:
surfaces and borders darkened, text inverted, and the two brand colours (the
indigo and the orange) lightened rather than replaced, because both lose
contrast against a dark surface at their original values.

Verified in a headless browser with prefers-color-scheme forced dark:
data-theme lands on <html> and --ap-surface resolves to #1b1b20 rather than
white. Six one-off colours remain hard-coded — a success green, an error red
and similar — each used exactly once and none of them a surface.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-01 16:33:39 +03:30

187 lines
4.8 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import Date from "./date";
import ServiceSelect from "./service";
import LocationSelect from "./location/LocationSelect";
// Components
import Content from "./Content";
import Layout from "@/components/layout";
import Paying from "@/components/appointment/paying";
import Detail from "@/components/appointment/detail";
import FailedPay from "@/components/appointment/failedPay";
import SuccessPay from "@/components/appointment/successPay";
import LogInPage from "@/components/register/LogInPage";
import VerificationPage from "@/components/register/verificationPage";
import LayoutRegister from "@/components/register/LayoutRegister";
function Container({
step,
data,
doctor,
setData,
setStep,
prevData,
matchedCity,
isForAnother,
setIsForAnother,
disabledDates,
// Login states
num,
setNum,
uuid,
setUuid,
isSendMsg,
setIsSendMsg,
// Appointment slot states
selectedSlot,
setSelectedSlot,
selectedDate,
setSelectedDate,
appointmentId,
setAppointmentId,
appointmentExpiresAt,
setAppointmentExpiresAt,
// Service-based booking
bookingMode,
bookingServices,
selectedServiceUuids,
setSelectedServiceUuids,
// Booking location (مطب شخصی / کلینیک)
bookingLocations,
selectedLocation,
locationConfirmed,
changeLocation,
reopenLocationChoice,
onDateChange,
selectedClosedOnDate,
}) {
const serviceMode = bookingMode === "service";
const clinicUuid = selectedLocation?.clinic_uuid ?? null;
const multiLocation = bookingLocations.length > 1;
let dateStep;
if (bookingLocations.length === 0) {
dateStep = (
<p className="w-full max-w-[520px] mx-auto py-[40px] text-center text-[14px] text-[var(--ap-text-3)]">
نوبتدهی آنلاین برای این پزشک فعال نیست.
</p>
);
} else if (multiLocation && !locationConfirmed) {
dateStep = (
<LocationSelect
locations={bookingLocations}
selected={selectedLocation}
onSelect={changeLocation}
/>
);
} else if (serviceMode && selectedServiceUuids.length === 0) {
dateStep = (
<ServiceSelect
services={bookingServices}
doctorUuid={doctor?.uuid}
clinicUuid={clinicUuid}
onContinue={(uuids) => setSelectedServiceUuids(uuids)}
/>
);
} else {
dateStep = (
<Date
doctor={doctor}
setStep={setStep}
disabledDates={disabledDates}
setSelectedSlot={setSelectedSlot}
setSelectedDate={setSelectedDate}
serviceMode={serviceMode}
selectedServiceUuids={selectedServiceUuids}
onChangeService={() => setSelectedServiceUuids([])}
selectedLocation={selectedLocation}
clinicUuid={clinicUuid}
onChangeLocation={multiLocation ? reopenLocationChoice : null}
onDateChange={onDateChange}
closedOnDate={selectedClosedOnDate}
/>
);
}
const elements = [
dateStep,
<LogInPage
num={num}
setNum={setNum}
setUuid={setUuid}
setStep={setStep}
setIsSendMsg={setIsSendMsg}
matchedCity={matchedCity}
/>,
<VerificationPage
num={num}
uuid={uuid}
setStep={setStep}
setUuid={setUuid}
isSendMsg={isSendMsg}
setIsSendMsg={setIsSendMsg}
link={false}
/>,
<Detail
data={data}
setStep={setStep}
setData={setData}
prevData={prevData}
isForAnother={isForAnother}
setIsForAnother={setIsForAnother}
doctor={doctor}
selectedSlot={selectedSlot}
selectedDate={selectedDate}
setAppointmentId={setAppointmentId}
setAppointmentExpiresAt={setAppointmentExpiresAt}
selectedServiceUuids={selectedServiceUuids}
clinicUuid={clinicUuid}
/>,
<Paying
setStep={setStep}
appointmentId={appointmentId}
expiresAt={appointmentExpiresAt}
doctor={doctor}
data={data}
isForAnother={isForAnother}
selectedSlot={selectedSlot}
selectedDate={selectedDate}
/>,
<SuccessPay setStep={setStep} />,
<FailedPay setStep={setStep} />,
];
return (
<>
{step === 1 || step === 2 ? (
<LayoutRegister matchedCity={matchedCity}>
{elements[step]}
</LayoutRegister>
) : (
<Layout
title="رزرو"
name="booking"
disableFooter={step > 4}
matchedCity={matchedCity}
paddingBottom="pb-[80px]"
>
<Content
disableSide={step === 5 || step === 6}
isFirst={step === 0}
setStep={setStep}
doctor={doctor}
step={step}
selectedSlot={selectedSlot}
selectedDate={selectedDate}
selectedLocation={selectedLocation}
>
{elements[step]}
</Content>
</Layout>
)}
</>
);
}
export default Container;