From 3ae85d5e7db1d93da16de544d6483c5726b9b69e Mon Sep 17 00:00:00 2001 From: austinkelsay Date: Wed, 4 Dec 2024 19:33:44 -0600 Subject: [PATCH] Actvity chart for if github is not connected --- .../charts/ActivityContributionChart.js | 174 ++++++++++++++++++ src/components/profile/UserProfile.js | 3 +- 2 files changed, 176 insertions(+), 1 deletion(-) create mode 100644 src/components/charts/ActivityContributionChart.js diff --git a/src/components/charts/ActivityContributionChart.js b/src/components/charts/ActivityContributionChart.js new file mode 100644 index 0000000..37159c4 --- /dev/null +++ b/src/components/charts/ActivityContributionChart.js @@ -0,0 +1,174 @@ +import React, { useState, useCallback } from 'react'; +import { Tooltip } from 'primereact/tooltip'; +import { formatDateTime } from "@/utils/time"; + +const ActivityContributionChart = ({ session }) => { + const [contributionData, setContributionData] = useState({}); + const [totalActivities, setTotalActivities] = useState(0); + + // Prepare activity data + const prepareActivityData = useCallback(() => { + if (!session?.user?.userCourses) return {}; + + const activityData = {}; + const allActivities = []; + + // ... existing course activities processing ... + session.user.userCourses.forEach(courseProgress => { + if (courseProgress.started) { + const startDate = new Date(courseProgress.startedAt); + startDate.setFullYear(new Date().getFullYear()); + const date = startDate.toISOString().split('T')[0]; + activityData[date] = (activityData[date] || 0) + 1; + allActivities.push({ + type: 'course_started', + name: courseProgress.course?.name, + date: date + }); + } + // ... rest of the course processing ... + }); + + // ... existing lesson activities processing ... + session.user.userLessons?.forEach(lessonProgress => { + // ... lesson processing ... + }); + + setContributionData(activityData); + setTotalActivities(Object.values(activityData).reduce((a, b) => a + b, 0)); + + return activityData; + }, [session]); + + // Initialize data + React.useEffect(() => { + prepareActivityData(); + }, [prepareActivityData]); + + const getColor = useCallback((count) => { + if (count === 0) return 'bg-gray-100'; + if (count === 1) return 'bg-purple-300'; + if (count === 2) return 'bg-purple-400'; + if (count === 3) return 'bg-purple-600'; + return 'bg-purple-700'; + }, []); + + const generateCalendar = useCallback(() => { + const today = new Date(); + const oneYearAgo = new Date(today.getFullYear() - 1, today.getMonth(), today.getDate()); + const calendar = []; + + // Create 7 rows for days of the week + for (let i = 0; i < 7; i++) { + calendar[i] = []; + } + + // Fill in the dates + for (let d = new Date(oneYearAgo); d <= today; d.setDate(d.getDate() + 1)) { + const dateString = d.toISOString().split('T')[0]; + const activityCount = contributionData[dateString] || 0; + calendar[d.getDay()].push({ + date: new Date(d), + count: activityCount + }); + } + + return calendar; + }, [contributionData]); + + const getMonthLabels = useCallback(() => { + const today = new Date(); + const oneYearAgo = new Date(today.getFullYear() - 1, today.getMonth(), today.getDate()); + const months = []; + let currentMonth = -1; + const calendar = generateCalendar(); + + 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; + }, [generateCalendar]); + + const calendar = generateCalendar(); + const weekDays = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']; + + return ( +
+
+

+ {totalActivities} learning 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].count} activit${row[weekIndex].count !== 1 ? 'ies' : 'y'}` + : 'No activities' + }`} + >
+ ) + ))} +
+ ))} +
+ {/* Month labels */} +
+ {getMonthLabels().map((month, index) => ( +
+ {month.name} +
+ ))} +
+
+
+ {/* Legend */} +
+ Less +
+
+
+
+
+
+
+ More +
+
+ ); +}; + +export default ActivityContributionChart; diff --git a/src/components/profile/UserProfile.js b/src/components/profile/UserProfile.js index 70ed3c1..a59b2e3 100644 --- a/src/components/profile/UserProfile.js +++ b/src/components/profile/UserProfile.js @@ -9,6 +9,7 @@ import { nip19 } from "nostr-tools"; import Image from "next/image"; import CombinedContributionChart from "@/components/charts/CombinedContributionChart"; import GithubContributionChart from "@/components/charts/GithubContributionChart"; +import ActivityContributionChart from "@/components/charts/ActivityContributionChart"; import GithubContributionChartDisabled from "@/components/charts/GithubContributionChartDisabled"; import useCheckCourseProgress from "@/hooks/tracking/useCheckCourseProgress"; import useWindowWidth from "@/hooks/useWindowWidth"; @@ -135,7 +136,7 @@ const UserProfile = () => { {account && account?.provider === "github" ? ( ) : ( - + )}