import { AttachFile, Image } from '@mui/icons-material'
import {
Box,
CircularProgress,
List,
ListItem,
ListItemButton,
Typography,
} from '@mui/joy'
import { useEffect, useState } from 'react'
import EmptyState from '../../../components/common/EmptyState'
import ModalActions from '../../../components/common/ModalActions'
import { useResponsiveModal } from '../../../hooks/useResponsiveModal'
import { GetChoreAttachments } from '../../../utils/Fetcher'
import { resolvePhotoURL } from '../../../utils/Helpers'
import { cacheChoreImages, getImageSrc } from '../../../utils/ImageCache'
import AttachmentViewerModal from './AttachmentViewerModal'
import { useTranslation } from 'react-i18next'
const IMAGE_EXTENSIONS = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'bmp', 'svg']
const isImageFile = fileName => {
if (!fileName) return false
const ext = fileName.split('.').pop().toLowerCase()
return IMAGE_EXTENSIONS.includes(ext)
}
const downloadFile = (url, fileName) => {
const a = document.createElement('a')
a.href = url
a.download = fileName || 'attachment'
a.rel = 'noopener'
document.body.appendChild(a)
a.click()
document.body.removeChild(a)
}
function AttachmentBrowserModal({ choreId, isOpen, onClose }) {
const { t } = useTranslation('common')
const { ResponsiveModal } = useResponsiveModal()
const [attachments, setAttachments] = useState([])
const [isLoading, setIsLoading] = useState(false)
const [viewerConfig, setViewerConfig] = useState({ isOpen: false })
useEffect(() => {
if (!isOpen || !choreId) return
setIsLoading(true)
GetChoreAttachments(choreId)
.then(async res => {
if (!res.ok) throw new Error(t('chores:dataError.attachmentsFailed'))
return res.json()
})
.then(data => {
const list = Array.isArray(data) ? data : []
setAttachments(list)
// Fire-and-forget: store attachments so they open offline later
cacheChoreImages({ id: choreId, attachments: list })
})
.catch(() => setAttachments([]))
.finally(() => setIsLoading(false))
}, [isOpen, choreId, t])
const handleClose = () => {
setAttachments([])
onClose?.()
}
const handleAttachmentClick = async attachment => {
const url = await getImageSrc(
attachment.file_path,
attachment.sign ? resolvePhotoURL(attachment.sign) : null,
{ choreId: String(choreId), kind: 'attachment' },
).catch(() => resolvePhotoURL(attachment.sign))
if (isImageFile(attachment.file_name)) {
setViewerConfig({
isOpen: true,
url,
fileName: attachment.file_name,
onClose: () => setViewerConfig({ isOpen: false }),
})
} else {
downloadFile(url, attachment.file_name)
}
}
return (
<>
}
>
{isLoading ? (
) : attachments.length === 0 ? (
}
title='No attachments'
description='Photos and files added to this task will show up here.'
/>
) : (
{attachments.map((attachment, index) => (
handleAttachmentClick(attachment)}
sx={{ borderRadius: 'sm', gap: 1.5, py: 1 }}
>
{isImageFile(attachment.file_name) ? (
) : (
)}
{attachment.file_name || t('fileNumbered', { index: index + 1 })}
{attachment.size_bytes > 0 && (
{(attachment.size_bytes / 1024).toFixed(1)} KB
)}
))}
)}
>
)
}
export default AttachmentBrowserModal