From 80d59f31207feff5c885b4ef7f7bc8a44be5a613 Mon Sep 17 00:00:00 2001 From: faiztyanirh Date: Thu, 9 Apr 2026 16:39:10 +0700 Subject: [PATCH] continue testmap & deleting testmap on test tab --- .../dictionary/contact/page/edit-page.svelte | 25 +- .../test/config/test-form-config.js | 144 ------ .../dictionary/test/page/create-page.svelte | 119 +---- .../dictionary/test/page/edit-page.svelte | 118 +---- .../testmap/config/testmap-config.js | 2 +- .../config/testmap-form-config copy.js | 185 ++++++++ .../testmap/config/testmap-form-config.js | 26 +- .../testmap/page/create-page.svelte | 186 ++++---- .../dictionary/testmap/page/edit-page.svelte | 446 +++++++++++++++++- .../testmap/page/master-page.svelte | 4 +- .../dictionary/testmap/page/view-page.svelte | 2 +- .../patient/list/config/patient-config.js | 8 +- .../patient/list/page/master-page.svelte | 10 +- .../form/dictionary-form-renderer.svelte | 1 + 14 files changed, 773 insertions(+), 503 deletions(-) create mode 100644 src/lib/components/dictionary/testmap/config/testmap-form-config copy.js diff --git a/src/lib/components/dictionary/contact/page/edit-page.svelte b/src/lib/components/dictionary/contact/page/edit-page.svelte index 7d355af..8e825ee 100644 --- a/src/lib/components/dictionary/contact/page/edit-page.svelte +++ b/src/lib/components/dictionary/contact/page/edit-page.svelte @@ -7,16 +7,10 @@ import { API } from "$lib/config/api"; import ReusableAlertDialog from "$lib/components/reusable/reusable-alert-dialog.svelte"; import { Separator } from "$lib/components/ui/separator/index.js"; - import PlusIcon from "@lucide/svelte/icons/plus"; - import * as Card from "$lib/components/ui/card/index.js"; - import { Badge } from "$lib/components/ui/badge/index.js"; - import TopbarWrapper from "$lib/components/topbar/topbar-wrapper.svelte"; import { contactDetailSchema, contactDetailInitialForm, contactDetailDefaultErrors, contactDetailFormFields, buildContactPayload } from "$lib/components/dictionary/contact/config/contact-form-config"; import { Button } from "$lib/components/ui/button/index.js"; import { useForm } from "$lib/components/composable/use-form.svelte"; - import XIcon from "@lucide/svelte/icons/x"; - import Edit2Icon from "@lucide/svelte/icons/edit-2"; - // import { getChangedFields } from "$lib/utils/getChangedFields"; + import { getChangedFields } from "$lib/utils/getChangedFields"; import * as Table from '$lib/components/ui/table/index.js'; import PencilIcon from "@lucide/svelte/icons/pencil"; import Trash2Icon from "@lucide/svelte/icons/trash-2"; @@ -95,11 +89,6 @@ const orig = originalMap.get(item.ContactDetID); if (!orig) continue; - // console.log('ITEM:', item); - // console.log('ORIG:', orig); - // console.log('KEYS current:', Object.keys(item)); - // console.log('KEYS original:', Object.keys(orig)); - const changed = Object.keys(item).some( key => item[key] !== orig[key] ); @@ -110,16 +99,6 @@ return updated; } - 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 currentPayload = buildContactPayload({ mainForm: formState.form, @@ -279,7 +258,7 @@ function handleCancelEditDetail() { resetContactDetailForm(); } -$inspect(deletedDetailIds) + function handleRemoveDetail(id) { const row = tempDetailContact.find(r => r.id === id); if (row?.ContactDetID) { diff --git a/src/lib/components/dictionary/test/config/test-form-config.js b/src/lib/components/dictionary/test/config/test-form-config.js index 3a16e21..1ba0b79 100644 --- a/src/lib/components/dictionary/test/config/test-form-config.js +++ b/src/lib/components/dictionary/test/config/test-form-config.js @@ -195,29 +195,6 @@ export const refTxtSchema = z } }); -export const testMapSchema = z - .object({ - HostID: z.string().optional(), - ClientID: z.string().optional() - }) - .superRefine((data, ctx) => { - const hostID = data.HostID; - const clientID = data.ClientID; - - if (hostID && clientID && hostID === clientID) { - ctx.addIssue({ - code: z.ZodIssueCode.custom, - message: 'ClientID must be different from HostID', - path: ['ClientID'] - }); - ctx.addIssue({ - code: z.ZodIssueCode.custom, - message: 'HostID must be different from ClientID', - path: ['HostID'] - }); - } - }); - export const testInitialForm = { TestSiteID: '', SiteID: '', @@ -297,19 +274,6 @@ export const refTxtInitialForm = { Notes: '' }; -export const testMapInitialForm = { - TestMapID: '', - HostType: '', - HostID: '', - HostTestCode: '', - HostTestName: '', - ClientType: '', - ClientID: '', - ClientTestCode: '', - ClientTestName: '', - ConDefID: '' -}; - export const testDefaultErrors = { TestSiteCode: 'Required', TestSiteName: 'Required', @@ -340,11 +304,6 @@ export const refTxtDefaultErrors = { AgeEnd: null }; -export const testMapDefaultErrors = { - HostID: null, - ClientID: null -}; - export const testFormFields = [ { title: 'Basic Information', @@ -947,101 +906,6 @@ export const refTxtFormFields = [ } ]; -export const testMapFormFields = [ - { - title: 'Host & Client Information', - rows: [ - { - type: 'row', - columns: [ - { - key: 'HostType', - label: 'Host Type', - required: false, - type: 'select', - optionsEndpoint: `${API.BASE_URL}${API.VALUESET}/entity_type` - }, - { - key: 'ClientType', - label: 'Client Type', - required: false, - type: 'select', - optionsEndpoint: `${API.BASE_URL}${API.VALUESET}/entity_type` - } - ] - }, - { - type: 'row', - columns: [ - { - key: 'HostID', - label: 'Host ID', - required: false, - type: 'text', - validateOn: ['input'] - }, - { - key: 'ClientID', - label: 'Client ID', - required: false, - type: 'text', - validateOn: ['input'] - } - ] - }, - { - type: 'row', - columns: [ - { - key: 'HostTestCode', - label: 'Host Test Code', - required: false, - type: 'text' - }, - { - key: 'ClientTestCode', - label: 'Client Test Code', - required: false, - type: 'text' - } - ] - }, - { - type: 'row', - columns: [ - { - key: 'HostTestName', - label: 'Host Test Name', - required: false, - type: 'text' - }, - { - key: 'ClientTestName', - label: 'Client Test Name', - required: false, - type: 'text' - } - ] - }, - { - type: 'row', - columns: [ - { - key: 'ConDefID', - label: 'Container Definition', - required: false, - type: 'select', - optionsEndpoint: `${API.BASE_URL}${API.CONTAINER}`, - valueKey: 'ConDefID', - labelKey: (item) => `${item.ConCode} - ${item.ConName}`, - fullWidth: false - } - ] - } - ] - } -]; - export function getTestFormActions(handlers) { return [ { @@ -1058,7 +922,6 @@ export function buildTestPayload({ testType, refNumData, refTxtData, - mapData }) { let payload = { ...mainForm @@ -1085,19 +948,12 @@ export function buildTestPayload({ TestSiteID: Number(m.value) })) } - } else if (key === 'map' && mapData?.length > 0) { - payload.testmap = mapData; } else if (key === 'cal') { payload.testdefcal = { ...state.form, FormulaInput: state.form?.FormulaInput?.map((m) => ({ TestSiteID: Number(m.testid) })) }; } - // else if ((key === 'cal' || key === 'map') && state?.form) { - // payload[key] = { - // ...state.form - // }; - // } } return cleanEmptyStrings(payload); diff --git a/src/lib/components/dictionary/test/page/create-page.svelte b/src/lib/components/dictionary/test/page/create-page.svelte index 8f956fa..5c63a06 100644 --- a/src/lib/components/dictionary/test/page/create-page.svelte +++ b/src/lib/components/dictionary/test/page/create-page.svelte @@ -20,10 +20,6 @@ refTxtDefaultErrors, refTxtInitialForm, refTxtFormFields, - testMapSchema, - testMapInitialForm, - testMapDefaultErrors, - testMapFormFields, testGroupSchema, testGroupInitialForm, testGroupDefaultErrors, @@ -33,7 +29,6 @@ import RefNum from './tabs/ref-num.svelte'; import RefTxt from './tabs/ref-txt.svelte'; import Calculation from './tabs/calculation.svelte'; - import Map from './tabs/map.svelte'; import Group from './tabs/group.svelte'; import { API } from '$lib/config/api'; import { untrack } from 'svelte'; @@ -42,10 +37,8 @@ let resetRefNum = $state(); let resetRefTxt = $state(); - let resetMap = $state(); let refNumData = $state([]); let refTxtData = $state([]); - let mapData = $state([]); const { masterDetail, formFields, formActions, schema, initialForm } = props.context; @@ -75,13 +68,6 @@ defaultErrors: refTxtDefaultErrors }); - const mapFormState = useForm({ - schema: testMapSchema, - initialForm: testMapInitialForm, - defaultErrors: testMapDefaultErrors, - modeOpt: 'cascade' - }); - const activeFormStates = $derived.by(() => { const testType = formState.form.TestType ?? ''; const refType = formState.form.RefType ?? ''; @@ -99,18 +85,15 @@ case 'PARAM': return { ...refState, - map: mapFormState }; case 'CALC': return { cal: calFormState, ...refState, - map: mapFormState }; case 'GROUP': return { group: groupFormState, - map: mapFormState } case 'TITLE': default: @@ -137,7 +120,6 @@ async function handleSave() { const mainForm = masterDetail.formState.form; const testType = mainForm.TestType; - const cleanMapData = mapData.map(({ options, ...rest }) => rest); const payload = buildTestPayload({ mainForm, @@ -145,7 +127,6 @@ testType: testType, refNumData: refNumData, refTxtData: refTxtData, - mapData: cleanMapData, }); console.log(payload); @@ -172,11 +153,11 @@ switch (testType) { case 'TEST': case 'PARAM': - return ['definition', 'map', 'reference']; + return ['definition', 'reference']; case 'CALC': - return ['definition', 'calculation', 'map', 'reference']; + return ['definition', 'calculation', 'reference']; case 'GROUP': - return ['definition', 'group', 'map']; + return ['definition', 'group']; default: return ['definition']; } @@ -258,81 +239,6 @@ })); }); - const testMapFormFieldsTransformed = $derived.by(() => { - return testMapFormFields.map((group) => ({ - ...group, - rows: group.rows.map((row) => ({ - ...row, - columns: row.columns.map((col) => { - if (col.key === 'HostID') { - if (mapFormState.form.HostType === 'SITE') { - return { - ...col, - type: 'select', - optionsEndpoint: `${API.BASE_URL}${API.SITE}`, - valueKey: 'SiteID', - labelKey: (item) => `${item.SiteCode} - ${item.SiteName}` - }; - } - return col; - } - - if (col.key === 'ClientID') { - if (mapFormState.form.ClientType === 'SITE') { - return { - ...col, - type: 'select', - optionsEndpoint: `${API.BASE_URL}${API.SITE}`, - valueKey: 'SiteID', - labelKey: (item) => `${item.SiteCode} - ${item.SiteName}` - }; - } - return col; - } - - if (col.key === 'HostTestCode' || col.key === 'HostTestName') { - if (mapFormState.form.HostType === 'SITE' && mapFormState.form.HostID) { - return { - ...col, - type: 'select', - optionsEndpoint: `${API.BASE_URL}${API.TEST}?SiteID=${mapFormState.form.HostID}`, - valueKey: 'TestSiteID', - labelKey: (item) => `${item.TestSiteCode} - ${item.TestSiteName}` - }; - } - // kalau belum pilih HostID, kembalikan default (misal input biasa) - return { - ...col, - type: 'text', - optionsEndpoint: undefined - }; - } - - if (col.key === 'ClientTestCode' || col.key === 'ClientTestName') { - if (mapFormState.form.ClientType === 'SITE' && mapFormState.form.ClientID) { - return { - ...col, - type: 'select', - optionsEndpoint: `${API.BASE_URL}${API.TEST}?SiteID=${mapFormState.form.ClientID}`, - valueKey: 'TestSiteID', - labelKey: (item) => `${item.TestSiteCode} - ${item.TestSiteName}` - }; - } - // kalau belum pilih HostID, kembalikan default (misal input biasa) - return { - ...col, - type: 'text', - optionsEndpoint: undefined - }; - } - - return col; - }) - })) - })); - }); - - // $inspect(activeFormState.errors) let activeTab = $state('definition'); $effect(() => { @@ -347,14 +253,6 @@ } }); - // $effect(() => { - // if (formState.form.Factor && !formState.form.Unit2) { - // formState.errors.Unit2 = 'Required'; - // } else { - // formState.errors.Unit2 = null; - // } - // }); - $effect(() => { const allColumns = formFields.flatMap((section) => section.rows.flatMap((row) => row.columns ?? []) @@ -440,11 +338,6 @@ refTxtState.form.TxtRefType = value; } } - - // $inspect({ - // definition: formState.errors, - // active: Object.values(activeFormStates).map(fs => fs.errors) - // }); @@ -462,9 +355,6 @@ {#if availableTabs.includes('reference')} Reference {/if} - {#if availableTabs.includes('map')} - Map - {/if} - - -
{#if refComponent === 'numeric'} diff --git a/src/lib/components/dictionary/test/page/edit-page.svelte b/src/lib/components/dictionary/test/page/edit-page.svelte index 1917846..4d4acd9 100644 --- a/src/lib/components/dictionary/test/page/edit-page.svelte +++ b/src/lib/components/dictionary/test/page/edit-page.svelte @@ -20,10 +20,6 @@ refTxtDefaultErrors, refTxtInitialForm, refTxtFormFields, - testMapSchema, - testMapInitialForm, - testMapDefaultErrors, - testMapFormFields, testGroupSchema, testGroupInitialForm, testGroupDefaultErrors, @@ -33,7 +29,6 @@ import RefNum from './tabs/ref-num.svelte'; import RefTxt from './tabs/ref-txt.svelte'; import Calculation from './tabs/calculation.svelte'; - import Map from './tabs/map.svelte'; import Group from './tabs/group.svelte'; import { API } from "$lib/config/api"; import { untrack } from "svelte"; @@ -43,10 +38,8 @@ let resetRefNum = $state(); let resetRefTxt = $state(); - let resetMap = $state(); let refNumData = $state([]); let refTxtData = $state([]); - let mapData = $state([]); const { masterDetail, formFields, formActions, schema, initialForm } = props.context; @@ -76,13 +69,6 @@ defaultErrors: refTxtDefaultErrors }); - const mapFormState = useForm({ - schema: testMapSchema, - initialForm: testMapInitialForm, - defaultErrors: testMapDefaultErrors, - modeOpt: 'cascade' - }); - const activeFormStates = $derived.by(() => { const testType = formState.form.TestType ?? ''; const refType = formState.form.RefType ?? ''; @@ -100,13 +86,11 @@ case 'PARAM': return { ...refState, - map: mapFormState }; case 'CALC': return { cal: calFormState, ...refState, - map: mapFormState }; case 'GROUP': return { @@ -129,7 +113,6 @@ async function handleEdit() { const mainForm = masterDetail.formState.form; const testType = mainForm.TestType; - const cleanMapData = mapData.map(({ options, ...rest }) => rest); const payload = buildTestPayload({ mainForm, @@ -137,7 +120,6 @@ testType: testType, refNumData: refNumData, refTxtData: refTxtData, - mapData: cleanMapData, }); console.log(payload); @@ -162,9 +144,9 @@ switch (testType) { case 'TEST': case 'PARAM': - return ['definition', 'map', 'reference']; + return ['definition', 'reference']; case 'CALC': - return ['definition', 'calculation', 'map', 'reference']; + return ['definition', 'calculation', 'reference']; case 'GROUP': return ['definition', 'group']; default: @@ -248,80 +230,6 @@ })); }); - const testMapFormFieldsTransformed = $derived.by(() => { - return testMapFormFields.map((group) => ({ - ...group, - rows: group.rows.map((row) => ({ - ...row, - columns: row.columns.map((col) => { - if (col.key === 'HostID') { - if (mapFormState.form.HostType === 'SITE') { - return { - ...col, - type: 'select', - optionsEndpoint: `${API.BASE_URL}${API.SITE}`, - valueKey: 'SiteID', - labelKey: (item) => `${item.SiteCode} - ${item.SiteName}` - }; - } - return col; - } - - if (col.key === 'ClientID') { - if (mapFormState.form.ClientType === 'SITE') { - return { - ...col, - type: 'select', - optionsEndpoint: `${API.BASE_URL}${API.SITE}`, - valueKey: 'SiteID', - labelKey: (item) => `${item.SiteCode} - ${item.SiteName}` - }; - } - return col; - } - - if (col.key === 'HostTestCode' || col.key === 'HostTestName') { - if (mapFormState.form.HostType === 'SITE' && mapFormState.form.HostID) { - return { - ...col, - type: 'select', - optionsEndpoint: `${API.BASE_URL}${API.TEST}?SiteID=${mapFormState.form.HostID}`, - valueKey: 'TestSiteID', - labelKey: (item) => `${item.TestSiteCode} - ${item.TestSiteName}` - }; - } - // kalau belum pilih HostID, kembalikan default (misal input biasa) - return { - ...col, - type: 'text', - optionsEndpoint: undefined - }; - } - - if (col.key === 'ClientTestCode' || col.key === 'ClientTestName') { - if (mapFormState.form.ClientType === 'SITE' && mapFormState.form.ClientID) { - return { - ...col, - type: 'select', - optionsEndpoint: `${API.BASE_URL}${API.TEST}?SiteID=${mapFormState.form.ClientID}`, - valueKey: 'TestSiteID', - labelKey: (item) => `${item.TestSiteCode} - ${item.TestSiteName}` - }; - } - // kalau belum pilih HostID, kembalikan default (misal input biasa) - return { - ...col, - type: 'text', - optionsEndpoint: undefined - }; - } - - return col; - }) - })) - })); - }); - let activeTab = $state('definition'); let groupInitialized = $state(false); @@ -343,7 +251,7 @@ AgeEnd: typeof row.AgeEnd === 'number' ? buildAgeText(daysToAge(row.AgeEnd)) : row.AgeEnd, })); } - // groupFormState.form.Members = []; + if (!groupInitialized && mainForm.testdefgrp?.members && Array.isArray(mainForm.testdefgrp.members)) { groupFormState.form.Members = mainForm.testdefgrp.members.map((m, index) => ({ id: m.id ?? index + 1, @@ -351,12 +259,6 @@ })); groupInitialized = true; } - // if (mainForm.testmap && Array.isArray(mainForm.testmap)) { - // mapData = mainForm.testmap.map((row, index) => ({ - // id: row.id ?? index + 1, - // ...row, - // })); - // } }) $effect(() => { @@ -453,14 +355,6 @@ refTxtState.form.TxtRefType = value; } } - - // $effect(() => { - // if (formState.form.Factor && !formState.form.Unit2) { - // formState.errors.Unit2 = 'Required'; - // } else { - // formState.errors.Unit2 = null; - // } - // }); $effect(() => { const refType = formState.form.RefType; @@ -488,9 +382,6 @@ {#if availableTabs.includes('reference')} Reference {/if} - {#if availableTabs.includes('map')} - Map - {/if} - - -
{#if refComponent === 'numeric'} diff --git a/src/lib/components/dictionary/testmap/config/testmap-config.js b/src/lib/components/dictionary/testmap/config/testmap-config.js index b5fb9d5..6031de3 100644 --- a/src/lib/components/dictionary/testmap/config/testmap-config.js +++ b/src/lib/components/dictionary/testmap/config/testmap-config.js @@ -30,7 +30,7 @@ export const detailSections = [ { key: "ClientTypeLabel", label: "Client Type" }, { key: "HostID", label: "Host ID" }, { key: "ClientID", label: "Client ID" }, - { key: "Details", label: "Details", fullWidth: true }, + { key: "details", label: "Details", fullWidth: true }, ] }, ]; diff --git a/src/lib/components/dictionary/testmap/config/testmap-form-config copy.js b/src/lib/components/dictionary/testmap/config/testmap-form-config copy.js new file mode 100644 index 0000000..40be4da --- /dev/null +++ b/src/lib/components/dictionary/testmap/config/testmap-form-config copy.js @@ -0,0 +1,185 @@ +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 testMapSchema = z + .object({ + HostID: z.string().optional(), + ClientID: z.string().optional() + }) + // .superRefine((data, ctx) => { + // const hostID = data.HostID; + // const clientID = data.ClientID; + + // if (hostID && clientID && hostID === clientID) { + // ctx.addIssue({ + // code: z.ZodIssueCode.custom, + // message: 'ClientID must be different from HostID', + // path: ['ClientID'] + // }); + // ctx.addIssue({ + // code: z.ZodIssueCode.custom, + // message: 'HostID must be different from ClientID', + // path: ['HostID'] + // }); + // } + // }); + +export const testMapDetailSchema = z.object({}); + +export const testMapInitialForm = { + TestMapID: '', + HostType: '', + HostID: '', + ClientType: '', + ClientID: '', +}; + +export const testMapDetailInitialForm = { + HostTestCode: '', + HostTestName: '', + ClientTestCode: '', + ClientTestName: '', + ConDefID: '' +} + +export const testMapDefaultErrors = { + HostID: null, + ClientID: null +}; + +export const testMapDetailDefaultErrors = {}; + +export const testMapFormFields = [ + { + rows: [ + { + type: 'row', + columns: [ + { + key: 'HostType', + label: 'Host Type', + required: false, + type: 'select', + optionsEndpoint: `${API.BASE_URL}${API.VALUESET}/entity_type`, + tabIndex: 1, + }, + { + key: 'ClientType', + label: 'Client Type', + required: false, + type: 'select', + optionsEndpoint: `${API.BASE_URL}${API.VALUESET}/entity_type`, + tabIndex: 5, + } + ] + }, + { + type: 'row', + columns: [ + { + key: 'HostID', + label: 'Host ID', + required: false, + type: 'text', + validateOn: ['input'], + tabIndex: 2, + }, + { + key: 'ClientID', + label: 'Client ID', + required: false, + type: 'text', + validateOn: ['input'], + tabIndex: 6, + } + ] + }, + { + type: 'row', + columns: [ + { + key: 'HostTestCode', + label: 'Host Test Code', + required: false, + type: 'text', + tabIndex: 3, + }, + { + key: 'ClientTestCode', + label: 'Client Test Code', + required: false, + type: 'text', + tabIndex: 7, + } + ] + }, + { + type: 'row', + columns: [ + { + key: 'HostTestName', + label: 'Host Test Name', + required: false, + type: 'text', + tabIndex: 4, + }, + { + key: 'ClientTestName', + label: 'Client Test Name', + required: false, + type: 'text', + tabIndex: 8, + } + ] + }, + { + type: 'row', + columns: [ + { + key: 'ConDefID', + label: 'Container Definition', + required: false, + type: 'select', + optionsEndpoint: `${API.BASE_URL}${API.CONTAINER}`, + valueKey: 'ConDefID', + labelKey: (item) => `${item.ConCode} - ${item.ConName}`, + fullWidth: false, + tabIndex: 9, + } + ] + } + ] + } +]; + +export function getTestMapFormActions(handlers) { + return [ + { + Icon: EraserIcon, + label: 'Clear Form', + onClick: handlers.clearForm + } + ]; +} + +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/config/testmap-form-config.js b/src/lib/components/dictionary/testmap/config/testmap-form-config.js index 4baab34..d5c9f60 100644 --- a/src/lib/components/dictionary/testmap/config/testmap-form-config.js +++ b/src/lib/components/dictionary/testmap/config/testmap-form-config.js @@ -26,24 +26,35 @@ export const testMapSchema = z // } // }); +export const testMapDetailSchema = z.object({ + ConDefID: z.string().trim().optional(), +}); + export const testMapInitialForm = { TestMapID: '', HostType: '', HostID: '', - HostTestCode: '', - HostTestName: '', ClientType: '', ClientID: '', +}; + +export const testMapDetailInitialForm = { + HostTestCode: '', + HostTestName: '', ClientTestCode: '', ClientTestName: '', ConDefID: '' -}; +} export const testMapDefaultErrors = { HostID: null, ClientID: null }; +export const testMapDetailDefaultErrors = { + ConDefID: null, +}; + export const testMapFormFields = [ { rows: [ @@ -89,6 +100,13 @@ export const testMapFormFields = [ } ] }, + ] + } +]; + +export const testMapDetailFormFields = [ + { + rows: [ { type: 'row', columns: [ @@ -145,7 +163,7 @@ export const testMapFormFields = [ } ] } -]; +] export function getTestMapFormActions(handlers) { return [ diff --git a/src/lib/components/dictionary/testmap/page/create-page.svelte b/src/lib/components/dictionary/testmap/page/create-page.svelte index 6c755f3..523ecfb 100644 --- a/src/lib/components/dictionary/testmap/page/create-page.svelte +++ b/src/lib/components/dictionary/testmap/page/create-page.svelte @@ -4,6 +4,8 @@ import DictionaryFormRenderer from "$lib/components/reusable/form/dictionary-form-renderer.svelte"; import { toast } from "svelte-sonner"; import ReusableAlertDialog from "$lib/components/reusable/reusable-alert-dialog.svelte"; + import { useForm } from "$lib/components/composable/use-form.svelte"; + import { testMapDetailSchema, testMapDetailInitialForm, testMapDetailDefaultErrors, testMapDetailFormFields, buildTestMapPayload } from "$lib/components/dictionary/testmap/config/testmap-form-config"; import { Separator } from "$lib/components/ui/separator/index.js"; import PencilIcon from "@lucide/svelte/icons/pencil"; import Trash2Icon from "@lucide/svelte/icons/trash-2"; @@ -11,23 +13,30 @@ 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(); + const { masterDetail, formFields, formActions, schema } = props.context; + + const { formState } = masterDetail; + let editingId = $state(null); let idCounter = $state(0); let tempMap = $state([]); - const { masterDetail, formFields, formActions, schema } = props.context; - - const { formState } = masterDetail; + const testMapDetailFormState = useForm({ + schema: testMapDetailSchema, + initialForm: testMapDetailInitialForm, + defaultErrors: testMapDetailDefaultErrors, + }); const helpers = useDictionaryForm(formState); const handlers = { clearForm: () => { formState.reset(); + resetTestMapDetailForm(); + tempMap = []; } }; @@ -37,7 +46,7 @@ function snapshotForm() { return untrack(() => { - const f = formState.form; + const f = testMapDetailFormState.form; return { HostTestCode: f.HostTestCode ?? "", HostTestName: f.HostTestName ?? "", @@ -48,24 +57,13 @@ }); } - function resetForm() { - formState.reset(); + function resetTestMapDetailForm() { + testMapDetailFormState.reset(); 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() { + function handleInsertDetail() { + console.log('object'); const row = { id: ++idCounter, ...snapshotForm() @@ -73,47 +71,38 @@ tempMap = [...tempMap, row]; - resetTest(); + resetTestMapDetailForm(); } - async function handleEdit(row) { + async function handleEditDetail(row) { editingId = row.id; untrack(() => { - const f = formState.form; - // f.HostType = row.HostType; - // f.HostID = row.HostID; + const f = testMapDetailFormState.form; + f.HostTestCode = row.HostTestCode; f.HostTestName = row.HostTestName; - // f.ClientType = row.ClientType; - // f.ClientID = row.ClientID; f.ClientTestCode = row.ClientTestCode; f.ClientTestName = row.ClientTestName; f.ConDefID = row.ConDefID; - - // if (row.options) { - // for (const key in row.options) { - // masterDetail.formState.selectOption[key] = row.options[key]; - // } - // } }); } - function handleUpdate() { + function handleUpdateDetail() { tempMap = tempMap.map((row) => row.id === editingId ? { id: row.id, ...snapshotForm() } : row ); - resetTest(); + resetTestMapDetailForm(); } - function handleCancelEdit() { - resetTest(); + function handleCancelEditDetail() { + resetTestMapDetailForm(); } - function handleRemove(id) { + function handleRemoveDetail(id) { tempMap = tempMap.filter((row) => row.id !== id); if (editingId === id) { - resetTest(); + resetTestMapDetailForm(); } } @@ -125,10 +114,10 @@ tempMap, }); console.log(payload) - const result = await formState.save(masterDetail.mode, payload); + // const result = await formState.save(masterDetail.mode, payload); - toast('Test Map Created!'); - masterDetail?.exitForm(true); + // toast('Test Map Created!'); + // masterDetail?.exitForm(true); } const primaryAction = $derived({ @@ -176,7 +165,15 @@ } if (col.key === 'ClientID') { - if (formState.form.ClientType === 'SITE') { + if (formState.form.ClientType === 'HIS') { + return { + ...col, + type: 'select', + optionsEndpoint: `${API.BASE_URL}${API.HOSTAPP}`, + valueKey: 'HostAppID', + labelKey: 'HostAppName' + } + } else if (formState.form.ClientType === 'SITE') { return { ...col, type: 'select', @@ -184,55 +181,61 @@ valueKey: 'SiteID', labelKey: (item) => `${item.SiteCode} - ${item.SiteName}` }; + } else if (formState.form.ClientType === 'WST') { + return { + ...col, + type: 'select', + optionsEndpoint: `${API.BASE_URL}${API.WORKSTATION}`, + valueKey: 'WorkstationID', + labelKey: 'WorkstationName' + }; } return { ...col, type: 'text', optionsEndpoint: undefined }; } - if (col.key === 'HostTestCode') { - if (formState.form.HostType === 'SITE' && formState.form.HostID) { - return { - ...col, - type: 'select', - optionsEndpoint: `${API.BASE_URL}${API.TEST}?SiteID=${formState.form.HostID}`, - valueKey: 'TestSiteID', - labelKey: (item) => `${item.TestSiteCode} - ${item.TestSiteName}` - }; - } - return { - ...col, - type: 'text', - optionsEndpoint: undefined - }; - } - - if (col.key === 'ClientTestCode') { - if (formState.form.ClientType === 'SITE' && formState.form.ClientID) { - return { - ...col, - type: 'select', - optionsEndpoint: `${API.BASE_URL}${API.TEST}?SiteID=${formState.form.ClientID}`, - valueKey: 'TestSiteID', - labelKey: (item) => `${item.TestSiteCode} - ${item.TestSiteName}` - }; - } - return { - ...col, - type: 'text', - optionsEndpoint: undefined - }; - } - return col; }) })) })); }); - // $effect(() => { - // if (formState.form.ClientTestCode) { - // formState.form.ClientTestName = 'nyaho'; - // } - // }) + const mapDetailFormFieldsTransformed = $derived.by(() => { + return testMapDetailFormFields.map((group) => ({ + ...group, + rows: group.rows.map((row) => ({ + ...row, + columns: row.columns.map((col) => { + if (col.key === 'HostTestCode') { + if (formState.form.HostType === 'SITE' && formState.form.HostID) { + return { + ...col, + type: 'select', + optionsEndpoint: `${API.BASE_URL}${API.TEST}?SiteID=${formState.form.HostID}`, + valueKey: 'TestSiteCode', + labelKey: (item) => `${item.TestSiteCode} - ${item.TestSiteName}` + }; + } + return { ...col, type: 'text', optionsEndpoint: undefined }; + } + + if (col.key === 'ClientTestCode') { + if (formState.form.ClientType === 'SITE' && formState.form.ClientID) { + return { + ...col, + type: 'select', + optionsEndpoint: `${API.BASE_URL}${API.TEST}?SiteID=${formState.form.ClientID}`, + valueKey: 'TestSiteCode', + labelKey: (item) => `${item.TestSiteCode} - ${item.TestSiteName}` + }; + } + return { ...col, type: 'text', optionsEndpoint: undefined }; + } + + return col + }) + })) + })) + }) @@ -241,17 +244,22 @@ formFields={mapFormFieldsTransformed} mode="create" /> +
{#if editingId !== null} - - {:else} - {/if} @@ -262,12 +270,8 @@ - Host Test Code Host Test Name - Client Test Code Client Test Name Container @@ -297,7 +301,7 @@ size="icon" variant="ghost" class="h-7 w-7 cursor-pointer" - onclick={() => handleEdit(row)} + onclick={() => handleEditDetail(row)} > @@ -305,7 +309,7 @@ size="icon" variant="ghost" class="h-7 w-7 cursor-pointer" - onclick={() => handleRemove(row.id)} + onclick={() => handleRemoveDetail(row.id)} > diff --git a/src/lib/components/dictionary/testmap/page/edit-page.svelte b/src/lib/components/dictionary/testmap/page/edit-page.svelte index 9a58f89..b6f3553 100644 --- a/src/lib/components/dictionary/testmap/page/edit-page.svelte +++ b/src/lib/components/dictionary/testmap/page/edit-page.svelte @@ -1 +1,445 @@ -ed \ No newline at end of file + + + + + +
+
+ {#if editingId !== null} + + + {:else} + + {/if} +
+ +
+ + + + + Host Test Code + Host Test Name + Client Test Code + Client Test Name + Container + + + + + {#if tempMap.length === 0} + + + No data. Fill the form above and click Insert. + + + {:else} + {#each tempMap as row (row.id)} + + {row.HostTestCode} + {row.HostTestName} + {row.ClientTestCode} + {row.ClientTestName} + {row.ConDefID} + +
+ + +
+
+
+ {/each} + {/if} +
+
+
+
+
+ + \ No newline at end of file diff --git a/src/lib/components/dictionary/testmap/page/master-page.svelte b/src/lib/components/dictionary/testmap/page/master-page.svelte index 83bb814..e73ab44 100644 --- a/src/lib/components/dictionary/testmap/page/master-page.svelte +++ b/src/lib/components/dictionary/testmap/page/master-page.svelte @@ -8,7 +8,7 @@ import ReusableEmpty from "$lib/components/reusable/reusable-empty.svelte"; import ReusableDataTable from "$lib/components/reusable/reusable-data-table.svelte"; import MapIcon from "@lucide/svelte/icons/map"; - import ArrowLeftIcon from "@lucide/svelte/icons/arrow-left"; + import MoveLeftIcon from "@lucide/svelte/icons/move-left"; let props = $props(); @@ -40,7 +40,7 @@
{#if props.masterDetail.isFormMode} - +
{#each "BACK TO TEST MAP".split("") as c} {c} diff --git a/src/lib/components/dictionary/testmap/page/view-page.svelte b/src/lib/components/dictionary/testmap/page/view-page.svelte index 2c37fa4..68560d9 100644 --- a/src/lib/components/dictionary/testmap/page/view-page.svelte +++ b/src/lib/components/dictionary/testmap/page/view-page.svelte @@ -13,7 +13,7 @@ let testMap = $derived(masterDetail?.selectedItem?.data); const handlers = { - editTest: () => masterDetail.enterEdit("data"), + editTestMap: () => masterDetail.enterEdit("data"), }; const actions = viewActions(handlers); diff --git a/src/lib/components/patient/list/config/patient-config.js b/src/lib/components/patient/list/config/patient-config.js index 56b047f..2c911d2 100644 --- a/src/lib/components/patient/list/config/patient-config.js +++ b/src/lib/components/patient/list/config/patient-config.js @@ -3,6 +3,7 @@ import Settings2Icon from "@lucide/svelte/icons/settings-2"; import FlaskConicalIcon from "@lucide/svelte/icons/flask-conical"; import ActivityIcon from "@lucide/svelte/icons/activity"; import PencilIcon from "@lucide/svelte/icons/pencil"; +import RefreshIcon from "@lucide/svelte/icons/refresh-cw"; import NotepadTextIcon from "@lucide/svelte/icons/notepad-text"; export const searchFields = [ @@ -104,8 +105,13 @@ export const detailSections = [ } ] -export function patientActions(masterDetail, patientInitialForm) { +export function patientActions(masterDetail, handlers) { return [ + { + Icon: RefreshIcon, + label: 'Refresh Data', + onClick: handlers.refresh, + }, { Icon: PlusIcon, label: 'Add Patient', diff --git a/src/lib/components/patient/list/page/master-page.svelte b/src/lib/components/patient/list/page/master-page.svelte index b2628f4..888f416 100644 --- a/src/lib/components/patient/list/page/master-page.svelte +++ b/src/lib/components/patient/list/page/master-page.svelte @@ -7,13 +7,15 @@ import ReusableSearchParam from "$lib/components/reusable/reusable-search-param.svelte"; import ReusableEmpty from "$lib/components/reusable/reusable-empty.svelte"; import ReusableDataTable from "$lib/components/reusable/reusable-data-table.svelte"; - import ArrowLeftIcon from "@lucide/svelte/icons/arrow-left"; + import MoveLeftIcon from "@lucide/svelte/icons/move-left"; let props = $props(); const search = useSearch(searchFields, searchParam); - const initialForm = props.masterDetail.formState.form; - const actions = patientActions(props.masterDetail, initialForm) + const handlers = { + refresh: () => alert('velom visa, savar!'), + }; + const actions = patientActions(props.masterDetail, handlers) actions.find(a => a.label === 'Search Parameters').popoverContent = searchParamSnippet; let activeRowId = $state(null); @@ -36,7 +38,7 @@
{#if props.masterDetail.isFormMode} - +
{#each "BACK TO PATIENT".split("") as c} {c} diff --git a/src/lib/components/reusable/form/dictionary-form-renderer.svelte b/src/lib/components/reusable/form/dictionary-form-renderer.svelte index c0220e6..45c636b 100644 --- a/src/lib/components/reusable/form/dictionary-form-renderer.svelte +++ b/src/lib/components/reusable/form/dictionary-form-renderer.svelte @@ -269,6 +269,7 @@ formState.form.ClientID = ''; formState.form.ClientTestCode = ''; formState.form.ClientTestName = ''; + formState.selectOptions.ClientID = []; formState.selectOptions.ClientTestCode = []; formState.selectOptions.ClientTestName = []; }