Dockerfile updates
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
ThroughputQuantityType
|
||||
} from '$lib/types';
|
||||
import { CheckCircle2, AlertTriangle, ArrowLeft } from 'lucide-svelte';
|
||||
import ThroughputProductPicker from '$lib/components/throughput/ThroughputProductPicker.svelte';
|
||||
|
||||
let { data } = $props<{ data: { products: ThroughputProduct[] } }>();
|
||||
const products = $derived(data.products ?? []);
|
||||
@@ -18,10 +19,10 @@
|
||||
let bagSize = $state<string>('');
|
||||
let quantity = $state<string>('');
|
||||
let quantityType = $state<ThroughputQuantityType>('bags');
|
||||
let scalesChecked = $state(true);
|
||||
let labelCorrect = $state(true);
|
||||
let bagSealed = $state(true);
|
||||
let palletGood = $state(true);
|
||||
let forOrder = $state(false);
|
||||
let forStock = $state(false);
|
||||
let jobNumber = $state('');
|
||||
let stockQty = $state('');
|
||||
let sampleBoxNo = $state('');
|
||||
let tw1 = $state('');
|
||||
let tw2 = $state('');
|
||||
@@ -39,6 +40,8 @@
|
||||
productId ? products.find((p: ThroughputProduct) => String(p.id) === productId) ?? null : null
|
||||
);
|
||||
|
||||
const isSplit = $derived(forOrder && forStock);
|
||||
|
||||
$effect(() => {
|
||||
if (selectedProduct) {
|
||||
if (!bagSize && selectedProduct.default_bag_size != null) {
|
||||
@@ -50,8 +53,6 @@
|
||||
}
|
||||
});
|
||||
|
||||
const qaWarning = $derived(!(scalesChecked && labelCorrect && bagSealed && palletGood));
|
||||
|
||||
function toNum(value: string): number | null {
|
||||
const trimmed = value.trim();
|
||||
if (!trimmed) return null;
|
||||
@@ -64,10 +65,10 @@
|
||||
bagSize = '';
|
||||
quantity = '';
|
||||
quantityType = 'bags';
|
||||
scalesChecked = true;
|
||||
labelCorrect = true;
|
||||
bagSealed = true;
|
||||
palletGood = true;
|
||||
forOrder = false;
|
||||
forStock = false;
|
||||
jobNumber = '';
|
||||
stockQty = '';
|
||||
sampleBoxNo = '';
|
||||
tw1 = '';
|
||||
tw2 = '';
|
||||
@@ -97,15 +98,37 @@
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!forOrder && !forStock) {
|
||||
errorMessage = 'Mark where this run goes: for an order, for stock, or both.';
|
||||
return null;
|
||||
}
|
||||
const job = jobNumber.trim();
|
||||
if (forOrder && !job) {
|
||||
errorMessage = 'Enter the job number for the order.';
|
||||
return null;
|
||||
}
|
||||
let stock: number | null = null;
|
||||
if (isSplit) {
|
||||
stock = toNum(stockQty);
|
||||
if (stock === null || stock <= 0) {
|
||||
errorMessage = `Enter how much goes to stock (in ${quantityType === 'bags' ? 'bags' : 'kg'}).`;
|
||||
return null;
|
||||
}
|
||||
if (stock >= qty) {
|
||||
errorMessage = 'Stock amount must be less than the total packed for a split.';
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
production_date: productionDate,
|
||||
product_id: Number(productId),
|
||||
product_name_snapshot: selectedProduct?.name ?? '',
|
||||
bag_size: bag,
|
||||
scales_checked: scalesChecked,
|
||||
label_correct: labelCorrect,
|
||||
bag_sealed: bagSealed,
|
||||
pallet_good_condition: palletGood,
|
||||
for_order: forOrder,
|
||||
for_stock: forStock,
|
||||
job_number: forOrder ? job : null,
|
||||
stock_quantity: stock,
|
||||
sample_box_no: sampleBoxNo.trim() || null,
|
||||
test_weight_1: toNum(tw1),
|
||||
test_weight_2: toNum(tw2),
|
||||
@@ -162,15 +185,10 @@
|
||||
<input type="date" bind:value={productionDate} required />
|
||||
</label>
|
||||
|
||||
<label>
|
||||
<span>Product *</span>
|
||||
<select bind:value={productId} required>
|
||||
<option value="">Select product…</option>
|
||||
{#each products as p (p.id)}
|
||||
<option value={String(p.id)}>{p.name}{p.item_id ? ` · ${p.item_id}` : ''}</option>
|
||||
{/each}
|
||||
</select>
|
||||
</label>
|
||||
<div class="picker-field">
|
||||
<span class="picker-label">Product *</span>
|
||||
<ThroughputProductPicker {products} bind:productId inputId="throughput-full-product" />
|
||||
</div>
|
||||
|
||||
<label>
|
||||
<span>Bag size (kg)</span>
|
||||
@@ -196,15 +214,26 @@
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<fieldset class="qa">
|
||||
<legend>QA checklist</legend>
|
||||
<label class="check"><input type="checkbox" bind:checked={scalesChecked} /> Scales checked</label>
|
||||
<label class="check"><input type="checkbox" bind:checked={labelCorrect} /> Label correct</label>
|
||||
<label class="check"><input type="checkbox" bind:checked={bagSealed} /> Bag sealed</label>
|
||||
<label class="check"><input type="checkbox" bind:checked={palletGood} /> Pallet in good condition</label>
|
||||
{#if qaWarning}
|
||||
<p class="qa-warning"><AlertTriangle size={14} /> One or more QA checks failed — this entry will be flagged.</p>
|
||||
{/if}
|
||||
<fieldset class="destination">
|
||||
<legend>Where does this run go?</legend>
|
||||
<div class="dest-checks">
|
||||
<label class="check"><input type="checkbox" bind:checked={forOrder} /> For an order</label>
|
||||
<label class="check"><input type="checkbox" bind:checked={forStock} /> For stock</label>
|
||||
</div>
|
||||
<div class="dest-fields">
|
||||
{#if forOrder}
|
||||
<label>
|
||||
<span>Job number (Order Circle)</span>
|
||||
<input type="text" bind:value={jobNumber} placeholder="e.g. job number" />
|
||||
</label>
|
||||
{/if}
|
||||
{#if isSplit}
|
||||
<label>
|
||||
<span>Amount going to stock ({quantityType === 'bags' ? 'bags' : 'kg'})</span>
|
||||
<input type="number" min="0" step="0.01" bind:value={stockQty} placeholder="Remainder goes to the order" />
|
||||
</label>
|
||||
{/if}
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="weights">
|
||||
@@ -308,25 +337,30 @@
|
||||
font-weight: 600;
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
.qa {
|
||||
.picker-field {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.3rem;
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
.picker-label {
|
||||
font-weight: 500;
|
||||
}
|
||||
.dest-checks {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.4rem 1.25rem;
|
||||
}
|
||||
.dest-fields {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||
gap: 0.4rem 1rem;
|
||||
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
|
||||
gap: 0.5rem 1rem;
|
||||
}
|
||||
.check {
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: 0.45rem;
|
||||
}
|
||||
.qa-warning {
|
||||
grid-column: 1 / -1;
|
||||
margin: 0;
|
||||
color: #92400e;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.35rem;
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
.weight-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(5, minmax(0, 1fr));
|
||||
|
||||
Reference in New Issue
Block a user