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: 3, version: '1.0.0', name: '테스트 서버 모드팩', date: '2024-12-01', size: '8.0 MB' },
|
||||
]);
|
||||
const [modpackDeleteTarget, setModpackDeleteTarget] = useState(null); // 삭제 확인 다이얼로그용
|
||||
|
||||
// 권한 확인
|
||||
useEffect(() => {
|
||||
|
|
@ -1614,12 +1615,7 @@ export default function Admin({ isMobile = false }) {
|
|||
<Pencil size={14} />
|
||||
</button>
|
||||
<button
|
||||
onClick={() => {
|
||||
if (confirm(`${pack.name} v${pack.version}을(를) 삭제하시겠습니까?`)) {
|
||||
setModpacks(prev => prev.filter(p => p.id !== pack.id));
|
||||
setToast('모드팩이 삭제되었습니다.');
|
||||
}
|
||||
}}
|
||||
onClick={() => setModpackDeleteTarget(pack)}
|
||||
className="p-1.5 text-zinc-400 hover:text-red-400 transition-colors"
|
||||
>
|
||||
<Trash2 size={14} />
|
||||
|
|
@ -1659,12 +1655,7 @@ export default function Admin({ isMobile = false }) {
|
|||
<Pencil size={16} />
|
||||
</button>
|
||||
<button
|
||||
onClick={() => {
|
||||
if (confirm(`${pack.name} v${pack.version}을(를) 삭제하시겠습니까?`)) {
|
||||
setModpacks(prev => prev.filter(p => p.id !== pack.id));
|
||||
setToast('모드팩이 삭제되었습니다.');
|
||||
}
|
||||
}}
|
||||
onClick={() => setModpackDeleteTarget(pack)}
|
||||
className="p-2 text-zinc-400 hover:text-red-400 transition-colors"
|
||||
title="삭제"
|
||||
>
|
||||
|
|
@ -2012,6 +2003,55 @@ export default function Admin({ isMobile = false }) {
|
|||
</motion.div>
|
||||
)}
|
||||
</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>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue