SPA preview in PrintMenu
This commit is contained in:
@ -362,100 +362,102 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="page-container">
|
{#if !activeFile}
|
||||||
<header class="header">
|
<div class="page-container">
|
||||||
<button class="back-btn" onclick={onBack}>← Назад</button>
|
<header class="header">
|
||||||
<h1>Печать</h1>
|
<button class="back-btn" onclick={onBack}>← Назад</button>
|
||||||
</header>
|
<h1>Печать</h1>
|
||||||
|
</header>
|
||||||
|
|
||||||
<main class="options">
|
<main class="options">
|
||||||
{#if files.length === 0}
|
{#if files.length === 0}
|
||||||
<div class="empty-upload">
|
<div class="empty-upload">
|
||||||
<p class="empty-hint">Загрузите файлы для печати</p>
|
<p class="empty-hint">Загрузите файлы для печати</p>
|
||||||
<button class="action-btn primary" onclick={triggerFileInput}>Загрузить файл(ы)</button>
|
<button class="action-btn primary" onclick={triggerFileInput}>Загрузить файл(ы)</button>
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
{#each files as file (file.id)}
|
{#each files as file (file.id)}
|
||||||
<section class="option-group file-card" class:expanded={file.expanded}>
|
<section class="option-group file-card" class:expanded={file.expanded}>
|
||||||
<div class="file-row" onclick={() => toggleExpanded(file)}>
|
<div class="file-row" onclick={() => toggleExpanded(file)}>
|
||||||
<span class="chevron">{#if file.expanded}▼{:else}►{/if}</span>
|
<span class="chevron">{#if file.expanded}▼{:else}►{/if}</span>
|
||||||
<span class="file-name" title={file.file.name}>{file.file.name}</span>
|
<span class="file-name" title={file.file.name}>{file.file.name}</span>
|
||||||
<span class="file-row-actions" onclick={(e) => e.stopPropagation()}>
|
<span class="file-row-actions" onclick={(e) => e.stopPropagation()}>
|
||||||
{#if file.previewUrl}
|
{#if file.previewUrl}
|
||||||
<button type="button" class="icon-btn" onclick={() => openPreview(file)} title="Предпросмотр">🔍</button>
|
<button type="button" class="icon-btn" onclick={() => openPreview(file)} title="Предпросмотр">🔍</button>
|
||||||
{/if}
|
{/if}
|
||||||
<button type="button" class="icon-btn danger" onclick={() => removeFile(file)} title="Удалить">✕</button>
|
<button type="button" class="icon-btn danger" onclick={() => removeFile(file)} title="Удалить">✕</button>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if file.expanded}
|
{#if file.expanded}
|
||||||
<div class="file-options">
|
<div class="file-options">
|
||||||
<div class="option-sub print-params-row">
|
<div class="option-sub print-params-row">
|
||||||
<div class="pages-control">
|
<div class="pages-control">
|
||||||
<label class="option-title compact">Страницы:</label>
|
<label class="option-title compact">Страницы:</label>
|
||||||
<button type="button" class="pages-btn" onclick={() => handlePagesClick(file)}>
|
<button type="button" class="pages-btn" onclick={() => handlePagesClick(file)}>
|
||||||
{pagesLabel(file)}
|
{pagesLabel(file)}
|
||||||
</button>
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="copies-control-inline">
|
||||||
|
<label class="option-title compact">Кол-во:</label>
|
||||||
|
<div class="mini-counter">
|
||||||
|
<button type="button" class="circle-btn small" onclick={() => decrementCopies(file)} disabled={file.copies <= 1}>−</button>
|
||||||
|
<span class="copies-value">{file.copies} шт.</span>
|
||||||
|
<button type="button" class="circle-btn small" onclick={() => incrementCopies(file)}>+</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="copies-control-inline">
|
|
||||||
<label class="option-title compact">Кол-во:</label>
|
<div class="option-sub">
|
||||||
<div class="mini-counter">
|
<label class="option-title">Формат</label>
|
||||||
<button type="button" class="circle-btn small" onclick={() => decrementCopies(file)} disabled={file.copies <= 1}>−</button>
|
<div class="toggle-group horizontal">
|
||||||
<span class="copies-value">{file.copies} шт.</span>
|
{#each formats as f}
|
||||||
<button type="button" class="circle-btn small" onclick={() => incrementCopies(file)}>+</button>
|
<button type="button" class="toggle-btn {file.format === f ? 'active' : ''}" onclick={() => toggleFormat(file, f)}>{f}</button>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="option-sub">
|
||||||
|
<label class="option-title">Цветность</label>
|
||||||
|
<div class="toggle-group horizontal">
|
||||||
|
{#each colorModes as c}
|
||||||
|
<button type="button" class="toggle-btn {file.colorMode === c.id ? 'active' : ''}" onclick={() => toggleColor(file, c)}>{c.label}</button>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="option-sub quality-sub">
|
||||||
|
<label class="option-title">Качество – {qualities[file.qualityIndex].label}</label>
|
||||||
|
<input type="range" min={0} max={qualities.length - 1} step={1} bind:value={file.qualityIndex} class="quality-slider" style="--fill: {qualityFillFor(file)}%" />
|
||||||
|
<div class="quality-marks-inline">
|
||||||
|
{#each qualities as q}<span class="quality-mark">{q.label}</span>{/each}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{/if}
|
||||||
|
</section>
|
||||||
|
{/each}
|
||||||
|
<button type="button" class="add-file-btn" onclick={triggerFileInput}>+ Добавить файлы</button>
|
||||||
|
{/if}
|
||||||
|
</main>
|
||||||
|
|
||||||
<div class="option-sub">
|
<footer class="actions">
|
||||||
<label class="option-title">Формат</label>
|
{#if files.length > 0}
|
||||||
<div class="toggle-group horizontal">
|
<p class="file-count">
|
||||||
{#each formats as f}
|
{files.length} {plFiles(files.length)}
|
||||||
<button type="button" class="toggle-btn {file.format === f ? 'active' : ''}" onclick={() => toggleFormat(file, f)}>{f}</button>
|
{#if extraCopies > 0}, {extraCopies} {plCopies(extraCopies)}{/if}
|
||||||
{/each}
|
</p>
|
||||||
</div>
|
{/if}
|
||||||
</div>
|
<div class="price-summary">
|
||||||
|
<span class="summary-itogo">Итого</span>
|
||||||
<div class="option-sub">
|
<span class="summary-price">{totalPrice}</span>
|
||||||
<label class="option-title">Цветность</label>
|
</div>
|
||||||
<div class="toggle-group horizontal">
|
<button type="button" class="action-btn secondary" onclick={onPrint}>Печать</button>
|
||||||
{#each colorModes as c}
|
<!-- Input можно оставить здесь, он скрыт через display:none и не влияет на верстку -->
|
||||||
<button type="button" class="toggle-btn {file.colorMode === c.id ? 'active' : ''}" onclick={() => toggleColor(file, c)}>{c.label}</button>
|
<input type="file" bind:this={fileInput} accept="image/*,.pdf" multiple onchange={handleFileSelect} style="display:none" />
|
||||||
{/each}
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
{/if}
|
||||||
|
|
||||||
<div class="option-sub quality-sub">
|
|
||||||
<label class="option-title">Качество – {qualities[file.qualityIndex].label}</label>
|
|
||||||
<input type="range" min={0} max={qualities.length - 1} step={1} bind:value={file.qualityIndex} class="quality-slider" style="--fill: {qualityFillFor(file)}%" />
|
|
||||||
<div class="quality-marks-inline">
|
|
||||||
{#each qualities as q}<span class="quality-mark">{q.label}</span>{/each}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
</section>
|
|
||||||
{/each}
|
|
||||||
<button type="button" class="add-file-btn" onclick={triggerFileInput}>+ Добавить файлы</button>
|
|
||||||
{/if}
|
|
||||||
</main>
|
|
||||||
|
|
||||||
<footer class="actions">
|
|
||||||
{#if files.length > 0}
|
|
||||||
<p class="file-count">
|
|
||||||
{files.length} {plFiles(files.length)}
|
|
||||||
{#if extraCopies > 0}, {extraCopies} {plCopies(extraCopies)}{/if}
|
|
||||||
</p>
|
|
||||||
{/if}
|
|
||||||
<div class="price-summary">
|
|
||||||
<span class="summary-itogo">Итого</span>
|
|
||||||
<span class="summary-price">{totalPrice}</span>
|
|
||||||
</div>
|
|
||||||
<button type="button" class="action-btn secondary" onclick={onPrint}>Печать</button>
|
|
||||||
<div class="home-bar-spacer"><div class="home-bar"></div></div>
|
|
||||||
<input type="file" bind:this={fileInput} accept="image/*,.pdf" multiple onchange={handleFileSelect} style="display:none" />
|
|
||||||
</footer>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- ═══════════════════════════════════════════════════════════ -->
|
<!-- ═══════════════════════════════════════════════════════════ -->
|
||||||
<!-- УНИВЕРСАЛЬНЫЙ ОВЕРЛЕЙ (Галерея выбора ИЛИ Просмотр) -->
|
<!-- УНИВЕРСАЛЬНЫЙ ОВЕРЛЕЙ (Галерея выбора ИЛИ Просмотр) -->
|
||||||
@ -620,8 +622,6 @@
|
|||||||
.price-summary { display: flex; justify-content: space-between; align-items: baseline; width: 100%; }
|
.price-summary { display: flex; justify-content: space-between; align-items: baseline; width: 100%; }
|
||||||
.summary-itogo { font-size: 30px; font-weight: 700; color: #8b93a1; }
|
.summary-itogo { font-size: 30px; font-weight: 700; color: #8b93a1; }
|
||||||
.summary-price { font-size: 38px; font-weight: 800; color: #fff; }
|
.summary-price { font-size: 38px; font-weight: 800; color: #fff; }
|
||||||
.home-bar-spacer { margin-top: auto; padding: 24px 0 8px; display: flex; justify-content: center; }
|
|
||||||
.home-bar { width: 134px; height: 5px; border-radius: 3px; background: rgba(255, 255, 255, 0.3); }
|
|
||||||
|
|
||||||
/* ═══════════════════════════════════════ */
|
/* ═══════════════════════════════════════ */
|
||||||
/* ОБЩИЙ ОВЕРЛЕЙ */
|
/* ОБЩИЙ ОВЕРЛЕЙ */
|
||||||
|
|||||||
0
src/lib/preview/PreviewPage.svelte
Normal file
0
src/lib/preview/PreviewPage.svelte
Normal file
0
src/lib/preview/SelectionPage.svelte
Normal file
0
src/lib/preview/SelectionPage.svelte
Normal file
Reference in New Issue
Block a user