archive and unarchive functionality to ChoreCard component

This commit is contained in:
Mo Tarbin 2024-12-22 11:59:54 -05:00
commit 959e0fffa3
4 changed files with 115 additions and 9 deletions

View file

@ -65,6 +65,18 @@ const GetArchivedChores = () => {
headers: HEADERS(), headers: HEADERS(),
}) })
} }
const ArchiveChore = id => {
return Fetch(`${API_URL}/chores/${id}/archive`, {
method: 'PUT',
headers: HEADERS(),
})
}
const UnArchiveChore = id => {
return Fetch(`${API_URL}/chores/${id}/unarchive`, {
method: 'PUT',
headers: HEADERS(),
})
}
const GetChoreByID = id => { const GetChoreByID = id => {
return Fetch(`${API_URL}/chores/${id}`, { return Fetch(`${API_URL}/chores/${id}`, {
@ -348,6 +360,7 @@ const DeleteLabel = id => {
export { export {
AcceptCircleMemberRequest, AcceptCircleMemberRequest,
ArchiveChore,
CancelSubscription, CancelSubscription,
createChore, createChore,
CreateChore, CreateChore,
@ -384,6 +397,7 @@ export {
SaveThing, SaveThing,
signUp, signUp,
SkipChore, SkipChore,
UnArchiveChore,
UpdateChoreAssignee, UpdateChoreAssignee,
UpdateChoreHistory, UpdateChoreHistory,
UpdateChorePriority, UpdateChorePriority,

View file

@ -1,4 +1,5 @@
import { import {
Archive,
CancelScheduleSend, CancelScheduleSend,
Check, Check,
Delete, Delete,
@ -18,6 +19,7 @@ import {
Report, Report,
SwitchAccessShortcut, SwitchAccessShortcut,
TimesOneMobiledata, TimesOneMobiledata,
Unarchive,
Update, Update,
ViewCarousel, ViewCarousel,
Webhook, Webhook,
@ -43,8 +45,10 @@ import { useNavigate } from 'react-router-dom'
import { API_URL } from '../../Config' import { API_URL } from '../../Config'
import { UserContext } from '../../contexts/UserContext' import { UserContext } from '../../contexts/UserContext'
import { import {
ArchiveChore,
MarkChoreComplete, MarkChoreComplete,
SkipChore, SkipChore,
UnArchiveChore,
UpdateChoreAssignee, UpdateChoreAssignee,
} from '../../utils/Fetcher' } from '../../utils/Fetcher'
import { getTextColorFromBackgroundColor } from '../../utils/LabelColors' import { getTextColorFromBackgroundColor } from '../../utils/LabelColors'
@ -137,6 +141,30 @@ const ChoreCard = ({
}, },
}) })
} }
const handleArchive = () => {
if (chore.isActive) {
ArchiveChore(chore.id).then(response => {
if (response.ok) {
response.json().then(data => {
const newChore = { ...chore, isActive: false }
onChoreUpdate(newChore, 'archive')
})
}
})
} else {
UnArchiveChore(chore.id).then(response => {
if (response.ok) {
response.json().then(data => {
const newChore = { ...chore, isActive: true }
onChoreUpdate(newChore, 'unarchive')
})
}
})
}
handleMenuClose()
}
const handleTaskCompletion = () => { const handleTaskCompletion = () => {
setIsPendingCompletion(true) setIsPendingCompletion(true)
@ -691,6 +719,12 @@ const ChoreCard = ({
<ViewCarousel /> <ViewCarousel />
View View
</MenuItem> </MenuItem>
<MenuItem onClick={handleArchive} color='neutral'>
{chore.isActive ? <Archive /> : <Unarchive />}
{chore.isActive ? 'Archive' : 'Unarchive'}
</MenuItem>
<Divider />
<MenuItem onClick={handleDelete} color='danger'> <MenuItem onClick={handleDelete} color='danger'>
<Delete /> <Delete />
Delete Delete

View file

@ -172,19 +172,40 @@ const MyChores = () => {
case 4: case 4:
groupRaw['p4'].push(chore) groupRaw['p4'].push(chore)
break break
default:
groupRaw['no_priority'].push(chore)
break
} }
}) })
groups = [
{ name: 'Priority 1', content: groupRaw['p1'] },
{ name: 'Priority 2', content: groupRaw['p2'] },
{ name: 'Priority 3', content: groupRaw['p3'] },
{ name: 'Priority 4', content: groupRaw['p4'] },
{ name: 'No Priority', content: groupRaw['no_priority'] },
]
break break
case 'labels': case 'labels':
groupRaw = {} groupRaw = {}
var labels = {}
chores.forEach(chore => { chores.forEach(chore => {
chore.labelsV2.forEach(label => { chore.labelsV2.forEach(label => {
labels[label.id] = label
if (groupRaw[label.id] === undefined) { if (groupRaw[label.id] === undefined) {
groupRaw[label.id] = [] groupRaw[label.id] = []
} }
groupRaw[label.id].push(chore) groupRaw[label.id].push(chore)
}) })
}) })
groups = Object.keys(groupRaw).map(key => {
return {
name: labels[key].name,
content: groupRaw[key],
}
})
groups.sort((a, b) => {
a.name < b.name ? 1 : -1
})
} }
return groups return groups
} }
@ -272,22 +293,39 @@ const MyChores = () => {
} }
const handleChoreUpdated = (updatedChore, event) => { const handleChoreUpdated = (updatedChore, event) => {
const newChores = chores.map(chore => { var newChores = chores.map(chore => {
if (chore.id === updatedChore.id) { if (chore.id === updatedChore.id) {
return updatedChore return updatedChore
} }
return chore return chore
}) })
const newFilteredChores = filteredChores.map(chore => { var newFilteredChores = filteredChores.map(chore => {
if (chore.id === updatedChore.id) { if (chore.id === updatedChore.id) {
return updatedChore return updatedChore
} }
return chore return chore
}) })
if (event === 'archive') {
newChores = newChores.filter(chore => chore.id !== updatedChore.id)
newFilteredChores = newFilteredChores.filter(
chore => chore.id !== updatedChore.id,
)
if (archivedChores !== null) {
setArchivedChores([...archivedChores, updatedChore])
}
}
if (event === 'unarchive') {
newChores.push(updatedChore)
newFilteredChores.push(updatedChore)
setArchivedChores(
archivedChores.filter(chore => chore.id !== updatedChore.id),
)
}
setChores(newChores) setChores(newChores)
setFilteredChores(newFilteredChores) setFilteredChores(newFilteredChores)
setChoreSections(sectionSorter('due_date', newChores)) setChoreSections(sectionSorter('due_date', newChores))
switch (event) { switch (event) {
case 'completed': case 'completed':
setSnackBarMessage('Completed') setSnackBarMessage('Completed')
@ -298,6 +336,12 @@ const MyChores = () => {
case 'rescheduled': case 'rescheduled':
setSnackBarMessage('Rescheduled') setSnackBarMessage('Rescheduled')
break break
case 'unarchive':
setSnackBarMessage('Unarchive')
break
case 'archive':
setSnackBarMessage('Archived')
break
default: default:
setSnackBarMessage('Updated') setSnackBarMessage('Updated')
} }

View file

@ -1,7 +1,9 @@
import { CopyAll } from '@mui/icons-material'
import { import {
Box, Box,
Button, Button,
Checkbox, Checkbox,
Input,
ListItem, ListItem,
Modal, Modal,
ModalDialog, ModalDialog,
@ -38,7 +40,9 @@ function WriteNFCModal({ config }) {
} }
} else { } else {
setNfcStatus('error') setNfcStatus('error')
setErrorMessage('NFC is not supported by this browser.') setErrorMessage(
'NFC is not supported by this browser. You can still copy the URL and write it to an NFC tag using a compatible device.',
)
} }
} }
@ -73,6 +77,22 @@ function WriteNFCModal({ config }) {
? errorMessage ? errorMessage
: 'Press the button below to write to NFC.'} : 'Press the button below to write to NFC.'}
</Typography> </Typography>
<Input
value={getURL()}
fullWidth
readOnly
label='URL'
sx={{ mt: 1 }}
endDecorator={
<CopyAll
sx={{ cursor: 'pointer' }}
onClick={() => {
navigator.clipboard.writeText(getURL())
alert('URL copied to clipboard!')
}}
/>
}
/>
<ListItem> <ListItem>
<Checkbox <Checkbox
checked={isAutoCompleteWhenScan} checked={isAutoCompleteWhenScan}
@ -95,12 +115,6 @@ function WriteNFCModal({ config }) {
</Box> </Box>
</> </>
)} )}
<Box display={'flex'} justifyContent={'center'} mt={2}>
<Button onClick={handleClose} variant='outlined'>
Close
</Button>
</Box>
</ModalDialog> </ModalDialog>
</Modal> </Modal>
) )