Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | 1x 1x 1x 1x 1x 23x 23x 23x 23x 23x 23x 7x 5x 5x 5x 5x 8x 8x 8x 8x 8x 7x 1x 6x 2x 2x 5x 5x 5x 9x 5x 5x 7x 5x 2x 23x 11x 3x 11x 11x 11x 23x | import { useEffect, useState } from "react";
import { UserActivityLogItem } from "../types";
import { getClassActivityByClassId } from "../api/classes";
import { calculateProgress, ProgressData } from "../utils/calculateProgress";
import { UserClass } from "../api/types/user";
import { LogEvent } from "../api/types/event";
/**
* Custom hook to fetch and manage class activity logs.
* It fetches all activity logs for the provided classes and filters them based on the selected class ID.
* @param classes - Array of UserClass objects representing the classes to fetch activity for.
* @param selectedClassId - The ID of the selected class to filter activity logs by.
* @returns An object containing the following properties:
*/
export const useClassActivity = (
classes: UserClass[],
selectedClassId: string | null
) => {
const [allActivity, setAllActivity] = useState<UserActivityLogItem[]>([]);
const [classActivity, setClassActivity] = useState<UserActivityLogItem[]>([]);
const [progressData, setProgressData] = useState<ProgressData>({
totalAccepted: 0,
correctSuggestions: 0,
percentageCorrect: 0,
});
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
// Fetch all logs only once
useEffect(() => {
const fetchAllClassActivity = async () => {
try {
setError(null);
setLoading(true);
const classRequests = classes
.filter((classInfo) => classInfo.id !== "all")
.map(async (classInfo) => {
try {
const response = await getClassActivityByClassId(classInfo.id!);
if (response.error) throw new Error(response.error);
if (!Array.isArray(response.data)) {
throw new Error(
"Invalid response: expected an array of activity logs"
);
}
return response.data;
} catch (err) {
console.error(
`Failed to fetch for class ${classInfo.classTitle}`,
err
);
return [];
}
});
const allLogsArrays = await Promise.all(classRequests);
const allLogs = allLogsArrays.flat();
const validLogs = allLogs.filter(
(log) =>
log.event === LogEvent.USER_ACCEPT ||
log.event === LogEvent.USER_REJECT
);
setAllActivity(validLogs);
} catch (err) {
setError(err instanceof Error ? err.message : "Unknown error");
} finally {
setLoading(false);
}
};
if (classes.length > 0) {
fetchAllClassActivity();
} else {
setLoading(false);
}
}, [classes]);
// Filter logs by selected class
useEffect(() => {
const filtered =
selectedClassId && selectedClassId !== "all"
? allActivity.filter(
(log) => log.metadata.userClassId === selectedClassId
)
: allActivity;
setClassActivity(filtered);
const progress = calculateProgress(
selectedClassId === "all" ? allActivity : filtered
);
setProgressData(progress);
}, [selectedClassId, allActivity]);
return {
allActivity,
classActivity,
progressData,
loading,
error,
isEmpty: !loading && classActivity.length === 0,
};
};
|