clqms-fe1/src/routes/(app)/master-data/tests/test-modal/TechnicalConfigForm.svelte

240 lines
8.0 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.

<script>
import { onMount } from 'svelte';
import { FlaskConical, Ruler, Clock, Beaker } from 'lucide-svelte';
import { fetchValueSetByKey } from '$lib/api/valuesets.js';
/**
* @typedef {Object} Props
* @property {Object} formData - Form data object
* @property {(formData: Object) => void} onupdateFormData - Update handler
*/
/** @type {Props} */
let {
formData = $bindable({}),
onupdateFormData = () => {}
} = $props();
// Value set options
let resultTypeOptions = $state([]);
let loading = $state(true);
onMount(async () => {
try {
loading = true;
const resultTypeRes = await fetchValueSetByKey('result_type');
console.log('result_type response:', resultTypeRes);
// Handle different response structures
const resultItems = resultTypeRes.data?.items || resultTypeRes.data?.ValueSetItems || (Array.isArray(resultTypeRes.data) ? resultTypeRes.data : []) || [];
resultTypeOptions = resultItems.map(item => ({
value: item.value || item.itemCode || item.ItemCode || item.code || item.Code,
label: item.label || item.itemValue || item.ItemValue || item.value || item.Value || item.description || item.Description
})).filter(opt => opt.value);
console.log('resultTypeOptions:', resultTypeOptions);
} catch (err) {
console.error('Failed to load value sets:', err);
} finally {
loading = false;
}
});
function updateField(field, value) {
onupdateFormData({ ...formData, [field]: value });
}
// Check if test is calculated type (doesn't have specimen requirements)
const isCalculated = $derived(formData.TestType === 'CALC');
</script>
{#if loading}
<div class="flex justify-center items-center py-12">
<span class="loading loading-spinner loading-lg"></span>
</div>
{:else}
<div class="space-y-3">
<!-- Result Configuration -->
<div class="bg-base-100 rounded-lg border border-base-200 p-4">
<div class="flex items-center gap-2 mb-4">
<FlaskConical class="w-5 h-5 text-primary" />
<h3 class="font-semibold">Result Configuration</h3>
</div>
<div class="form-control max-w-md">
<label class="label" for="resultType">
<span class="label-text text-sm font-medium">Result Type</span>
</label>
<select
id="resultType"
class="select select-sm select-bordered w-full"
bind:value={formData.ResultType}
onchange={(e) => updateField('ResultType', e.target.value)}
>
<option value="">Select result type...</option>
{#each resultTypeOptions as option}
<option value={option.value}>{option.label}</option>
{/each}
</select>
</div>
</div>
<!-- Units and Precision -->
<div class="bg-base-100 rounded-lg border border-base-200 p-4">
<div class="flex items-center gap-2 mb-4">
<Ruler class="w-5 h-5 text-primary" />
<h3 class="font-semibold">Units and Precision</h3>
</div>
<div class="grid grid-cols-1 md:grid-cols-4 gap-4">
<div class="form-control">
<label class="label" for="unit1">
<span class="label-text text-sm font-medium">Unit 1</span>
</label>
<input
id="unit1"
type="text"
class="input input-sm input-bordered w-full"
value={formData.Unit1}
oninput={(e) => updateField('Unit1', e.target.value)}
placeholder="e.g., mg/dL"
/>
</div>
<div class="form-control">
<label class="label" for="factor">
<span class="label-text text-sm font-medium">Factor</span>
</label>
<input
id="factor"
type="number"
step="0.000001"
class="input input-sm input-bordered w-full"
value={formData.Factor}
oninput={(e) => updateField('Factor', e.target.value ? parseFloat(e.target.value) : null)}
placeholder="Conversion factor"
/>
</div>
<div class="form-control">
<label class="label" for="unit2">
<span class="label-text text-sm font-medium">Unit 2</span>
</label>
<input
id="unit2"
type="text"
class="input input-sm input-bordered w-full"
value={formData.Unit2}
oninput={(e) => updateField('Unit2', e.target.value)}
placeholder="e.g., mmol/L"
/>
</div>
<div class="form-control">
<label class="label" for="decimal">
<span class="label-text text-sm font-medium">Decimal Places</span>
</label>
<input
id="decimal"
type="number"
min="0"
max="6"
class="input input-sm input-bordered w-full"
value={formData.Decimal}
oninput={(e) => updateField('Decimal', parseInt(e.target.value) || 0)}
placeholder="0-6"
/>
</div>
</div>
{#if formData.Factor}
<div class="mt-3 text-sm text-gray-600 bg-base-200 p-2 rounded">
Formula: {formData.Unit1 || 'Unit1'} × {formData.Factor} = {formData.Unit2 || 'Unit2'}
</div>
{/if}
</div>
<!-- Specimen Requirements -->
{#if !isCalculated}
<div class="bg-base-100 rounded-lg border border-base-200 p-4">
<div class="flex items-center gap-2 mb-4">
<Beaker class="w-5 h-5 text-primary" />
<h3 class="font-semibold">Specimen Requirements</h3>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div class="form-control">
<label class="label" for="reqQty">
<span class="label-text text-sm font-medium">Required Quantity</span>
</label>
<input
id="reqQty"
type="number"
step="0.01"
class="input input-sm input-bordered w-full"
value={formData.ReqQty}
oninput={(e) => updateField('ReqQty', e.target.value ? parseFloat(e.target.value) : null)}
placeholder="Amount"
/>
</div>
<div class="form-control">
<label class="label" for="reqQtyUnit">
<span class="label-text text-sm font-medium">Quantity Unit</span>
</label>
<input
id="reqQtyUnit"
type="text"
class="input input-sm input-bordered w-full"
value={formData.ReqQtyUnit}
oninput={(e) => updateField('ReqQtyUnit', e.target.value)}
placeholder="e.g., mL"
/>
</div>
</div>
</div>
{/if}
<!-- Method and TAT -->
<div class="bg-base-100 rounded-lg border border-base-200 p-4">
<div class="flex items-center gap-2 mb-4">
<Clock class="w-5 h-5 text-primary" />
<h3 class="font-semibold">Method and Turnaround</h3>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div class="form-control">
<label class="label" for="method">
<span class="label-text text-sm font-medium">Method</span>
</label>
<input
id="method"
type="text"
class="input input-sm input-bordered w-full"
value={formData.Method}
oninput={(e) => updateField('Method', e.target.value)}
placeholder="e.g., Enzymatic"
/>
</div>
<div class="form-control">
<label class="label" for="expectedTAT">
<span class="label-text text-sm font-medium">Expected TAT (minutes)</span>
</label>
<input
id="expectedTAT"
type="number"
min="0"
class="input input-sm input-bordered w-full"
value={formData.ExpectedTAT}
oninput={(e) => updateField('ExpectedTAT', e.target.value ? parseInt(e.target.value) : null)}
placeholder="e.g., 60"
/>
</div>
</div>
</div>
</div>
{/if}