웹: AlbumDetail, AlbumGallery 페이지 useQuery로 리팩토링
This commit is contained in:
parent
443bd203ca
commit
dc65858d6b
4 changed files with 65 additions and 89 deletions
|
|
@ -1,6 +1,7 @@
|
|||
import { motion, AnimatePresence } from 'framer-motion';
|
||||
import { useState, useEffect, useCallback, useRef } from 'react';
|
||||
import { useState, useEffect, useCallback, useRef, useMemo } from 'react';
|
||||
import { useParams, useNavigate } from 'react-router-dom';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { Play, Calendar, Music2, Clock, X, Download, ChevronDown, ChevronUp, FileText, ChevronRight } from 'lucide-react';
|
||||
import { Swiper, SwiperSlide } from 'swiper/react';
|
||||
import { Virtual } from 'swiper/modules';
|
||||
|
|
@ -9,17 +10,21 @@ import { getAlbumByName } from '../../../api/public/albums';
|
|||
import { formatDate } from '../../../utils/date';
|
||||
import LightboxIndicator from '../../../components/common/LightboxIndicator';
|
||||
|
||||
// 모바일 앨범 상세 페이지
|
||||
function MobileAlbumDetail() {
|
||||
const { name } = useParams();
|
||||
const navigate = useNavigate();
|
||||
const [album, setAlbum] = useState(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [lightbox, setLightbox] = useState({ open: false, images: [], index: 0, showNav: true });
|
||||
const [showAllTracks, setShowAllTracks] = useState(false);
|
||||
const [showDescriptionModal, setShowDescriptionModal] = useState(false);
|
||||
const swiperRef = useRef(null);
|
||||
|
||||
// useQuery로 앨범 데이터 로드
|
||||
const { data: album, isLoading: loading } = useQuery({
|
||||
queryKey: ['album', name],
|
||||
queryFn: () => getAlbumByName(name),
|
||||
enabled: !!name,
|
||||
});
|
||||
|
||||
// 라이트박스 열기 - 히스토리 추가
|
||||
const openLightbox = useCallback((images, index, options = {}) => {
|
||||
setLightbox({ open: true, images, index, showNav: options.showNav !== false, teasers: options.teasers });
|
||||
|
|
@ -85,18 +90,6 @@ function MobileAlbumDetail() {
|
|||
return () => { document.body.style.overflow = ''; };
|
||||
}, [lightbox.open, showDescriptionModal]);
|
||||
|
||||
useEffect(() => {
|
||||
getAlbumByName(name)
|
||||
.then(data => {
|
||||
setAlbum(data);
|
||||
setLoading(false);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('앨범 로드 오류:', error);
|
||||
setLoading(false);
|
||||
});
|
||||
}, [name]);
|
||||
|
||||
// 총 재생 시간 계산
|
||||
const getTotalDuration = () => {
|
||||
if (!album?.tracks) return '';
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { useState, useEffect, useCallback, useRef } from 'react';
|
||||
import { useState, useEffect, useCallback, useRef, useMemo } from 'react';
|
||||
import { useParams, useNavigate } from 'react-router-dom';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { X, Download, ChevronRight, Info, Users, Tag } from 'lucide-react';
|
||||
import { motion, AnimatePresence } from 'framer-motion';
|
||||
import { Swiper, SwiperSlide } from 'swiper/react';
|
||||
|
|
@ -12,34 +13,29 @@ import LightboxIndicator from '../../../components/common/LightboxIndicator';
|
|||
function MobileAlbumGallery() {
|
||||
const { name } = useParams();
|
||||
const navigate = useNavigate();
|
||||
const [album, setAlbum] = useState(null);
|
||||
const [photos, setPhotos] = useState([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [selectedIndex, setSelectedIndex] = useState(null);
|
||||
const [showInfo, setShowInfo] = useState(false);
|
||||
const swiperRef = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
getAlbumByName(name)
|
||||
.then(data => {
|
||||
setAlbum(data);
|
||||
const allPhotos = [];
|
||||
if (data.conceptPhotos && typeof data.conceptPhotos === 'object') {
|
||||
Object.entries(data.conceptPhotos).forEach(([concept, photos]) => {
|
||||
photos.forEach(p => allPhotos.push({
|
||||
...p,
|
||||
concept: concept !== 'Default' ? concept : null
|
||||
}));
|
||||
});
|
||||
}
|
||||
setPhotos(allPhotos);
|
||||
setLoading(false);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('앨범 데이터 로드 오류:', error);
|
||||
setLoading(false);
|
||||
});
|
||||
}, [name]);
|
||||
// useQuery로 앨범 데이터 로드
|
||||
const { data: album, isLoading: loading } = useQuery({
|
||||
queryKey: ['album', name],
|
||||
queryFn: () => getAlbumByName(name),
|
||||
enabled: !!name,
|
||||
});
|
||||
|
||||
// 앨범 데이터에서 사진 목록 추출
|
||||
const photos = useMemo(() => {
|
||||
if (!album?.conceptPhotos) return [];
|
||||
const allPhotos = [];
|
||||
Object.entries(album.conceptPhotos).forEach(([concept, conceptPhotos]) => {
|
||||
conceptPhotos.forEach(p => allPhotos.push({
|
||||
...p,
|
||||
concept: concept !== 'Default' ? concept : null
|
||||
}));
|
||||
});
|
||||
return allPhotos;
|
||||
}, [album]);
|
||||
|
||||
// 라이트박스 열기 - 히스토리 추가
|
||||
const openLightbox = useCallback((index) => {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { useState, useEffect, useCallback, memo } from 'react';
|
||||
import { useParams, useNavigate } from 'react-router-dom';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { motion, AnimatePresence } from 'framer-motion';
|
||||
import { Calendar, Music2, Clock, X, ChevronLeft, ChevronRight, Download, MoreVertical, FileText } from 'lucide-react';
|
||||
import { getAlbumByName } from '../../../api/public/albums';
|
||||
|
|
@ -9,15 +10,20 @@ import LightboxIndicator from '../../../components/common/LightboxIndicator';
|
|||
function AlbumDetail() {
|
||||
const { name } = useParams();
|
||||
const navigate = useNavigate();
|
||||
const [album, setAlbum] = useState(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [lightbox, setLightbox] = useState({ open: false, images: [], index: 0 });
|
||||
const [slideDirection, setSlideDirection] = useState(0);
|
||||
const [imageLoaded, setImageLoaded] = useState(false);
|
||||
const [preloadedImages] = useState(() => new Set()); // 프리로드된 이미지 URL 추적
|
||||
const [preloadedImages] = useState(() => new Set());
|
||||
const [showDescriptionModal, setShowDescriptionModal] = useState(false);
|
||||
const [showMenu, setShowMenu] = useState(false);
|
||||
|
||||
// useQuery로 앨범 데이터 로드
|
||||
const { data: album, isLoading: loading } = useQuery({
|
||||
queryKey: ['album', name],
|
||||
queryFn: () => getAlbumByName(name),
|
||||
enabled: !!name,
|
||||
});
|
||||
|
||||
// 라이트박스 네비게이션 함수
|
||||
const goToPrev = useCallback(() => {
|
||||
if (lightbox.images.length <= 1) return;
|
||||
|
|
@ -125,18 +131,6 @@ function AlbumDetail() {
|
|||
});
|
||||
}, [lightbox.open, lightbox.index, lightbox.images, preloadedImages]);
|
||||
|
||||
useEffect(() => {
|
||||
getAlbumByName(name)
|
||||
.then(data => {
|
||||
setAlbum(data);
|
||||
setLoading(false);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('앨범 데이터 로드 오류:', error);
|
||||
setLoading(false);
|
||||
});
|
||||
}, [name]);
|
||||
|
||||
// URL 헬퍼 함수는 더 이상 필요 없음 - API에서 직접 제공
|
||||
|
||||
// 총 재생 시간 계산
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { useState, useEffect, useCallback, memo } from 'react';
|
||||
import { useState, useEffect, useCallback, memo, useMemo } from 'react';
|
||||
import { useParams, useNavigate } from 'react-router-dom';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { motion, AnimatePresence } from 'framer-motion';
|
||||
import { X, ChevronLeft, ChevronRight, Download } from 'lucide-react';
|
||||
import { RowsPhotoAlbum } from 'react-photo-album';
|
||||
|
|
@ -40,42 +41,34 @@ const galleryStyles = `
|
|||
function AlbumGallery() {
|
||||
const { name } = useParams();
|
||||
const navigate = useNavigate();
|
||||
const [album, setAlbum] = useState(null);
|
||||
const [photos, setPhotos] = useState([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [lightbox, setLightbox] = useState({ open: false, index: 0 });
|
||||
const [imageLoaded, setImageLoaded] = useState(false);
|
||||
const [slideDirection, setSlideDirection] = useState(0);
|
||||
const [preloadedImages] = useState(() => new Set()); // 프리로드된 이미지 URL 추적
|
||||
const [preloadedImages] = useState(() => new Set());
|
||||
|
||||
useEffect(() => {
|
||||
getAlbumByName(name)
|
||||
.then(data => {
|
||||
setAlbum(data);
|
||||
const allPhotos = [];
|
||||
// useQuery로 앨범 데이터 로드
|
||||
const { data: album, isLoading: loading } = useQuery({
|
||||
queryKey: ['album', name],
|
||||
queryFn: () => getAlbumByName(name),
|
||||
enabled: !!name,
|
||||
});
|
||||
|
||||
if (data.conceptPhotos && typeof data.conceptPhotos === 'object') {
|
||||
Object.entries(data.conceptPhotos).forEach(([concept, photos]) => {
|
||||
photos.forEach(p => allPhotos.push({
|
||||
// API에서 직접 제공하는 URL 및 크기 정보 사용
|
||||
mediumUrl: p.medium_url,
|
||||
originalUrl: p.original_url,
|
||||
width: p.width || 800,
|
||||
height: p.height || 1200,
|
||||
title: concept,
|
||||
members: p.members ? p.members.split(', ') : []
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
setPhotos(allPhotos);
|
||||
setLoading(false);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('앨범 데이터 로드 오류:', error);
|
||||
setLoading(false);
|
||||
});
|
||||
}, [name]);
|
||||
// 앨범 데이터에서 사진 목록 추출
|
||||
const photos = useMemo(() => {
|
||||
if (!album?.conceptPhotos) return [];
|
||||
const allPhotos = [];
|
||||
Object.entries(album.conceptPhotos).forEach(([concept, conceptPhotos]) => {
|
||||
conceptPhotos.forEach(p => allPhotos.push({
|
||||
mediumUrl: p.medium_url,
|
||||
originalUrl: p.original_url,
|
||||
width: p.width || 800,
|
||||
height: p.height || 1200,
|
||||
title: concept,
|
||||
members: p.members ? p.members.split(', ') : []
|
||||
}));
|
||||
});
|
||||
return allPhotos;
|
||||
}, [album]);
|
||||
|
||||
// 라이트박스 열기
|
||||
const openLightbox = (index) => {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue