"use client"; import React, { useState, useMemo } from "react"; import Link from "next/link"; import Markdown from "./Markdown"; import { extractDocCategory, extractDocPoints, extractDocDifficulty, sortExportDocuments, compileExportMarkdown, type Document, type ExportData, type ExportSortOption, } from "@mcpedia/core/export-helpers"; import { getSectionMeta } from "@mcpedia/config/sections"; interface PdfExportViewProps { exportData: ExportData; backHref: string; } export default function PdfExportView({ exportData, backHref, }: PdfExportViewProps) { const { summary, documents: initialDocs } = exportData; // Filter out any leftover index / meta files const cleanDocs = useMemo(() => { return initialDocs.filter((d) => { const slug = d.slug.toLowerCase(); return ( !slug.endsWith("/_index") && !slug.endsWith("/index") && slug !== "_index" && slug !== "index" && d.type !== "writeup-index" ); }); }, [initialDocs]); // Configuration and interactive state const [sortBy, setSortBy] = useState("category_points"); const [showTOC, setShowTOC] = useState(cleanDocs.length > 1); const [pageBreaks, setPageBreaks] = useState(true); const [selectedCategory, setSelectedCategory] = useState("all"); const [copiedMd, setCopiedMd] = useState(false); const sectionMeta = getSectionMeta(summary.section); const authorsList = summary.authors || []; // Available categories for filtering const allCategories = useMemo(() => { const set = new Set(); for (const doc of cleanDocs) { set.add(extractDocCategory(doc)); } return Array.from(set).sort(); }, [cleanDocs]); // Filtered & Sorted documents const filteredAndSortedDocs = useMemo(() => { let docs = [...cleanDocs]; if (selectedCategory !== "all") { docs = docs.filter( (d) => extractDocCategory(d).toLowerCase() === selectedCategory.toLowerCase(), ); } return sortExportDocuments(docs, sortBy); }, [cleanDocs, selectedCategory, sortBy]); // Calculate dynamic stats for currently filtered view const currentTotalPoints = useMemo(() => { return filteredAndSortedDocs.reduce( (sum, d) => sum + extractDocPoints(d), 0, ); }, [filteredAndSortedDocs]); function handlePrint() { window.print(); } function handleCopyMarkdown() { const md = compileExportMarkdown({ summary, documents: filteredAndSortedDocs, }); navigator.clipboard.writeText(md); setCopiedMd(true); setTimeout(() => setCopiedMd(false), 2000); } function handleDownloadMarkdown() { const md = compileExportMarkdown({ summary, documents: filteredAndSortedDocs, }); const blob = new Blob([md], { type: "text/markdown;charset=utf-8" }); const url = URL.createObjectURL(blob); const a = document.createElement("a"); a.href = url; const safeName = summary.title .toLowerCase() .replace(/[^a-z0-9]+/g, "-") .replace(/^-|-$/g, ""); a.download = `${safeName}.md`; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); } return (
{/* ========================================================================= Export Control Toolbar (Screen Only — Hidden in Print) ========================================================================= */} {/* ========================================================================= Clean, Simple, Human-Written Writeup Document Flow (No Cards) ========================================================================= */}
{/* Document Header */}

{summary.title}

Scope: {summary.scope} Total Challenges: {filteredAndSortedDocs.length} {currentTotalPoints > 0 && ( Total Points: {currentTotalPoints.toLocaleString()} pts )} {authorsList.length > 0 && ( Author(s): {authorsList.map((a) => `@${a}`).join(", ")} )} Date: {new Date(summary.generatedAt).toLocaleDateString(undefined, { dateStyle: "long" })}
{/* Table of Contents (Simple & Clean) */} {showTOC && filteredAndSortedDocs.length > 1 && (

Table of Contents

    {filteredAndSortedDocs.map((doc, idx) => { const cat = extractDocCategory(doc); const pts = extractDocPoints(doc); return (
  1. {doc.title} [{cat}{pts > 0 ? ` · ${pts} pts` : ""}]
  2. ); })}
)} {/* Challenges / Writeups Flow ("Mirip Writeup Manusia") */}
{filteredAndSortedDocs.map((doc, idx) => { const chNum = idx + 1; const cat = extractDocCategory(doc); const pts = extractDocPoints(doc); const diff = extractDocDifficulty(doc); const extra = doc.extraFields || {}; return (
0 ? "page-break-before" : "" } pt-6 first:pt-0`} > {/* Challenge Title & Metadata */}

{chNum}. {doc.title}

Category: {cat} {pts > 0 && Points: {pts} pts} {diff && Difficulty: {diff}} {doc.author && Author: @{doc.author}} {doc.slug && Slug: {doc.slug}} {/* Extra fields */} {Object.entries(extra).map(([k, v]) => { const lowerKey = k.toLowerCase(); if ( [ "category", "points", "score", "pts", "difficulty", "solved", "author", "event", "challenge", ].includes(lowerKey) || v === null || v === undefined || v === "" ) { return null; } return ( {k}: {String(v)} ); })}
{/* Markdown Writeup Content */}
{/* Divider between challenges (screen only) */}
); })}
); }