Skip to content

Commit

Permalink
feat(TimeSlot): multiselect days slots
Browse files Browse the repository at this point in the history
  • Loading branch information
Daniel Dobkowski committed Sep 19, 2023
1 parent ec2615f commit c8fbf19
Show file tree
Hide file tree
Showing 6 changed files with 37 additions and 31 deletions.
7 changes: 4 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
"@tabler/icons": "^1.84.0",
"@trivago/prettier-plugin-sort-imports": "^4.1.1",
"axios": "^1.2.1",
"caniuse-lite": "^1.0.30001534",
"countries-and-timezones": "^3.3.0",
"date-fns": "^2.28.0",
"date-fns-tz": "^1.3.5",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { BOOKING_FORM_TYPES } from "models/service";
import { useTranslation } from "react-i18next";
import { useSearchParams } from "react-router-dom";
import { useParams } from "react-router-dom";
import { useRecoilValue } from "recoil";
import { useRecoilState, useRecoilValue } from "recoil";
import { hoursSystemAtom } from "state/atoms";
import { selectedDateRange } from "state/atoms/selectedDateRange";
import { selectedSlot } from "state/atoms/selectedSlot";
Expand All @@ -24,7 +24,6 @@ import { serviceAtom } from "state/atoms/service";
import { slotsFiltersAtom } from "state/atoms/slotsFilters";
import { timeZoneAtom } from "state/atoms/timeZone";
import { uploadAttachmentsAtom } from "state/atoms/uploadAttachments";
import { selectedSlotSelector } from "state/selectors/selectedSlotSelector";
import styled from "styled-components";
import { IconInfoCircle } from "@tabler/icons";
import { BookingServiceFormContent } from "../BookingServiceFormContent/BookingServiceFormContent";
Expand Down Expand Up @@ -93,14 +92,14 @@ const BookService = () => {
formFields: [],
};
const showWarning = useRecoilValue(slotsFiltersAtom).triggerId !== 0;
const slot = useRecoilValue(selectedSlotSelector);
const { bookSlotMutation, loading, error } = useBookSlot();
const { bookDateRangeMutation, loadingDateRange, errorDateRange } = useBookDateRange();
const { id } = useParams<{ id: string }>();
const uploadState = useRecoilValue(uploadAttachmentsAtom);
const timeZone = useRecoilValue(timeZoneAtom);
const hoursSystem = useRecoilValue(hoursSystemAtom);
const is12HoursSystem = useMemo(() => hoursSystem === HOURS_SYSTEMS.h12, [hoursSystem]);
const [, setSelectedSlots] = useRecoilState(selectedSlots);

const isUploading = Object.values(uploadState).filter((item) => item.isLoading).length > 0;

Expand All @@ -117,7 +116,6 @@ const BookService = () => {
});

