2026-02-18 07:12:58 +07:00
|
|
|
<script>
|
|
|
|
|
import { Ruler, Calculator, FileText, Box } from 'lucide-svelte';
|
|
|
|
|
import HelpTooltip from '$lib/components/HelpTooltip.svelte';
|
|
|
|
|
import NumericRefRange from './NumericRefRange.svelte';
|
|
|
|
|
import ThresholdRefRange from './ThresholdRefRange.svelte';
|
|
|
|
|
import TextRefRange from './TextRefRange.svelte';
|
|
|
|
|
import ValueSetRefRange from './ValueSetRefRange.svelte';
|
|
|
|
|
import { createNumRef, createTholdRef, createTextRef, createVsetRef } from '../referenceRange.js';
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @typedef {Object} Props
|
|
|
|
|
* @property {Object} formData - Form data object
|
|
|
|
|
* @property {(formData: Object) => void} onupdateFormData - Update handler
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/** @type {Props} */
|
|
|
|
|
let {
|
|
|
|
|
formData = $bindable({}),
|
|
|
|
|
onupdateFormData = () => {}
|
|
|
|
|
} = $props();
|
|
|
|
|
|
refactor(tests): Move TestModal to route folder and add technical config support
- Move TestModal from lib/components to routes/(app)/master-data/tests
- Add technical configuration form (ResultType, RefType, SpcType, units, etc.)
- Add GroupMembersTab for managing group test members
- Enhance reference ranges with refvset and refthold support
- Update API to handle new test fields (ReqQty, Factor, Decimal, TAT, etc.)
- Add database schema documentation (DBML format)
- Remove old test-types-reference.md documentation
- UI improvements: compact design, updated sidebar, modal sizing
- Update DataTable, Modal, SelectDropdown components for compact style
- Enhance patient and visit modals with compact layout
2026-02-18 16:31:20 +07:00
|
|
|
// Ensure all reference range items have defined values, never undefined
|
|
|
|
|
function normalizeRefNum(ref) {
|
|
|
|
|
return {
|
|
|
|
|
Sex: ref.Sex ?? '2',
|
|
|
|
|
LowSign: ref.LowSign ?? 'GE',
|
|
|
|
|
HighSign: ref.HighSign ?? 'LE',
|
|
|
|
|
Low: ref.Low ?? null,
|
|
|
|
|
High: ref.High ?? null,
|
|
|
|
|
AgeStart: ref.AgeStart ?? 0,
|
|
|
|
|
AgeEnd: ref.AgeEnd ?? 120,
|
|
|
|
|
Flag: ref.Flag ?? 'N',
|
|
|
|
|
Interpretation: ref.Interpretation ?? 'Normal',
|
|
|
|
|
SpcType: ref.SpcType ?? '',
|
|
|
|
|
Criteria: ref.Criteria ?? ''
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function normalizeRefThold(ref) {
|
|
|
|
|
return {
|
|
|
|
|
Sex: ref.Sex ?? '2',
|
|
|
|
|
LowSign: ref.LowSign ?? 'GE',
|
|
|
|
|
HighSign: ref.HighSign ?? 'LE',
|
|
|
|
|
Low: ref.Low ?? null,
|
|
|
|
|
High: ref.High ?? null,
|
|
|
|
|
AgeStart: ref.AgeStart ?? 0,
|
|
|
|
|
AgeEnd: ref.AgeEnd ?? 120,
|
|
|
|
|
Flag: ref.Flag ?? 'N',
|
|
|
|
|
Interpretation: ref.Interpretation ?? 'Normal',
|
|
|
|
|
SpcType: ref.SpcType ?? '',
|
|
|
|
|
Criteria: ref.Criteria ?? ''
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function normalizeRefTxt(ref) {
|
|
|
|
|
return {
|
|
|
|
|
Sex: ref.Sex ?? '2',
|
|
|
|
|
AgeStart: ref.AgeStart ?? 0,
|
|
|
|
|
AgeEnd: ref.AgeEnd ?? 120,
|
|
|
|
|
RefTxt: ref.RefTxt ?? '',
|
|
|
|
|
Flag: ref.Flag ?? 'N',
|
|
|
|
|
SpcType: ref.SpcType ?? '',
|
|
|
|
|
Criteria: ref.Criteria ?? ''
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function normalizeRefVset(ref) {
|
|
|
|
|
return {
|
|
|
|
|
Sex: ref.Sex ?? '2',
|
|
|
|
|
AgeStart: ref.AgeStart ?? 0,
|
|
|
|
|
AgeEnd: ref.AgeEnd ?? 120,
|
|
|
|
|
RefTxt: ref.RefTxt ?? '',
|
|
|
|
|
Flag: ref.Flag ?? 'N',
|
|
|
|
|
SpcType: ref.SpcType ?? '',
|
|
|
|
|
Criteria: ref.Criteria ?? ''
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Reactive normalized data
|
|
|
|
|
let normalizedRefnum = $derived((formData.refnum || []).map(normalizeRefNum));
|
|
|
|
|
let normalizedRefthold = $derived((formData.refthold || []).map(normalizeRefThold));
|
|
|
|
|
let normalizedReftxt = $derived((formData.reftxt || []).map(normalizeRefTxt));
|
|
|
|
|
let normalizedRefvset = $derived((formData.refvset || []).map(normalizeRefVset));
|
|
|
|
|
|
2026-02-18 07:12:58 +07:00
|
|
|
function updateRefRangeType(type) {
|
|
|
|
|
let newFormData = {
|
|
|
|
|
...formData,
|
|
|
|
|
refRangeType: type,
|
|
|
|
|
refnum: [],
|
|
|
|
|
refthold: [],
|
|
|
|
|
reftxt: [],
|
|
|
|
|
refvset: []
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Initialize the selected type
|
|
|
|
|
if (type === 'num') {
|
|
|
|
|
newFormData.refnum = [createNumRef()];
|
|
|
|
|
} else if (type === 'thold') {
|
|
|
|
|
newFormData.refthold = [createTholdRef()];
|
|
|
|
|
} else if (type === 'text') {
|
|
|
|
|
newFormData.reftxt = [createTextRef()];
|
|
|
|
|
} else if (type === 'vset') {
|
|
|
|
|
newFormData.refvset = [createVsetRef()];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
onupdateFormData(newFormData);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function updateRefnum(refnum) {
|
|
|
|
|
onupdateFormData({ ...formData, refnum });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function updateRefthold(refthold) {
|
|
|
|
|
onupdateFormData({ ...formData, refthold });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function updateReftxt(reftxt) {
|
|
|
|
|
onupdateFormData({ ...formData, reftxt });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function updateRefvset(refvset) {
|
|
|
|
|
onupdateFormData({ ...formData, refvset });
|
|
|
|
|
}
|
|
|
|
|
</script>
|
|
|
|
|
|
refactor(tests): Move TestModal to route folder and add technical config support
- Move TestModal from lib/components to routes/(app)/master-data/tests
- Add technical configuration form (ResultType, RefType, SpcType, units, etc.)
- Add GroupMembersTab for managing group test members
- Enhance reference ranges with refvset and refthold support
- Update API to handle new test fields (ReqQty, Factor, Decimal, TAT, etc.)
- Add database schema documentation (DBML format)
- Remove old test-types-reference.md documentation
- UI improvements: compact design, updated sidebar, modal sizing
- Update DataTable, Modal, SelectDropdown components for compact style
- Enhance patient and visit modals with compact layout
2026-02-18 16:31:20 +07:00
|
|
|
<div class="space-y-3">
|
2026-02-18 07:12:58 +07:00
|
|
|
<!-- Reference Range Type Selection -->
|
|
|
|
|
<div class="bg-base-100 rounded-lg border border-base-200 p-4">
|
|
|
|
|
<div class="flex items-center gap-2 mb-3">
|
|
|
|
|
<Ruler class="w-5 h-5 text-primary" />
|
|
|
|
|
<h3 class="font-semibold">Reference Range Type</h3>
|
|
|
|
|
<HelpTooltip
|
|
|
|
|
text="Choose how to define normal/abnormal ranges for this test."
|
|
|
|
|
title="Reference Range Help"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="flex flex-wrap gap-3">
|
|
|
|
|
<label class="label cursor-pointer gap-2 p-3 bg-base-200 rounded-lg hover:bg-base-300 transition-colors flex-1 min-w-[100px]">
|
|
|
|
|
<input
|
|
|
|
|
type="radio"
|
|
|
|
|
name="refRangeType"
|
|
|
|
|
class="radio radio-primary"
|
|
|
|
|
value="none"
|
|
|
|
|
checked={formData.refRangeType === 'none'}
|
|
|
|
|
onchange={() => updateRefRangeType('none')}
|
|
|
|
|
/>
|
|
|
|
|
<div class="flex flex-col">
|
|
|
|
|
<span class="label-text font-medium">None</span>
|
|
|
|
|
<span class="text-xs text-gray-500">No reference range</span>
|
|
|
|
|
</div>
|
|
|
|
|
</label>
|
|
|
|
|
<label class="label cursor-pointer gap-2 p-3 bg-base-200 rounded-lg hover:bg-base-300 transition-colors flex-1 min-w-[100px]">
|
|
|
|
|
<input
|
|
|
|
|
type="radio"
|
|
|
|
|
name="refRangeType"
|
|
|
|
|
class="radio radio-primary"
|
|
|
|
|
value="num"
|
|
|
|
|
checked={formData.refRangeType === 'num'}
|
|
|
|
|
onchange={() => updateRefRangeType('num')}
|
|
|
|
|
/>
|
|
|
|
|
<div class="flex flex-col">
|
|
|
|
|
<span class="label-text font-medium flex items-center gap-1">
|
|
|
|
|
Numeric
|
|
|
|
|
<Calculator class="w-3 h-3" />
|
|
|
|
|
</span>
|
|
|
|
|
<span class="text-xs text-gray-500">Range (e.g., 70-100)</span>
|
|
|
|
|
</div>
|
|
|
|
|
</label>
|
|
|
|
|
<label class="label cursor-pointer gap-2 p-3 bg-base-200 rounded-lg hover:bg-base-300 transition-colors flex-1 min-w-[100px]">
|
|
|
|
|
<input
|
|
|
|
|
type="radio"
|
|
|
|
|
name="refRangeType"
|
|
|
|
|
class="radio radio-primary"
|
|
|
|
|
value="thold"
|
|
|
|
|
checked={formData.refRangeType === 'thold'}
|
|
|
|
|
onchange={() => updateRefRangeType('thold')}
|
|
|
|
|
/>
|
|
|
|
|
<div class="flex flex-col">
|
|
|
|
|
<span class="label-text font-medium flex items-center gap-1">
|
|
|
|
|
Threshold
|
|
|
|
|
<Ruler class="w-3 h-3" />
|
|
|
|
|
</span>
|
|
|
|
|
<span class="text-xs text-gray-500">Limit values</span>
|
|
|
|
|
</div>
|
|
|
|
|
</label>
|
|
|
|
|
<label class="label cursor-pointer gap-2 p-3 bg-base-200 rounded-lg hover:bg-base-300 transition-colors flex-1 min-w-[100px]">
|
|
|
|
|
<input
|
|
|
|
|
type="radio"
|
|
|
|
|
name="refRangeType"
|
|
|
|
|
class="radio radio-primary"
|
|
|
|
|
value="text"
|
|
|
|
|
checked={formData.refRangeType === 'text'}
|
|
|
|
|
onchange={() => updateRefRangeType('text')}
|
|
|
|
|
/>
|
|
|
|
|
<div class="flex flex-col">
|
|
|
|
|
<span class="label-text font-medium flex items-center gap-1">
|
|
|
|
|
Text
|
|
|
|
|
<FileText class="w-3 h-3" />
|
|
|
|
|
</span>
|
|
|
|
|
<span class="text-xs text-gray-500">Descriptive</span>
|
|
|
|
|
</div>
|
|
|
|
|
</label>
|
|
|
|
|
<label class="label cursor-pointer gap-2 p-3 bg-base-200 rounded-lg hover:bg-base-300 transition-colors flex-1 min-w-[100px]">
|
|
|
|
|
<input
|
|
|
|
|
type="radio"
|
|
|
|
|
name="refRangeType"
|
|
|
|
|
class="radio radio-primary"
|
|
|
|
|
value="vset"
|
|
|
|
|
checked={formData.refRangeType === 'vset'}
|
|
|
|
|
onchange={() => updateRefRangeType('vset')}
|
|
|
|
|
/>
|
|
|
|
|
<div class="flex flex-col">
|
|
|
|
|
<span class="label-text font-medium flex items-center gap-1">
|
|
|
|
|
Value Set
|
|
|
|
|
<Box class="w-3 h-3" />
|
|
|
|
|
</span>
|
|
|
|
|
<span class="text-xs text-gray-500">Predefined values</span>
|
|
|
|
|
</div>
|
|
|
|
|
</label>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- Numeric Reference Ranges -->
|
|
|
|
|
{#if formData.refRangeType === 'num'}
|
refactor(tests): Move TestModal to route folder and add technical config support
- Move TestModal from lib/components to routes/(app)/master-data/tests
- Add technical configuration form (ResultType, RefType, SpcType, units, etc.)
- Add GroupMembersTab for managing group test members
- Enhance reference ranges with refvset and refthold support
- Update API to handle new test fields (ReqQty, Factor, Decimal, TAT, etc.)
- Add database schema documentation (DBML format)
- Remove old test-types-reference.md documentation
- UI improvements: compact design, updated sidebar, modal sizing
- Update DataTable, Modal, SelectDropdown components for compact style
- Enhance patient and visit modals with compact layout
2026-02-18 16:31:20 +07:00
|
|
|
<NumericRefRange refnum={normalizedRefnum} onupdateRefnum={updateRefnum} />
|
2026-02-18 07:12:58 +07:00
|
|
|
{/if}
|
|
|
|
|
|
|
|
|
|
<!-- Threshold Reference Ranges -->
|
|
|
|
|
{#if formData.refRangeType === 'thold'}
|
refactor(tests): Move TestModal to route folder and add technical config support
- Move TestModal from lib/components to routes/(app)/master-data/tests
- Add technical configuration form (ResultType, RefType, SpcType, units, etc.)
- Add GroupMembersTab for managing group test members
- Enhance reference ranges with refvset and refthold support
- Update API to handle new test fields (ReqQty, Factor, Decimal, TAT, etc.)
- Add database schema documentation (DBML format)
- Remove old test-types-reference.md documentation
- UI improvements: compact design, updated sidebar, modal sizing
- Update DataTable, Modal, SelectDropdown components for compact style
- Enhance patient and visit modals with compact layout
2026-02-18 16:31:20 +07:00
|
|
|
<ThresholdRefRange refthold={normalizedRefthold} onupdateRefthold={updateRefthold} />
|
2026-02-18 07:12:58 +07:00
|
|
|
{/if}
|
|
|
|
|
|
|
|
|
|
<!-- Text Reference Ranges -->
|
|
|
|
|
{#if formData.refRangeType === 'text'}
|
refactor(tests): Move TestModal to route folder and add technical config support
- Move TestModal from lib/components to routes/(app)/master-data/tests
- Add technical configuration form (ResultType, RefType, SpcType, units, etc.)
- Add GroupMembersTab for managing group test members
- Enhance reference ranges with refvset and refthold support
- Update API to handle new test fields (ReqQty, Factor, Decimal, TAT, etc.)
- Add database schema documentation (DBML format)
- Remove old test-types-reference.md documentation
- UI improvements: compact design, updated sidebar, modal sizing
- Update DataTable, Modal, SelectDropdown components for compact style
- Enhance patient and visit modals with compact layout
2026-02-18 16:31:20 +07:00
|
|
|
<TextRefRange reftxt={normalizedReftxt} onupdateReftxt={updateReftxt} />
|
2026-02-18 07:12:58 +07:00
|
|
|
{/if}
|
|
|
|
|
|
|
|
|
|
<!-- Value Set Reference Ranges -->
|
|
|
|
|
{#if formData.refRangeType === 'vset'}
|
refactor(tests): Move TestModal to route folder and add technical config support
- Move TestModal from lib/components to routes/(app)/master-data/tests
- Add technical configuration form (ResultType, RefType, SpcType, units, etc.)
- Add GroupMembersTab for managing group test members
- Enhance reference ranges with refvset and refthold support
- Update API to handle new test fields (ReqQty, Factor, Decimal, TAT, etc.)
- Add database schema documentation (DBML format)
- Remove old test-types-reference.md documentation
- UI improvements: compact design, updated sidebar, modal sizing
- Update DataTable, Modal, SelectDropdown components for compact style
- Enhance patient and visit modals with compact layout
2026-02-18 16:31:20 +07:00
|
|
|
<ValueSetRefRange refvset={normalizedRefvset} onupdateRefvset={updateRefvset} />
|
2026-02-18 07:12:58 +07:00
|
|
|
{/if}
|
|
|
|
|
</div>
|