feat: 앨범 상세 UI 개선 - 소개 스크롤, 작사/작곡 자동변환, 타입별 개수 표시

This commit is contained in:
caadiq 2026-01-02 17:04:27 +09:00
parent d9d1a447c4
commit 3c06a20ea4
5 changed files with 28 additions and 16 deletions

View file

@ -1,8 +1,10 @@
services: services:
# 프론트엔드 - Vite 개발 서버 # 프론트엔드 - Vite 개발 서버
fromis9-web: fromis9-frontend:
image: node:20-alpine image: node:20-alpine
container_name: fromis9-web container_name: fromis9-frontend
labels:
- "com.centurylinklabs.watchtower.enable=false"
working_dir: /app working_dir: /app
command: sh -c "npm install && npm run dev -- --host 0.0.0.0 --port 80" command: sh -c "npm install && npm run dev -- --host 0.0.0.0 --port 80"
volumes: volumes:

View file

@ -1,7 +1,9 @@
services: services:
fromis9-web: fromis9-web:
build: . build: .
container_name: fromis9-web container_name: fromis9-frontend
labels:
- "com.centurylinklabs.watchtower.enable=false"
env_file: env_file:
- .env - .env
networks: networks:

View file

@ -279,10 +279,12 @@ function AlbumDetail() {
className="col-span-1" className="col-span-1"
> >
<h2 className="text-xl font-bold mb-4">앨범 소개</h2> <h2 className="text-xl font-bold mb-4">앨범 소개</h2>
<div className="bg-white rounded-2xl shadow-lg p-6"> <div className="bg-white rounded-2xl shadow-lg overflow-hidden">
<p className="text-gray-600 leading-relaxed text-sm whitespace-pre-line"> <div className="max-h-[460px] overflow-y-auto p-6">
{album.description} <p className="text-gray-600 leading-relaxed text-sm whitespace-pre-line text-justify break-all">
</p> {album.description}
</p>
</div>
</div> </div>
</motion.div> </motion.div>
)} )}

View file

@ -35,11 +35,12 @@ function Discography() {
return titleTrack ? titleTrack.title : tracks[0].title; return titleTrack ? titleTrack.title : tracks[0].title;
}; };
// // (album_type_short )
const getAlbumType = (album) => album.album_type_short || album.album_type;
const albumStats = { const albumStats = {
정규: albums.filter(a => a.album_type === '정규').length, 정규: albums.filter(a => getAlbumType(a) === '정규').length,
미니: albums.filter(a => a.album_type === '미니').length, 미니: albums.filter(a => getAlbumType(a) === '미니').length,
싱글: albums.filter(a => a.album_type === '싱글').length, 싱글: albums.filter(a => getAlbumType(a) === '싱글').length,
: albums.length : albums.length
}; };

View file

@ -456,8 +456,14 @@ function AdminAlbumForm() {
}; };
const updateTrack = (index, field, value) => { const updateTrack = (index, field, value) => {
// // '' ( ) ', '
let processedValue = value;
if (['lyricist', 'composer', 'arranger'].includes(field)) {
processedValue = value.replace(/[|]/g, ', ');
}
setTracks(prev => prev.map((track, i) => setTracks(prev => prev.map((track, i) =>
i === index ? { ...track, [field]: value } : track i === index ? { ...track, [field]: processedValue } : track
)); ));
}; };
@ -746,7 +752,7 @@ function AdminAlbumForm() {
name="description" name="description"
value={formData.description} value={formData.description}
onChange={handleInputChange} onChange={handleInputChange}
rows={4} rows={8}
className="w-full px-4 py-2.5 border border-gray-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent resize-none" className="w-full px-4 py-2.5 border border-gray-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent resize-none"
placeholder="앨범에 대한 설명을 입력하세요..." placeholder="앨범에 대한 설명을 입력하세요..."
/> />
@ -830,7 +836,7 @@ function AdminAlbumForm() {
value={track.duration || ''} value={track.duration || ''}
onChange={(e) => updateTrack(index, 'duration', e.target.value)} onChange={(e) => updateTrack(index, 'duration', e.target.value)}
className="w-full px-3 py-2 border border-gray-200 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent text-center" className="w-full px-3 py-2 border border-gray-200 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent text-center"
placeholder="3:30" placeholder="0:00"
/> />
</div> </div>
</div> </div>
@ -857,7 +863,6 @@ function AdminAlbumForm() {
animate={{ height: 'auto', opacity: 1 }} animate={{ height: 'auto', opacity: 1 }}
exit={{ height: 0, opacity: 0 }} exit={{ height: 0, opacity: 0 }}
transition={{ duration: 0.2 }} transition={{ duration: 0.2 }}
className="overflow-hidden"
> >
{/* 작사/작곡/편곡 */} {/* 작사/작곡/편곡 */}
<div className="space-y-3 mt-3"> <div className="space-y-3 mt-3">
@ -912,7 +917,7 @@ function AdminAlbumForm() {
value={track.lyrics || ''} value={track.lyrics || ''}
onChange={(e) => updateTrack(index, 'lyrics', e.target.value)} onChange={(e) => updateTrack(index, 'lyrics', e.target.value)}
rows={12} rows={12}
className="w-full px-3 py-2 border border-gray-200 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent resize-y min-h-[200px]" className="w-full px-3 py-2 border border-gray-200 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent resize-none min-h-[200px]"
placeholder="가사를 입력하세요..." placeholder="가사를 입력하세요..."
/> />
</div> </div>