import { useRoute, useLocation, Link } from "wouter"; import { useQuery, useMutation } from "@tanstack/react-query"; import { useState } from "react"; import { useAuth } from "@/hooks/useAuth"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Textarea } from "@/components/ui/textarea"; import { Card } from "@/components/ui/card"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Badge } from "@/components/ui/badge"; import { Eye, MessageCircle, ThumbsUp, Pin, Search, Info, Settings, User, LogOut } from "lucide-react"; import type { MediaOutlet, CommunityPost } from "@shared/schema"; import { queryClient, apiRequest } from "@/lib/queryClient"; import SearchModal from "@/components/SearchModal"; import LoginModal from "@/components/LoginModal"; export default function Community() { const [, params] = useRoute("/media/:slug/community"); const [, setLocation] = useLocation(); const { user, isAuthenticated } = useAuth(); const [isNewPostOpen, setIsNewPostOpen] = useState(false); const [sortBy, setSortBy] = useState("latest"); const [searchTerm, setSearchTerm] = useState(""); const [isSearchModalOpen, setIsSearchModalOpen] = useState(false); const [isLoginModalOpen, setIsLoginModalOpen] = useState(false); const [enlargedImage, setEnlargedImage] = useState(null); const slug = params?.slug || ''; const { data: outlet, isLoading: outletLoading } = useQuery({ queryKey: ["/api/media-outlets", slug], enabled: !!slug }); const { data: posts = [], isLoading: postsLoading } = useQuery({ queryKey: [`/api/media-outlets/${slug}/community?sort=${sortBy}`], enabled: !!slug && !!outlet }); const createPostMutation = useMutation({ mutationFn: async (data: { title: string; content: string; imageUrl?: string }) => { return await apiRequest("POST", `/api/media-outlets/${slug}/community`, data); }, onSuccess: () => { queryClient.invalidateQueries({ predicate: (query) => query.queryKey[0]?.toString().startsWith(`/api/media-outlets/${slug}/community`) ?? false }); setIsNewPostOpen(false); } }); const handleLogout = async () => { try { const response = await fetch("/api/logout", { method: "POST", credentials: "include", }); if (response.ok) { window.location.href = "/"; } } catch (error) { console.error("Logout failed:", error); } }; const handleAdminPage = () => { if (user?.role === "admin" || user?.role === "superadmin") { setLocation("/admin"); } }; const formatTimeAgo = (createdAt: Date | string | null) => { if (!createdAt) return ""; const now = new Date(); const postDate = new Date(createdAt); const diffInMs = now.getTime() - postDate.getTime(); const diffInMinutes = Math.floor(diffInMs / 60000); if (diffInMinutes < 1) return "방금"; if (diffInMinutes < 60) return `${diffInMinutes}분 전`; const diffInHours = Math.floor(diffInMinutes / 60); if (diffInHours < 24) return `${diffInHours}시간 전`; const diffInDays = Math.floor(diffInHours / 24); if (diffInDays < 30) return `${diffInDays}일 전`; return postDate.toLocaleDateString('ko-KR'); }; const filteredPosts = posts.filter(post => searchTerm === "" || post.title.toLowerCase().includes(searchTerm.toLowerCase()) || post.content.toLowerCase().includes(searchTerm.toLowerCase()) ); const pinnedPosts = filteredPosts.filter(post => post.isPinned || post.isNotice); const regularPosts = filteredPosts.filter(post => !post.isPinned && !post.isNotice); if (outletLoading) { return (

로딩 중...

); } if (!outlet) { return
미디어 아울렛을 찾을 수 없습니다
; } return (
{/* Header */}
{outlet.imageUrl ? ( {outlet.name} setEnlargedImage(outlet.imageUrl!)} data-testid="image-outlet-header-profile" /> ) : (
{outlet.name.charAt(0)}
)}
setLocation(`/media/${slug}`)}> SAPIENS
{outlet.name}
setIsSearchModalOpen(true)} data-testid="search-container" >
{isAuthenticated && user && (
{(user.role === 'admin' || user.role === 'superadmin') && ( )} {user.firstName || user.email}
)}
setIsSearchModalOpen(false)} /> {enlargedImage && (
setEnlargedImage(null)} > Enlarged view
)} {/* Community Content */}
{/* Community Header */}

{outlet.name} 커뮤니티

자유롭게 의견을 나눠보세요

새 글 작성
{ e.preventDefault(); const formData = new FormData(e.currentTarget); createPostMutation.mutate({ title: formData.get('title') as string, content: formData.get('content') as string, imageUrl: formData.get('imageUrl') as string || undefined }); }}>