"use client"; import { useEffect, useState } from "react"; import { useSession } from "next-auth/react"; import { Play, ChevronLeft, Server, Music, Loader2, SearchX, MonitorPlay, Disc } from "lucide-react"; import { ViewMode } from "@/app/page"; // 🌟 [좔가됨] μ „μ—­ ν† μŠ€νŠΈ ν›… 뢈러였기 import { useToast } from "@/components/ToastProvider"; import type { DiscordServer, SearchTrack, SearchResults } from "@/types/music"; interface MainContentProps { viewMode: ViewMode; setViewMode: (mode: ViewMode) => void; selectedServer: DiscordServer | null; setSelectedServer: (server: DiscordServer | null) => void; searchQuery: string; setSearchQuery: (query: string) => void; onSelectServer: (server: DiscordServer) => void; } export default function MainContent({ viewMode, setViewMode, selectedServer, setSelectedServer, searchQuery, setSearchQuery, onSelectServer, }: MainContentProps) { const { data: session, status } = useSession(); // 🌟 [좔가됨] 훅을 μ‹€ν–‰ν•΄μ„œ showToast ν•¨μˆ˜ κΊΌλ‚΄κΈ° const { showToast } = useToast(); const [servers, setServers] = useState([]); const [isFetching, setIsFetching] = useState(false); const [searchResults, setSearchResults] = useState({ spotify: [], youtubeMusic: [], youtubeVideo: [] }); const [isSearching, setIsSearching] = useState(false); const handleMusicAction = async (actionType: 'player_play' | 'player_playlist', track?: SearchTrack, playlistUrl?: string) => { if (!selectedServer) { // 🌟 alert -> showToast ꡐ체 showToast("λͺ…령을 내릴 λ””μŠ€μ½”λ“œ μ„œλ²„κ°€ μ„ νƒλ˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€.", "error"); return; } const userId = session?.user?.id; if (!userId) { showToast("둜그인이 ν•„μš”ν•©λ‹ˆλ‹€.", "error"); return; } let endpoint = ""; const bodyData: Record = { serverId: selectedServer.id }; if (actionType === 'player_play') { endpoint = "/api/player/play"; bodyData.track = track; } else if (actionType === 'player_playlist') { endpoint = "/api/player/playlist"; bodyData.playlistUrl = playlistUrl; } try { const res = await fetch(endpoint, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(bodyData), }); const data = await res.json(); if (res.ok && data.success) { // 🌟 성곡 μ‹œ μ΄ˆλ‘μƒ‰ μ•Œλ¦Ό showToast("μž¬μƒλͺ©λ‘μ— 곑을 μΆ”κ°€ν–ˆμŠ΅λ‹ˆλ‹€!", "success"); } else { // 🌟 μ—λŸ¬ μ‹œ 빨간색 μ•Œλ¦Ό showToast(data.message || data.error || "μš”μ²­ 처리 쀑 λ¬Έμ œκ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€.", "error"); } } catch (error) { console.error("Music Action Error:", error); // 🌟 λ„€νŠΈμ›Œν¬ μ—λŸ¬ μ‹œ μ•Œλ¦Ό showToast('μ„œλ²„μ™€ 톡신할 수 μ—†μŠ΅λ‹ˆλ‹€.', "error"); } }; const getPermissionLabel = (server: DiscordServer | null) => { if (!server) return "μ•Œ 수 μ—†μŒ"; if (server.owner) return "πŸ‘‘ μ„œλ²„ 주인"; // Discord permissions λŠ” 큰 μ •μˆ˜ λ¬Έμžμ—΄λ‘œ 도착함. 숫자/λ¬Έμžμ—΄λ§Œ λ°›μ•„ μ•ˆμ „ν•˜κ²Œ BigInt ν™”. const raw: unknown = server.permissions; if (typeof raw !== "string" && typeof raw !== "number") return "πŸ‘€ 일반 멀버"; try { const perms = BigInt(raw); if ((perms & 0x8n) === 0x8n) return "πŸ› οΈ κ΄€λ¦¬μž"; if ((perms & 0x20n) === 0x20n) return "βš™οΈ λ§€λ‹ˆμ €"; return "πŸ‘€ 일반 멀버"; } catch { return "πŸ‘€ 일반 멀버"; } }; useEffect(() => { if (status === "authenticated") { setIsFetching(true); const cached = sessionStorage.getItem("filtered_servers"); if (cached) { try { const parsed = JSON.parse(cached); if (Array.isArray(parsed)) { setServers(parsed); setIsFetching(false); } } catch { // μΊμ‹œ 손상 μ‹œ λ¬΄μ‹œν•˜κ³  μ•„λž˜ fetch둜 μƒˆλ‘œ λ°›λŠ”λ‹€. sessionStorage.removeItem("filtered_servers"); } } fetch("/api/servers") .then((res) => res.json()) .then((data) => { if (Array.isArray(data)) { setServers(data); sessionStorage.setItem("filtered_servers", JSON.stringify(data)); } }) .finally(() => setIsFetching(false)); } }, [status]); useEffect(() => { if (viewMode === "SEARCH_RESULT" && searchQuery) { setIsSearching(true); setSearchResults({ spotify: [], youtubeMusic: [], youtubeVideo: [] }); fetch(`/api/search?q=${encodeURIComponent(searchQuery)}`) .then(async (res) => { const data = await res.json(); if (res.ok && data) { setSearchResults({ spotify: data.spotify || [], youtubeMusic: data.youtubeMusic || [], youtubeVideo: data.youtubeVideo || [] }); } else { console.error("Search Error:", data); } }) .catch(err => console.error("Fetch Error:", err)) .finally(() => setIsSearching(false)); } }, [viewMode, searchQuery]); if (status === "unauthenticated") { return (

