mirror of
https://github.com/solidtime-io/solidtime.git
synced 2026-08-08 16:22:16 +01:00
307 lines
9.3 KiB
TypeScript
307 lines
9.3 KiB
TypeScript
import type { QueryClient } from '@tanstack/vue-query';
|
|
import { api } from '@/packages/api/src';
|
|
import { getCurrentOrganizationId, getCurrentMembershipId } from '@/utils/useUser';
|
|
import { canViewClients, canViewMembers } from '@/utils/permissions';
|
|
|
|
/**
|
|
* Route patterns mapped to their prefetch functions.
|
|
* Each function receives the QueryClient and prefetches relevant data.
|
|
*/
|
|
const routePrefetchers: Record<string, (queryClient: QueryClient) => void> = {
|
|
'/': (queryClient) => {
|
|
prefetchDashboard(queryClient);
|
|
},
|
|
|
|
'/dashboard': (queryClient) => {
|
|
prefetchDashboard(queryClient);
|
|
},
|
|
|
|
'/time': (queryClient) => {
|
|
prefetchProjects(queryClient);
|
|
prefetchTasks(queryClient);
|
|
prefetchTags(queryClient);
|
|
prefetchClients(queryClient);
|
|
prefetchTimeEntries(queryClient);
|
|
},
|
|
|
|
'/calendar': (queryClient) => {
|
|
prefetchProjects(queryClient);
|
|
prefetchTasks(queryClient);
|
|
prefetchTags(queryClient);
|
|
prefetchClients(queryClient);
|
|
},
|
|
|
|
'/projects': (queryClient) => {
|
|
prefetchProjects(queryClient);
|
|
prefetchClients(queryClient);
|
|
},
|
|
|
|
'/clients': (queryClient) => {
|
|
prefetchClients(queryClient);
|
|
},
|
|
|
|
'/tags': (queryClient) => {
|
|
prefetchTags(queryClient);
|
|
},
|
|
|
|
'/members': (queryClient) => {
|
|
prefetchMembers(queryClient);
|
|
},
|
|
|
|
'/reporting': (queryClient) => {
|
|
prefetchProjects(queryClient);
|
|
prefetchTags(queryClient);
|
|
prefetchClients(queryClient);
|
|
prefetchMembers(queryClient);
|
|
},
|
|
|
|
'/reporting/detailed': (queryClient) => {
|
|
prefetchProjects(queryClient);
|
|
prefetchTasks(queryClient);
|
|
prefetchTags(queryClient);
|
|
prefetchClients(queryClient);
|
|
prefetchMembers(queryClient);
|
|
},
|
|
|
|
'/reporting/shared': (queryClient) => {
|
|
prefetchReports(queryClient);
|
|
},
|
|
};
|
|
|
|
function prefetchDashboard(queryClient: QueryClient) {
|
|
const organizationId = getCurrentOrganizationId();
|
|
if (!organizationId) return;
|
|
|
|
// Prefetch all dashboard card data
|
|
queryClient.prefetchQuery({
|
|
queryKey: ['timeEntries', organizationId],
|
|
queryFn: () =>
|
|
api.getTimeEntries({
|
|
params: { organization: organizationId },
|
|
queries: { limit: 10, offset: 0, only_full_dates: 'true' },
|
|
}),
|
|
staleTime: 30000,
|
|
});
|
|
|
|
queryClient.prefetchQuery({
|
|
queryKey: ['lastSevenDays', organizationId],
|
|
queryFn: () => api.lastSevenDays({ params: { organization: organizationId } }),
|
|
staleTime: 30000,
|
|
});
|
|
|
|
queryClient.prefetchQuery({
|
|
queryKey: ['dailyTrackedHours', organizationId],
|
|
queryFn: () => api.dailyTrackedHours({ params: { organization: organizationId } }),
|
|
staleTime: 30000,
|
|
});
|
|
|
|
queryClient.prefetchQuery({
|
|
queryKey: ['weeklyProjectOverview', organizationId],
|
|
queryFn: () => api.weeklyProjectOverview({ params: { organization: organizationId } }),
|
|
staleTime: 30000,
|
|
});
|
|
|
|
queryClient.prefetchQuery({
|
|
queryKey: ['totalWeeklyTime', organizationId],
|
|
queryFn: () => api.totalWeeklyTime({ params: { organization: organizationId } }),
|
|
staleTime: 30000,
|
|
});
|
|
|
|
queryClient.prefetchQuery({
|
|
queryKey: ['totalWeeklyBillableTime', organizationId],
|
|
queryFn: () => api.totalWeeklyBillableTime({ params: { organization: organizationId } }),
|
|
staleTime: 30000,
|
|
});
|
|
|
|
queryClient.prefetchQuery({
|
|
queryKey: ['totalWeeklyBillableAmount', organizationId],
|
|
queryFn: () => api.totalWeeklyBillableAmount({ params: { organization: organizationId } }),
|
|
staleTime: 30000,
|
|
});
|
|
|
|
queryClient.prefetchQuery({
|
|
queryKey: ['weeklyHistory', organizationId],
|
|
queryFn: () => api.weeklyHistory({ params: { organization: organizationId } }),
|
|
staleTime: 30000,
|
|
});
|
|
|
|
// Prefetch team activity only if user has permission
|
|
if (canViewMembers()) {
|
|
queryClient.prefetchQuery({
|
|
queryKey: ['latestTeamActivity', organizationId],
|
|
queryFn: () => api.latestTeamActivity({ params: { organization: organizationId } }),
|
|
staleTime: 30000,
|
|
});
|
|
}
|
|
}
|
|
|
|
function prefetchProjects(queryClient: QueryClient) {
|
|
const organizationId = getCurrentOrganizationId();
|
|
if (!organizationId) return;
|
|
|
|
queryClient.prefetchQuery({
|
|
queryKey: ['projects'],
|
|
queryFn: () =>
|
|
api.getProjects({
|
|
params: { organization: organizationId },
|
|
queries: { archived: 'all' },
|
|
}),
|
|
staleTime: 30000, // Consider fresh for 30 seconds
|
|
});
|
|
}
|
|
|
|
function prefetchTasks(queryClient: QueryClient) {
|
|
const organizationId = getCurrentOrganizationId();
|
|
if (!organizationId) return;
|
|
|
|
queryClient.prefetchQuery({
|
|
queryKey: ['tasks'],
|
|
queryFn: () =>
|
|
api.getTasks({
|
|
params: { organization: organizationId },
|
|
queries: { done: 'all' },
|
|
}),
|
|
staleTime: 30000,
|
|
});
|
|
}
|
|
|
|
function prefetchTags(queryClient: QueryClient) {
|
|
const organizationId = getCurrentOrganizationId();
|
|
if (!organizationId) return;
|
|
|
|
queryClient.prefetchQuery({
|
|
queryKey: ['tags'],
|
|
queryFn: () =>
|
|
api.getTags({
|
|
params: { organization: organizationId },
|
|
}),
|
|
staleTime: 30000,
|
|
});
|
|
}
|
|
|
|
function prefetchClients(queryClient: QueryClient) {
|
|
const organizationId = getCurrentOrganizationId();
|
|
if (!organizationId || !canViewClients()) return;
|
|
|
|
queryClient.prefetchQuery({
|
|
queryKey: ['clients'],
|
|
queryFn: () =>
|
|
api.getClients({
|
|
params: { organization: organizationId },
|
|
queries: { archived: 'all' },
|
|
}),
|
|
staleTime: 30000,
|
|
});
|
|
}
|
|
|
|
function prefetchMembers(queryClient: QueryClient) {
|
|
const organizationId = getCurrentOrganizationId();
|
|
if (!organizationId || !canViewMembers()) return;
|
|
|
|
queryClient.prefetchQuery({
|
|
queryKey: ['members'],
|
|
queryFn: () =>
|
|
api.getMembers({
|
|
params: { organization: organizationId },
|
|
}),
|
|
staleTime: 30000,
|
|
});
|
|
}
|
|
|
|
function prefetchReports(queryClient: QueryClient) {
|
|
const organizationId = getCurrentOrganizationId();
|
|
if (!organizationId) return;
|
|
|
|
queryClient.prefetchQuery({
|
|
queryKey: ['reports', 1],
|
|
queryFn: () =>
|
|
api.getReports({
|
|
params: { organization: organizationId },
|
|
}),
|
|
staleTime: 30000,
|
|
});
|
|
}
|
|
|
|
function prefetchTimeEntries(queryClient: QueryClient) {
|
|
const organizationId = getCurrentOrganizationId();
|
|
const memberId = getCurrentMembershipId();
|
|
if (!organizationId) return;
|
|
|
|
queryClient.prefetchInfiniteQuery({
|
|
queryKey: ['timeEntries', 'infinite', { organizationId, memberId }],
|
|
queryFn: async () => {
|
|
const response = await api.getTimeEntries({
|
|
params: { organization: organizationId },
|
|
queries: {
|
|
only_full_dates: 'true',
|
|
member_id: memberId,
|
|
},
|
|
});
|
|
return response;
|
|
},
|
|
initialPageParam: undefined,
|
|
staleTime: 30000,
|
|
});
|
|
}
|
|
|
|
function prefetchProjectMembers(queryClient: QueryClient, projectId: string) {
|
|
const organizationId = getCurrentOrganizationId();
|
|
if (!organizationId || !canViewMembers()) return;
|
|
|
|
queryClient.prefetchQuery({
|
|
queryKey: ['projectMembers', projectId],
|
|
queryFn: () =>
|
|
api.getProjectMembers({
|
|
params: { organization: organizationId, project: projectId },
|
|
}),
|
|
staleTime: 30000,
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Matches a URL to find the appropriate prefetcher.
|
|
* Handles both exact matches and pattern matching for dynamic routes.
|
|
*/
|
|
function findPrefetcher(url: string): ((queryClient: QueryClient) => void) | undefined {
|
|
// Extract pathname from URL
|
|
const pathname = url.startsWith('http') ? new URL(url).pathname : url.split('?')[0];
|
|
|
|
// Try exact match first
|
|
if (routePrefetchers[pathname]) {
|
|
return routePrefetchers[pathname];
|
|
}
|
|
|
|
// Try pattern matching for dynamic routes like /projects/{id}
|
|
const projectMatch = pathname.match(/^\/projects\/([^/]+)$/);
|
|
if (projectMatch) {
|
|
const projectId = projectMatch[1];
|
|
return (queryClient) => {
|
|
prefetchProjects(queryClient);
|
|
prefetchTasks(queryClient);
|
|
prefetchProjectMembers(queryClient, projectId);
|
|
};
|
|
}
|
|
|
|
return undefined;
|
|
}
|
|
|
|
/**
|
|
* Sets up Inertia prefetch event listener to warm TanStack Query cache.
|
|
* Call this once during app initialization.
|
|
*/
|
|
export function setupPrefetching(queryClient: QueryClient) {
|
|
// Listen for the 'prefetching' event which fires when Inertia starts prefetching a page
|
|
// The event detail contains the visit object with the URL being prefetched
|
|
document.addEventListener('inertia:prefetching', ((event: CustomEvent) => {
|
|
const visit = event.detail?.visit;
|
|
if (!visit?.url) return;
|
|
|
|
const url = visit.url.href || visit.url.toString();
|
|
const prefetcher = findPrefetcher(url);
|
|
|
|
if (prefetcher) {
|
|
prefetcher(queryClient);
|
|
}
|
|
}) as EventListener);
|
|
}
|