66 lines
2.7 KiB
JavaScript
66 lines
2.7 KiB
JavaScript
|
|
export function renderScannerModal({
|
||
|
|
title = 'Scan barcode',
|
||
|
|
subtitle = 'Point your camera at the barcode.',
|
||
|
|
optionsMarkup = '',
|
||
|
|
manualCodeModel = 'scannerManualCode',
|
||
|
|
manualSubmitAction = 'processScannerManualCode()',
|
||
|
|
manualPlaceholder = 'Scan with hardware reader or paste code',
|
||
|
|
manualHelp = 'Manual entry works with keyboard-style barcode scanners.',
|
||
|
|
manualButtonLabel = 'Run',
|
||
|
|
manualDisabledExpression = 'scannerState.isLoading',
|
||
|
|
}) {
|
||
|
|
return `
|
||
|
|
<div
|
||
|
|
class="scanner-modal-backdrop"
|
||
|
|
x-show="scannerState.isOpen"
|
||
|
|
@click.self="closeScanner()"
|
||
|
|
@keydown.escape.window="closeScanner()"
|
||
|
|
>
|
||
|
|
<div class="scanner-modal card border-0 shadow-lg">
|
||
|
|
<div class="card-body p-3 p-md-4">
|
||
|
|
<div class="d-flex align-items-center justify-content-between gap-3 mb-3">
|
||
|
|
<div>
|
||
|
|
<h2 class="h5 mb-1">${title}</h2>
|
||
|
|
<p class="text-body-secondary small mb-0">${subtitle}</p>
|
||
|
|
</div>
|
||
|
|
<button class="btn btn-sm btn-outline-secondary" type="button" @click="closeScanner()">Close</button>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
${optionsMarkup}
|
||
|
|
|
||
|
|
<form class="mb-3" @submit.prevent="${manualSubmitAction}">
|
||
|
|
<label class="form-label">Manual scan code</label>
|
||
|
|
<div class="input-group">
|
||
|
|
<input
|
||
|
|
class="form-control"
|
||
|
|
type="text"
|
||
|
|
x-model="${manualCodeModel}"
|
||
|
|
placeholder="${manualPlaceholder}"
|
||
|
|
autocomplete="off"
|
||
|
|
/>
|
||
|
|
<button class="btn btn-outline-primary" type="submit" :disabled="${manualDisabledExpression}">
|
||
|
|
${manualButtonLabel}
|
||
|
|
</button>
|
||
|
|
</div>
|
||
|
|
<div class="form-text">${manualHelp}</div>
|
||
|
|
</form>
|
||
|
|
|
||
|
|
<div class="scanner-video-shell mb-3">
|
||
|
|
<video class="scanner-video" x-ref="scannerVideo" autoplay muted playsinline></video>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="d-flex flex-wrap align-items-center gap-2">
|
||
|
|
<div class="small text-body-secondary" x-show="scannerState.isLoading">Starting camera...</div>
|
||
|
|
<div class="small text-success" x-show="scannerState.lastDetectedCode" x-text="'Detected: ' + scannerState.lastDetectedCode"></div>
|
||
|
|
<button class="btn btn-outline-secondary btn-sm" type="button" @click="startScanner()" :disabled="scannerState.isLoading">Retry</button>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<template x-if="scannerState.error">
|
||
|
|
<div class="alert alert-warning py-2 mt-3 mb-0" x-text="scannerState.error"></div>
|
||
|
|
</template>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
`;
|
||
|
|
}
|