import { useState, useEffect } from "react"; import Layout from "@/components/Layout"; import SEO from "@/components/SEO"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from "@/components/ui/card"; import { Badge } from "@/components/ui/badge"; import { Input } from "@/components/ui/input"; import { Book, Search, FileText, AlertCircle, Zap, Users, Settings, Code, Loader2, ThumbsUp, Eye, } from "lucide-react"; import { useAuth } from "@/contexts/AuthContext"; import { aethexToast } from "@/lib/aethex-toast"; interface KnowledgeArticle { id: string; title: string; category: string; content: string; tags: string[]; views: number; helpful_count: number; updated_at: string; author?: { full_name: string; avatar_url?: string; }; } const getCategoryIcon = (category: string) => { switch (category) { case "Onboarding": return ; case "Support": return ; case "Development": return ; case "Process": return ; case "Security": return ; default: return ; } }; export default function StaffKnowledgeBase() { const { session } = useAuth(); const [articles, setArticles] = useState([]); const [categories, setCategories] = useState([]); const [searchQuery, setSearchQuery] = useState(""); const [selectedCategory, setSelectedCategory] = useState("all"); const [loading, setLoading] = useState(true); useEffect(() => { if (session?.access_token) { fetchArticles(); } }, [session?.access_token, selectedCategory, searchQuery]); const fetchArticles = async () => { try { const params = new URLSearchParams(); if (selectedCategory !== "all") params.append("category", selectedCategory); if (searchQuery) params.append("search", searchQuery); const res = await fetch(`/api/staff/knowledge-base?${params}`, { headers: { Authorization: `Bearer ${session?.access_token}` }, }); const data = await res.json(); if (res.ok) { setArticles(data.articles || []); setCategories(data.categories || []); } } catch (err) { aethexToast.error("Failed to load articles"); } finally { setLoading(false); } }; const trackView = async (articleId: string) => { try { await fetch("/api/staff/knowledge-base", { method: "POST", headers: { "Content-Type": "application/json", Authorization: `Bearer ${session?.access_token}`, }, body: JSON.stringify({ action: "view", id: articleId }), }); } catch (err) { // Silent fail for analytics } }; const markHelpful = async (articleId: string) => { try { await fetch("/api/staff/knowledge-base", { method: "POST", headers: { "Content-Type": "application/json", Authorization: `Bearer ${session?.access_token}`, }, body: JSON.stringify({ action: "helpful", id: articleId }), }); aethexToast.success("Marked as helpful!"); fetchArticles(); } catch (err) { aethexToast.error("Failed to mark as helpful"); } }; const formatDate = (dateStr: string) => { const date = new Date(dateStr); const now = new Date(); const diff = now.getTime() - date.getTime(); const days = Math.floor(diff / (1000 * 60 * 60 * 24)); if (days === 0) return "Today"; if (days === 1) return "Yesterday"; if (days < 7) return `${days} days ago`; if (days < 30) return `${Math.floor(days / 7)} weeks ago`; return date.toLocaleDateString(); }; if (loading) { return (
); } return (
{/* Background effects */}
{/* Header */}

Knowledge Base

Internal documentation, SOPs, and troubleshooting guides

{/* Search */}
setSearchQuery(e.target.value)} className="pl-10 bg-slate-800 border-slate-700 text-slate-100 placeholder:text-slate-500" />
{/* Category Filter */}
{categories.map((category) => ( ))}
{/* Articles Grid */}
{articles.map((article) => ( trackView(article.id)} >
{getCategoryIcon(article.category)}
{article.category}
{article.title} {article.content.substring(0, 150)}...
{article.tags && article.tags.length > 0 && (
{article.tags.map((tag) => ( {tag} ))}
)}
{article.views} {article.helpful_count} {formatDate(article.updated_at)}
))}
{articles.length === 0 && (

No articles found

)}
); }