Files
cal.diy/packages/features/bookings/Booker/hooks/useLocalSet.tsx
T
73f51920c5 refactor: move Booker hooks from packages/features to apps/web/modules (#27343)
* refactor: move Booker hooks from packages/features to apps/web/modules

Migrate the following Booker hooks:
- useOverlayCalendar
- useSkipConfirmStep
- useInitializeWeekStart
- useIsQuickAvailabilityCheckFeatureEnabled
- useDecoyBooking

These hooks are only imported by apps/web files, making them safe to move
without creating circular dependencies.

Part of the tRPC-driven UI migration from packages/features to apps/web/modules.

Co-Authored-By: benny@cal.com <sldisek783@gmail.com>

* fix: revert useIsQuickAvailabilityCheckFeatureEnabled move and fix import paths

- Reverted useIsQuickAvailabilityCheckFeatureEnabled.ts back to packages/features since it's imported by useSlots.ts in packages/features (would create circular dependency)
- Fixed import paths in useOverlayCalendar.ts to use @calcom/features paths
- Fixed import paths in useSkipConfirmStep.ts to use @calcom/features paths
- Updated Booker.tsx to import useIsQuickAvailabilityCheckFeatureEnabled from original location

Co-Authored-By: benny@cal.com <sldisek783@gmail.com>

* fix: use @calcom/web alias for hook imports to fix vitest resolution

Co-Authored-By: benny@cal.com <sldisek783@gmail.com>

* refactor

* migrate more hooks

* fix

* mv types

* fix

* fix

* fix

* fix

* revert: remove formatting-only changes to make PR easier to review

Co-Authored-By: benny@cal.com <sldisek783@gmail.com>

* fix

* fix

* fix

* revert: restore original import ordering in moved hooks

Co-Authored-By: benny@cal.com <sldisek783@gmail.com>

* fix imports

* fix

* fix

* wip

* wip

* wip

* wip

* wip

* wip

* fix: add isBrowser guard to useSlotsViewOnSmallScreen hook

Address Cubic AI review feedback (confidence 9/10) by adding the isBrowser
guard to the useSlotsViewOnSmallScreen hook to follow the file's client-only
contract and avoid executing during SSR/prerendering.

Co-Authored-By: unknown <>

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-01-31 07:33:33 -03:00

71 lines
1.7 KiB
TypeScript

import { useEffect, useState } from "react";
import { localStorage } from "@calcom/lib/webstorage";
export interface HasExternalId {
externalId: string;
}
export function useLocalSet<T extends HasExternalId>(key: string, initialValue: T[]) {
const [set, setSet] = useState<Set<T>>(() => {
const storedValue = localStorage.getItem(key);
return storedValue ? new Set(JSON.parse(storedValue)) : new Set(initialValue);
});
useEffect(() => {
localStorage.setItem(key, JSON.stringify(Array.from(set)));
}, [key, set]);
const addValue = (value: T) => {
setSet((prevSet) => new Set(prevSet).add(value));
};
const removeById = (id: string) => {
setSet((prevSet) => {
const updatedSet = new Set(prevSet);
updatedSet.forEach((item) => {
if (item.externalId === id) {
updatedSet.delete(item);
}
});
return updatedSet;
});
};
const toggleValue = (value: T): Set<T> => {
let newSet = new Set<T>();
setSet((prevSet) => {
const updatedSet = new Set<T>(prevSet);
let itemFound = false;
updatedSet.forEach((item) => {
if (item.externalId === value.externalId) {
itemFound = true;
updatedSet.delete(item);
}
});
if (!itemFound) {
updatedSet.add(value);
}
newSet = updatedSet;
return updatedSet;
});
return newSet;
};
const hasItem = (value: T) => {
return Array.from(set).some((item) => item.externalId === value.externalId);
};
const clearSet = () => {
setSet(() => new Set());
// clear local storage too
localStorage.removeItem(key);
};
return { set, addValue, removeById, toggleValue, hasItem, clearSet };
}