feat: add MoreVert icon button for toggle actions in multiple components
This commit is contained in:
@@ -14,11 +14,19 @@ import {
|
||||
History,
|
||||
Star,
|
||||
Timelapse,
|
||||
TrendingUp,
|
||||
TrendingUp
|
||||
} from '@mui/icons-material'
|
||||
import DeleteIcon from '@mui/icons-material/Delete'
|
||||
import EditIcon from '@mui/icons-material/Edit'
|
||||
import { Box, Button, Card, Container, Grid, Sheet, Typography } from '@mui/joy'
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Card,
|
||||
Container,
|
||||
Grid,
|
||||
Sheet,
|
||||
Typography
|
||||
} from '@mui/joy'
|
||||
import moment from 'moment'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { Link, useParams } from 'react-router-dom'
|
||||
@@ -42,6 +50,7 @@ const ChoreHistory = () => {
|
||||
const [isEditModalOpen, setIsEditModalOpen] = useState(false)
|
||||
const [editHistory, setEditHistory] = useState({})
|
||||
const { confirmModalConfig, showConfirmation } = useConfirmationModal()
|
||||
const [showMoreInfoId, setShowMoreInfoId] = useState(null)
|
||||
|
||||
// React Query hooks
|
||||
const { data: choreHistoryData, isLoading } = useChoreHistory(choreId)
|
||||
@@ -298,6 +307,11 @@ const ChoreHistory = () => {
|
||||
{choreHistory.map((historyEntry, index) => (
|
||||
<SwipeableListItem
|
||||
key={historyEntry.id || index}
|
||||
swipeActionOpen={
|
||||
showMoreInfoId === (historyEntry.id || index)
|
||||
? 'trailing'
|
||||
: null
|
||||
}
|
||||
trailingActions={
|
||||
<TrailingActions>
|
||||
<Box
|
||||
@@ -355,6 +369,14 @@ const ChoreHistory = () => {
|
||||
performers={performers}
|
||||
allHistory={choreHistory}
|
||||
index={index}
|
||||
onToggleActions={() => {
|
||||
const id = historyEntry.id || index
|
||||
if (showMoreInfoId === id) {
|
||||
setShowMoreInfoId(null)
|
||||
} else {
|
||||
setShowMoreInfoId(id)
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</SwipeableListItem>
|
||||
))}
|
||||
|
||||
@@ -5,13 +5,14 @@ import {
|
||||
CheckCircle,
|
||||
EventNote,
|
||||
HourglassEmpty,
|
||||
MoreVert,
|
||||
Person,
|
||||
Redo,
|
||||
ThumbDown,
|
||||
Timelapse,
|
||||
Toll,
|
||||
} from '@mui/icons-material'
|
||||
import { Avatar, Box, Chip, Grid, Typography } from '@mui/joy'
|
||||
import { Avatar, Box, Chip, Grid, IconButton, Typography } from '@mui/joy'
|
||||
import moment from 'moment'
|
||||
import { TASK_COLOR } from '../../utils/Colors.jsx'
|
||||
|
||||
@@ -85,7 +86,13 @@ const formatTime = seconds => {
|
||||
/**
|
||||
* Compact HistoryCard component - content only
|
||||
*/
|
||||
const HistoryCard = ({ allHistory, performers, historyEntry, index }) => {
|
||||
const HistoryCard = ({
|
||||
allHistory,
|
||||
performers,
|
||||
historyEntry,
|
||||
index,
|
||||
onToggleActions,
|
||||
}) => {
|
||||
const performer = performers.find(p => p.userId === historyEntry.completedBy)
|
||||
const assignedTo = performers.find(p => p.userId === historyEntry.assignedTo)
|
||||
|
||||
@@ -149,7 +156,7 @@ const HistoryCard = ({ allHistory, performers, historyEntry, index }) => {
|
||||
borderColor: 'divider',
|
||||
}}
|
||||
>
|
||||
<Box sx={{ flex: 1 }}>
|
||||
<Box sx={{ flex: 1, minWidth: 0 }}>
|
||||
<Grid container spacing={1} alignItems='center'>
|
||||
{/* First Row/Column: Status and Time Info */}
|
||||
<Grid xs={12} sm={8}>
|
||||
@@ -282,6 +289,21 @@ const HistoryCard = ({ allHistory, performers, historyEntry, index }) => {
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Box>
|
||||
<Box>
|
||||
{onToggleActions && (
|
||||
<IconButton
|
||||
color='neutral'
|
||||
variant='plain'
|
||||
size='sm'
|
||||
onClick={e => {
|
||||
e.stopPropagation()
|
||||
onToggleActions()
|
||||
}}
|
||||
>
|
||||
<MoreVert sx={{ fontSize: 18 }} />
|
||||
</IconButton>
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ import {
|
||||
TrailingActions,
|
||||
} from '@meauxt/react-swipeable-list'
|
||||
import '@meauxt/react-swipeable-list/dist/styles.css'
|
||||
import { Add } from '@mui/icons-material'
|
||||
import { Add, MoreVert } from '@mui/icons-material'
|
||||
import { useQueryClient } from '@tanstack/react-query'
|
||||
import { useUserProfile } from '../../queries/UserQueries'
|
||||
import { getTextColorFromBackgroundColor } from '../../utils/Colors'
|
||||
@@ -30,7 +30,7 @@ import { getSafeBottomStyles } from '../../utils/SafeAreaUtils'
|
||||
import ConfirmationModal from '../Modals/Inputs/ConfirmationModal'
|
||||
import { useLabels } from './LabelQueries'
|
||||
|
||||
const LabelCardContent = ({ label, currentUserId }) => {
|
||||
const LabelCardContent = ({ label, currentUserId, onToggleActions }) => {
|
||||
// Check if current user owns this label
|
||||
const isOwnedByCurrentUser = label.created_by === currentUserId
|
||||
|
||||
@@ -128,6 +128,21 @@ const LabelCardContent = ({ label, currentUserId }) => {
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
<Box>
|
||||
{onToggleActions && (
|
||||
<IconButton
|
||||
color='neutral'
|
||||
variant='plain'
|
||||
size='sm'
|
||||
onClick={e => {
|
||||
e.stopPropagation()
|
||||
onToggleActions()
|
||||
}}
|
||||
>
|
||||
<MoreVert sx={{ fontSize: 18 }} />
|
||||
</IconButton>
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
@@ -142,6 +157,7 @@ const LabelView = () => {
|
||||
const [currentLabel, setCurrentLabel] = useState(null)
|
||||
const queryClient = useQueryClient()
|
||||
const [confirmationModel, setConfirmationModel] = useState({})
|
||||
const [showMoreInfoId, setShowMoreInfoId] = useState(null)
|
||||
|
||||
const handleAddLabel = () => {
|
||||
setCurrentLabel(null)
|
||||
@@ -260,6 +276,7 @@ const LabelView = () => {
|
||||
{userLabels.map(label => (
|
||||
<SwipeableListItem
|
||||
key={label.id}
|
||||
swipeActionOpen={showMoreInfoId === label.id ? 'trailing' : null}
|
||||
trailingActions={
|
||||
<TrailingActions>
|
||||
<Box
|
||||
@@ -311,7 +328,17 @@ const LabelView = () => {
|
||||
</TrailingActions>
|
||||
}
|
||||
>
|
||||
<LabelCardContent label={label} currentUserId={userProfile?.id} />
|
||||
<LabelCardContent
|
||||
label={label}
|
||||
currentUserId={userProfile?.id}
|
||||
onToggleActions={() => {
|
||||
if (showMoreInfoId === label.id) {
|
||||
setShowMoreInfoId(null)
|
||||
} else {
|
||||
setShowMoreInfoId(label.id)
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</SwipeableListItem>
|
||||
))}
|
||||
</SwipeableList>
|
||||
|
||||
@@ -22,7 +22,7 @@ import {
|
||||
TrailingActions,
|
||||
} from '@meauxt/react-swipeable-list'
|
||||
import '@meauxt/react-swipeable-list/dist/styles.css'
|
||||
import { Add, Task } from '@mui/icons-material'
|
||||
import { Add, MoreVert, Task } from '@mui/icons-material'
|
||||
import { useQueryClient } from '@tanstack/react-query'
|
||||
import { useChores } from '../../queries/ChoreQueries'
|
||||
import { useUserProfile } from '../../queries/UserQueries'
|
||||
@@ -38,6 +38,7 @@ const ProjectCardContent = ({
|
||||
currentUserId,
|
||||
taskCounts = {},
|
||||
onCardClick,
|
||||
onToggleActions,
|
||||
}) => {
|
||||
// Check if current user owns this project
|
||||
const isOwnedByCurrentUser = project.created_by === currentUserId
|
||||
@@ -197,6 +198,21 @@ const ProjectCardContent = ({
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
<Box>
|
||||
{onToggleActions && (
|
||||
<IconButton
|
||||
color='neutral'
|
||||
variant='plain'
|
||||
size='sm'
|
||||
onClick={e => {
|
||||
e.stopPropagation()
|
||||
onToggleActions()
|
||||
}}
|
||||
>
|
||||
<MoreVert sx={{ fontSize: 18 }} />
|
||||
</IconButton>
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
@@ -215,6 +231,7 @@ const ProjectView = () => {
|
||||
const [taskCounts, setTaskCounts] = useState({})
|
||||
const queryClient = useQueryClient()
|
||||
const [confirmationModel, setConfirmationModel] = useState({})
|
||||
const [showMoreInfoId, setShowMoreInfoId] = useState(null)
|
||||
|
||||
const handleAddProject = () => {
|
||||
setCurrentProject(null)
|
||||
@@ -373,6 +390,9 @@ const ProjectView = () => {
|
||||
<SwipeableListItem
|
||||
onClick={() => handleCardClick(project)}
|
||||
key={project.id}
|
||||
swipeActionOpen={
|
||||
showMoreInfoId === project.id ? 'trailing' : null
|
||||
}
|
||||
trailingActions={
|
||||
<TrailingActions>
|
||||
<Box
|
||||
@@ -430,7 +450,13 @@ const ProjectView = () => {
|
||||
project={project}
|
||||
currentUserId={userProfile?.id}
|
||||
taskCounts={taskCounts}
|
||||
// onCardClick={}
|
||||
onToggleActions={() => {
|
||||
if (showMoreInfoId === project.id) {
|
||||
setShowMoreInfoId(null)
|
||||
} else {
|
||||
setShowMoreInfoId(project.id)
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</SwipeableListItem>
|
||||
))}
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
Delete,
|
||||
Edit,
|
||||
Flip,
|
||||
MoreVert,
|
||||
PlusOne,
|
||||
ToggleOff,
|
||||
ToggleOn,
|
||||
@@ -40,7 +41,7 @@ import ConfirmationModal from '../Modals/Inputs/ConfirmationModal'
|
||||
import CreateThingModal from '../Modals/Inputs/CreateThingModal'
|
||||
import EditThingStateModal from '../Modals/Inputs/EditThingState'
|
||||
|
||||
const ThingCardContent = ({ thing, onCardClick }) => {
|
||||
const ThingCardContent = ({ thing, onCardClick, onToggleActions }) => {
|
||||
const getThingIcon = type => {
|
||||
if (type === 'text') {
|
||||
return <Flip />
|
||||
@@ -183,6 +184,21 @@ const ThingCardContent = ({ thing, onCardClick }) => {
|
||||
</Chip>
|
||||
</Box>
|
||||
</Box>
|
||||
<Box>
|
||||
{onToggleActions && (
|
||||
<IconButton
|
||||
color='neutral'
|
||||
variant='plain'
|
||||
size='sm'
|
||||
onClick={e => {
|
||||
e.stopPropagation()
|
||||
onToggleActions()
|
||||
}}
|
||||
>
|
||||
<MoreVert sx={{ fontSize: 18 }} />
|
||||
</IconButton>
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
@@ -194,6 +210,7 @@ const ThingsView = () => {
|
||||
const [isShowEditThingStateModal, setIsShowEditStateModal] = useState(false)
|
||||
const [createModalThing, setCreateModalThing] = useState(null)
|
||||
const [confirmModelConfig, setConfirmModelConfig] = useState({})
|
||||
const [showMoreInfoId, setShowMoreInfoId] = useState(null)
|
||||
const { showError, showNotification } = useNotification()
|
||||
|
||||
useEffect(() => {
|
||||
@@ -388,6 +405,7 @@ const ThingsView = () => {
|
||||
<SwipeableListItem
|
||||
onClick={() => navigate(`/things/${thing?.id}`)}
|
||||
key={thing.id}
|
||||
swipeActionOpen={showMoreInfoId === thing.id ? 'trailing' : null}
|
||||
trailingActions={
|
||||
<TrailingActions>
|
||||
<Box
|
||||
@@ -474,7 +492,16 @@ const ThingsView = () => {
|
||||
</TrailingActions>
|
||||
}
|
||||
>
|
||||
<ThingCardContent thing={thing} />
|
||||
<ThingCardContent
|
||||
thing={thing}
|
||||
onToggleActions={() => {
|
||||
if (showMoreInfoId === thing.id) {
|
||||
setShowMoreInfoId(null)
|
||||
} else {
|
||||
setShowMoreInfoId(thing.id)
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</SwipeableListItem>
|
||||
))}
|
||||
</SwipeableList>
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
BrowseGallery,
|
||||
Delete,
|
||||
Edit,
|
||||
MoreVert,
|
||||
PauseCircle,
|
||||
Person,
|
||||
PlayArrow,
|
||||
@@ -56,6 +57,7 @@ const TimerDetails = () => {
|
||||
const [editingSessions, setEditingSessions] = useState({})
|
||||
const [currentTime, setCurrentTime] = useState(new Date())
|
||||
const [timerActionLoading, setTimerActionLoading] = useState(false)
|
||||
const [showMoreInfoId, setShowMoreInfoId] = useState(null)
|
||||
const { showError, showSuccess } = useNotification()
|
||||
|
||||
// Fetch circle members data
|
||||
@@ -940,6 +942,11 @@ const TimerDetails = () => {
|
||||
return (
|
||||
<SwipeableListItem
|
||||
key={pauseIndex}
|
||||
swipeActionOpen={
|
||||
showMoreInfoId === pauseIndex
|
||||
? 'trailing'
|
||||
: null
|
||||
}
|
||||
trailingActions={
|
||||
<TrailingActions>
|
||||
<Box
|
||||
@@ -1131,6 +1138,22 @@ const TimerDetails = () => {
|
||||
{endTime ? `→ ${endTime}` : '→ ongoing'}
|
||||
</Typography>
|
||||
</Box>
|
||||
|
||||
<IconButton
|
||||
color='neutral'
|
||||
variant='plain'
|
||||
size='sm'
|
||||
onClick={e => {
|
||||
e.stopPropagation()
|
||||
if (showMoreInfoId === pauseIndex) {
|
||||
setShowMoreInfoId(null)
|
||||
} else {
|
||||
setShowMoreInfoId(pauseIndex)
|
||||
}
|
||||
}}
|
||||
>
|
||||
<MoreVert sx={{ fontSize: 18 }} />
|
||||
</IconButton>
|
||||
</Card>
|
||||
</SwipeableListItem>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user