coupon code system eingeführt. coupons werden vom super admin gemanaged. coupons werden mit paddle synchronisiert und dort validiert. plus: einige mobil-optimierungen im tenant admin pwa.
This commit is contained in:
93
resources/js/admin/context/EventContext.tsx
Normal file
93
resources/js/admin/context/EventContext.tsx
Normal file
@@ -0,0 +1,93 @@
|
||||
import React from 'react';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
|
||||
import { getEvents, type TenantEvent } from '../api';
|
||||
|
||||
const STORAGE_KEY = 'tenant-admin.active-event';
|
||||
|
||||
export interface EventContextValue {
|
||||
events: TenantEvent[];
|
||||
isLoading: boolean;
|
||||
activeEvent: TenantEvent | null;
|
||||
selectEvent: (slug: string | null) => void;
|
||||
}
|
||||
|
||||
const EventContext = React.createContext<EventContextValue | undefined>(undefined);
|
||||
|
||||
export function EventProvider({ children }: { children: React.ReactNode }) {
|
||||
const [storedSlug, setStoredSlug] = React.useState<string | null>(() => {
|
||||
if (typeof window === 'undefined') {
|
||||
return null;
|
||||
}
|
||||
return window.localStorage.getItem(STORAGE_KEY);
|
||||
});
|
||||
|
||||
const { data: events = [], isLoading } = useQuery<TenantEvent[]>({
|
||||
queryKey: ['tenant-events'],
|
||||
queryFn: async () => {
|
||||
try {
|
||||
return await getEvents();
|
||||
} catch (error) {
|
||||
console.warn('[EventContext] Failed to fetch events', error);
|
||||
return [];
|
||||
}
|
||||
},
|
||||
staleTime: 60 * 1000,
|
||||
cacheTime: 5 * 60 * 1000,
|
||||
});
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!storedSlug && events.length === 1 && events[0]?.slug && typeof window !== 'undefined') {
|
||||
setStoredSlug(events[0].slug);
|
||||
window.localStorage.setItem(STORAGE_KEY, events[0].slug);
|
||||
}
|
||||
}, [events, storedSlug]);
|
||||
|
||||
const activeEvent = React.useMemo(() => {
|
||||
if (!events.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const matched = events.find((event) => event.slug && event.slug === storedSlug);
|
||||
if (matched) {
|
||||
return matched;
|
||||
}
|
||||
|
||||
if (!storedSlug && events.length === 1) {
|
||||
return events[0];
|
||||
}
|
||||
|
||||
return null;
|
||||
}, [events, storedSlug]);
|
||||
|
||||
const selectEvent = React.useCallback((slug: string | null) => {
|
||||
setStoredSlug(slug);
|
||||
if (typeof window !== 'undefined') {
|
||||
if (slug) {
|
||||
window.localStorage.setItem(STORAGE_KEY, slug);
|
||||
} else {
|
||||
window.localStorage.removeItem(STORAGE_KEY);
|
||||
}
|
||||
}
|
||||
}, []);
|
||||
|
||||
const value = React.useMemo<EventContextValue>(
|
||||
() => ({
|
||||
events,
|
||||
isLoading,
|
||||
activeEvent,
|
||||
selectEvent,
|
||||
}),
|
||||
[events, isLoading, activeEvent, selectEvent]
|
||||
);
|
||||
|
||||
return <EventContext.Provider value={value}>{children}</EventContext.Provider>;
|
||||
}
|
||||
|
||||
export function useEventContext(): EventContextValue {
|
||||
const ctx = React.useContext(EventContext);
|
||||
if (!ctx) {
|
||||
throw new Error('useEventContext must be used within an EventProvider');
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
Reference in New Issue
Block a user