import { Bar, BarChart, CartesianGrid, ResponsiveContainer, XAxis, YAxis, } from 'recharts' import { CreditCard, Toll } from '@mui/icons-material' import { Avatar, Box, Button, Card, Chip, Container, Option, Select, Tab, TabList, Tabs, Typography, } from '@mui/joy' import { useContext, useEffect, useState } from 'react' import { UserContext } from '../../contexts/UserContext.js' import LoadingComponent from '../components/Loading.jsx' import { useChoresHistory } from '../../queries/ChoreQueries.jsx' import { useCircleMembers } from '../../queries/UserQueries.jsx' import { RedeemPoints } from '../../utils/Fetcher.jsx' import { resolvePhotoURL } from '../../utils/Helpers.jsx' import RedeemPointsModal from '../Modals/RedeemPointsModal' const UserPoints = () => { const [tabValue, setTabValue] = useState(7) const [isRedeemModalOpen, setIsRedeemModalOpen] = useState(false) const { data: circleMembersData, isLoading: isCircleMembersLoading, handleRefetch: handleCircleMembersRefetch, } = useCircleMembers() const { data: choresHistoryData, isLoading: isChoresHistoryLoading, handleLimitChange: handleChoresHistoryLimitChange, } = useChoresHistory(7) const { userProfile } = useContext(UserContext) const [selectedUser, setSelectedUser] = useState(userProfile?.id) const [circleUsers, setCircleUsers] = useState([]) const [selectedHistory, setSelectedHistory] = useState([]) const [userPointsBarChartData, setUserPointsBarChartData] = useState([]) const [choresHistory, setChoresHistory] = useState([]) useEffect(() => { if (circleMembersData && choresHistoryData && userProfile) { setCircleUsers(circleMembersData.res) setSelectedHistory(generateWeeklySummary(choresHistory, userProfile?.id)) } }, [circleMembersData, choresHistoryData]) useEffect(() => { if (choresHistoryData) { var history if (tabValue === 7) { history = generateWeeklySummary(choresHistoryData, selectedUser) } else if (tabValue === 30) { history = generateMonthSummary(choresHistoryData, selectedUser) } else if (tabValue === 6 * 30) { history = generateMonthlySummary(choresHistoryData, selectedUser) } else { history = generateYearlySummary(choresHistoryData, selectedUser) } setSelectedHistory(history) } }, [selectedUser, choresHistoryData]) useEffect(() => { setSelectedUser(userProfile?.id) }, [userProfile]) const generateUserPointsHistory = history => { const userPoints = {} for (let i = 0; i < history.length; i++) { const chore = history[i] if (!userPoints[chore.completedBy]) { userPoints[chore.completedBy] = chore.points ? chore.points : 0 } else { userPoints[chore.completedBy] += chore.points ? chore.points : 0 } } return userPoints } const generateWeeklySummary = (history, userId) => { const daysAggregated = [] for (let i = 6; i > -1; i--) { const currentDate = new Date() currentDate.setDate(currentDate.getDate() - i) daysAggregated.push({ label: currentDate.toLocaleString('en-US', { weekday: 'short' }), points: 0, tasks: 0, }) } history.forEach(chore => { const dayName = new Date(chore.completedAt).toLocaleString('en-US', { weekday: 'short', }) const dayIndex = daysAggregated.findIndex(dayData => { if (userId) return dayData.label === dayName && chore.completedBy === userId return dayData.label === dayName }) if (dayIndex !== -1) { if (chore.points) daysAggregated[dayIndex].points += chore.points daysAggregated[dayIndex].tasks += 1 } }) return daysAggregated } const generateMonthSummary = (history, userId) => { const daysAggregated = [] for (let i = 29; i > -1; i--) { const currentDate = new Date() currentDate.setDate(currentDate.getDate() - i) daysAggregated.push({ label: currentDate.toLocaleString('en-US', { day: 'numeric' }), points: 0, tasks: 0, }) } history.forEach(chore => { const dayName = new Date(chore.completedAt).toLocaleString('en-US', { day: 'numeric', }) const dayIndex = daysAggregated.findIndex(dayData => { if (userId) return dayData.label === dayName && chore.completedBy === userId return dayData.label === dayName }) if (dayIndex !== -1) { if (chore.points) daysAggregated[dayIndex].points += chore.points daysAggregated[dayIndex].tasks += 1 } }) return daysAggregated } const generateMonthlySummary = (history, userId) => { const monthlyAggregated = [] for (let i = 5; i > -1; i--) { const currentMonth = new Date() currentMonth.setMonth(currentMonth.getMonth() - i) monthlyAggregated.push({ label: currentMonth.toLocaleString('en-US', { month: 'short' }), points: 0, tasks: 0, }) } history.forEach(chore => { const monthName = new Date(chore.completedAt).toLocaleString('en-US', { month: 'short', }) const monthIndex = monthlyAggregated.findIndex(monthData => { if (userId) return monthData.label === monthName && chore.completedBy === userId return monthData.label === monthName }) if (monthIndex !== -1) { if (chore.points) monthlyAggregated[monthIndex].points += chore.points monthlyAggregated[monthIndex].tasks += 1 } }) return monthlyAggregated } const generateYearlySummary = (history, userId) => { const yearlyAggregated = [] for (let i = 11; i > -1; i--) { const currentYear = new Date() currentYear.setFullYear(currentYear.getFullYear() - i) yearlyAggregated.push({ label: currentYear.toLocaleString('en-US', { year: 'numeric' }), points: 0, tasks: 0, }) } history.forEach(chore => { const yearName = new Date(chore.completedAt).toLocaleString('en-US', { year: 'numeric', }) const yearIndex = yearlyAggregated.findIndex(yearData => { if (userId) return yearData.label === yearName && chore.completedBy === userId return yearData.label === yearName }) if (yearIndex !== -1) { if (chore.points) yearlyAggregated[yearIndex].points += chore.points yearlyAggregated[yearIndex].tasks += 1 } }) return yearlyAggregated } if (isChoresHistoryLoading || isCircleMembersLoading || !userProfile) { return } return ( Points Overview {circleUsers.find(user => user.userId === userProfile.id)?.role === 'admin' && ( )} {[ { title: 'Total', value: circleMembersData.res.find( user => user.userId === selectedUser, )?.points, color: 'primary', }, { title: 'Available', value: (function () { const user = circleMembersData.res.find( user => user.userId === selectedUser, ) if (!user) return 0 return user.points - user.pointsRedeemed })(), color: 'success', }, { title: 'Redeemed', value: circleMembersData.res.find( user => user.userId === selectedUser, )?.pointsRedeemed, color: 'warning', }, ].map(card => ( {card.title} {card.value} ))} Points History { setTabValue(tabValue) handleChoresHistoryLimitChange(tabValue) }} defaultValue={tabValue} sx={{ py: 0.5, borderRadius: 16, maxWidth: 400, mb: 1, }} > {[ { label: '7 Days', value: 7 }, // { label: '3 Month', value: 30 }, { label: '6 Months', value: 6 * 30 }, { label: 'All Time', value: 24 * 30 }, ].map((tab, index) => ( {tab.label} ))} {[ { title: 'Points', value: selectedHistory.reduce((acc, cur) => acc + cur.points, 0), color: 'success', }, { title: 'Tasks', value: selectedHistory.reduce((acc, cur) => acc + cur.tasks, 0), color: 'primary', }, ].map(card => ( {card.title} {card.value} ))} {/* Bar Chart for points overtime : */} {/* Rounded top corners, blue fill, set bar width */} {/* Add a slightly darker top section to the 'Jul' bar */} { setIsRedeemModalOpen(false) }, isOpen: isRedeemModalOpen, available: circleUsers.find(user => user.userId === selectedUser) ?.points, user: circleUsers.find(user => user.userId === selectedUser), onSave: ({ userId, points }) => { RedeemPoints(userId, points, userProfile.circleID) .then(res => { setIsRedeemModalOpen(false) handleCircleMembersRefetch() }) .catch(err => { console.log(err) }) }, }} /> ) } export default UserPoints