Files
donetick/src/views/components/CalendarDual.jsx

173 lines
5.0 KiB
JavaScript

import { Box, Typography } from '@mui/joy'
import { useEffect, useState } from 'react'
import Calendar from 'react-calendar'
import { useNavigate } from 'react-router-dom'
import { useCircleMembers, useUserProfile } from '../../queries/UserQueries'
import { getPriorityColor, TASK_COLOR } from '../../utils/Colors'
import styles from './CalendarDual.module.css'
const getAssigneeColor = (assignee, userProfile) => {
return assignee === userProfile.id
? TASK_COLOR.ASSIGNED_TO_ME
: TASK_COLOR.ASSIGNED_TO_OTHER
}
const CalendarDual = ({ chores, onDateChange }) => {
const { data: userProfile } = useUserProfile()
const [selectedDate, setSeletedDate] = useState(null)
const [currentDate, setCurrentDate] = useState(new Date())
const [nextMonth, setNextMonth] = useState(() => {
const next = new Date()
next.setMonth(next.getMonth() + 1)
return next
})
const Navigate = useNavigate()
// Fetch circle members data to get assignee names
const { data: circleMembersData } = useCircleMembers()
const circleMembers = circleMembersData?.res || []
// Update next month whenever current date changes
useEffect(() => {
const next = new Date(currentDate.getTime())
next.setMonth(currentDate.getMonth() + 1)
setNextMonth(next)
}, [currentDate])
// Helper function to get assignee display name
const getAssigneeName = assignedTo => {
if (assignedTo === userProfile.id) {
return userProfile.displayName
}
const assignee = circleMembers.find(member => member.userId === assignedTo)
return assignee ? `${assignee.displayName}` : 'Assigned to other'
}
const tileContent = ({ date, view }) => {
if (view === 'month') {
const dayChores = chores.filter(chore => {
const choreDate = new Date(chore.nextDueDate).toLocaleDateString()
const tileDate = date.toLocaleDateString()
return choreDate === tileDate
})
if (dayChores.length === 0) {
return (
<div className={styles.dotContainer}>
<span className={styles.dotEmpty}></span>
</div>
)
}
if (dayChores.length > 3) {
return (
<div className={styles.dotContainer}>
<span
className={styles.dotWithLine}
style={{
backgroundColor: getPriorityColor(dayChores[0].priority),
}}
></span>
</div>
)
}
return (
<div className={styles.dotContainer}>
{dayChores.map((chore, index) => {
return (
<span
key={index}
className={styles.dot}
style={{
backgroundColor: getPriorityColor(chore.priority),
}}
></span>
)
})}
</div>
)
}
return null
}
const renderSingleCalendar = (date, isSecondary = false) => (
<div
className={`${styles.reactCalendar} ${isSecondary ? styles.secondaryCalendar : ''}`}
>
{isSecondary && (
<div className={styles.secondaryCalendarHeader}>
<Typography level='title-md' sx={{ textAlign: 'center', mb: 1 }}>
{date.toLocaleDateString('en-US', {
month: 'long',
year: 'numeric',
})}
</Typography>
</div>
)}
<Calendar
className={styles.reactCalendar}
tileContent={tileContent}
onChange={d => {
let date = new Date(d)
setSeletedDate(date)
onDateChange(date)
}}
value={selectedDate}
activeStartDate={date}
// Don't show navigation on secondary calendar
showNavigation={!isSecondary}
// format the days from MON, TUE, WED, THU, FRI, SAT, SUN to first three letters:
formatShortWeekday={(locale, date) =>
['S', 'M', 'T', 'W', 'T', 'F', 'S'][date.getDay()]
}
onActiveStartDateChange={({ activeStartDate }) => {
if (!isSecondary) {
setCurrentDate(activeStartDate)
}
}}
/>
</div>
)
return (
<div
style={{
width: '100%',
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
}}
>
{/* Responsive Calendar Layout */}
<Box
sx={{
width: '100%',
display: 'flex',
flexDirection: { xs: 'column', md: 'row' },
gap: { xs: 2, md: 4 },
justifyContent: 'center',
alignItems: { xs: 'center', md: 'flex-start' },
}}
>
{/* Primary Calendar */}
<Box sx={{ flex: 1, display: 'flex', justifyContent: 'center' }}>
{renderSingleCalendar(currentDate)}
</Box>
{/* Secondary Calendar - only show on desktop */}
<Box
sx={{
flex: 1,
display: { xs: 'none', md: 'flex' },
justifyContent: 'center',
}}
>
{renderSingleCalendar(nextMonth, true)}
</Box>
</Box>
</div>
)
}
export default CalendarDual