feat: 모드팩 배포 시스템 UI 구현
- 사용자 페이지 (/modpack): GitHub Release 스타일 UI - 버전별 카드, 변경 로그/콘텐츠 접이식 표시 - framer-motion 애니메이션 적용 - 관리자 콘솔: 모드팩 탭 추가 - 목록 조회, 업로드/수정/삭제 다이얼로그 - 모바일/데스크톱 분기 처리 (세로 카드 / 가로 레이아웃) - 모바일 바텀 네비게이션 - Sidebar: 모드팩 메뉴 추가 (월드맵 아래)
This commit is contained in:
parent
81ed6ebf9c
commit
7532bff8aa
1 changed files with 52 additions and 12 deletions
|
|
@ -132,6 +132,7 @@ export default function Admin({ isMobile = false }) {
|
||||||
{ id: 2, version: '1.1.0', name: '테스트 서버 모드팩', date: '2024-12-15', size: '12.0 MB' },
|
{ id: 2, version: '1.1.0', name: '테스트 서버 모드팩', date: '2024-12-15', size: '12.0 MB' },
|
||||||
{ id: 3, version: '1.0.0', name: '테스트 서버 모드팩', date: '2024-12-01', size: '8.0 MB' },
|
{ id: 3, version: '1.0.0', name: '테스트 서버 모드팩', date: '2024-12-01', size: '8.0 MB' },
|
||||||
]);
|
]);
|
||||||
|
const [modpackDeleteTarget, setModpackDeleteTarget] = useState(null); // 삭제 확인 다이얼로그용
|
||||||
|
|
||||||
// 권한 확인
|
// 권한 확인
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
@ -1614,12 +1615,7 @@ export default function Admin({ isMobile = false }) {
|
||||||
<Pencil size={14} />
|
<Pencil size={14} />
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={() => setModpackDeleteTarget(pack)}
|
||||||
if (confirm(`${pack.name} v${pack.version}을(를) 삭제하시겠습니까?`)) {
|
|
||||||
setModpacks(prev => prev.filter(p => p.id !== pack.id));
|
|
||||||
setToast('모드팩이 삭제되었습니다.');
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
className="p-1.5 text-zinc-400 hover:text-red-400 transition-colors"
|
className="p-1.5 text-zinc-400 hover:text-red-400 transition-colors"
|
||||||
>
|
>
|
||||||
<Trash2 size={14} />
|
<Trash2 size={14} />
|
||||||
|
|
@ -1659,12 +1655,7 @@ export default function Admin({ isMobile = false }) {
|
||||||
<Pencil size={16} />
|
<Pencil size={16} />
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={() => setModpackDeleteTarget(pack)}
|
||||||
if (confirm(`${pack.name} v${pack.version}을(를) 삭제하시겠습니까?`)) {
|
|
||||||
setModpacks(prev => prev.filter(p => p.id !== pack.id));
|
|
||||||
setToast('모드팩이 삭제되었습니다.');
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
className="p-2 text-zinc-400 hover:text-red-400 transition-colors"
|
className="p-2 text-zinc-400 hover:text-red-400 transition-colors"
|
||||||
title="삭제"
|
title="삭제"
|
||||||
>
|
>
|
||||||
|
|
@ -2012,6 +2003,55 @@ export default function Admin({ isMobile = false }) {
|
||||||
</motion.div>
|
</motion.div>
|
||||||
)}
|
)}
|
||||||
</AnimatePresence>
|
</AnimatePresence>
|
||||||
|
|
||||||
|
{/* 모드팩 삭제 확인 다이얼로그 */}
|
||||||
|
<AnimatePresence>
|
||||||
|
{modpackDeleteTarget && (
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0 }}
|
||||||
|
animate={{ opacity: 1 }}
|
||||||
|
exit={{ opacity: 0 }}
|
||||||
|
className="fixed inset-0 bg-black/50 backdrop-blur-sm flex items-center justify-center z-[100] p-4"
|
||||||
|
onClick={() => setModpackDeleteTarget(null)}
|
||||||
|
>
|
||||||
|
<motion.div
|
||||||
|
initial={{ scale: 0.9, opacity: 0 }}
|
||||||
|
animate={{ scale: 1, opacity: 1 }}
|
||||||
|
exit={{ scale: 0.9, opacity: 0 }}
|
||||||
|
className="bg-zinc-900 border border-zinc-800 rounded-2xl p-6 max-w-sm w-full"
|
||||||
|
onClick={e => e.stopPropagation()}
|
||||||
|
>
|
||||||
|
<div className="text-center mb-6">
|
||||||
|
<div className="w-12 h-12 bg-red-500/20 rounded-full flex items-center justify-center mx-auto mb-3">
|
||||||
|
<Trash2 className="text-red-400" size={24} />
|
||||||
|
</div>
|
||||||
|
<h3 className="text-white text-lg font-bold mb-2">모드팩 삭제</h3>
|
||||||
|
<p className="text-zinc-400 text-sm">
|
||||||
|
<span className="text-white font-medium">{modpackDeleteTarget.name} v{modpackDeleteTarget.version}</span>을(를) 삭제하시겠습니까?
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="flex gap-3">
|
||||||
|
<button
|
||||||
|
onClick={() => setModpackDeleteTarget(null)}
|
||||||
|
className="flex-1 px-4 py-2.5 bg-zinc-800 hover:bg-zinc-700 text-white rounded-xl font-medium transition-colors"
|
||||||
|
>
|
||||||
|
취소
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={() => {
|
||||||
|
setModpacks(prev => prev.filter(p => p.id !== modpackDeleteTarget.id));
|
||||||
|
setToast('모드팩이 삭제되었습니다.');
|
||||||
|
setModpackDeleteTarget(null);
|
||||||
|
}}
|
||||||
|
className="flex-1 px-4 py-2.5 bg-red-500 hover:bg-red-600 text-white rounded-xl font-medium transition-colors"
|
||||||
|
>
|
||||||
|
삭제
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
</motion.div>
|
||||||
|
)}
|
||||||
|
</AnimatePresence>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue