first commit

This commit is contained in:
2025-11-26 18:02:58 +01:00
commit baacb7cfac
15 changed files with 1269 additions and 0 deletions

View File

@@ -0,0 +1,125 @@
import React, { useState } from 'react';
import type { SplitResult } from '../pdf/pdfTypes';
interface ActionsPanelProps {
hasPdf: boolean;
onSplit: () => void;
onExtractRange: (from: number, to: number) => void;
isBusy: boolean;
splitResults: SplitResult[];
rangeDownloadUrl: string | null;
rangeFilename: string | null;
}
const ActionsPanel: React.FC<ActionsPanelProps> = ({
hasPdf,
onSplit,
onExtractRange,
isBusy,
splitResults,
rangeDownloadUrl,
rangeFilename,
}) => {
const [fromPage, setFromPage] = useState<string>('');
const [toPage, setToPage] = useState<string>('');
const handleExtractClick = () => {
const from = parseInt(fromPage, 10);
const to = parseInt(toPage, 10);
if (!Number.isFinite(from) || !Number.isFinite(to)) return;
onExtractRange(from, to);
};
return (
<div className="card">
<h2>3. Actions</h2>
<p>Split into single pages or extract a continuous range.</p>
<div className="button-row">
<button
className="primary"
disabled={!hasPdf || isBusy}
onClick={onSplit}
>
{isBusy ? 'Splitting…' : 'Split into single pages'}
</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}
>
{isBusy ? 'Working…' : 'Extract'}
</button>
</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>
{splitResults.length > 0 && (
<div style={{ marginTop: '0.75rem', fontSize: '0.9rem' }}>
<strong>Split result:</strong>
<div>
{splitResults.map((r) => {
const url = URL.createObjectURL(r.blob);
return (
<a
key={r.pageIndex}
className="download-link"
href={url}
download={r.filename}
onClick={() => {
setTimeout(() => URL.revokeObjectURL(url), 5000);
}}
>
Download {r.filename}
</a>
);
})}
</div>
</div>
)}
</div>
);
};
export default ActionsPanel;