feat: (Overlay) Persist toggle option (#11961)
parent
0c92fbe11d
commit
0b46f61a23
|
@ -19,7 +19,8 @@ export const LargeCalendar = ({ extraDays }: { extraDays: number }) => {
|
||||||
const schedule = useScheduleForEvent({
|
const schedule = useScheduleForEvent({
|
||||||
prefetchNextMonth: !!extraDays && dayjs(date).month() !== dayjs(date).add(extraDays, "day").month(),
|
prefetchNextMonth: !!extraDays && dayjs(date).month() !== dayjs(date).add(extraDays, "day").month(),
|
||||||
});
|
});
|
||||||
const displayOverlay = getQueryParam("overlayCalendar") === "true";
|
const displayOverlay =
|
||||||
|
getQueryParam("overlayCalendar") === "true" || localStorage.getItem("overlayCalendarSwitchDefault");
|
||||||
|
|
||||||
const event = useEvent();
|
const event = useEvent();
|
||||||
const eventDuration = selectedEventDuration || event?.data?.length || 30;
|
const eventDuration = selectedEventDuration || event?.data?.length || 30;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { useSession } from "next-auth/react";
|
import { useSession } from "next-auth/react";
|
||||||
import { useRouter, useSearchParams, usePathname } from "next/navigation";
|
import { useSearchParams, useRouter, usePathname } from "next/navigation";
|
||||||
import { useState, useCallback, useEffect } from "react";
|
import { useState, useCallback, useEffect } from "react";
|
||||||
|
|
||||||
import dayjs from "@calcom/dayjs";
|
import dayjs from "@calcom/dayjs";
|
||||||
|
@ -17,19 +17,108 @@ import { OverlayCalendarSettingsModal } from "../OverlayCalendar/OverlayCalendar
|
||||||
import { useLocalSet } from "../hooks/useLocalSet";
|
import { useLocalSet } from "../hooks/useLocalSet";
|
||||||
import { useOverlayCalendarStore } from "./store";
|
import { useOverlayCalendarStore } from "./store";
|
||||||
|
|
||||||
export function OverlayCalendarContainer() {
|
interface OverlayCalendarSwitchProps {
|
||||||
|
setContinueWithProvider: (val: boolean) => void;
|
||||||
|
setCalendarSettingsOverlay: (val: boolean) => void;
|
||||||
|
enabled?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
function OverlayCalendarSwitch({
|
||||||
|
setCalendarSettingsOverlay,
|
||||||
|
setContinueWithProvider,
|
||||||
|
enabled,
|
||||||
|
}: OverlayCalendarSwitchProps) {
|
||||||
const { t } = useLocale();
|
const { t } = useLocale();
|
||||||
|
const layout = useBookerStore((state) => state.layout);
|
||||||
|
const searchParams = useSearchParams();
|
||||||
|
const { data: session } = useSession();
|
||||||
|
const router = useRouter();
|
||||||
|
const pathname = usePathname();
|
||||||
|
const switchEnabled = enabled;
|
||||||
|
|
||||||
|
// Toggle query param for overlay calendar
|
||||||
|
const toggleOverlayCalendarQueryParam = useCallback(
|
||||||
|
(state: boolean) => {
|
||||||
|
const current = new URLSearchParams(Array.from(searchParams.entries()));
|
||||||
|
if (state) {
|
||||||
|
current.set("overlayCalendar", "true");
|
||||||
|
localStorage.setItem("overlayCalendarSwitchDefault", "true");
|
||||||
|
} else {
|
||||||
|
current.delete("overlayCalendar");
|
||||||
|
localStorage.removeItem("overlayCalendarSwitchDefault");
|
||||||
|
}
|
||||||
|
// cast to string
|
||||||
|
const value = current.toString();
|
||||||
|
const query = value ? `?${value}` : "";
|
||||||
|
router.push(`${pathname}${query}`);
|
||||||
|
},
|
||||||
|
[searchParams, pathname, router]
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If a user is not logged in and the overlay calendar query param is true,
|
||||||
|
* show the continue modal so they can login / create an account
|
||||||
|
*/
|
||||||
|
useEffect(() => {
|
||||||
|
if (!session && switchEnabled) {
|
||||||
|
toggleOverlayCalendarQueryParam(false);
|
||||||
|
setContinueWithProvider(true);
|
||||||
|
}
|
||||||
|
}, [session, switchEnabled, setContinueWithProvider, toggleOverlayCalendarQueryParam]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={classNames(
|
||||||
|
"hidden gap-2",
|
||||||
|
layout === "week_view" || layout === "column_view" ? "xl:flex" : "md:flex"
|
||||||
|
)}>
|
||||||
|
<div className="flex items-center gap-2 pr-2">
|
||||||
|
<Switch
|
||||||
|
data-testid="overlay-calendar-switch"
|
||||||
|
checked={switchEnabled}
|
||||||
|
id="overlayCalendar"
|
||||||
|
onCheckedChange={(state) => {
|
||||||
|
if (!session) {
|
||||||
|
setContinueWithProvider(state);
|
||||||
|
} else {
|
||||||
|
toggleOverlayCalendarQueryParam(state);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<label
|
||||||
|
htmlFor="overlayCalendar"
|
||||||
|
className="text-emphasis text-sm font-medium leading-none hover:cursor-pointer">
|
||||||
|
{t("overlay_my_calendar")}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
{session && (
|
||||||
|
<Button
|
||||||
|
size="base"
|
||||||
|
data-testid="overlay-calendar-settings-button"
|
||||||
|
variant="icon"
|
||||||
|
color="secondary"
|
||||||
|
StartIcon={Settings}
|
||||||
|
onClick={() => {
|
||||||
|
setCalendarSettingsOverlay(true);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function OverlayCalendarContainer() {
|
||||||
const isEmbed = useIsEmbed();
|
const isEmbed = useIsEmbed();
|
||||||
|
const searchParams = useSearchParams();
|
||||||
const [continueWithProvider, setContinueWithProvider] = useState(false);
|
const [continueWithProvider, setContinueWithProvider] = useState(false);
|
||||||
const [calendarSettingsOverlay, setCalendarSettingsOverlay] = useState(false);
|
const [calendarSettingsOverlay, setCalendarSettingsOverlay] = useState(false);
|
||||||
const { data: session } = useSession();
|
const { data: session } = useSession();
|
||||||
const setOverlayBusyDates = useOverlayCalendarStore((state) => state.setOverlayBusyDates);
|
const setOverlayBusyDates = useOverlayCalendarStore((state) => state.setOverlayBusyDates);
|
||||||
|
const switchEnabled =
|
||||||
|
searchParams.get("overlayCalendar") === "true" ||
|
||||||
|
localStorage.getItem("overlayCalendarSwitchDefault") === "true";
|
||||||
|
|
||||||
const layout = useBookerStore((state) => state.layout);
|
|
||||||
const selectedDate = useBookerStore((state) => state.selectedDate);
|
const selectedDate = useBookerStore((state) => state.selectedDate);
|
||||||
const router = useRouter();
|
|
||||||
const pathname = usePathname();
|
|
||||||
const searchParams = useSearchParams();
|
|
||||||
const { timezone } = useTimePreferences();
|
const { timezone } = useTimePreferences();
|
||||||
|
|
||||||
// Move this to a hook
|
// Move this to a hook
|
||||||
|
@ -37,7 +126,6 @@ export function OverlayCalendarContainer() {
|
||||||
credentialId: number;
|
credentialId: number;
|
||||||
externalId: string;
|
externalId: string;
|
||||||
}>("toggledConnectedCalendars", []);
|
}>("toggledConnectedCalendars", []);
|
||||||
const overlayCalendarQueryParam = searchParams.get("overlayCalendar");
|
|
||||||
|
|
||||||
const { data: overlayBusyDates } = trpc.viewer.availability.calendarOverlay.useQuery(
|
const { data: overlayBusyDates } = trpc.viewer.availability.calendarOverlay.useQuery(
|
||||||
{
|
{
|
||||||
|
@ -50,7 +138,7 @@ export function OverlayCalendarContainer() {
|
||||||
})),
|
})),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
enabled: !!session && set.size > 0 && overlayCalendarQueryParam === "true",
|
enabled: !!session && set.size > 0 && switchEnabled,
|
||||||
onError: () => {
|
onError: () => {
|
||||||
clearSet();
|
clearSet();
|
||||||
},
|
},
|
||||||
|
@ -76,77 +164,17 @@ export function OverlayCalendarContainer() {
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [overlayBusyDates]);
|
}, [overlayBusyDates]);
|
||||||
|
|
||||||
// Toggle query param for overlay calendar
|
|
||||||
const toggleOverlayCalendarQueryParam = useCallback(
|
|
||||||
(state: boolean) => {
|
|
||||||
const current = new URLSearchParams(Array.from(searchParams.entries()));
|
|
||||||
if (state) {
|
|
||||||
current.set("overlayCalendar", "true");
|
|
||||||
} else {
|
|
||||||
current.delete("overlayCalendar");
|
|
||||||
}
|
|
||||||
// cast to string
|
|
||||||
const value = current.toString();
|
|
||||||
const query = value ? `?${value}` : "";
|
|
||||||
router.push(`${pathname}${query}`);
|
|
||||||
},
|
|
||||||
[searchParams, pathname, router]
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If a user is not logged in and the overlay calendar query param is true,
|
|
||||||
* show the continue modal so they can login / create an account
|
|
||||||
*/
|
|
||||||
useEffect(() => {
|
|
||||||
if (!session && overlayCalendarQueryParam === "true") {
|
|
||||||
toggleOverlayCalendarQueryParam(false);
|
|
||||||
setContinueWithProvider(true);
|
|
||||||
}
|
|
||||||
}, [session, overlayCalendarQueryParam, toggleOverlayCalendarQueryParam]);
|
|
||||||
|
|
||||||
if (isEmbed) {
|
if (isEmbed) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div
|
<OverlayCalendarSwitch
|
||||||
className={classNames(
|
setCalendarSettingsOverlay={setCalendarSettingsOverlay}
|
||||||
"hidden gap-2",
|
setContinueWithProvider={setContinueWithProvider}
|
||||||
layout === "week_view" || layout === "column_view" ? "xl:flex" : "md:flex"
|
enabled={switchEnabled}
|
||||||
)}>
|
/>
|
||||||
<div className="flex items-center gap-2 pr-2">
|
|
||||||
<Switch
|
|
||||||
data-testid="overlay-calendar-switch"
|
|
||||||
checked={overlayCalendarQueryParam === "true"}
|
|
||||||
id="overlayCalendar"
|
|
||||||
onCheckedChange={(state) => {
|
|
||||||
if (!session) {
|
|
||||||
setContinueWithProvider(state);
|
|
||||||
} else {
|
|
||||||
toggleOverlayCalendarQueryParam(state);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<label
|
|
||||||
htmlFor="overlayCalendar"
|
|
||||||
className="text-emphasis text-sm font-medium leading-none hover:cursor-pointer">
|
|
||||||
{t("overlay_my_calendar")}
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
{session && (
|
|
||||||
<Button
|
|
||||||
size="base"
|
|
||||||
data-testid="overlay-calendar-settings-button"
|
|
||||||
variant="icon"
|
|
||||||
color="secondary"
|
|
||||||
StartIcon={Settings}
|
|
||||||
onClick={() => {
|
|
||||||
setCalendarSettingsOverlay(true);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<OverlayCalendarContinueModal
|
<OverlayCalendarContinueModal
|
||||||
open={continueWithProvider}
|
open={continueWithProvider}
|
||||||
onClose={(val) => {
|
onClose={(val) => {
|
||||||
|
|
|
@ -48,7 +48,8 @@ const SlotItem = ({
|
||||||
}) => {
|
}) => {
|
||||||
const { t } = useLocale();
|
const { t } = useLocale();
|
||||||
|
|
||||||
const overlayCalendarToggled = getQueryParam("overlayCalendar") === "true";
|
const overlayCalendarToggled =
|
||||||
|
getQueryParam("overlayCalendar") === "true" || localStorage.getItem("overlayCalendarSwitchDefault");
|
||||||
const [timeFormat, timezone] = useTimePreferences((state) => [state.timeFormat, state.timezone]);
|
const [timeFormat, timezone] = useTimePreferences((state) => [state.timeFormat, state.timezone]);
|
||||||
const selectedDuration = useBookerStore((state) => state.selectedDuration);
|
const selectedDuration = useBookerStore((state) => state.selectedDuration);
|
||||||
const bookingData = useBookerStore((state) => state.bookingData);
|
const bookingData = useBookerStore((state) => state.bookingData);
|
||||||
|
|
Loading…
Reference in New Issue