Files
web-app/src/lib/pages/print/PrintMenu.svelte

139 lines
5.3 KiB
Svelte
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!-- lib/pages/print/PrintMenu.svelte -->
<script>
import { createPrintStore } from './store.svelte.js';
import PrintUI from './PrintUI.svelte';
import PreviewOverlay from './PreviewOverlay.svelte';
import PrintProgress from './PrintProgress.svelte';
import PaymentPage from '$lib/common/ui/PaymentPage.svelte';
import { plFiles, plCopies } from '$lib/common/utils/pricing.util.js';
import NetworkGate from '$lib/common/ui/NetworkGate.svelte';
let { onBack = () => {} } = $props();
const store = createPrintStore();
let fileInput = $state(null);
function handleFileSelect(event) {
store.addFiles(event.target.files);
event.target.value = '';
}
const hasDuplex = $derived(
store.files.some((f) => f.sides === 'Двусторонняя')
);
const hasTierSmall = $derived(
store.files.some((f) => {
const s = f.selectedPages?.size || 0;
return f.sides !== 'Двусторонняя' && s > 0 && s < 25;
})
);
const hasTierMedium = $derived(
store.files.some((f) => {
const s = f.selectedPages?.size || 0;
return f.sides !== 'Двусторонняя' && s >= 25;
})
);
/* ── Проверка сети перед отправкой печати ──
* Печать работает только в локальной сети принтера (домен → 192.168.20.1).
* Гейт открывается мгновенно по нажатию «Я оплатил(а)» и сам внутри себя
* делает первую проверку: если мы уже в локалке — короткая зелёная вспышка
* и печать ушла; если нет — инструкции и авто-проход при появлении сети.
*/
/** true → показываем экран подключения к принтеру */
let printNetGate = $state(false);
function handleConfirmPayment() {
// Гейт сам проверит сеть: если уже локальная — сразу пропустит и напечатает,
// если нет — покажет инструкции и будет ждать появления сети.
printNetGate = true;
}
function handleGateReady() {
// сеть принтера появилась — пропускаем пользователя и сразу печатаем
printNetGate = false;
store.submitPrint();
}
function handleGateBack() {
printNetGate = false; // возврат к странице оплаты
}
</script>
{#if store.job}
<!-- Страница прогресса печати (после оплаты) -->
<PrintProgress {store} onBack={onBack} />
{:else if store.showPayment}
{#if printNetGate}
<NetworkGate mode="need-local" onReady={handleGateReady} onBack={handleGateBack} />
{:else}
<PaymentPage
totalPrice={store.totalPrice}
filesCount={store.files.length}
onBack={store.hidePayment}
onConfirmPayment={handleConfirmPayment}
/>
{/if}
{:else if !store.activeFile}
<div class="page-container">
<header class="header">
<button class="back-btn" onclick={onBack}>←</button>
<h1>Печать</h1>
</header>
<main class="options">
{#if store.files.length === 0}
<PrintUI as="upload-zone" onSelect={() => fileInput.click()} />
{:else}
{#each store.files as file (file.id)}
<PrintUI
as="file-card"
{file}
onToggle={store.toggleExpand}
onRemove={store.removeFile}
onUpdate={store.updateFile}
onPreview={(f) => store.openPreview(f)}
onPageSelect={(f) => (f.fileType === 'pdf' ? store.openGallery(f) : store.openPreview(f))}
pagesLabel={store.pagesLabel}
/>
{/each}
<button class="add-file-btn" onclick={() => fileInput.click()}> Добавить файлы</button>
{/if}
</main>
<PrintUI
as="footer"
totalPrice={store.totalPrice}
filesCount={store.files.length}
extraCopies={store.extraCopies}
isPrinting={store.isPrinting}
onSubmit={store.openPayment}
hasDuplex={hasDuplex}
hasTierSmall={hasTierSmall}
hasTierMedium={hasTierMedium}
plFiles={plFiles}
plCopies={plCopies}
/>
<input
type="file"
bind:this={fileInput}
accept="image/*,.pdf,.doc,.docx,.odt,.xls,.xlsx,.ods,.ppt,.pptx,.odp"
multiple
onchange={handleFileSelect}
hidden
/>
</div>
{/if}
{#if !store.job}
<PreviewOverlay {store} />
{/if}
<style>
.page-container { width: 100%; min-height: 100dvh; display: flex; flex-direction: column; background: radial-gradient(120% 60% at 50% -10%, rgba(99,102,241,0.18) 0%, transparent 60%); font-family: system-ui, -apple-system, sans-serif; color: #f5f7fa; }
.header { padding: 24px 20px 8px; display: flex; align-items: center; position: relative; }
.back-btn { background: none; border: none; color: #6366f1; font-size: 15px; font-weight: 600; cursor: pointer; padding: 8px 4px; margin-right: auto; min-height: 44px; }
.header h1 { margin: 0; font-size: 28px; font-weight: 700; position: absolute; left: 50%; transform: translateX(-50%); white-space: nowrap; }
.options { flex: 1; padding: 24px 20px 16px; display: flex; flex-direction: column; gap: 14px; }
.add-file-btn { align-self: center; background: none; border: 1px dashed rgba(255,255,255,0.18); color: #a9b0c0; font-size: 14px; font-weight: 600; padding: 12px 18px; border-radius: 14px; cursor: pointer; margin-top: 8px; }
</style>