import React, { useState, useCallback, useEffect } from 'react'; import { useFetchGithubCommits } from '@/hooks/githubQueries/useFetchGithubCommits'; import { Tooltip } from 'primereact/tooltip'; import { formatDateTime } from "@/utils/time"; const CombinedContributionChart = ({ username, session }) => { const [contributionData, setContributionData] = useState({}); const [totalContributions, setTotalContributions] = useState(0); const prepareProgressData = useCallback(() => { if (!session?.user?.userCourses) return {}; const activityData = {}; const allActivities = []; // Array to store all activities for logging // Process course activities session.user.userCourses.forEach(courseProgress => { if (courseProgress.started) { const startDate = new Date(courseProgress.startedAt); const date = new Date(startDate.getTime() - startDate.getTimezoneOffset() * 60000) .toLocaleDateString('en-CA'); activityData[date] = (activityData[date] || 0) + 1; allActivities.push({ type: 'course_started', name: courseProgress.course?.name, date: date }); } if (courseProgress.completed) { const completeDate = new Date(courseProgress.completedAt); const date = new Date(completeDate.getTime() - completeDate.getTimezoneOffset() * 60000) .toLocaleDateString('en-CA'); activityData[date] = (activityData[date] || 0) + 1; allActivities.push({ type: 'course_completed', name: courseProgress.course?.name, date: date }); } }); // Process lesson activities session.user.userLessons?.forEach(lessonProgress => { if (lessonProgress.opened) { const openDate = new Date(lessonProgress.openedAt); const date = new Date(openDate.getTime() - openDate.getTimezoneOffset() * 60000) .toLocaleDateString('en-CA'); activityData[date] = (activityData[date] || 0) + 1; allActivities.push({ type: 'lesson_started', name: lessonProgress.lesson?.name, date: date }); } if (lessonProgress.completed) { const completeDate = new Date(lessonProgress.completedAt); const date = new Date(completeDate.getTime() - completeDate.getTimezoneOffset() * 60000) .toLocaleDateString('en-CA'); activityData[date] = (activityData[date] || 0) + 1; allActivities.push({ type: 'lesson_completed', name: lessonProgress.lesson?.name, date: date }); } }); console.log('All Learning Activities:', allActivities); console.log('Activities by Date:', activityData); return activityData; }, [session]); const handleNewCommit = useCallback(({ contributionData, totalCommits }) => { const activityData = prepareProgressData(); console.log("GitHub Contribution Data:", contributionData); // Create a new object with GitHub commits const combinedData = { ...contributionData }; // Add activities to the combined data Object.entries(activityData).forEach(([date, count]) => { combinedData[date] = (combinedData[date] || 0) + count; }); console.log("Combined Data:", combinedData); setContributionData(combinedData); setTotalContributions(totalCommits + Object.values(activityData).reduce((a, b) => a + b, 0)); }, [prepareProgressData]); const { data, isLoading, isFetching } = useFetchGithubCommits(username, handleNewCommit); // Initialize from cached data if available useEffect(() => { if (data && !isLoading) { const activityData = prepareProgressData(); const combinedData = { ...data.contributionData }; // Add activities to the combined data Object.entries(activityData).forEach(([date, count]) => { combinedData[date] = (combinedData[date] || 0) + count; }); setContributionData(combinedData); setTotalContributions(data.totalCommits + Object.values(activityData).reduce((a, b) => a + b, 0)); } }, [data, isLoading, prepareProgressData]); const getColor = useCallback((count) => { if (count === 0) return 'bg-gray-100'; if (count < 3) return 'bg-green-300'; if (count < 6) return 'bg-green-400'; if (count < 12) return 'bg-green-600'; return 'bg-green-700'; }, []); const generateCalendar = useCallback(() => { const today = new Date(); today.setHours(23, 59, 59, 999); // Calculate the start date (52 weeks + remaining days to today) const oneYearAgo = new Date(today); oneYearAgo.setDate(today.getDate() - 364); // 52 weeks * 7 days = 364 days // Start from the first Sunday before or on oneYearAgo const startDate = new Date(oneYearAgo); startDate.setDate(startDate.getDate() - startDate.getDay()); const calendar = []; // Create 7 rows for days of the week (Sunday to Saturday) for (let i = 0; i < 7; i++) { calendar[i] = []; } // Fill in the dates by week columns let currentDate = new Date(startDate); while (currentDate <= today) { const weekDay = currentDate.getDay(); const dateString = currentDate.toLocaleDateString('en-CA'); const githubCount = data?.contributionData[dateString] || 0; const activityCount = (contributionData[dateString] || 0) - (data?.contributionData[dateString] || 0); const totalCount = githubCount + activityCount; calendar[weekDay].push({ date: new Date(currentDate), count: totalCount, githubCount, activityCount }); currentDate.setDate(currentDate.getDate() + 1); } return calendar; }, [contributionData, data?.contributionData]); const calendar = generateCalendar(); const weekDays = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']; const getMonthLabels = useCallback(() => { const today = new Date(); const oneYearAgo = new Date(today); oneYearAgo.setFullYear(today.getFullYear() - 1); oneYearAgo.setDate(today.getDate() + 1); const months = []; let currentMonth = -1; for (let d = new Date(oneYearAgo); d <= today; d.setDate(d.getDate() + 1)) { const month = d.getMonth(); if (month !== currentMonth) { months.push({ name: d.toLocaleString('default', { month: 'short' }), index: calendar[0].findIndex( (_, weekIndex) => calendar[0][weekIndex]?.date.getMonth() === month ) }); currentMonth = month; } } return months; }, [calendar]); return (
{(isLoading || isFetching) &&

Loading contribution data... ({totalContributions} total contributions / activities fetched)

} {!isLoading && !isFetching &&

{totalContributions} total contributions / activities in the last year

}
{/* Days of week labels */}
{weekDays.map((day, index) => (
{index % 2 === 0 && day}
))}
{/* Calendar grid */}
{calendar[0].map((_, weekIndex) => (
{calendar.map((row, dayIndex) => ( row[weekIndex] && (
0 ? `${row[weekIndex].githubCount} contribution${row[weekIndex].githubCount !== 1 ? 's' : ''}` : '', row[weekIndex].activityCount > 0 ? `${row[weekIndex].activityCount} activit${row[weekIndex].activityCount !== 1 ? 'ies' : 'y'}` : '' ].filter(Boolean).join(' & ') || 'No contributions or activities' }`} >
) ))}
))}
{/* Month labels moved to bottom */}
{getMonthLabels().map((month, index) => (
{month.name}
))}
Less
More
); }; export default CombinedContributionChart;