diff --git a/src/pages/travel/Travel.css b/src/pages/travel/Travel.css index 3c7dacb..4782a25 100644 --- a/src/pages/travel/Travel.css +++ b/src/pages/travel/Travel.css @@ -200,6 +200,24 @@ .tv-map { height: 300px; } + + /* 지도 높이 축소 */ + .tv-map { + height: 35vh !important; + } + + /* 라이트박스 풀스크린 */ + .lightbox { + border-radius: 0; + } + + .lightbox__inner { + max-width: 100vw; + max-height: 100vh; + width: 100vw; + height: 100vh; + border-radius: 0; + } } /* Leaflet map tooltip override */ @@ -1020,6 +1038,10 @@ .photo-card--wide { grid-column: span 2; } + + .photo-mosaic { + grid-template-columns: 1fr; + } } /* ═══════════════════════════════════════════════════ diff --git a/src/pages/travel/Travel.jsx b/src/pages/travel/Travel.jsx index 0703369..14a5b29 100644 --- a/src/pages/travel/Travel.jsx +++ b/src/pages/travel/Travel.jsx @@ -2,6 +2,8 @@ import React, { useCallback, useEffect, useRef, useState } from 'react'; import { GeoJSON, MapContainer, TileLayer, useMap } from 'react-leaflet'; import 'leaflet/dist/leaflet.css'; import './Travel.css'; +import { useIsMobile } from '../../hooks/useIsMobile'; +import PullToRefresh from '../../components/PullToRefresh'; /* ───────────────────────────────────────────── Constants @@ -547,6 +549,8 @@ const Travel = () => { const [page, setPage] = useState(1); const [hasNext, setHasNext] = useState(true); + const isMobile = useIsMobile(); + const touchStartXRef = useRef(null); const pendingAdvanceRef = useRef(null); const toastTimerRef = useRef(null); @@ -685,6 +689,34 @@ const Travel = () => { } }, [hasNext, loading, loadingMore, page, photoSummary, selectedRegion]); + /* ── Reload photos (pull-to-refresh) ──── */ + const reloadPhotos = useCallback(async () => { + if (!selectedRegion) return; + cacheRef.current.delete(selectedRegion.id); + const res = await fetch( + `/api/travel/photos?region=${encodeURIComponent(selectedRegion.id)}&page=1&size=${PAGE_SIZE}` + ); + if (!res.ok) throw new Error(`지역 사진 로딩 실패 (${res.status})`); + const json = await res.json(); + const items = Array.isArray(json) ? json : json.items ?? []; + const meta = Array.isArray(json) ? {} : json ?? {}; + const normalized = normalizePhotos(items); + const nextHasNext = typeof meta.has_next === 'boolean' + ? meta.has_next + : typeof meta.hasNext === 'boolean' ? meta.hasNext : normalized.length >= PAGE_SIZE; + const summary = hasSummaryInfo(meta) + ? { total: meta.total, albums: meta.matched_albums ?? [] } + : null; + setPhotos(normalized); + setPage(2); + setHasNext(nextHasNext); + cacheRef.current.set(selectedRegion.id, { + timestamp: Date.now(), + items: normalized, page: 2, hasNext: nextHasNext, summary, + }); + if (summary) setPhotoSummary(summary); + }, [selectedRegion]); + /* ── Slide helpers ─────────────────────── */ const bumpSlide = (dir) => { setSlideDirection(dir); @@ -921,7 +953,7 @@ const Travel = () => { {/* ── Photo Mosaic ─────────────────── */} {!loading && !error && selectedRegion && photos.length > 0 && ( - <> +
{ hasNext={hasNext} isLoadingMore={loadingMore} /> - + )}