const checkDisableButton = useCallback(() => {
const disabledForSlot = selectedSlotValue === "" || loading || isUploading;
const disabledForSlots = !selectedSlotsValue.length || loading || isUploading;
const disabledForDateRange =
selectedDateRangeValue.dateTimeFrom === null ||
Expand All @@ -129,10 +127,9 @@ const BookService = () => {
const isEventType = serviceType === BOOKING_FORM_TYPES.LIST;

return (
(isSlotType && disabledForSlot) || (isDateRangeType && disabledForDateRange) || (isEventType && disabledForSlots)
(isSlotType && disabledForSlots) || (isDateRangeType && disabledForDateRange) || (isEventType && disabledForSlots)
);
}, [
selectedSlotValue,
loading,
isUploading,
selectedDateRangeValue.dateTimeFrom,
Expand Down Expand Up @@ -170,19 +167,19 @@ const BookService = () => {
...Object.assign({}, ...customFormFields),
});

if (serviceType === BOOKING_FORM_TYPES.DAYS && slot !== undefined) {
if (serviceType === BOOKING_FORM_TYPES.DAYS && selectedSlotsValue.length) {
bookSlotMutation({
variables: {
serviceId: id!,
slots: [slot.slotId],
slots: selectedSlotsValue,
formFields: json,
timezone: timeZone,
...(service?.paymentProviders.length && {
paymentProvider: service.paymentProviders[0],
}),
locale: locale.code,
},
});
}).then(() => setSelectedSlots([]));
} else if (
serviceType === BOOKING_FORM_TYPES.CALENDAR &&
selectedDateRangeValue.dateTimeFrom !== null &&
Expand Down Expand Up @@ -212,7 +209,7 @@ const BookService = () => {
}),
locale: locale.code,
},
});
}).then(() => setSelectedSlots([]));
}
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ const ServiceCalendarDay: React.FC<ServiceCalendarDayProps> = ({ day }) => {
key={`${dayPart}-${item.key}`}
dateFrom={`${dayPart}T${item.from}`}
dateTo={`${dayPart}T${item.to}`}
day={day}
is12HoursSystem={is12HoursSystem}
/>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { Slot } from "models/slots";
import { TimeSlotButtonType } from "models/theme";
import { TFunction, useTranslation } from "react-i18next";
import { useRecoilState, useRecoilValue } from "recoil";
import { selectedSlot } from "state/atoms/selectedSlot";
import { selectedSlots } from "state/atoms/selectedSlots";
import { serviceAtom } from "state/atoms/service";
import { timeZoneAtom } from "state/atoms/timeZone";
import { slotsViewConfiguration } from "state/selectors/slotsViewConfiguration";
Expand Down Expand Up @@ -110,16 +110,11 @@ const DummySlot: React.FC<DummySlotProps> = ({ showDuration, showQuantity }) =>
interface TimeSlotProps {
dateFrom: string;
dateTo: string;
day: string;
is12HoursSystem: boolean;
}

const getTimeSlotButtonState = (
dateString: string,
selectedDateString: string,
isAvailable: boolean,
): TimeSlotButtonState => {
if (dateString === selectedDateString) return "selected";
const getTimeSlotButtonState = (selected: boolean, isAvailable: boolean): TimeSlotButtonState => {
if (selected) return "selected";

if (isAvailable) return "available";

Expand Down Expand Up @@ -306,13 +301,29 @@ const getDurationSlotContent = (
);
};

const TimeSlot: React.FC<TimeSlotProps> = ({ dateFrom, dateTo, day, is12HoursSystem }) => {
const TimeSlot: React.FC<TimeSlotProps> = ({ dateFrom, dateTo, is12HoursSystem }) => {
const slot = useRecoilValue(timeSlot({ from: dateFrom, to: dateTo }));
const [selected, setSelectedSlot] = useRecoilState(selectedSlot);
const slotId = slot?.slotId!;
const { showDuration, showQuantity } = useRecoilValue(slotsViewConfiguration);
const { t } = useTranslation();
const timeZone = useRecoilValue(timeZoneAtom);
const service = useRecoilValue(serviceAtom);
const service = useRecoilValue(serviceAtom)!;
const [selectedSlotsValue, setSelectedSlots] = useRecoilState(selectedSlots);
const selected = selectedSlotsValue.includes(slotId);

const handleSlotClick = () => {
const hasMultipleSlots = service.viewConfig?.days?.multiSelect;

if (hasMultipleSlots) {
if (selected) {
setSelectedSlots(selectedSlotsValue.filter((id: string) => id !== slotId));
} else {
setSelectedSlots([...selectedSlotsValue, slotId]);
}
} else {
setSelectedSlots(selected ? [] : [slotId]);
}
};

return (
<Column mt={0.5} mb={0.5} w="100%">
Expand All @@ -322,11 +333,9 @@ const TimeSlot: React.FC<TimeSlotProps> = ({ dateFrom, dateTo, day, is12HoursSys
<TimeSlotButton
showDuration={showDuration}
showQuantity={showQuantity}
state={getTimeSlotButtonState(dateFrom, selected, slot.quantity > 0)}
state={getTimeSlotButtonState(selected, slot.quantity > 0)}
disabled={slot.quantity === 0}
onClick={() => {
setSelectedSlot(dateFrom);
}}
onClick={handleSlotClick}
>
{showDuration &&
showQuantity &&
Expand Down
3 changes: 2 additions & 1 deletion src/state/selectors/slotsDayPattern.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ export const slotsDayPattern = selector({
return Object.values(item).map((slot) => {
const from = slot.dateTimeFrom.split("T")[1];
const to = slot.dateTimeTo.split("T")[1];
const slotId = slot.slotId;

return { key: `${from}-${to}`, from, to };
return { key: `${from}-${to}`, from, to, slotId };
});
});

Expand Down

0 comments on commit c8fbf19

Please sign in to comment.