diff --git a/package-lock.json b/package-lock.json
index 19d2817..914047f 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -3724,23 +3724,6 @@
"node": ">=0.10.0"
}
},
- "node_modules/yaml": {
- "version": "2.8.2",
- "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.2.tgz",
- "integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==",
- "license": "ISC",
- "optional": true,
- "peer": true,
- "bin": {
- "yaml": "bin.mjs"
- },
- "engines": {
- "node": ">= 14.6"
- },
- "funding": {
- "url": "https://github.com/sponsors/eemeli"
- }
- },
"node_modules/yocto-queue": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
diff --git a/src/lib/api/api-client.js b/src/lib/api/api-client.js
index 63ab0f7..514c5c5 100644
--- a/src/lib/api/api-client.js
+++ b/src/lib/api/api-client.js
@@ -15,25 +15,6 @@ function cleanQuery(searchQuery) {
return result;
}
-// export async function getById(endpoint, id) {
-// try {
-// const res = await fetch(`${API.BASE_URL}${endpoint}/${id}`);
-
-// if (!res.ok) {
-// const error = await res.json();
-// console.error('API Error:', error);
-// return { data: null, error };
-// }
-
-// const response = await res.json();
-// console.log(response);
-// return { data: response.data?.[0] || response.data, error: null };
-// } catch (err) {
-// console.error('Network Error:', err);
-// return { data: null, error: err };
-// }
-// }
-
export async function getById(endpoint, id, returnAll = false) {
try {
const res = await fetch(`${API.BASE_URL}${endpoint}/${id}`);
diff --git a/src/lib/components/dictionary/testmap/config/testmap-form-config.js b/src/lib/components/dictionary/testmap/config/testmap-form-config.js
index d7d3571..c0bf5a2 100644
--- a/src/lib/components/dictionary/testmap/config/testmap-form-config.js
+++ b/src/lib/components/dictionary/testmap/config/testmap-form-config.js
@@ -157,6 +157,22 @@ export function getTestMapFormActions(handlers) {
];
}
-export function buildTestPayload() {
-
+export function buildTestMapPayload({
+ mainForm,
+ tempMap,
+}) {
+ const { HostTestCode, HostTestName, ClientTestCode, ClientTestName, ConDefID, ...rest } = mainForm;
+
+ let payload = {
+ ...rest,
+ details: tempMap.map((item) => ({
+ HostTestCode: item.HostTestCode,
+ HostTestName: item.HostTestName,
+ ClientTestCode: item.ClientTestCode,
+ ClientTestName: item.ClientTestName,
+ ConDefID: item.ConDefID,
+ })),
+ };
+
+ return cleanEmptyStrings(payload);
}
\ No newline at end of file
diff --git a/src/lib/components/dictionary/testmap/page/create-page.svelte b/src/lib/components/dictionary/testmap/page/create-page.svelte
index ac35a60..c3824e4 100644
--- a/src/lib/components/dictionary/testmap/page/create-page.svelte
+++ b/src/lib/components/dictionary/testmap/page/create-page.svelte
@@ -11,6 +11,7 @@
import { Button } from "$lib/components/ui/button/index.js";
import { untrack } from "svelte";
import { API } from '$lib/config/api';
+ import { buildTestMapPayload } from "$lib/components/dictionary/testmap/config/testmap-form-config";
let props = $props();
@@ -37,21 +38,12 @@
function snapshotForm() {
return untrack(() => {
const f = formState.form;
- // const options = {};
- // for (const key in masterDetail.formState.selectOptions) {
- // options[key] = [...masterDetail.formState.selectOptions[key]];
- // }
return {
- HostType: f.HostType ?? "",
- HostID: f.HostID ?? "",
HostTestCode: f.HostTestCode ?? "",
HostTestName: f.HostTestName ?? "",
- ClientType: f.ClientType ?? "",
- ClientID: f.ClientID ?? "",
ClientTestCode: f.ClientTestCode ?? "",
ClientTestName: f.ClientTestName ?? "",
ConDefID: f.ConDefID ?? "",
- // options: options
};
});
}
@@ -61,6 +53,18 @@
editingId = null;
}
+ function resetTest() {
+ untrack(() => {
+ const f = formState.form;
+ f.HostTestCode = null;
+ f.HostTestName = null;
+ f.ClientTestCode = null;
+ f.ClientTestName = null;
+ f.ConDefID = null;
+ });
+ editingId = null;
+ }
+
function handleInsert() {
const row = {
id: ++idCounter,
@@ -69,7 +73,7 @@
tempMap = [...tempMap, row];
- resetForm();
+ resetTest();
}
async function handleEdit(row) {
@@ -77,13 +81,12 @@
untrack(() => {
const f = formState.form;
- console.log(row);
- f.HostType = row.HostType;
- f.HostID = row.HostID;
+ // f.HostType = row.HostType;
+ // f.HostID = row.HostID;
f.HostTestCode = row.HostTestCode;
f.HostTestName = row.HostTestName;
- f.ClientType = row.ClientType;
- f.ClientID = row.ClientID;
+ // f.ClientType = row.ClientType;
+ // f.ClientID = row.ClientID;
f.ClientTestCode = row.ClientTestCode;
f.ClientTestName = row.ClientTestName;
f.ConDefID = row.ConDefID;
@@ -100,22 +103,29 @@
tempMap = tempMap.map((row) =>
row.id === editingId ? { id: row.id, ...snapshotForm() } : row
);
- resetForm();
+ resetTest();
}
function handleCancelEdit() {
- resetForm();
+ resetTest();
}
function handleRemove(id) {
tempMap = tempMap.filter((row) => row.id !== id);
if (editingId === id) {
- resetForm();
+ resetTest();
}
}
async function handleSave() {
- const result = await formState.save(masterDetail.mode);
+ const mainForm = masterDetail.formState.form;
+
+ const payload = buildTestMapPayload({
+ mainForm,
+ tempMap,
+ });
+ console.log(payload)
+ const result = await formState.save(masterDetail.mode, payload);
toast('Test Map Created!');
masterDetail?.exitForm(true);
@@ -243,12 +253,12 @@
- Host Type
- Host ID
+
Host Test Code
Host Test Name
- Client Type
- Client ID
+
Client Test Code
Client Test Name
Container
@@ -267,12 +277,8 @@
- {row.HostType}
- {row.HostID}
{row.HostTestCode}
{row.HostTestName}
- {row.ClientType}
- {row.ClientID}
{row.ClientTestCode}
{row.ClientTestName}
{row.ConDefID}
diff --git a/src/lib/components/order/api/order-api.js b/src/lib/components/order/api/order-api.js
new file mode 100644
index 0000000..1384cb7
--- /dev/null
+++ b/src/lib/components/order/api/order-api.js
@@ -0,0 +1,22 @@
+import { API } from '$lib/config/api.js';
+import { getById, searchWithParams, create, update } from '$lib/api/api-client';
+
+export async function searchParam(searchQuery) {
+ return await searchWithParams(API.PATIENTS, searchQuery)
+}
+
+export async function getVisitList(searchQuery) {
+ return await getById(API.VISITLIST, searchQuery, true)
+}
+
+export async function getVisit(searchQuery) {
+ return await getById(API.PATVISIT, searchQuery)
+}
+
+export async function createOrder(newOrderForm) {
+ return await create(API.ORDER, newOrderForm)
+}
+
+export async function editOrder(editOrderForm) {
+ return await update(API.ORDER, editOrderForm)
+}
\ No newline at end of file
diff --git a/src/lib/components/order/config/order-config.js b/src/lib/components/order/config/order-config.js
new file mode 100644
index 0000000..a699b5f
--- /dev/null
+++ b/src/lib/components/order/config/order-config.js
@@ -0,0 +1,72 @@
+import PlusIcon from "@lucide/svelte/icons/plus";
+import Settings2Icon from "@lucide/svelte/icons/settings-2";
+import PencilIcon from "@lucide/svelte/icons/pencil";
+
+export const searchFields = [
+ {
+ key: "PatientID",
+ label: "Patient ID",
+ placeholder: "",
+ type: "text",
+ defaultValue: "",
+ },
+ {
+ key: "Name",
+ label: "Patient Name",
+ placeholder: "",
+ type: "text",
+ defaultValue: "",
+ },
+ {
+ key: "Birthdate",
+ label: "Birthdate",
+ type: "date"
+ },
+ {
+ key: "Identifier",
+ label: "Identifier",
+ type: "text"
+ },
+ {
+ key: "VisitID",
+ label: "Visit ID",
+ type: "text"
+ },
+ {
+ key: "EpisodeID",
+ label: "Episode ID",
+ type: "text"
+ },
+];
+
+export const detailSections = [];
+
+export function orderActions(masterDetail, selectedPatient) {
+ return [
+ {
+ Icon: PlusIcon,
+ label: 'Add Order',
+ onClick: () => masterDetail.enterCreate({
+ PatientID: selectedPatient?.PatientID,
+ InternalPID: selectedPatient?.InternalPID
+ }),
+ disabled: !selectedPatient,
+ },
+ {
+ Icon: Settings2Icon,
+ label: 'Search Parameters',
+ popoverWidth: "w-full",
+ collisionPadding: 12,
+ },
+ ];
+}
+
+export function viewActions(handlers){
+ return [
+ {
+ Icon: PencilIcon,
+ label: 'Edit Order',
+ onClick: handlers.editOrder,
+ },
+ ]
+}
\ No newline at end of file
diff --git a/src/lib/components/order/config/order-form-config.js b/src/lib/components/order/config/order-form-config.js
new file mode 100644
index 0000000..288bb14
--- /dev/null
+++ b/src/lib/components/order/config/order-form-config.js
@@ -0,0 +1,22 @@
+import { API } from "$lib/config/api";
+import EraserIcon from "@lucide/svelte/icons/eraser";
+import { z } from "zod";
+import { cleanEmptyStrings } from "$lib/utils/cleanEmptyStrings";
+
+export const orderSchema = z.object({});
+
+export const orderInitialForm = {};
+
+export const orderDefaultErrors = {};
+
+export const orderFormFields = [];
+
+export function getOrderFormActions(handlers) {
+ return [
+ {
+ Icon: EraserIcon,
+ label: 'Clear Form',
+ onClick: handlers.clearForm,
+ },
+ ];
+}
\ No newline at end of file
diff --git a/src/lib/components/order/modal/search-param-modal.svelte b/src/lib/components/order/modal/search-param-modal.svelte
new file mode 100644
index 0000000..3bcd3d0
--- /dev/null
+++ b/src/lib/components/order/modal/search-param-modal.svelte
@@ -0,0 +1,142 @@
+
+
+
+
+
+
+ {#each props.searchFields as field}
+ {#if field.type === "text"}
+
+
+
+
+ {:else if field.type === "date"}
+
+
+
+ {:else if field.type === "select"}
+
+
+
+
+
+
+
+ {#each field.options as opt}
+
+ {opt.label}
+
+ {/each}
+
+
+
+ {/if}
+ {/each}
+
+
+
+
+
+
+
+ {#if props.search.searchData && props.search.searchData.length > 0}
+
+
+
+
+
+
+ Patient ID
+ Patient Name
+ Birthdate
+ Sex
+
+
+
+ {#each props.search.searchData as patient, i}
+ handleCheckboxChange(patient)}
+ >
+ e.stopPropagation()}>
+ handleCheckboxChange(patient)}
+ />
+
+ {patient.PatientID}
+ {patient.FullName}
+ {patient.Birthdate ? patient.Birthdate.split(" ")[0] : ""}
+ {patient.SexLabel}
+
+ {/each}
+
+
+
+
+
+
+
+
+
+ {:else}
+
+
+
+ {/if}
+
+
+
+
\ No newline at end of file
diff --git a/src/lib/components/order/page/create-page.svelte b/src/lib/components/order/page/create-page.svelte
new file mode 100644
index 0000000..e69de29
diff --git a/src/lib/components/order/page/edit-page.svelte b/src/lib/components/order/page/edit-page.svelte
new file mode 100644
index 0000000..e69de29
diff --git a/src/lib/components/order/page/master-page.svelte b/src/lib/components/order/page/master-page.svelte
new file mode 100644
index 0000000..13861ef
--- /dev/null
+++ b/src/lib/components/order/page/master-page.svelte
@@ -0,0 +1,90 @@
+
+
+{#snippet searchParamSnippet()}
+
+{/snippet}
+
+ props.masterDetail.isFormMode && props.masterDetail.exitForm()}
+ onkeydown={(e) => e.key === 'Enter' && props.masterDetail.isFormMode && props.masterDetail.exitForm()}
+ class={`
+ ${props.masterDetail.isMobile ? "w-full" : props.masterDetail.isFormMode ? "w-[3%] cursor-pointer" : "w-[35%]"}
+ transition-all duration-300 flex flex-col items-center p-2 h-full overflow-y-auto
+ `}
+>
+
+ {#if props.masterDetail.isFormMode}
+
+ {#each "ADMISSION".split("") as c}
+ {c}
+ {/each}
+
+ {/if}
+
+ {#if !props.masterDetail.isFormMode}
+
e.stopPropagation()} onkeydown={(e) => {
+ if (e.key === 'Enter' || e.key === ' ') {
+ e.preventDefault();
+ e.stopPropagation();
+ }
+ }}>
+
+
+ {#if searchData?.data?.length > 0}
+
+ {:else}
+
+
+
+ {/if}
+
+
+ {/if}
+
+
\ No newline at end of file
diff --git a/src/lib/components/order/page/view-page.svelte b/src/lib/components/order/page/view-page.svelte
new file mode 100644
index 0000000..e69de29
diff --git a/src/lib/components/order/table/order-columns.js b/src/lib/components/order/table/order-columns.js
new file mode 100644
index 0000000..8ff94d4
--- /dev/null
+++ b/src/lib/components/order/table/order-columns.js
@@ -0,0 +1,14 @@
+export const orderColumns = [
+ {
+ accessorKey: "InternalPVID",
+ header: "Patient ID"
+ },
+ {
+ accessorKey: "PVID",
+ header: "Visit ID",
+ },
+ {
+ accessorKey: "EpisodeID",
+ header: "Episode ID",
+ },
+];
\ No newline at end of file
diff --git a/src/lib/components/patient/admission/config/admission-config.js b/src/lib/components/patient/admission/config/admission-config.js
index 4153e94..7936fa5 100644
--- a/src/lib/components/patient/admission/config/admission-config.js
+++ b/src/lib/components/patient/admission/config/admission-config.js
@@ -93,7 +93,8 @@ export function admissionActions(masterDetail, selectedPatient) {
{
Icon: Settings2Icon,
label: 'Search Parameters',
- popoverWidth: "w-256",
+ popoverWidth: "w-full",
+ collisionPadding: 12,
},
];
}
diff --git a/src/lib/components/patient/admission/modal/search-param-modal.svelte b/src/lib/components/patient/admission/modal/search-param-modal.svelte
index 3781e36..42d5168 100644
--- a/src/lib/components/patient/admission/modal/search-param-modal.svelte
+++ b/src/lib/components/patient/admission/modal/search-param-modal.svelte
@@ -46,7 +46,7 @@
-
+
{#each props.searchFields as field}
{#if field.type === "text"}
diff --git a/src/lib/components/patient/list/config/patient-config.js b/src/lib/components/patient/list/config/patient-config.js
index 69bc792..56b047f 100644
--- a/src/lib/components/patient/list/config/patient-config.js
+++ b/src/lib/components/patient/list/config/patient-config.js
@@ -76,10 +76,10 @@ export const detailSections = [
{ parentKey: "Custodian", key: "PatientID", label: "Custodian ID" },
],
},
- { key: "DeathIndicatorLabel", label: "Death Indicator" },
+ { key: "isDeadLabel", label: "Deceased" },
{ key: "CreateDate", label: "Create Date", isUTCDate: true },
{ key: "DelDate", label: "Disabled Date" },
- { key: "TimeOfDeath", label: "Death Date", isUTCDate: true },
+ { key: "TimeOfDeath", label: "Time of Death", isUTCDate: true },
]
},
// {
diff --git a/src/lib/components/patient/list/config/patient-form-config.js b/src/lib/components/patient/list/config/patient-form-config.js
index 07462bb..9a09fd6 100644
--- a/src/lib/components/patient/list/config/patient-form-config.js
+++ b/src/lib/components/patient/list/config/patient-form-config.js
@@ -270,7 +270,7 @@ export const patientFormFields = [
type: "group",
columns: [
{
- key: "DeathIndicator",
+ key: "isDead",
label: "Deceased",
required: false,
type: "select",
diff --git a/src/lib/components/patient/list/page/edit-page.svelte b/src/lib/components/patient/list/page/edit-page.svelte
index c80db35..da446b3 100644
--- a/src/lib/components/patient/list/page/edit-page.svelte
+++ b/src/lib/components/patient/list/page/edit-page.svelte
@@ -47,7 +47,6 @@
});
});
- // if (formState.form.ProvinceID && formState.form.CityID) {
if (formState.form.Province) {
formState.fetchOptions(
{
@@ -61,9 +60,35 @@
}
});
});
+
+ function getChangedFields(original, current) {
+ const changed = {};
+ for (const key in current) {
+ if (JSON.stringify(current[key]) !== JSON.stringify(original[key])) {
+ changed[key] = current[key];
+ }
+ }
+ return changed;
+ }
async function handleEdit() {
- const payload = buildPatientPayload(formState.form);
+ const currentPayload = buildPatientPayload(formState.form);
+ const originalPayload = buildPatientPayload(masterDetail.formSnapshot);
+
+ const changedFields = getChangedFields(originalPayload, currentPayload);
+
+ if (Object.keys(changedFields).length === 0) {
+ toast('No changes detected');
+ return;
+ }
+
+ const payload = {
+ InternalPID: formState.form.InternalPID,
+ ...changedFields
+ };
+
+ console.log('Payload:', payload);
+
const result = await formState.save(masterDetail.mode, payload);
if (result.status === 'success') {
diff --git a/src/lib/components/patient/reusable/patient-form-renderer.svelte b/src/lib/components/patient/reusable/patient-form-renderer.svelte
index 2be932a..10b514e 100644
--- a/src/lib/components/patient/reusable/patient-form-renderer.svelte
+++ b/src/lib/components/patient/reusable/patient-form-renderer.svelte
@@ -68,7 +68,7 @@
}
let isDeathDateDisabled = $derived(
- formState.form.DeathIndicator !== 'Y'
+ formState.form.isDead !== 'Y'
);
$effect(() => {
diff --git a/src/lib/components/topbar/topbar-action.svelte b/src/lib/components/topbar/topbar-action.svelte
index e5b0c42..37bee19 100644
--- a/src/lib/components/topbar/topbar-action.svelte
+++ b/src/lib/components/topbar/topbar-action.svelte
@@ -27,7 +27,7 @@
{/snippet}
-
+
{@render props.popoverContent()}
diff --git a/src/routes/order/+page.svelte b/src/routes/order/+page.svelte
new file mode 100644
index 0000000..0579089
--- /dev/null
+++ b/src/routes/order/+page.svelte
@@ -0,0 +1,55 @@
+
+
+
+ {#if masterDetail.showMaster}
+
+ {/if}
+
+ {#if masterDetail.showDetail}
+
+ {#if masterDetail.mode === "view"}
+
+ {:else if masterDetail.mode === "create"}
+
+ {:else if masterDetail.mode === "edit"}
+
+ {/if}
+
+ {/if}
+
\ No newline at end of file