import { useCallback, useMemo, useState } from "react"; import { __ } from "@wordpress/i18n"; import { useDispatch, useSelect } from "@wordpress/data"; import DatePicker from "react-datepicker"; import Select from "react-select"; import classNames from "classnames"; import "react-datepicker/dist/react-datepicker.css"; import { store_name } from "../../../../store/backend"; import { getAdminSelectStyles } from "../../../utils/adminSelectStyles"; import { formatWbkDate } from "../../../components/Form/utils/dateTime"; import { Button } from "../../../components/Button/Button"; import { useSidebar } from "../../../components/Sidebar/SidebarContext"; import closeIcon from "../../../../../public/images/icon-close.svg"; import "../../../components/Form/Form.scss"; import "./BulkDateLockPopup.scss"; type SelectOption = { value: string; label: string; }; type BulkDateLockPopupProps = { onSuccess?: () => Promise | void; }; const DAYS_OF_WEEK: SelectOption[] = [ { value: "1", label: __("Monday", "webba-booking-lite") }, { value: "2", label: __("Tuesday", "webba-booking-lite") }, { value: "3", label: __("Wednesday", "webba-booking-lite") }, { value: "4", label: __("Thursday", "webba-booking-lite") }, { value: "5", label: __("Friday", "webba-booking-lite") }, { value: "6", label: __("Saturday", "webba-booking-lite") }, { value: "7", label: __("Sunday", "webba-booking-lite") }, ]; const selectStyles = getAdminSelectStyles(); export const BulkDateLockPopup = ({ onSuccess }: BulkDateLockPopupProps) => { const sidebar = useSidebar(); const { scheduleToolsAction, setToastNotification } = useDispatch(store_name); const { services, categories } = useSelect( (select) => { // @ts-ignore const preset = select(store_name).getPreset() || {}; // @ts-ignore const storeServices = select(store_name).getItems("services") || []; // @ts-ignore const storeCategories = select(store_name).getItems("service_categories") || []; return { services: Array.isArray(storeServices) && storeServices.length ? storeServices : preset.services || [], categories: Array.isArray(storeCategories) && storeCategories.length ? storeCategories : preset.categories || [], }; }, [] ); const [action, setAction] = useState<"lock" | "unlock">("lock"); const [serviceId, setServiceId] = useState(null); const [categoryId, setCategoryId] = useState(null); const [dateRange, setDateRange] = useState<[Date | null, Date | null]>([ null, null, ]); const [excludeDates, setExcludeDates] = useState([]); const [daysOfWeek, setDaysOfWeek] = useState(DAYS_OF_WEEK); const [dateRangeOpen, setDateRangeOpen] = useState(false); const [excludeDatesOpen, setExcludeDatesOpen] = useState(false); const [isSubmitting, setIsSubmitting] = useState(false); const [fieldErrors, setFieldErrors] = useState>({}); const [errorMessage, setErrorMessage] = useState(""); const serviceOptions = useMemo( () => (services || []) .map((service: any) => ({ value: String(service.id ?? service.value ?? ""), label: String(service.name ?? service.label ?? ""), })) .filter((option: SelectOption) => option.value && option.label), [services] ); const categoryOptions = useMemo( () => (categories || []) .map((category: any) => ({ value: String(category.id ?? category.value ?? ""), label: String(category.name ?? category.label ?? ""), })) .filter((option: SelectOption) => option.value && option.label), [categories] ); const validate = useCallback(() => { const errors: Record = {}; if (!serviceId && !categoryId) { errors.service = true; errors.category = true; } if (!dateRange[0] || !dateRange[1]) { errors.dateRange = true; } if (!daysOfWeek.length) { errors.daysOfWeek = true; } setFieldErrors(errors); return Object.keys(errors).length === 0; }, [serviceId, categoryId, dateRange, daysOfWeek]); const handleSubmit = useCallback(async () => { setErrorMessage(""); if (!validate() || isSubmitting) { return; } setIsSubmitting(true); try { const response = (await scheduleToolsAction({ lock_action: action, lock_target: "dates", service: serviceId?.value || "0", category: categoryId?.value || "0", date_range: `${formatWbkDate(dateRange[0]!)} - ${formatWbkDate(dateRange[1]!)}`, exclude_dates: (excludeDates || []).map((date) => formatWbkDate(date)).join(","), days_of_week: daysOfWeek.map((day) => day.value).join(","), })) as { status?: number; message?: string }; if (!response?.status) { const message = response?.message || __("Something went wrong.", "webba-booking-lite"); setErrorMessage(message); setToastNotification({ type: "error", message, }); return; } setToastNotification({ type: "success", message: response.message || __("Done.", "webba-booking-lite"), }); await onSuccess?.(); sidebar.close(); } catch (e: any) { const message = e?.message || e?.data?.message || __("Failed to update dates.", "webba-booking-lite"); setErrorMessage(String(message)); setToastNotification({ type: "error", message: String(message), }); } finally { setIsSubmitting(false); } }, [ validate, isSubmitting, scheduleToolsAction, action, serviceId, categoryId, dateRange, excludeDates, daysOfWeek, onSuccess, sidebar, setToastNotification, ]); return (
{__("Lock / Unlock multiple dates", "webba-booking-lite")}
{ setCategoryId(option as SelectOption | null); setFieldErrors((prev) => ({ ...prev, service: false, category: false })); }} placeholder={__("Select category", "webba-booking-lite")} isClearable />
{ setDateRange(range); if (range[0] && range[1]) { setDateRangeOpen(false); setFieldErrors((prev) => ({ ...prev, dateRange: false })); } }} open={dateRangeOpen} onClickOutside={() => setDateRangeOpen(false)} onInputClick={() => setDateRangeOpen(true)} />
{ setExcludeDates(dates); }} open={excludeDatesOpen} onClickOutside={() => setExcludeDatesOpen(false)} onInputClick={() => setExcludeDatesOpen(true)} isClearable />