* Init header + login modal component * Add calendar settings for authed user * Local storage and using query params for toggle * Toggle connect screen if query param present and no session * Local storage + store + way more than that should be in single commit * Display busy events on weekly view * Confirm booking slot of overlap exists * use chevron right when on column view * Show hover card - overlapping date times * Invalidate on switch * FIx clearing local storage when you login to another account * Force re-render on url state (atom quirks) * Add loading screen * Add dialog close * Remove extra grid config * Translations * [WIP] - tests * fix: google calendar busy times (#11696) Co-authored-by: CarinaWolli <wollencarina@gmail.com> * New Crowdin translations by Github Action * fix: rescheduled value DB update on reschedule and insights view cancelleds (#11474) * v3.3.5 * fix minutes string (#11703) Co-authored-by: CarinaWolli <wollencarina@gmail.com> * Regenerated yarn.lock * Add error component + loader * await tests * disable tests - add note * Refactor to include selected time * use no-scrollbar * Fix i18n * Fix tablet toolbar * overflow + i18n * Export empty object as test is TODO * Uses booker timezone * Fix hiding switch too early * Handle selected timezone * Fix timezone issues * Fix timezone issues --------- Co-authored-by: Carina Wollendorfer <30310907+CarinaWolli@users.noreply.github.com> Co-authored-by: CarinaWolli <wollencarina@gmail.com> Co-authored-by: Crowdin Bot <support+bot@crowdin.com> Co-authored-by: alannnc <alannnc@gmail.com> Co-authored-by: Alex van Andel <me@alexvanandel.com> Co-authored-by: Peer Richelsen <peer@cal.com> Co-authored-by: Peer Richelsen <peeroke@gmail.com>
65 lines
1.6 KiB
TypeScript
65 lines
1.6 KiB
TypeScript
import { useEffect, useState } from "react";
|
|
|
|
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) => {
|
|
setSet((prevSet) => {
|
|
const updatedSet = new Set(prevSet);
|
|
let itemFound = false;
|
|
|
|
updatedSet.forEach((item) => {
|
|
if (item.externalId === value.externalId) {
|
|
itemFound = true;
|
|
updatedSet.delete(item);
|
|
}
|
|
});
|
|
|
|
if (!itemFound) {
|
|
updatedSet.add(value);
|
|
}
|
|
|
|
return updatedSet;
|
|
});
|
|
};
|
|
|
|
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 };
|
|
}
|