use-calendar-tasks.ts2.5 KBView on GitHub
/**
 * Hook to fetch tasks for the calendar view
 *
 * This hook fetches 'todo' tasks for a specific week (Monday to Sunday)
 * based on the calendar's current week view.
 */

import type { HydratedUserTask } from '@/modules/userTasks/slice/userTasksSlice';
import { useTRPC } from '@/providers/query-provider';
import { useQuery } from '@tanstack/react-query';
import { useMemo } from 'react';

interface UseCalendarTasksOptions {
  /** The start date of the week (Monday) */
  weekStartDate: Date;
  /** Whether the hook is enabled */
  enabled?: boolean;
}

interface UseCalendarTasksResult {
  /** Tasks for the week */
  tasks: HydratedUserTask[];
  /** Whether tasks are currently loading */
  isLoading: boolean;
  /** Whether an error occurred */
  isError: boolean;
  /** The error if one occurred — a tRPC client error, which is shaped but not an `Error` */
  error: { message: string } | null;
  /** Refetch the tasks */
  refetch: () => void;
}

/**
 * Get date range for a week (Monday 00:00:00 to Sunday 23:59:59)
 */
function getWeekDateRange(weekStart: Date) {
  const startOfWeek = new Date(weekStart);
  startOfWeek.setHours(0, 0, 0, 0);

  const endOfWeek = new Date(weekStart);
  endOfWeek.setDate(weekStart.getDate() + 6); // Sunday
  endOfWeek.setHours(23, 59, 59, 999);

  return {
    dueDateAfter: startOfWeek.toISOString(),
    dueDateBefore: endOfWeek.toISOString(),
  };
}

export function useCalendarTasks({
  weekStartDate,
  enabled = true,
}: UseCalendarTasksOptions): UseCalendarTasksResult {
  const trpc = useTRPC();

  // Calculate the week range
  const weekRange = useMemo(() => getWeekDateRange(weekStartDate), [weekStartDate]);

  // Fetch tasks for the week
  const tasksQuery = useQuery({
    ...trpc.userTasks.listUserTasks.queryOptions(
      {
        status: 'todo',
        includeLabels: true,
        dueDateAfter: weekRange.dueDateAfter,
        dueDateBefore: weekRange.dueDateBefore,
        limit: 100,
      },
      {
        staleTime: 30 * 1000,
        refetchOnWindowFocus: true,
        refetchInterval: 1000 * 60 * 5,
      },
    ),
    enabled,
  });

  // Extract tasks from query
  const tasks = useMemo(() => {
    const queryTasks = tasksQuery.data?.tasks as HydratedUserTask[] | undefined;
    if (!queryTasks) return [];
    return queryTasks.filter((t) => t.status === 'todo');
  }, [tasksQuery.data?.tasks]);

  return {
    tasks,
    isLoading: tasksQuery.isLoading,
    isError: tasksQuery.isError,
    error: tasksQuery.error,
    refetch: tasksQuery.refetch,
  };
}