Spaces:
Sleeping
Sleeping
| /** | |
| * Study Plan React Query hooks. | |
| */ | |
| import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; | |
| import * as studyPlansApi from '../api/study-plans'; | |
| import type { | |
| StudyPlanCreate, | |
| StudyPlanUpdate, | |
| StudyTopicCreate, | |
| StudyTopicUpdate, | |
| StudySessionCreate, | |
| StudySessionUpdate, | |
| PlanGenerationRequest, | |
| } from '../types/study-plan'; | |
| // ============ Query Keys ============ | |
| export const studyPlanKeys = { | |
| all: ['study-plans'] as const, | |
| lists: () => [...studyPlanKeys.all, 'list'] as const, | |
| list: (notebookId?: string) => [...studyPlanKeys.lists(), { notebookId }] as const, | |
| active: () => [...studyPlanKeys.all, 'active'] as const, | |
| details: () => [...studyPlanKeys.all, 'detail'] as const, | |
| detail: (planId: string) => [...studyPlanKeys.details(), planId] as const, | |
| stats: (planId: string) => [...studyPlanKeys.all, 'stats', planId] as const, | |
| schedule: (planId: string, weekStart?: string) => [...studyPlanKeys.all, 'schedule', planId, weekStart] as const, | |
| topics: (planId: string) => [...studyPlanKeys.all, 'topics', planId] as const, | |
| sessions: (planId: string) => [...studyPlanKeys.all, 'sessions', planId] as const, | |
| todaySessions: (planId?: string) => [...studyPlanKeys.all, 'today', planId] as const, | |
| adjustments: (planId: string) => [...studyPlanKeys.all, 'adjustments', planId] as const, | |
| }; | |
| // ============ Plan Hooks ============ | |
| export function useStudyPlans(notebookId?: string) { | |
| return useQuery({ | |
| queryKey: studyPlanKeys.list(notebookId), | |
| queryFn: () => studyPlansApi.getStudyPlans(notebookId), | |
| }); | |
| } | |
| export function useActivePlans() { | |
| return useQuery({ | |
| queryKey: studyPlanKeys.active(), | |
| queryFn: () => studyPlansApi.getStudyPlans(undefined, true), | |
| }); | |
| } | |
| export function useStudyPlan(planId: string) { | |
| return useQuery({ | |
| queryKey: studyPlanKeys.detail(planId), | |
| queryFn: () => studyPlansApi.getStudyPlan(planId), | |
| enabled: !!planId, | |
| }); | |
| } | |
| export function useStudyPlanStats(planId: string) { | |
| return useQuery({ | |
| queryKey: studyPlanKeys.stats(planId), | |
| queryFn: () => studyPlansApi.getStudyPlanStats(planId), | |
| enabled: !!planId, | |
| }); | |
| } | |
| export function useWeeklySchedule(planId: string, weekStart?: string) { | |
| return useQuery({ | |
| queryKey: studyPlanKeys.schedule(planId, weekStart), | |
| queryFn: () => studyPlansApi.getWeeklySchedule(planId, weekStart), | |
| enabled: !!planId, | |
| }); | |
| } | |
| export function useTodaySessions(planId?: string) { | |
| return useQuery({ | |
| queryKey: studyPlanKeys.todaySessions(planId), | |
| queryFn: () => studyPlansApi.getTodaySessions(planId), | |
| }); | |
| } | |
| export function useCreateStudyPlan() { | |
| const queryClient = useQueryClient(); | |
| return useMutation({ | |
| mutationFn: (data: StudyPlanCreate) => studyPlansApi.createStudyPlan(data), | |
| onSuccess: () => { | |
| queryClient.invalidateQueries({ queryKey: studyPlanKeys.all }); | |
| }, | |
| }); | |
| } | |
| export function useGenerateStudyPlan() { | |
| const queryClient = useQueryClient(); | |
| return useMutation({ | |
| mutationFn: (request: PlanGenerationRequest) => studyPlansApi.generateStudyPlan(request), | |
| onSuccess: () => { | |
| queryClient.invalidateQueries({ queryKey: studyPlanKeys.all }); | |
| }, | |
| }); | |
| } | |
| export function useUpdateStudyPlan() { | |
| const queryClient = useQueryClient(); | |
| return useMutation({ | |
| mutationFn: ({ planId, data }: { planId: string; data: StudyPlanUpdate }) => | |
| studyPlansApi.updateStudyPlan(planId, data), | |
| onSuccess: (_, { planId }) => { | |
| queryClient.invalidateQueries({ queryKey: studyPlanKeys.detail(planId) }); | |
| queryClient.invalidateQueries({ queryKey: studyPlanKeys.lists() }); | |
| }, | |
| }); | |
| } | |
| export function useDeleteStudyPlan() { | |
| const queryClient = useQueryClient(); | |
| return useMutation({ | |
| mutationFn: (planId: string) => studyPlansApi.deleteStudyPlan(planId), | |
| onSuccess: () => { | |
| queryClient.invalidateQueries({ queryKey: studyPlanKeys.all }); | |
| }, | |
| }); | |
| } | |
| // ============ Topic Hooks ============ | |
| export function useTopics(planId: string) { | |
| return useQuery({ | |
| queryKey: studyPlanKeys.topics(planId), | |
| queryFn: () => studyPlansApi.getTopics(planId), | |
| enabled: !!planId, | |
| }); | |
| } | |
| export function useCreateTopic() { | |
| const queryClient = useQueryClient(); | |
| return useMutation({ | |
| mutationFn: ({ planId, data }: { planId: string; data: StudyTopicCreate }) => | |
| studyPlansApi.createTopic(planId, data), | |
| onSuccess: (_, { planId }) => { | |
| queryClient.invalidateQueries({ queryKey: studyPlanKeys.topics(planId) }); | |
| queryClient.invalidateQueries({ queryKey: studyPlanKeys.detail(planId) }); | |
| }, | |
| }); | |
| } | |
| export function useUpdateTopic() { | |
| const queryClient = useQueryClient(); | |
| return useMutation({ | |
| mutationFn: ({ topicId, data, planId }: { topicId: string; data: StudyTopicUpdate; planId: string }) => | |
| studyPlansApi.updateTopic(topicId, data), | |
| onSuccess: (_, { planId }) => { | |
| queryClient.invalidateQueries({ queryKey: studyPlanKeys.topics(planId) }); | |
| queryClient.invalidateQueries({ queryKey: studyPlanKeys.detail(planId) }); | |
| }, | |
| }); | |
| } | |
| export function useDeleteTopic() { | |
| const queryClient = useQueryClient(); | |
| return useMutation({ | |
| mutationFn: ({ topicId, planId }: { topicId: string; planId: string }) => | |
| studyPlansApi.deleteTopic(topicId), | |
| onSuccess: (_, { planId }) => { | |
| queryClient.invalidateQueries({ queryKey: studyPlanKeys.topics(planId) }); | |
| queryClient.invalidateQueries({ queryKey: studyPlanKeys.detail(planId) }); | |
| }, | |
| }); | |
| } | |
| // ============ Session Hooks ============ | |
| export function useSessions(planId: string) { | |
| return useQuery({ | |
| queryKey: studyPlanKeys.sessions(planId), | |
| queryFn: () => studyPlansApi.getSessions(planId), | |
| enabled: !!planId, | |
| }); | |
| } | |
| export function useCreateSession() { | |
| const queryClient = useQueryClient(); | |
| return useMutation({ | |
| mutationFn: ({ planId, data }: { planId: string; data: StudySessionCreate }) => | |
| studyPlansApi.createSession(planId, data), | |
| onSuccess: (_, { planId }) => { | |
| queryClient.invalidateQueries({ queryKey: studyPlanKeys.sessions(planId) }); | |
| queryClient.invalidateQueries({ queryKey: studyPlanKeys.detail(planId) }); | |
| queryClient.invalidateQueries({ queryKey: studyPlanKeys.todaySessions() }); | |
| }, | |
| }); | |
| } | |
| export function useUpdateSession() { | |
| const queryClient = useQueryClient(); | |
| return useMutation({ | |
| mutationFn: ({ sessionId, data, planId }: { sessionId: string; data: StudySessionUpdate; planId: string }) => | |
| studyPlansApi.updateSession(sessionId, data), | |
| onSuccess: (_, { planId }) => { | |
| queryClient.invalidateQueries({ queryKey: studyPlanKeys.sessions(planId) }); | |
| queryClient.invalidateQueries({ queryKey: studyPlanKeys.detail(planId) }); | |
| queryClient.invalidateQueries({ queryKey: studyPlanKeys.todaySessions() }); | |
| }, | |
| }); | |
| } | |
| export function useStartSession() { | |
| const queryClient = useQueryClient(); | |
| return useMutation({ | |
| mutationFn: ({ sessionId, planId }: { sessionId: string; planId: string }) => | |
| studyPlansApi.startSession(sessionId), | |
| onSuccess: (_, { planId }) => { | |
| queryClient.invalidateQueries({ queryKey: studyPlanKeys.sessions(planId) }); | |
| queryClient.invalidateQueries({ queryKey: studyPlanKeys.detail(planId) }); | |
| queryClient.invalidateQueries({ queryKey: studyPlanKeys.todaySessions() }); | |
| }, | |
| }); | |
| } | |
| export function useCompleteSession() { | |
| const queryClient = useQueryClient(); | |
| return useMutation({ | |
| mutationFn: async ({ sessionId, planId, rating, notes }: { | |
| sessionId: string; | |
| planId: string; | |
| rating?: number; | |
| notes?: string | |
| }) => { | |
| console.log('[useCompleteSession] Calling API with:', { sessionId, planId, rating, notes }); | |
| const result = await studyPlansApi.completeSession(sessionId, rating, notes); | |
| console.log('[useCompleteSession] API returned:', result); | |
| return result; | |
| }, | |
| onSuccess: (data, { planId }) => { | |
| console.log('[useCompleteSession] onSuccess - invalidating queries for planId:', planId); | |
| console.log('[useCompleteSession] Session data after completion:', data); | |
| queryClient.invalidateQueries({ queryKey: studyPlanKeys.sessions(planId) }); | |
| queryClient.invalidateQueries({ queryKey: studyPlanKeys.detail(planId) }); | |
| queryClient.invalidateQueries({ queryKey: studyPlanKeys.stats(planId) }); | |
| queryClient.invalidateQueries({ queryKey: studyPlanKeys.todaySessions() }); | |
| // Also invalidate the active plans list so progress % updates in the tab buttons | |
| queryClient.invalidateQueries({ queryKey: studyPlanKeys.active() }); | |
| console.log('[useCompleteSession] All queries invalidated'); | |
| }, | |
| onError: (error) => { | |
| console.error('[useCompleteSession] Error:', error); | |
| }, | |
| }); | |
| } | |
| export function useDeleteSession() { | |
| const queryClient = useQueryClient(); | |
| return useMutation({ | |
| mutationFn: ({ sessionId, planId }: { sessionId: string; planId: string }) => | |
| studyPlansApi.deleteSession(sessionId), | |
| onSuccess: (_, { planId }) => { | |
| queryClient.invalidateQueries({ queryKey: studyPlanKeys.sessions(planId) }); | |
| queryClient.invalidateQueries({ queryKey: studyPlanKeys.detail(planId) }); | |
| queryClient.invalidateQueries({ queryKey: studyPlanKeys.todaySessions() }); | |
| }, | |
| }); | |
| } | |
| export function useSkipSession() { | |
| const queryClient = useQueryClient(); | |
| return useMutation({ | |
| mutationFn: ({ sessionId, planId, reason }: { sessionId: string; planId: string; reason?: string }) => | |
| studyPlansApi.skipSession(sessionId, reason), | |
| onSuccess: (_, { planId }) => { | |
| queryClient.invalidateQueries({ queryKey: studyPlanKeys.sessions(planId) }); | |
| queryClient.invalidateQueries({ queryKey: studyPlanKeys.detail(planId) }); | |
| queryClient.invalidateQueries({ queryKey: studyPlanKeys.stats(planId) }); | |
| queryClient.invalidateQueries({ queryKey: studyPlanKeys.todaySessions() }); | |
| }, | |
| }); | |
| } | |
| // ============ Adjustment Hooks ============ | |
| export function useAdjustments(planId: string) { | |
| return useQuery({ | |
| queryKey: studyPlanKeys.adjustments(planId), | |
| queryFn: () => studyPlansApi.getAdjustments(planId), | |
| enabled: !!planId, | |
| }); | |
| } | |
| export function useRespondToAdjustment() { | |
| const queryClient = useQueryClient(); | |
| return useMutation({ | |
| mutationFn: ({ adjustmentId, accepted, planId }: { adjustmentId: string; accepted: boolean; planId: string }) => | |
| studyPlansApi.respondToAdjustment(adjustmentId, accepted), | |
| onSuccess: (_, { planId }) => { | |
| queryClient.invalidateQueries({ queryKey: studyPlanKeys.adjustments(planId) }); | |
| queryClient.invalidateQueries({ queryKey: studyPlanKeys.detail(planId) }); | |
| }, | |
| }); | |
| } | |