UI improvements, merge

This commit is contained in:
2025-11-27 10:52:44 +01:00
parent abfe6c347a
commit 9f660af924
7 changed files with 1089 additions and 310 deletions

View File

@@ -1,103 +1,117 @@
import React, { useState } from 'react';
import React from 'react';
import type { SplitResult } from '../pdf/pdfTypes';
interface ActionsPanelProps {
hasPdf: boolean;
onSplit: () => void;
onExtractRange: (from: number, to: number) => void;
isBusy: boolean;
selectedCount: number;
onSplit: () => void;
onExtractSelected: () => void;
onExportReordered: () => void;
splitResults: SplitResult[];
rangeDownloadUrl: string | null;
rangeFilename: string | null;
subsetDownloadUrl: string | null;
subsetFilename: string | null;
exportDownloadUrl: string | null;
exportFilename: string | null;
}
const ActionsPanel: React.FC<ActionsPanelProps> = ({
hasPdf,
onSplit,
onExtractRange,
isBusy,
selectedCount,
onSplit,
onExtractSelected,
onExportReordered,
splitResults,
rangeDownloadUrl,
rangeFilename,
subsetDownloadUrl,
subsetFilename,
exportDownloadUrl,
exportFilename,
}) => {
const [fromPage, setFromPage] = useState<string>('');
const [toPage, setToPage] = useState<string>('');
const disabled = !hasPdf || isBusy;
const handleExtractClick = () => {
const from = parseInt(fromPage, 10);
const to = parseInt(toPage, 10);
if (!Number.isFinite(from) || !Number.isFinite(to)) return;
onExtractRange(from, to);
const handleExtractSelectedClick = () => {
if (selectedCount === 0) return;
onExtractSelected();
};
return (
<div className="card">
<h2>3. Actions</h2>
<p>Split into single pages or extract a continuous range.</p>
<h2>Tools</h2>
<p style={{ fontSize: '0.85rem', color: '#6b7280' }}>
Use these tools on the current in-memory document (reordered, rotated,
with deletions). Nothing is uploaded to a server.
</p>
<div className="button-row">
<div
className="button-row"
style={{ justifyContent: 'space-between', flexWrap: 'wrap' }}
>
<button
className="primary"
disabled={!hasPdf || isBusy}
onClick={onSplit}
className="secondary"
disabled={disabled}
onClick={onExportReordered}
style={{ flex: '1 1 45%' }}
>
{isBusy ? 'Splitting…' : 'Split into single pages'}
🧾 Export new PDF
</button>
<button
className="secondary"
disabled={disabled || selectedCount === 0}
onClick={handleExtractSelectedClick}
style={{ flex: '1 1 45%' }}
title={
selectedCount === 0
? 'Select at least one page'
: 'Create a PDF from selected pages'
}
>
📤 Extract selected ({selectedCount})
</button>
<button
className="secondary"
disabled={disabled}
onClick={onSplit}
style={{ flex: '1 1 45%' }}
>
📂 Split into single PDFs
</button>
</div>
<hr style={{ margin: '0.75rem 0', borderColor: '#e5e7eb' }} />
<div style={{ display: 'flex', flexDirection: 'column', gap: '0.4rem' }}>
<div>
<strong>Extract range:</strong>
</div>
<div style={{ display: 'flex', gap: '0.5rem', alignItems: 'center' }}>
<label>
From
<input
type="number"
min={1}
value={fromPage}
onChange={(e) => setFromPage(e.target.value)}
style={{ marginLeft: '0.3rem', width: '4rem' }}
/>
</label>
<label>
To
<input
type="number"
min={1}
value={toPage}
onChange={(e) => setToPage(e.target.value)}
style={{ marginLeft: '0.3rem', width: '4rem' }}
/>
</label>
<button
className="secondary"
disabled={!hasPdf || isBusy}
onClick={handleExtractClick}
{subsetDownloadUrl && subsetFilename && (
<div style={{ marginTop: '0.5rem', fontSize: '0.9rem' }}>
<strong>Subset result:</strong>{' '}
<a
className="download-link"
href={subsetDownloadUrl}
download={subsetFilename}
>
{isBusy ? 'Working…' : 'Extract'}
</button>
Download {subsetFilename}
</a>
</div>
)}
{rangeDownloadUrl && rangeFilename && (
<div style={{ marginTop: '0.5rem', fontSize: '0.9rem' }}>
<strong>Range result:</strong>{' '}
<a
className="download-link"
href={rangeDownloadUrl}
download={rangeFilename}
>
Download {rangeFilename}
</a>
</div>
)}
</div>
{exportDownloadUrl && exportFilename && (
<div style={{ marginTop: '0.5rem', fontSize: '0.9rem' }}>
<strong>Exported document:</strong>{' '}
<a
className="download-link"
href={exportDownloadUrl}
download={exportFilename}
>
Download {exportFilename}
</a>
</div>
)}
{splitResults.length > 0 && (
<div style={{ marginTop: '0.75rem', fontSize: '0.9rem' }}>
<strong>Split result:</strong>
<strong>Single-page PDFs:</strong>
<div>
{splitResults.map((r) => {
const url = URL.createObjectURL(r.blob);
@@ -111,7 +125,7 @@ const ActionsPanel: React.FC<ActionsPanelProps> = ({
setTimeout(() => URL.revokeObjectURL(url), 5000);
}}
>
Download {r.filename}
{r.filename}
</a>
);
})}