import { CheckCircle2, AlertCircle, TrendingUp, Building2, Wrench, Shield, User, Users, Crown, MessageSquare, MessageCircle, Clock, Calendar, Eye, EyeOff, } from "lucide-react" /** * Q&A 상태에 따른 아이콘 반환 */ export function getQnaStatusIcon(status: string) { switch (status) { case "answered": return CheckCircle2 case "unanswered": return AlertCircle case "popular": return TrendingUp default: return MessageSquare } } /** * 벤더 타입에 따른 아이콘 반환 */ export function getVendorTypeIcon(vendorType: string) { switch (vendorType) { case "vendor": return Building2 case "techVendor": return Wrench default: return Building2 } } /** * 사용자 도메인에 따른 아이콘 반환 */ export function getDomainIcon(domain: string) { switch (domain) { case "partners": return Users case "tech": return Wrench case "admin": return Shield default: return User } } /** * Q&A 상태에 따른 배지 색상 반환 */ export function getQnaStatusBadge(qna: { hasAnswers: boolean isPopular: boolean totalAnswers: number totalComments: number }) { const badges = [] if (qna.hasAnswers) { badges.push({ label: "답변됨", variant: "secondary" as const, icon: CheckCircle2, }) } else { badges.push({ label: "답변 대기", variant: "outline" as const, icon: AlertCircle, }) } if (qna.isPopular) { badges.push({ label: "인기", variant: "default" as const, icon: TrendingUp, }) } return badges } /** * 도메인에 따른 사용자 라벨 반환 */ export function getDomainLabel(domain: string) { switch (domain) { case "partners": return "협력업체" case "tech": return "기술업체" case "admin": return "관리자" default: return domain } } /** * 벤더 타입에 따른 라벨 반환 */ export function getVendorTypeLabel(vendorType: string) { switch (vendorType) { case "vendor": return "일반 벤더" case "techVendor": return "기술 벤더" default: return vendorType } } /** * Q&A 활동 통계 포맷팅 */ export function formatQnaStats(qna: { totalAnswers: number totalComments: number lastActivityAt?: Date | null }) { const stats = [] if (qna.totalAnswers > 0) { stats.push(`답변 ${qna.totalAnswers}개`) } if (qna.totalComments > 0) { stats.push(`댓글 ${qna.totalComments}개`) } if (stats.length === 0) { return "활동 없음" } return stats.join(" • ") } /** * 상대적 시간 포맷팅 (예: "3시간 전", "2일 전") */ export function formatRelativeTime(date: Date | string) { const now = new Date() const targetDate = new Date(date) const diffInMilliseconds = now.getTime() - targetDate.getTime() const diffInSeconds = Math.floor(diffInMilliseconds / 1000) const diffInMinutes = Math.floor(diffInSeconds / 60) const diffInHours = Math.floor(diffInMinutes / 60) const diffInDays = Math.floor(diffInHours / 24) const diffInMonths = Math.floor(diffInDays / 30) const diffInYears = Math.floor(diffInDays / 365) if (diffInSeconds < 60) { return "방금 전" } else if (diffInMinutes < 60) { return `${diffInMinutes}분 전` } else if (diffInHours < 24) { return `${diffInHours}시간 전` } else if (diffInDays < 30) { return `${diffInDays}일 전` } else if (diffInMonths < 12) { return `${diffInMonths}개월 전` } else { return `${diffInYears}년 전` } } /** * Q&A 우선순위 계산 (정렬용) */ export function calculateQnaPriority(qna: { hasAnswers: boolean isPopular: boolean totalAnswers: number totalComments: number lastActivityAt?: Date | null createdAt: Date }) { let priority = 0 // 답변이 없는 질문에 높은 우선순위 if (!qna.hasAnswers) { priority += 100 } // 인기 질문에 우선순위 추가 if (qna.isPopular) { priority += 50 } // 최근 활동에 따른 우선순위 if (qna.lastActivityAt) { const daysSinceActivity = Math.floor( (new Date().getTime() - new Date(qna.lastActivityAt).getTime()) / (1000 * 60 * 60 * 24) ) priority += Math.max(0, 30 - daysSinceActivity) // 최근 30일 내 활동 } // 활동량에 따른 우선순위 priority += Math.min(qna.totalAnswers * 2, 20) // 답변 수 (최대 20점) priority += Math.min(qna.totalComments, 10) // 댓글 수 (최대 10점) return priority } /** * Q&A 텍스트 요약 (미리보기용) */ export function truncateQnaContent(content: string, maxLength: number = 100) { // HTML 태그 제거 const textContent = content.replace(/<[^>]*>/g, "").trim() if (textContent.length <= maxLength) { return textContent } return textContent.slice(0, maxLength).trim() + "..." } /** * Q&A 검색 키워드 하이라이팅 */ export function highlightSearchKeywords(text: string, keywords: string) { if (!keywords.trim()) return text const keywordList = keywords.trim().split(/\s+/) let highlightedText = text keywordList.forEach(keyword => { const regex = new RegExp(`(${keyword})`, "gi") highlightedText = highlightedText.replace( regex, '$1' ) }) return highlightedText } /** * Q&A 필터 조건 검증 */ export function validateQnaFilters(filters: { search?: string authorDomain?: string[] vendorType?: string[] hasAnswers?: string dateRange?: { from?: Date; to?: Date } }) { const errors: string[] = [] // 검색어 길이 체크 if (filters.search && filters.search.length > 100) { errors.push("검색어는 100자 이하로 입력해주세요.") } // 날짜 범위 체크 if (filters.dateRange?.from && filters.dateRange?.to) { if (filters.dateRange.from > filters.dateRange.to) { errors.push("시작 날짜가 종료 날짜보다 늦을 수 없습니다.") } } return { isValid: errors.length === 0, errors, } } /** * Q&A URL 생성 유틸리티 */ export function generateQnaUrls(qnaId: number) { const baseUrl = typeof window !== "undefined" ? window.location.origin : "" return { detail: `${baseUrl}/qna/${qnaId}`, edit: `${baseUrl}/qna/${qnaId}/edit`, share: `${baseUrl}/qna/${qnaId}?shared=true`, } } /** * Q&A 메타데이터 생성 (SEO용) */ export function generateQnaMetadata(qna: { title: string content: string authorName: string companyName?: string | null totalAnswers: number createdAt: Date }) { const description = truncateQnaContent(qna.content, 160) const keywords = [ "Q&A", "질문", "답변", qna.authorName, qna.companyName, ...qna.title.split(" ").slice(0, 5), // 제목의 첫 5단어 ].filter(Boolean).join(", ") return { title: `${qna.title} - Q&A`, description, keywords, author: qna.authorName, publishedTime: qna.createdAt.toISOString(), articleTag: ["Q&A", "질문", "답변"], } }