둜그인이 ν•„μš”ν•©λ‹ˆλ‹€

μ„œλΉ„μŠ€λ₯Ό μ΄μš©ν•˜μ‹œλ €λ©΄ λ””μŠ€μ½”λ“œ λ‘œκ·ΈμΈμ„ ν•΄μ£Όμ„Έμš”.

); } if (status === "loading") return
; const hasAnyResults = searchResults.spotify.length > 0 || searchResults.youtubeMusic.length > 0 || searchResults.youtubeVideo.length > 0; const renderTrackCard = (track: SearchTrack) => (
{track.thumbnail && {track.title}}

{track.title}

{track.artist}

); return (
{/* ν™”λ©΄ 1: μ„œλ²„ λͺ©λ‘ */} {viewMode === "SERVER_LIST" && ( <>

접속 쀑인 μ„œλ²„ 선택

{isFetching && servers.length === 0 ? (

μ„œλ²„ λͺ©λ‘μ„ λΆˆλŸ¬μ˜€λŠ” 쀑...

) : (
{servers.map((server) => (
onSelectServer(server)} className="bg-neutral-800/40 p-3 rounded-xl hover:bg-neutral-800 transition-all cursor-pointer group border border-transparent hover:border-neutral-700 shadow-md w-full" >
{server.icon ? ( ) : ( )}

{server.name}

))}
)} )} {/* ν™”λ©΄ 2: μ„œλ²„ 상세 λŒ€μ‹œλ³΄λ“œ */} {viewMode === "SERVER_DETAIL" && selectedServer && (
{selectedServer.icon ? ( ) : }
μ„œλ²„ λŒ€μ‹œλ³΄λ“œ

{selectedServer.name}

이 μ„œλ²„μ—μ„œ μŒμ•… 봇이 ν™œλ°œν•˜κ²Œ μž‘λ™ μ€‘μž…λ‹ˆλ‹€.

상세 정보

μ„œλ²„ 고유 ID

{selectedServer.id}

λ‚˜μ˜ μ„œλ²„ κΆŒν•œ

{getPermissionLabel(selectedServer)}

)} {/* ν™”λ©΄ 3: 검색 κ²°κ³Ό λͺ©λ‘ (3κ°€μ§€ μΉ΄ν…Œκ³ λ¦¬λ‘œ λΆ„ν• ) */} {viewMode === "SEARCH_RESULT" && (

“{searchQuery}” 검색 κ²°κ³Ό

μž…λ ₯ν•˜μ‹  검색어에 λŒ€ν•œ ν”Œλž«νΌλ³„ κ²°κ³Όμž…λ‹ˆλ‹€.

{isSearching ? (

λ…Έλž˜λ₯Ό μ°ΎλŠ” μ€‘μž…λ‹ˆλ‹€...

) : !hasAnyResults ? (

검색 κ²°κ³Όκ°€ μ—†μŠ΅λ‹ˆλ‹€.

) : (
{/* μΉ΄ν…Œκ³ λ¦¬ 1: Spotify */} {searchResults.spotify.length > 0 && (

Spotify κ²°κ³Ό

{searchResults.spotify.map(renderTrackCard)}
)} {/* μΉ΄ν…Œκ³ λ¦¬ 2: YouTube Music */} {searchResults.youtubeMusic.length > 0 && (

YouTube Music

{searchResults.youtubeMusic.map(renderTrackCard)}
)} {/* μΉ΄ν…Œκ³ λ¦¬ 3: YouTube Video */} {searchResults.youtubeVideo.length > 0 && (

YouTube μ˜μƒ

{searchResults.youtubeVideo.map(renderTrackCard)}
)}
)}
)}
); }