* refactor: apply biome formatting to packages/features (batch 1 - small subdirs) Format small subdirectories in packages/features: di, flags, holidays, oauth, settings, users, assignment-reason, selectedCalendar, hashedLink, host, form, form-builder, availability, data-table, pbac, schedules, troubleshooter, eventtypes, calendar-subscription, and root-level files. Also includes straggler apps/web BookEventForm.tsx. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: apply biome formatting to packages/features (batch 2 - medium subdirs) Format medium subdirectories in packages/features: auth, credentials, calendars, routing-forms, routing-trace, attributes, watchlist, calAIPhone, tasker, and webhooks. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: apply biome formatting to packages/features (batch 3 - bookings + insights) Format bookings and insights subdirectories in packages/features. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: apply biome formatting to packages/features (batch 4 - ee) Format packages/features/ee subdirectory covering billing, workflows, organizations, teams, managed-event-types, round-robin, dsync, integration-attribute-sync, and payments. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: apply biome formatting to packages/features (batch 5 - booking-audit part 1) Format booking-audit di, actions, common, dto, repository, and types subdirectories in packages/features/booking-audit. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: apply biome formatting to packages/features (batch 6 - booking-audit part 2) Format booking-audit service subdirectory in packages/features/booking-audit. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
72 lines
1.7 KiB
TypeScript
72 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 };
|
|
}
|