life-manager/codebase/features/learning/frontend/useLearning.ts
2026-03-17 17:51:06 -07:00

150 lines
4.5 KiB
TypeScript

import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import type { UseQueryResult, UseMutationResult } from '@tanstack/react-query';
import { apiClient } from '@/lib/api';
import type { PaginatedResponse } from '@life-platform/shared';
import type {
LearningPath, Lesson, LessonProgress, ReviewLog,
LearningDueResponse, LearningPathStats,
CreateLearningPathDto, UpdateLearningPathDto,
RecordReviewDto,
LearningPathFilters, LessonFilters,
} from '@life-platform/shared';
export function useLearningPaths(
params?: LearningPathFilters,
): UseQueryResult<PaginatedResponse<LearningPath>> {
return useQuery({
queryKey: ['learning', 'paths', params],
queryFn: () =>
apiClient
.get<PaginatedResponse<LearningPath>>('/learning/paths', { params })
.then((r) => r.data),
});
}
export function useLearningPath(id: string): UseQueryResult<LearningPath> {
return useQuery({
queryKey: ['learning', 'paths', id],
queryFn: () =>
apiClient.get<LearningPath>(`/learning/paths/${id}`).then((r) => r.data),
enabled: !!id,
});
}
export function useLearningPathStats(id: string): UseQueryResult<LearningPathStats> {
return useQuery({
queryKey: ['learning', 'paths', id, 'stats'],
queryFn: () =>
apiClient.get<LearningPathStats>(`/learning/paths/${id}/stats`).then((r) => r.data),
enabled: !!id,
});
}
export function useAllPathStats(): UseQueryResult<LearningPathStats[]> {
return useQuery({
queryKey: ['learning', 'stats'],
queryFn: () =>
apiClient.get<LearningPathStats[]>('/learning/stats').then((r) => r.data),
});
}
export function useLearningDue(limit?: number): UseQueryResult<LearningDueResponse> {
return useQuery({
queryKey: ['learning', 'due', limit],
queryFn: () =>
apiClient
.get<LearningDueResponse>('/learning/due', { params: limit ? { limit } : undefined })
.then((r) => r.data),
refetchInterval: 60_000,
});
}
export function usePathLessons(
pathId: string,
params?: LessonFilters,
): UseQueryResult<PaginatedResponse<Lesson>> {
return useQuery({
queryKey: ['learning', 'paths', pathId, 'lessons', params],
queryFn: () =>
apiClient
.get<PaginatedResponse<Lesson>>(`/learning/paths/${pathId}/lessons`, { params })
.then((r) => r.data),
enabled: !!pathId,
});
}
export function useLesson(id: string): UseQueryResult<Lesson> {
return useQuery({
queryKey: ['learning', 'lessons', id],
queryFn: () =>
apiClient.get<Lesson>(`/learning/lessons/${id}`).then((r) => r.data),
enabled: !!id,
});
}
export function useCreateLearningPath(): UseMutationResult<
LearningPath,
Error,
CreateLearningPathDto
> {
const qc = useQueryClient();
return useMutation({
mutationFn: (data: CreateLearningPathDto) =>
apiClient.post<LearningPath>('/learning/paths', data).then((r) => r.data),
onSuccess: () => {
qc.invalidateQueries({ queryKey: ['learning'] });
},
});
}
export function useUpdateLearningPath(): UseMutationResult<
LearningPath,
Error,
{ id: string; data: UpdateLearningPathDto }
> {
const qc = useQueryClient();
return useMutation({
mutationFn: ({ id, data }: { id: string; data: UpdateLearningPathDto }) =>
apiClient.patch<LearningPath>(`/learning/paths/${id}`, data).then((r) => r.data),
onSuccess: () => {
qc.invalidateQueries({ queryKey: ['learning'] });
},
});
}
export function useDeleteLearningPath(): UseMutationResult<unknown, Error, string> {
const qc = useQueryClient();
return useMutation({
mutationFn: (id: string) =>
apiClient.delete(`/learning/paths/${id}`).then((r) => r.data),
onSuccess: () => {
qc.invalidateQueries({ queryKey: ['learning'] });
},
});
}
export function useRecordReview(): UseMutationResult<
LessonProgress,
Error,
{ lessonId: string; data: RecordReviewDto }
> {
const qc = useQueryClient();
return useMutation({
mutationFn: ({ lessonId, data }: { lessonId: string; data: RecordReviewDto }) =>
apiClient
.post<LessonProgress>(`/learning/lessons/${lessonId}/review`, data)
.then((r) => r.data),
onSuccess: () => {
qc.invalidateQueries({ queryKey: ['learning'] });
},
});
}
export function useReviewHistory(lessonId: string): UseQueryResult<ReviewLog[]> {
return useQuery({
queryKey: ['learning', 'lessons', lessonId, 'reviews'],
queryFn: () =>
apiClient.get<ReviewLog[]>(`/learning/lessons/${lessonId}/reviews`).then((r) => r.data),
enabled: !!lessonId,
});
}