mirror of
https://github.com/hanzoai/calendar.git
synced 2026-10-30 14:46:43 +00:00
* feat(companion): add configurable landing page feature - Add useUserPreferences hook for persistent storage of landing page preference - Add LandingPagePicker component for both iOS and Android/web platforms - Update tabs index to redirect based on user preference - Update bookings index to accept initial filter from URL params - Add App Settings section in More screen with landing page selector - Clear user preferences on logout for fresh state * fix(companion): remove try-finally for React Compiler compatibility * fix(companion): use router.replace for dynamic landing page redirect Replace Redirect component with router.replace() to fix TypeScript strict typing issue with expo-router's Href type for dynamic routes. * fix(companion): use literal route strings for TypeScript strict typing Use switch statement with literal route strings instead of dynamic string variable to satisfy expo-router's strict Href type checking. * working fix * better css
93 lines
2.5 KiB
TypeScript
93 lines
2.5 KiB
TypeScript
import { useCallback, useEffect, useState } from "react";
|
|
import { generalStorage } from "@/utils/storage";
|
|
|
|
export type LandingPage = "event-types" | "bookings" | "bookings:unconfirmed";
|
|
|
|
export interface UserPreferences {
|
|
landingPage: LandingPage;
|
|
}
|
|
|
|
export const USER_PREFERENCES_KEY = "cal_user_preferences";
|
|
|
|
const DEFAULT_PREFERENCES: UserPreferences = {
|
|
landingPage: "event-types",
|
|
};
|
|
|
|
export interface LandingPageOption {
|
|
value: LandingPage;
|
|
label: string;
|
|
}
|
|
|
|
export const LANDING_PAGE_OPTIONS: LandingPageOption[] = [
|
|
{ value: "event-types", label: "Event Types" },
|
|
{ value: "bookings", label: "Bookings" },
|
|
{ value: "bookings:unconfirmed", label: "Bookings (Unconfirmed)" },
|
|
];
|
|
|
|
export function getLandingPageLabel(landingPage: LandingPage): string {
|
|
const option = LANDING_PAGE_OPTIONS.find((opt) => opt.value === landingPage);
|
|
return option?.label ?? "Event Types";
|
|
}
|
|
|
|
export function getRouteFromPreference(landingPage: LandingPage): string {
|
|
switch (landingPage) {
|
|
case "event-types":
|
|
return "/(tabs)/(event-types)";
|
|
case "bookings":
|
|
return "/(tabs)/(bookings)";
|
|
case "bookings:unconfirmed":
|
|
return "/(tabs)/(bookings)?filter=unconfirmed";
|
|
default:
|
|
return "/(tabs)/(event-types)";
|
|
}
|
|
}
|
|
|
|
export function useUserPreferences() {
|
|
const [preferences, setPreferences] = useState<UserPreferences>(DEFAULT_PREFERENCES);
|
|
const [isLoading, setIsLoading] = useState(true);
|
|
|
|
useEffect(() => {
|
|
const loadPreferences = async () => {
|
|
try {
|
|
const stored = await generalStorage.getItem(USER_PREFERENCES_KEY);
|
|
if (stored) {
|
|
const parsed = JSON.parse(stored) as UserPreferences;
|
|
setPreferences(parsed);
|
|
}
|
|
setIsLoading(false);
|
|
} catch {
|
|
console.warn("Failed to load user preferences");
|
|
setIsLoading(false);
|
|
}
|
|
};
|
|
|
|
loadPreferences();
|
|
}, []);
|
|
|
|
const setLandingPage = useCallback(
|
|
async (landingPage: LandingPage): Promise<void> => {
|
|
const newPreferences: UserPreferences = {
|
|
...preferences,
|
|
landingPage,
|
|
};
|
|
|
|
setPreferences(newPreferences);
|
|
|
|
try {
|
|
await generalStorage.setItem(USER_PREFERENCES_KEY, JSON.stringify(newPreferences));
|
|
} catch (error) {
|
|
console.error("Failed to save user preferences:", error);
|
|
throw error;
|
|
}
|
|
},
|
|
[preferences]
|
|
);
|
|
|
|
return {
|
|
preferences,
|
|
isLoading,
|
|
setLandingPage,
|
|
landingPageLabel: getLandingPageLabel(preferences.landingPage),
|
|
};
|
|
}
|