use-calendar-timezones.ts2.0 KBView on GitHub
import { useCallback, useMemo, useState } from 'react';

const TZ_STORAGE_KEY=[redacted];

/**
 * The ordered list of timezone columns shown in the calendar's time gutter. The primary
 * (browser) timezone is always LAST — i.e. the column sitting right against the grid, so the
 * hours you actually read line up with the events beside them — and cannot be removed.
 * Additional zones are prepended to its left and persisted to localStorage so they survive
 * reloads.
 */
export function useCalendarTimezones(primaryTimezone: string) {
  const [extra, setExtra] = useState<string[]>(() => {
    if (typeof window === 'undefined') return [];
    try {
      const raw = window.localStorage.getItem(TZ_STORAGE_KEY);
      const parsed = raw ? JSON.parse(raw) : [];
      return Array.isArray(parsed)
        ? parsed.filter((t): t is string => typeof t === 'string' && t !== primaryTimezone)
        : [];
    } catch {
      return [];
    }
  });

  const persist = useCallback((next: string[]) => {
    setExtra(next);
    try {
      window.localStorage.setItem(TZ_STORAGE_KEY, JSON.stringify(next));
    } catch {
      // localStorage may be unavailable (private mode); the in-memory list still works.
    }
  }, []);

  const addTimezone = useCallback(
    (tz: string) => {
      if (tz === primaryTimezone) return;
      setExtra((prev) => {
        if (prev.includes(tz)) return prev;
        const next = [...prev, tz];
        try {
          window.localStorage.setItem(TZ_STORAGE_KEY, JSON.stringify(next));
        } catch {
          // ignore
        }
        return next;
      });
    },
    [primaryTimezone],
  );

  const removeTimezone = useCallback(
    (tz: string) => {
      if (tz === primaryTimezone) return;
      persist(extra.filter((t) => t !== tz));
    },
    [extra, persist, primaryTimezone],
  );

  const timezones = useMemo(
    () => [...extra.filter((t) => t !== primaryTimezone), primaryTimezone],
    [primaryTimezone, extra],
  );

  return { timezones, addTimezone, removeTimezone };
}