mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-06-21 22:31:46 +00:00
refactoring: TypeScript migration, security fixes,
This commit is contained in:
+23
-5
@@ -1,11 +1,22 @@
|
||||
import React, { useState, useMemo } from 'react'
|
||||
import { useState, useMemo } from 'react'
|
||||
import { PhotoLightbox } from './PhotoLightbox'
|
||||
import { PhotoUpload } from './PhotoUpload'
|
||||
import { Upload, Camera } from 'lucide-react'
|
||||
import Modal from '../shared/Modal'
|
||||
import { useTranslation } from '../../i18n'
|
||||
import type { Photo, Place, Day } from '../../types'
|
||||
|
||||
export default function PhotoGallery({ photos, onUpload, onDelete, onUpdate, places, days, tripId }) {
|
||||
interface PhotoGalleryProps {
|
||||
photos: Photo[]
|
||||
onUpload: (fd: FormData) => Promise<void>
|
||||
onDelete: (photoId: number) => Promise<void>
|
||||
onUpdate: (photoId: number, data: Partial<Photo>) => Promise<void>
|
||||
places: Place[]
|
||||
days: Day[]
|
||||
tripId: number
|
||||
}
|
||||
|
||||
export default function PhotoGallery({ photos, onUpload, onDelete, onUpdate, places, days, tripId }: PhotoGalleryProps) {
|
||||
const { t } = useTranslation()
|
||||
const [lightboxIndex, setLightboxIndex] = useState(null)
|
||||
const [showUpload, setShowUpload] = useState(false)
|
||||
@@ -153,7 +164,14 @@ export default function PhotoGallery({ photos, onUpload, onDelete, onUpdate, pla
|
||||
)
|
||||
}
|
||||
|
||||
function PhotoThumbnail({ photo, days, places, onClick }) {
|
||||
interface PhotoThumbnailProps {
|
||||
photo: Photo
|
||||
days: Day[]
|
||||
places: Place[]
|
||||
onClick: () => void
|
||||
}
|
||||
|
||||
function PhotoThumbnail({ photo, days, places, onClick }: PhotoThumbnailProps) {
|
||||
const day = days?.find(d => d.id === photo.day_id)
|
||||
const place = places?.find(p => p.id === photo.place_id)
|
||||
|
||||
@@ -168,8 +186,8 @@ function PhotoThumbnail({ photo, days, places, onClick }) {
|
||||
className="w-full h-full object-cover transition-transform duration-200 group-hover:scale-105"
|
||||
loading="lazy"
|
||||
onError={e => {
|
||||
e.target.style.display = 'none'
|
||||
e.target.nextSibling && (e.target.nextSibling.style.display = 'flex')
|
||||
(e.target as HTMLImageElement).style.display = 'none'
|
||||
const next = (e.target as HTMLImageElement).nextSibling as HTMLElement; if (next) next.style.display = 'flex'
|
||||
}}
|
||||
/>
|
||||
|
||||
+14
-2
@@ -1,8 +1,20 @@
|
||||
import React, { useState, useEffect, useCallback } from 'react'
|
||||
import { useState, useEffect, useCallback } from 'react'
|
||||
import { X, ChevronLeft, ChevronRight, Edit2, Trash2, Check } from 'lucide-react'
|
||||
import { useTranslation } from '../../i18n'
|
||||
import type { Photo, Place, Day } from '../../types'
|
||||
|
||||
export function PhotoLightbox({ photos, initialIndex, onClose, onUpdate, onDelete, days, places, tripId }) {
|
||||
interface PhotoLightboxProps {
|
||||
photos: Photo[]
|
||||
initialIndex: number
|
||||
onClose: () => void
|
||||
onUpdate: (photoId: number, data: Partial<Photo>) => Promise<void>
|
||||
onDelete: (photoId: number) => Promise<void>
|
||||
days: Day[]
|
||||
places: Place[]
|
||||
tripId: number
|
||||
}
|
||||
|
||||
export function PhotoLightbox({ photos, initialIndex, onClose, onUpdate, onDelete, days, places, tripId }: PhotoLightboxProps) {
|
||||
const { t } = useTranslation()
|
||||
const [index, setIndex] = useState(initialIndex || 0)
|
||||
const [editCaption, setEditCaption] = useState(false)
|
||||
+12
-3
@@ -1,9 +1,18 @@
|
||||
import React, { useState, useCallback } from 'react'
|
||||
import { useState, useCallback } from 'react'
|
||||
import { useDropzone } from 'react-dropzone'
|
||||
import { Upload, X, Image } from 'lucide-react'
|
||||
import { useTranslation } from '../../i18n'
|
||||
import type { Place, Day } from '../../types'
|
||||
|
||||
export function PhotoUpload({ tripId, days, places, onUpload, onClose }) {
|
||||
interface PhotoUploadProps {
|
||||
tripId: number
|
||||
days: Day[]
|
||||
places: Place[]
|
||||
onUpload: (fd: FormData) => Promise<void>
|
||||
onClose: () => void
|
||||
}
|
||||
|
||||
export function PhotoUpload({ tripId, days, places, onUpload, onClose }: PhotoUploadProps) {
|
||||
const { t } = useTranslation()
|
||||
const [files, setFiles] = useState([])
|
||||
const [dayId, setDayId] = useState('')
|
||||
@@ -48,7 +57,7 @@ export function PhotoUpload({ tripId, days, places, onUpload, onClose }) {
|
||||
await onUpload(formData)
|
||||
files.forEach(f => URL.revokeObjectURL(f.preview))
|
||||
setFiles([])
|
||||
} catch (err) {
|
||||
} catch (err: unknown) {
|
||||
console.error('Upload failed:', err)
|
||||
} finally {
|
||||
setUploading(false)
|
||||
Reference in New Issue
Block a user