From 594c65d1a598922d0ba6826a0958643a6de024f6 Mon Sep 17 00:00:00 2001 From: elpatron Date: Sun, 7 Jun 2026 09:00:14 +0200 Subject: [PATCH] feat: make photo capture attachments section collapsible by default --- client/src/components/PhotoCapture.tsx | 252 ++++++++++++++----------- 1 file changed, 138 insertions(+), 114 deletions(-) diff --git a/client/src/components/PhotoCapture.tsx b/client/src/components/PhotoCapture.tsx index efd802b..ee594f2 100644 --- a/client/src/components/PhotoCapture.tsx +++ b/client/src/components/PhotoCapture.tsx @@ -9,7 +9,7 @@ import { saveEntryPhoto, deleteEntryPhoto } from '../services/photoAttachments.j import { fileToCompressedJpegDataUrl } from '../utils/imageCompress.js' import { useLiveQuery } from 'dexie-react-hooks' import { useDialog } from './ModalDialog.tsx' -import { Camera, Image, Trash2, X } from 'lucide-react' +import { Camera, Image, Trash2, X, ChevronDown, ChevronUp } from 'lucide-react' import { probeCameraAvailability } from '../utils/cameraAvailability.js' interface PhotoCaptureProps { @@ -29,6 +29,7 @@ interface DecryptedPhoto { export default function PhotoCapture({ entryId, logbookId, readOnly = false, preloadedPhotos }: PhotoCaptureProps) { const { t } = useTranslation() const { showConfirm } = useDialog() + const [collapsed, setCollapsed] = useState(true) const [caption, setCaption] = useState('') const [uploading, setUploading] = useState(false) const [error, setError] = useState(null) @@ -165,133 +166,156 @@ export default function PhotoCapture({ entryId, logbookId, readOnly = false, pre return (
-
- -

{t('logs.photos_title')}

+
setCollapsed(!collapsed)} + onKeyDown={(e) => { + if (e.key === 'Enter' || e.key === ' ') { + e.preventDefault() + setCollapsed(!collapsed) + } + }} + role="button" + aria-expanded={!collapsed} + tabIndex={0} + > +
+ +

{t('logs.photos_title')}

+
+ {collapsed ? ( + + ) : ( + + )}
- {error &&
{error}
} + {!collapsed && ( +
+ {error &&
{error}
} - {/* Upload area */} - {/* Upload Form */} - {!readOnly && ( -
-
-
- - setCaption(e.target.value)} - disabled={uploading} - /> -
+ {/* Upload area */} + {/* Upload Form */} + {!readOnly && ( +
+
+
+ + setCaption(e.target.value)} + disabled={uploading} + /> +
- + - + - {hasCamera ? ( - <> - - - - ) : ( - + + ) : ( - - )} - {uploading ? t('logs.photo_processing') : t('logs.photo_btn')} - - )} -
-
- )} - - {/* Photo Grid */} - {decryptedPhotos.length === 0 ? ( -
{t('logs.no_photos')}
- ) : ( -
- {decryptedPhotos.map((photo) => ( -
setMaximizedPhoto(photo)} - style={{ cursor: 'pointer' }} - > -
- {photo.caption - {!readOnly && ( )}
- {photo.caption && ( -
- {photo.caption} -
- )}
- ))} + )} + + {/* Photo Grid */} + {decryptedPhotos.length === 0 ? ( +
{t('logs.no_photos')}
+ ) : ( +
+ {decryptedPhotos.map((photo) => ( +
setMaximizedPhoto(photo)} + style={{ cursor: 'pointer' }} + > +
+ {photo.caption + {!readOnly && ( + + )} +
+ {photo.caption && ( +
+ {photo.caption} +
+ )} +
+ ))} +
+ )}
)}