diff --git a/src/queries/UserQueries.jsx b/src/queries/UserQueries.jsx
index 30dd203..d5f2d56 100644
--- a/src/queries/UserQueries.jsx
+++ b/src/queries/UserQueries.jsx
@@ -1,3 +1,4 @@
+import { useState } from 'react'
import { useQuery } from 'react-query'
import { GetAllCircleMembers, GetAllUsers } from '../utils/Fetcher'
@@ -6,5 +7,16 @@ export const useAllUsers = () => {
}
export const useCircleMembers = () => {
- return useQuery('allCircleMembers', GetAllCircleMembers)
+ const [refetchKey, setRefetchKey] = useState(0)
+
+ const { data, error, isLoading, refetch } = useQuery(
+ ['allCircleMembers', refetchKey],
+ GetAllCircleMembers,
+ )
+ const handleRefetch = () => {
+ setRefetchKey(prevKey => prevKey + 1)
+ refetch()
+ }
+
+ return { data, error, isLoading, handleRefetch }
}
diff --git a/src/views/Chores/Sidepanel.jsx b/src/views/Chores/Sidepanel.jsx
new file mode 100644
index 0000000..e5947c0
--- /dev/null
+++ b/src/views/Chores/Sidepanel.jsx
@@ -0,0 +1,91 @@
+import { Box, Sheet } from '@mui/joy'
+import { useMediaQuery } from '@mui/material'
+import { useEffect, useState } from 'react'
+import { ChoresGrouper } from '../../utils/Chores'
+import CalendarView from '../components/CalendarView'
+
+const Sidepanel = ({ chores }) => {
+ const isLargeScreen = useMediaQuery(theme => theme.breakpoints.up('md'))
+ const [dueDatePieChartData, setDueDatePieChartData] = useState([])
+
+ useEffect(() => {
+ setDueDatePieChartData(generateChoreDuePieChartData(chores))
+ }, [])
+
+ const generateChoreDuePieChartData = chores => {
+ const groups = ChoresGrouper('due_date', chores)
+ return groups
+ .map(group => {
+ return {
+ label: group.name,
+ value: group.content.length,
+ color: group.color,
+ id: group.name,
+ }
+ })
+ .filter(item => item.value > 0)
+ }
+
+ if (!isLargeScreen) {
+ return null
+ }
+ return (
+
+ {/*
+
+
+ {dueDatePieChartData.map((entry, index) => (
+ |
+ ))}
+
+
+
+ */}
+
+
+
+
+ )
+}
+
+export default Sidepanel
diff --git a/src/views/components/Calendar.css b/src/views/components/Calendar.css
new file mode 100644
index 0000000..02c3661
--- /dev/null
+++ b/src/views/components/Calendar.css
@@ -0,0 +1,79 @@
+.react-calendar {
+ width: 100%;
+ max-width: 600px;
+ font-family: 'Roboto', sans-serif;
+ background-color: transparent;
+}
+
+.react-calendar__tile {
+ padding: 1em;
+ min-height: 3rem;
+ text-align: center;
+ border-radius: 8px;
+ transition: background-color 0.3s ease;
+}
+.react-calendar__tile:enabled:hover {
+ /* lighten existing color: ; */
+ background-color: rgba(0, 123, 255, 0.2);
+}
+
+.react-calendar__tile--active {
+ background-color: #007bff !important;
+}
+
+/* Today's tile styles */
+.react-calendar .react-calendar__tile--now {
+ /* More specific selector */
+ /* background-color: #4ec1a2e3; */
+ border: 2px dotted #4ec1a2e3;
+ border-radius: 8px; /* Consistent with other tiles */
+ background-color: inherit;
+}
+
+.react-calendar .react-calendar__tile--now:enabled:hover {
+ background-color: rgba(0, 123, 255, 0.1);
+}
+
+/* Ensure dot container doesn't break row height */
+.dot-container {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ height: 16px;
+ /* if more than 4 dot make them go to the new line: */
+ flex-wrap: wrap;
+}
+
+.dot {
+ width: 0.3em;
+ height: 0.3em;
+ border-radius: 50%;
+ margin: 0 1px;
+}
+
+/* Tooltip styles */
+.dot-container {
+ position: relative;
+}
+
+.chore-tooltip {
+ position: absolute;
+ top: 100%;
+ left: 50%;
+ transform: translateX(-50%);
+ background-color: #333;
+ color: white;
+ padding: 5px 10px;
+ border-radius: 4px;
+ z-index: 10;
+ visibility: hidden;
+ opacity: 0;
+ transition:
+ opacity 0.2s ease,
+ visibility 0.2s ease;
+}
+
+/* remove different color on weekend: */
+.react-calendar__month-view__days__day--weekend {
+ color: inherit;
+}
diff --git a/src/views/components/CalendarView.jsx b/src/views/components/CalendarView.jsx
new file mode 100644
index 0000000..43e44b8
--- /dev/null
+++ b/src/views/components/CalendarView.jsx
@@ -0,0 +1,176 @@
+import { Box, Card, CardContent, Chip, Grid, Typography } from '@mui/joy'
+import moment from 'moment'
+import React, { useState } from 'react'
+import Calendar from 'react-calendar'
+import 'react-calendar/dist/Calendar.css'
+import { useNavigate } from 'react-router-dom'
+import { UserContext } from '../../contexts/UserContext'
+import { getTextColorFromBackgroundColor, TASK_COLOR } from '../../utils/Colors'
+import './Calendar.css'
+
+const getAssigneeColor = (assignee, userProfile) => {
+ return assignee === userProfile.id
+ ? TASK_COLOR.ASSIGNED_TO_ME
+ : TASK_COLOR.ASSIGNED_TO_OTHER
+}
+
+const CalendarView = ({ chores }) => {
+ const { userProfile } = React.useContext(UserContext)
+ const [selectedDate, setSeletedDate] = useState(null)
+ const Navigate = useNavigate()
+
+ const tileContent = ({ date, view }) => {
+ if (view === 'month') {
+ const dayChores = chores.filter(
+ chore =>
+ new Date(chore.nextDueDate)?.toISOString().split('T')[0] ===
+ date.toISOString().split('T')[0],
+ )
+
+ return (
+
+ {dayChores.map((chore, index) => {
+ if (index > 6) {
+ return null
+ }
+
+ return (
+
+ )
+ })}
+
+ )
+ }
+ return null
+ }
+
+ return (
+
+ {
+ setSeletedDate(new Date(d))
+ }}
+ />
+ {!selectedDate && (
+
+ {[
+ { name: 'Assigned to me', color: TASK_COLOR.ASSIGNED_TO_ME },
+ { name: 'Assigned to other', color: TASK_COLOR.ASSIGNED_TO_OTHER },
+ ].map((item, index) => (
+
+
+
+ {item.name}
+
+
+ ))}
+
+ )}
+ {selectedDate && (
+
+ {chores
+ .filter(
+ chore =>
+ new Date(chore.nextDueDate)?.toISOString().split('T')[0] ===
+ selectedDate.toISOString().split('T')[0],
+ )
+ .map((chore, idx) => (
+ {
+ Navigate('/chores/' + chore.id)
+ }}
+ sx={{
+ mb: 0.4,
+ py: 1,
+ px: 1,
+
+ // backgroundColor: getAssigneeColor(
+ // chore.assignedTo,
+ // userProfile,
+ // ),
+ // everything show in one row:
+ }}
+ >
+
+
+
+ {moment(chore.nextDueDate).format('hh:mm A')}
+
+ {chore.name}
+
+
+
+ ))}
+
+ )}
+
+ )
+}
+
+export default CalendarView
diff --git a/src/views/components/IconButtonTouchable.jsx b/src/views/components/IconButtonTouchable.jsx
new file mode 100644
index 0000000..c8cc4e5
--- /dev/null
+++ b/src/views/components/IconButtonTouchable.jsx
@@ -0,0 +1,34 @@
+import IconButton from '@mui/joy/IconButton'
+import React, { useRef, useState } from 'react'
+
+const IconButtonTouchable = ({ onHold, onClick, ...props }) => {
+ const [holdTimeout, setHoldTimeout] = useState(null)
+ const holdRef = useRef(false)
+
+ const handleMouseDown = () => {
+ holdRef.current = false
+ setHoldTimeout(
+ setTimeout(() => {
+ holdRef.current = true
+ onHold && onHold()
+ }, 1000),
+ )
+ }
+
+ const handleMouseUp = () => {
+ clearTimeout(holdTimeout)
+ if (!holdRef.current) {
+ onClick && onClick()
+ }
+ }
+
+ return (
+
+ )
+}
+
+export default IconButtonTouchable