feat: update PDF tool pages with interactive options, promote split/compress to phase 1

- pdf-split: page range input (1-3,5,7-9) with example
- pdf-compress: upload zone with description
- tool-grid: split/compress jadi phase 1 (backend udah implement)
- merge/images-to-pdf tetap phase 2 (butuh multi-file upload)

Co-Authored-By: Kilo <kilo@kilo.ai>
This commit is contained in:
asepharyana
2026-07-24 19:54:26 +07:00
co-authored by Kilo
parent d4bbde9320
commit e8b92ed157
3 changed files with 42 additions and 60 deletions
+7 -26
View File
@@ -16,10 +16,7 @@ export default function PdfCompressPage() {
const [jobId, setJobId] = useState<string | null>(null);
const [errorMsg, setErrorMsg] = useState<string | null>(null);
const { upload } = useUpload({
tool: "pdf-compress",
options: { quality: 80 },
});
const { upload } = useUpload({ tool: "pdf-compress" });
const handleComplete = useCallback(() => setPageState("result"), []);
const handleError = useCallback(
@@ -58,44 +55,28 @@ export default function PdfCompressPage() {
title="Compress PDF"
description="Kecilin ukuran PDF"
icon={FileImage}
phase={2}
phase={1}
>
{pageState === "upload" && (
<UploadZone
accept="application/pdf"
accept=".pdf,application/pdf"
tool="pdf-compress"
onUpload={handleUpload}
/>
)}
{pageState === "processing" && jobId && (
<ProgressBar
progress={progress}
stage={stage}
message={message}
status={status}
onRetry={handleRetry}
/>
<ProgressBar progress={progress} stage={stage} message={message} status={status} onRetry={handleRetry} />
)}
{pageState === "result" && result && (
<ResultPreview
result={result}
onProcessAnother={handleRetry}
/>
<ResultPreview result={result} onProcessAnother={handleRetry} />
)}
{pageState === "error" && (
<div className="p-6 rounded-xl border border-destructive/20 bg-destructive/5 text-center">
<p className="text-destructive font-medium mb-4">
{errorMsg || "Terjadi kesalahan"}
</p>
<button
onClick={handleRetry}
className="px-4 py-2 bg-primary text-primary-foreground rounded-lg hover:opacity-90"
>
Coba Lagi
</button>
<p className="text-destructive font-medium mb-4">{errorMsg || "Terjadi kesalahan"}</p>
<button onClick={handleRetry} className="px-4 py-2 bg-primary text-primary-foreground rounded-lg hover:opacity-90">Coba Lagi</button>
</div>
)}
</ToolLayout>
+25 -24
View File
@@ -15,10 +15,11 @@ export default function PdfSplitPage() {
const [pageState, setPageState] = useState<PageState>("upload");
const [jobId, setJobId] = useState<string | null>(null);
const [errorMsg, setErrorMsg] = useState<string | null>(null);
const [pages, setPages] = useState("1,3-5");
const { upload } = useUpload({
tool: "pdf-split",
options: { quality: 80 },
options: { pages },
});
const handleComplete = useCallback(() => setPageState("result"), []);
@@ -56,46 +57,46 @@ export default function PdfSplitPage() {
return (
<ToolLayout
title="Split PDF"
description="Ekstrak halaman tertentu"
description="Ekstrak halaman tertentu dari PDF"
icon={Split}
phase={2}
phase={1}
>
{pageState === "upload" && (
<div className="space-y-6">
<div className="p-6 rounded-xl border glass space-y-3">
<h3 className="font-semibold">Page Range</h3>
<p className="text-xs text-muted-foreground">
Contoh: <code className="bg-muted px-1 rounded">1-3,5,7-9</code> ambil halaman 1-3, 5, dan 7-9
</p>
<input
type="text"
value={pages}
onChange={(e) => setPages(e.target.value)}
className="w-full bg-muted border rounded px-3 py-2 text-sm font-mono"
placeholder="1-3,5,7-9"
/>
</div>
<UploadZone
accept="application/pdf"
accept=".pdf,application/pdf"
tool="pdf-split"
onUpload={handleUpload}
/>
</div>
)}
{pageState === "processing" && jobId && (
<ProgressBar
progress={progress}
stage={stage}
message={message}
status={status}
onRetry={handleRetry}
/>
<ProgressBar progress={progress} stage={stage} message={message} status={status} onRetry={handleRetry} />
)}
{pageState === "result" && result && (
<ResultPreview
result={result}
onProcessAnother={handleRetry}
/>
<ResultPreview result={result} onProcessAnother={handleRetry} />
)}
{pageState === "error" && (
<div className="p-6 rounded-xl border border-destructive/20 bg-destructive/5 text-center">
<p className="text-destructive font-medium mb-4">
{errorMsg || "Terjadi kesalahan"}
</p>
<button
onClick={handleRetry}
className="px-4 py-2 bg-primary text-primary-foreground rounded-lg hover:opacity-90"
>
Coba Lagi
</button>
<p className="text-destructive font-medium mb-4">{errorMsg || "Terjadi kesalahan"}</p>
<button onClick={handleRetry} className="px-4 py-2 bg-primary text-primary-foreground rounded-lg hover:opacity-90">Coba Lagi</button>
</div>
)}
</ToolLayout>
+4 -4
View File
@@ -82,10 +82,10 @@ const tools: ToolDefinition[] = [
{
id: "pdf-split",
title: "Split PDF",
description: "Ekstrak halaman tertentu dari PDF. Pilih via thumbnail atau range.",
description: "Ekstrak halaman tertentu dari PDF. Pilih page range seperti 1-3,5,7-9.",
icon: Split,
href: "/pdf/split",
phase: 2,
phase: 1,
},
{
id: "images-to-pdf",
@@ -98,10 +98,10 @@ const tools: ToolDefinition[] = [
{
id: "pdf-compress",
title: "Compress PDF",
description: "Kecilin ukuran PDF dengan kompresi embedded images.",
description: "Kecilin ukuran PDF dengan kompresi ulang.",
icon: FileImage,
href: "/pdf/compress",
phase: 2,
phase: 1,
},
{
id: "video-compress",