Update Label to confirm deletion
Add More Filter to chores Improve the Priority
This commit is contained in:
commit
d216a30eec
7 changed files with 280 additions and 44 deletions
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "donetick",
|
"name": "donetick",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.1.79",
|
"version": "0.1.80",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"lint-staged": {
|
"lint-staged": {
|
||||||
"*.{js,jsx,ts,tsx}": [
|
"*.{js,jsx,ts,tsx}": [
|
||||||
|
|
|
@ -103,12 +103,13 @@ const ChoreView = () => {
|
||||||
}
|
}
|
||||||
}, [chore, performers])
|
}, [chore, performers])
|
||||||
const handleUpdatePriority = priority => {
|
const handleUpdatePriority = priority => {
|
||||||
if (priority.value === 0) {
|
UpdateChorePriority(choreId, priority.value).then(response => {
|
||||||
setChorePriority(null)
|
if (response.ok) {
|
||||||
} else {
|
response.json().then(data => {
|
||||||
setChorePriority(priority)
|
setChorePriority(priority)
|
||||||
}
|
})
|
||||||
UpdateChorePriority(choreId, priority.value)
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
const generateInfoCards = chore => {
|
const generateInfoCards = chore => {
|
||||||
const cards = [
|
const cards = [
|
||||||
|
@ -265,7 +266,6 @@ const ChoreView = () => {
|
||||||
? `Due at ${moment(chore.nextDueDate).format('MM/DD/YYYY hh:mm A')}`
|
? `Due at ${moment(chore.nextDueDate).format('MM/DD/YYYY hh:mm A')}`
|
||||||
: 'N/A'}
|
: 'N/A'}
|
||||||
</Chip>
|
</Chip>
|
||||||
{/* show each label : */}
|
|
||||||
{chore?.labelsV2?.map((label, index) => (
|
{chore?.labelsV2?.map((label, index) => (
|
||||||
<Chip
|
<Chip
|
||||||
key={index}
|
key={index}
|
||||||
|
|
|
@ -48,6 +48,7 @@ import {
|
||||||
UpdateChoreAssignee,
|
UpdateChoreAssignee,
|
||||||
} from '../../utils/Fetcher'
|
} from '../../utils/Fetcher'
|
||||||
import { getTextColorFromBackgroundColor } from '../../utils/LabelColors'
|
import { getTextColorFromBackgroundColor } from '../../utils/LabelColors'
|
||||||
|
import Priorities from '../../utils/Priorities'
|
||||||
import { Fetch } from '../../utils/TokenManager'
|
import { Fetch } from '../../utils/TokenManager'
|
||||||
import ConfirmationModal from '../Modals/Inputs/ConfirmationModal'
|
import ConfirmationModal from '../Modals/Inputs/ConfirmationModal'
|
||||||
import DateModal from '../Modals/Inputs/DateModal'
|
import DateModal from '../Modals/Inputs/DateModal'
|
||||||
|
@ -62,6 +63,7 @@ const ChoreCard = ({
|
||||||
userLabels,
|
userLabels,
|
||||||
sx,
|
sx,
|
||||||
viewOnly,
|
viewOnly,
|
||||||
|
onChipClick,
|
||||||
}) => {
|
}) => {
|
||||||
const [activeUserId, setActiveUserId] = React.useState(0)
|
const [activeUserId, setActiveUserId] = React.useState(0)
|
||||||
const [isChangeDueDateModalOpen, setIsChangeDueDateModalOpen] =
|
const [isChangeDueDateModalOpen, setIsChangeDueDateModalOpen] =
|
||||||
|
@ -504,6 +506,13 @@ const ChoreCard = ({
|
||||||
? 'warning'
|
? 'warning'
|
||||||
: 'neutral'
|
: 'neutral'
|
||||||
}
|
}
|
||||||
|
startDecorator={
|
||||||
|
Priorities.find(p => p.value === chore.priority)?.icon
|
||||||
|
}
|
||||||
|
onClick={e => {
|
||||||
|
e.stopPropagation()
|
||||||
|
onChipClick({ priority: chore.priority })
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
P{chore.priority}
|
P{chore.priority}
|
||||||
</Chip>
|
</Chip>
|
||||||
|
@ -512,16 +521,22 @@ const ChoreCard = ({
|
||||||
return (
|
return (
|
||||||
<Chip
|
<Chip
|
||||||
variant='solid'
|
variant='solid'
|
||||||
key={l.id}
|
key={`chorecard-${chore.id}-label-${l.id}`}
|
||||||
color='primary'
|
color='primary'
|
||||||
sx={{
|
sx={{
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
ml: index === 0 ? 0 : 0.5,
|
ml: index === 0 ? 0 : 0.5,
|
||||||
top: 2,
|
top: 2,
|
||||||
zIndex: 1,
|
zIndex: 1,
|
||||||
backgroundColor: l?.color,
|
backgroundColor: `${l?.color} !important`,
|
||||||
color: getTextColorFromBackgroundColor(l?.color),
|
color: getTextColorFromBackgroundColor(l?.color),
|
||||||
|
|
||||||
|
// apply background color for th clickable button:
|
||||||
}}
|
}}
|
||||||
|
// onClick={e => {
|
||||||
|
// e.stopPropagation()
|
||||||
|
// onChipClick({ label: l })
|
||||||
|
// }}
|
||||||
|
|
||||||
// startDecorator={getIconForLabel(label)}
|
// startDecorator={getIconForLabel(label)}
|
||||||
>
|
>
|
||||||
|
@ -719,7 +734,9 @@ const ChoreCard = ({
|
||||||
handleAssigneChange(selected.id)
|
handleAssigneChange(selected.id)
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<ConfirmationModal config={confirmModelConfig} />
|
{confirmModelConfig?.isOpen && (
|
||||||
|
<ConfirmationModal config={confirmModelConfig} />
|
||||||
|
)}
|
||||||
<TextModal
|
<TextModal
|
||||||
isOpen={isCompleteWithNoteModalOpen}
|
isOpen={isCompleteWithNoteModalOpen}
|
||||||
title='Add note to attach to this completion:'
|
title='Add note to attach to this completion:'
|
||||||
|
|
102
src/views/Chores/IconButtonWithMenu.jsx
Normal file
102
src/views/Chores/IconButtonWithMenu.jsx
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
import { Chip, Menu, MenuItem } from '@mui/joy'
|
||||||
|
import IconButton from '@mui/joy/IconButton'
|
||||||
|
import React, { useEffect, useRef, useState } from 'react'
|
||||||
|
import { getTextColorFromBackgroundColor } from '../../utils/LabelColors'
|
||||||
|
|
||||||
|
const IconButtonWithMenu = ({
|
||||||
|
key,
|
||||||
|
icon,
|
||||||
|
options,
|
||||||
|
onItemSelect,
|
||||||
|
selectedItem,
|
||||||
|
setSelectedItem,
|
||||||
|
isActive,
|
||||||
|
useChips,
|
||||||
|
}) => {
|
||||||
|
const [anchorEl, setAnchorEl] = useState(null)
|
||||||
|
const menuRef = useRef(null)
|
||||||
|
|
||||||
|
const handleMenuOpen = event => {
|
||||||
|
setAnchorEl(event.currentTarget)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleMenuClose = () => {
|
||||||
|
setAnchorEl(null)
|
||||||
|
}
|
||||||
|
useEffect(() => {
|
||||||
|
document.addEventListener('mousedown', handleMenuOutsideClick)
|
||||||
|
return () => {
|
||||||
|
document.removeEventListener('mousedown', handleMenuOutsideClick)
|
||||||
|
}
|
||||||
|
}, [anchorEl])
|
||||||
|
|
||||||
|
const handleMenuOutsideClick = event => {
|
||||||
|
if (menuRef.current && !menuRef.current.contains(event.target)) {
|
||||||
|
handleMenuClose()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<IconButton
|
||||||
|
onClick={handleMenuOpen}
|
||||||
|
variant='outlined'
|
||||||
|
color={isActive ? 'primary' : 'neutral'}
|
||||||
|
size='sm'
|
||||||
|
sx={{
|
||||||
|
height: 24,
|
||||||
|
borderRadius: 24,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{icon}
|
||||||
|
</IconButton>
|
||||||
|
|
||||||
|
<Menu
|
||||||
|
key={key}
|
||||||
|
ref={menuRef}
|
||||||
|
anchorEl={anchorEl}
|
||||||
|
open={Boolean(anchorEl)}
|
||||||
|
onClose={handleMenuClose}
|
||||||
|
>
|
||||||
|
{options?.map(item => (
|
||||||
|
<MenuItem
|
||||||
|
key={`${key}-${item?.id}`}
|
||||||
|
onClick={() => {
|
||||||
|
onItemSelect(item)
|
||||||
|
setSelectedItem?.selectedItem(item.name)
|
||||||
|
handleMenuClose()
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{useChips ? (
|
||||||
|
<Chip
|
||||||
|
sx={{
|
||||||
|
backgroundColor: item.color ? item.color : null,
|
||||||
|
color: getTextColorFromBackgroundColor(item.color),
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{item.name}
|
||||||
|
</Chip>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
{item?.icon}
|
||||||
|
{item.name}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</MenuItem>
|
||||||
|
))}
|
||||||
|
{/* {selectedItem && selectedItem !== 'All' && (
|
||||||
|
<MenuItem
|
||||||
|
id={`${id}cancel-all-filters`}
|
||||||
|
onClick={() => {
|
||||||
|
onItemSelect(null)
|
||||||
|
setSelectedItem?.setSelectedItem('All')
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Cancel All Filters
|
||||||
|
</MenuItem>
|
||||||
|
)} */}
|
||||||
|
</Menu>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
export default IconButtonWithMenu
|
|
@ -3,10 +3,12 @@ import {
|
||||||
CancelRounded,
|
CancelRounded,
|
||||||
EditCalendar,
|
EditCalendar,
|
||||||
FilterAlt,
|
FilterAlt,
|
||||||
FilterAltOff,
|
PriorityHigh,
|
||||||
|
Style,
|
||||||
} from '@mui/icons-material'
|
} from '@mui/icons-material'
|
||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
|
Button,
|
||||||
Chip,
|
Chip,
|
||||||
Container,
|
Container,
|
||||||
IconButton,
|
IconButton,
|
||||||
|
@ -23,9 +25,11 @@ import { useNavigate } from 'react-router-dom'
|
||||||
import { UserContext } from '../../contexts/UserContext'
|
import { UserContext } from '../../contexts/UserContext'
|
||||||
import { useChores } from '../../queries/ChoreQueries'
|
import { useChores } from '../../queries/ChoreQueries'
|
||||||
import { GetAllUsers, GetUserProfile } from '../../utils/Fetcher'
|
import { GetAllUsers, GetUserProfile } from '../../utils/Fetcher'
|
||||||
|
import Priorities from '../../utils/Priorities'
|
||||||
import LoadingComponent from '../components/Loading'
|
import LoadingComponent from '../components/Loading'
|
||||||
import { useLabels } from '../Labels/LabelQueries'
|
import { useLabels } from '../Labels/LabelQueries'
|
||||||
import ChoreCard from './ChoreCard'
|
import ChoreCard from './ChoreCard'
|
||||||
|
import IconButtonWithMenu from './IconButtonWithMenu'
|
||||||
|
|
||||||
const MyChores = () => {
|
const MyChores = () => {
|
||||||
const { userProfile, setUserProfile } = useContext(UserContext)
|
const { userProfile, setUserProfile } = useContext(UserContext)
|
||||||
|
@ -122,6 +126,28 @@ const MyChores = () => {
|
||||||
const handleFilterMenuClose = () => {
|
const handleFilterMenuClose = () => {
|
||||||
setAnchorEl(null)
|
setAnchorEl(null)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleLabelFiltering = chipClicked => {
|
||||||
|
console.log('chipClicked', chipClicked)
|
||||||
|
|
||||||
|
if (chipClicked.label) {
|
||||||
|
const label = chipClicked.label
|
||||||
|
const labelFiltered = [...chores].filter(chore =>
|
||||||
|
chore.labelsV2.some(l => l.id === label.id),
|
||||||
|
)
|
||||||
|
console.log('labelFiltered', labelFiltered)
|
||||||
|
setFilteredChores(labelFiltered)
|
||||||
|
setSelectedFilter('Label: ' + label.name)
|
||||||
|
} else if (chipClicked.priority) {
|
||||||
|
const priority = chipClicked.priority
|
||||||
|
const priorityFiltered = chores.filter(
|
||||||
|
chore => chore.priority === priority,
|
||||||
|
)
|
||||||
|
setFilteredChores(priorityFiltered)
|
||||||
|
setSelectedFilter('Priority: ' + priority)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const handleChoreUpdated = (updatedChore, event) => {
|
const handleChoreUpdated = (updatedChore, event) => {
|
||||||
const newChores = chores.map(chore => {
|
const newChores = chores.map(chore => {
|
||||||
if (chore.id === updatedChore.id) {
|
if (chore.id === updatedChore.id) {
|
||||||
|
@ -175,13 +201,16 @@ const MyChores = () => {
|
||||||
chores.map(c => ({
|
chores.map(c => ({
|
||||||
...c,
|
...c,
|
||||||
raw_label: c.labelsV2
|
raw_label: c.labelsV2
|
||||||
.map(l => userLabels.find(x => (x.id = l.id)).name)
|
.map(l => userLabels.find(x => x.id === l.id).name)
|
||||||
.join(' '),
|
.join(' '),
|
||||||
})),
|
})),
|
||||||
searchOptions,
|
searchOptions,
|
||||||
)
|
)
|
||||||
|
|
||||||
const handleSearchChange = e => {
|
const handleSearchChange = e => {
|
||||||
|
if (selectedFilter !== 'All') {
|
||||||
|
setSelectedFilter('All')
|
||||||
|
}
|
||||||
const search = e.target.value
|
const search = e.target.value
|
||||||
if (search === '') {
|
if (search === '') {
|
||||||
setFilteredChores(chores)
|
setFilteredChores(chores)
|
||||||
|
@ -209,7 +238,6 @@ const MyChores = () => {
|
||||||
My Chores
|
My Chores
|
||||||
</Typography> */}
|
</Typography> */}
|
||||||
{/* <Sheet> */}
|
{/* <Sheet> */}
|
||||||
|
|
||||||
{/* Search box to filter */}
|
{/* Search box to filter */}
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
|
@ -217,7 +245,7 @@ const MyChores = () => {
|
||||||
justifyContent: 'space-between',
|
justifyContent: 'space-between',
|
||||||
alignContent: 'center',
|
alignContent: 'center',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
gap: 1,
|
gap: 0.5,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Input
|
<Input
|
||||||
|
@ -245,11 +273,37 @@ const MyChores = () => {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
<IconButtonWithMenu
|
||||||
|
key={'icon-menu-labels-filter'}
|
||||||
|
icon={<PriorityHigh />}
|
||||||
|
options={Priorities}
|
||||||
|
selectedItem={selectedFilter}
|
||||||
|
onItemSelect={selected => {
|
||||||
|
handleLabelFiltering({ priority: selected.value })
|
||||||
|
}}
|
||||||
|
mouseClickHandler={handleMenuOutsideClick}
|
||||||
|
isActive={selectedFilter.startsWith('Priority: ')}
|
||||||
|
/>
|
||||||
|
<IconButtonWithMenu
|
||||||
|
key={'icon-menu-labels-filter'}
|
||||||
|
icon={<Style />}
|
||||||
|
options={userLabels}
|
||||||
|
selectedItem={selectedFilter}
|
||||||
|
onItemSelect={selected => {
|
||||||
|
handleLabelFiltering({ label: selected })
|
||||||
|
}}
|
||||||
|
isActive={selectedFilter.startsWith('Label: ')}
|
||||||
|
mouseClickHandler={handleMenuOutsideClick}
|
||||||
|
useChips
|
||||||
|
/>
|
||||||
|
|
||||||
<IconButton
|
<IconButton
|
||||||
onClick={handleFilterMenuOpen}
|
onClick={handleFilterMenuOpen}
|
||||||
variant='outlined'
|
variant='outlined'
|
||||||
color={
|
color={
|
||||||
selectedFilter && selectedFilter != 'All' ? 'primary' : 'neutral'
|
selectedFilter && FILTERS[selectedFilter] && selectedFilter != 'All'
|
||||||
|
? 'primary'
|
||||||
|
: 'neutral'
|
||||||
}
|
}
|
||||||
size='sm'
|
size='sm'
|
||||||
sx={{
|
sx={{
|
||||||
|
@ -257,40 +311,24 @@ const MyChores = () => {
|
||||||
borderRadius: 24,
|
borderRadius: 24,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{selectedFilter && selectedFilter != 'All' ? (
|
<FilterAlt />
|
||||||
<FilterAltOff />
|
|
||||||
) : (
|
|
||||||
<FilterAlt />
|
|
||||||
)}
|
|
||||||
</IconButton>
|
</IconButton>
|
||||||
<List
|
<List
|
||||||
orientation='horizontal'
|
orientation='horizontal'
|
||||||
wrap
|
wrap
|
||||||
sx={{
|
sx={{
|
||||||
// '--List-gap': '8px',
|
|
||||||
// '--ListItem-radius': '20px',
|
|
||||||
// '--ListItem-minHeight': '32px',
|
|
||||||
// '--ListItem-gap': '4px',
|
|
||||||
mt: 0.2,
|
mt: 0.2,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{/* <Checkbox
|
|
||||||
key='checkboxAll'
|
|
||||||
label=''
|
|
||||||
disableIcon
|
|
||||||
overlay
|
|
||||||
size='sm'
|
|
||||||
/> */}
|
|
||||||
|
|
||||||
<Menu
|
<Menu
|
||||||
ref={menuRef}
|
ref={menuRef}
|
||||||
anchorEl={anchorEl}
|
anchorEl={anchorEl}
|
||||||
open={Boolean(anchorEl)}
|
open={Boolean(anchorEl)}
|
||||||
onClose={handleFilterMenuClose}
|
onClose={handleFilterMenuClose}
|
||||||
>
|
>
|
||||||
{Object.keys(FILTERS).map(filter => (
|
{Object.keys(FILTERS).map((filter, index) => (
|
||||||
<MenuItem
|
<MenuItem
|
||||||
key={filter}
|
key={`filter-list-${filter}-${index}`}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
const filterFunction = FILTERS[filter]
|
const filterFunction = FILTERS[filter]
|
||||||
const filteredChores =
|
const filteredChores =
|
||||||
|
@ -310,10 +348,40 @@ const MyChores = () => {
|
||||||
</Chip>
|
</Chip>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
))}
|
))}
|
||||||
|
{selectedFilter.startsWith('Label: ') ||
|
||||||
|
(selectedFilter.startsWith('Priority: ') && (
|
||||||
|
<MenuItem
|
||||||
|
key={`filter-list-cancel-all-filters`}
|
||||||
|
onClick={() => {
|
||||||
|
setFilteredChores(chores)
|
||||||
|
setSelectedFilter('All')
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Cancel All Filters
|
||||||
|
</MenuItem>
|
||||||
|
))}
|
||||||
</Menu>
|
</Menu>
|
||||||
</List>
|
</List>
|
||||||
</Box>
|
</Box>
|
||||||
|
{selectedFilter !== 'All' && (
|
||||||
|
<Chip
|
||||||
|
level='title-md'
|
||||||
|
gutterBottom
|
||||||
|
color='warning'
|
||||||
|
label={selectedFilter}
|
||||||
|
onDelete={() => {
|
||||||
|
setFilteredChores(chores)
|
||||||
|
setSelectedFilter('All')
|
||||||
|
}}
|
||||||
|
endDecorator={<CancelRounded />}
|
||||||
|
onClick={() => {
|
||||||
|
setFilteredChores(chores)
|
||||||
|
setSelectedFilter('All')
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Current Filter: {selectedFilter}
|
||||||
|
</Chip>
|
||||||
|
)}
|
||||||
{/* </Sheet> */}
|
{/* </Sheet> */}
|
||||||
{filteredChores.length === 0 && (
|
{filteredChores.length === 0 && (
|
||||||
<Box
|
<Box
|
||||||
|
@ -335,6 +403,17 @@ const MyChores = () => {
|
||||||
<Typography level='title-md' gutterBottom>
|
<Typography level='title-md' gutterBottom>
|
||||||
Nothing scheduled
|
Nothing scheduled
|
||||||
</Typography>
|
</Typography>
|
||||||
|
{chores.length > 0 && (
|
||||||
|
<>
|
||||||
|
<Button
|
||||||
|
onClick={() => setFilteredChores(chores)}
|
||||||
|
variant='outlined'
|
||||||
|
color='neutral'
|
||||||
|
>
|
||||||
|
Reset filters
|
||||||
|
</Button>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
@ -346,6 +425,7 @@ const MyChores = () => {
|
||||||
onChoreRemove={handleChoreDeleted}
|
onChoreRemove={handleChoreDeleted}
|
||||||
performers={performers}
|
performers={performers}
|
||||||
userLabels={userLabels}
|
userLabels={userLabels}
|
||||||
|
onChipClick={handleLabelFiltering}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
|
@ -421,6 +501,13 @@ const FILTERS = {
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
'Due Later': function (chores) {
|
||||||
|
return chores.filter(chore => {
|
||||||
|
return (
|
||||||
|
new Date(chore.nextDueDate) > new Date(Date.now() + 24 * 60 * 60 * 1000)
|
||||||
|
)
|
||||||
|
})
|
||||||
|
},
|
||||||
'Created By Me': function (chores, userID) {
|
'Created By Me': function (chores, userID) {
|
||||||
return chores.filter(chore => {
|
return chores.filter(chore => {
|
||||||
return chore.createdBy === userID
|
return chore.createdBy === userID
|
||||||
|
|
|
@ -15,33 +15,55 @@ import { useLabels } from './LabelQueries'
|
||||||
// import { useMutation, useQueryClient } from '@tanstack/react-query'
|
// import { useMutation, useQueryClient } from '@tanstack/react-query'
|
||||||
import { Add } from '@mui/icons-material'
|
import { Add } from '@mui/icons-material'
|
||||||
import { useQueryClient } from 'react-query'
|
import { useQueryClient } from 'react-query'
|
||||||
|
import { useNavigate } from 'react-router-dom'
|
||||||
import { DeleteLabel } from '../../utils/Fetcher'
|
import { DeleteLabel } from '../../utils/Fetcher'
|
||||||
|
import ConfirmationModal from '../Modals/Inputs/ConfirmationModal'
|
||||||
|
|
||||||
const LabelView = () => {
|
const LabelView = () => {
|
||||||
const { data: labels, isLabelsLoading, isError } = useLabels()
|
const { data: labels, isLabelsLoading, isError } = useLabels()
|
||||||
const [userLabels, setUserLabels] = useState([labels])
|
const [userLabels, setUserLabels] = useState([labels])
|
||||||
const [modalOpen, setModalOpen] = useState(false)
|
const [modalOpen, setModalOpen] = useState(false)
|
||||||
const [currentLabel, setCurrentLabel] = useState(null) // Label being edited or null for new label
|
const [currentLabel, setCurrentLabel] = useState(null)
|
||||||
const queryClient = useQueryClient()
|
const queryClient = useQueryClient()
|
||||||
|
const [confirmationModel, setConfirmationModel] = useState({})
|
||||||
|
const Navigate = useNavigate()
|
||||||
const handleAddLabel = () => {
|
const handleAddLabel = () => {
|
||||||
setCurrentLabel(null) // Adding a new label
|
setCurrentLabel(null)
|
||||||
setModalOpen(true)
|
setModalOpen(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleEditLabel = label => {
|
const handleEditLabel = label => {
|
||||||
setCurrentLabel(label) // Editing an existing label
|
setCurrentLabel(label)
|
||||||
setModalOpen(true)
|
setModalOpen(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleDeleteClicked = id => {
|
||||||
|
setConfirmationModel({
|
||||||
|
isOpen: true,
|
||||||
|
title: 'Delete Label',
|
||||||
|
|
||||||
|
message:
|
||||||
|
'Are you sure you want to delete this label? This will remove the label from all tasks.',
|
||||||
|
|
||||||
|
confirmText: 'Delete',
|
||||||
|
color: 'danger',
|
||||||
|
cancelText: 'Cancel',
|
||||||
|
onClose: confirmed => {
|
||||||
|
if (confirmed) {
|
||||||
|
handleDeleteLabel(id)
|
||||||
|
}
|
||||||
|
setConfirmationModel({})
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const handleDeleteLabel = id => {
|
const handleDeleteLabel = id => {
|
||||||
DeleteLabel(id).then(res => {
|
DeleteLabel(id).then(res => {
|
||||||
// Invalidate and refetch labels after deleting a label
|
|
||||||
const updatedLabels = userLabels.filter(label => label.id !== id)
|
const updatedLabels = userLabels.filter(label => label.id !== id)
|
||||||
setUserLabels(updatedLabels)
|
setUserLabels(updatedLabels)
|
||||||
|
|
||||||
queryClient.invalidateQueries('labels')
|
queryClient.invalidateQueries('labels')
|
||||||
})
|
})
|
||||||
// Implement deletion logic here
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleSaveLabel = newOrUpdatedLabel => {
|
const handleSaveLabel = newOrUpdatedLabel => {
|
||||||
|
@ -92,7 +114,13 @@ const LabelView = () => {
|
||||||
<tbody>
|
<tbody>
|
||||||
{userLabels.map(label => (
|
{userLabels.map(label => (
|
||||||
<tr key={label.id}>
|
<tr key={label.id}>
|
||||||
<td>{label.name}</td>
|
<td
|
||||||
|
onClick={() => {
|
||||||
|
Navigate('/my/chores', { state: { label: label.id } })
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{label.name}
|
||||||
|
</td>
|
||||||
<td
|
<td
|
||||||
style={{
|
style={{
|
||||||
// center without display flex:
|
// center without display flex:
|
||||||
|
@ -121,7 +149,7 @@ const LabelView = () => {
|
||||||
<EditIcon />
|
<EditIcon />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
<IconButton
|
<IconButton
|
||||||
onClick={() => handleDeleteLabel(label.id)}
|
onClick={() => handleDeleteClicked(label.id)}
|
||||||
color='danger'
|
color='danger'
|
||||||
>
|
>
|
||||||
<DeleteIcon />
|
<DeleteIcon />
|
||||||
|
@ -151,7 +179,7 @@ const LabelView = () => {
|
||||||
position: 'fixed',
|
position: 'fixed',
|
||||||
bottom: 0,
|
bottom: 0,
|
||||||
left: 10,
|
left: 10,
|
||||||
p: 2, // padding
|
p: 2,
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
justifyContent: 'flex-end',
|
justifyContent: 'flex-end',
|
||||||
gap: 2,
|
gap: 2,
|
||||||
|
@ -171,6 +199,7 @@ const LabelView = () => {
|
||||||
<Add />
|
<Add />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</Box>
|
</Box>
|
||||||
|
<ConfirmationModal config={confirmationModel} />
|
||||||
</Container>
|
</Container>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ function ConfirmationModal({ config }) {
|
||||||
}}
|
}}
|
||||||
fullWidth
|
fullWidth
|
||||||
sx={{ mr: 1 }}
|
sx={{ mr: 1 }}
|
||||||
|
color={config.color ? config.color : 'primary'}
|
||||||
>
|
>
|
||||||
{config?.confirmText}
|
{config?.confirmText}
|
||||||
</Button>
|
</Button>
|
||||||
|
|
Loading…
Add table
Reference in a new issue