mirror of
https://github.com/faiztyanirh/clqms-shadcn-v1.git
synced 2026-04-26 10:56:32 +07:00
fix for location and patient list
location : tambah rule loccode max 6 fix handlesave if result.status success patient list : fix emailaddress1&2 kosong masih trigger rule add rule for phone change deceased to type toggle isDead fix rule timeOfDeath fix derived isDeathDateDisabled
This commit is contained in:
parent
3ebea51ee7
commit
ffb57539e8
@ -28,7 +28,7 @@ export function usePatientForm(formState, patientSchema) {
|
|||||||
),
|
),
|
||||||
EmailAddress1: patientSchema.shape.EmailAddress1.refine(
|
EmailAddress1: patientSchema.shape.EmailAddress1.refine(
|
||||||
async (value) => {
|
async (value) => {
|
||||||
if (!value) return false;
|
if (!value) return true;
|
||||||
const res = await fetch(`${API.BASE_URL}${API.CHECK}?EmailAddress1=${value}`);
|
const res = await fetch(`${API.BASE_URL}${API.CHECK}?EmailAddress1=${value}`);
|
||||||
const { status, data } = await res.json();
|
const { status, data } = await res.json();
|
||||||
return status === "success" && data === false ? false : true;
|
return status === "success" && data === false ? false : true;
|
||||||
@ -37,13 +37,22 @@ export function usePatientForm(formState, patientSchema) {
|
|||||||
),
|
),
|
||||||
EmailAddress2: patientSchema.shape.EmailAddress2.refine(
|
EmailAddress2: patientSchema.shape.EmailAddress2.refine(
|
||||||
async (value) => {
|
async (value) => {
|
||||||
if (!value) return false;
|
if (!value) return true;
|
||||||
const res = await fetch(`${API.BASE_URL}${API.CHECK}?EmailAddress1=${value}`);
|
const res = await fetch(`${API.BASE_URL}${API.CHECK}?EmailAddress1=${value}`);
|
||||||
const { status, data } = await res.json();
|
const { status, data } = await res.json();
|
||||||
return status === "success" && data === false ? false : true;
|
return status === "success" && data === false ? false : true;
|
||||||
},
|
},
|
||||||
{ message: "Email address already used" }
|
{ message: "Email address already used" }
|
||||||
),
|
),
|
||||||
|
Phone: patientSchema.shape.Phone.refine(
|
||||||
|
async (value) => {
|
||||||
|
if (!value) return true;
|
||||||
|
const res = await fetch(`${API.BASE_URL}${API.CHECK}?Phone=${value}`);
|
||||||
|
const { status, data } = await res.json();
|
||||||
|
return status === "success" && data === false ? false : true;
|
||||||
|
},
|
||||||
|
{ message: "Phone number already used" }
|
||||||
|
),
|
||||||
});
|
});
|
||||||
|
|
||||||
const partial = asyncSchema.pick({ [field]: true });
|
const partial = asyncSchema.pick({ [field]: true });
|
||||||
|
|||||||
@ -113,10 +113,10 @@
|
|||||||
tempDetailContact,
|
tempDetailContact,
|
||||||
});
|
});
|
||||||
console.log(payload)
|
console.log(payload)
|
||||||
// const result = await formState.save(masterDetail.mode);
|
const result = await formState.save(masterDetail.mode);
|
||||||
|
|
||||||
// toast('Contact Created!');
|
toast('Contact Created!');
|
||||||
// masterDetail?.exitForm(true);
|
masterDetail?.exitForm(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
const primaryAction = $derived({
|
const primaryAction = $derived({
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import EraserIcon from "@lucide/svelte/icons/eraser";
|
|||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
export const locationSchema = z.object({
|
export const locationSchema = z.object({
|
||||||
LocCode: z.string().min(1, "Required"),
|
LocCode: z.string().min(1, "Required").max(6, "Max 6 chars"),
|
||||||
LocFull: z.string().min(1, "Required"),
|
LocFull: z.string().min(1, "Required"),
|
||||||
Email: z.string().trim().optional().refine((val) => !val || /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(val),"Invalid email format"),
|
Email: z.string().trim().optional().refine((val) => !val || /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(val),"Invalid email format"),
|
||||||
Phone: z.string().max(14, "Max 14 chars").regex(/^$|^[0-9]+$/, "Can only contain numbers"),
|
Phone: z.string().max(14, "Max 14 chars").regex(/^$|^[0-9]+$/, "Can only contain numbers"),
|
||||||
|
|||||||
@ -26,8 +26,14 @@
|
|||||||
async function handleSave() {
|
async function handleSave() {
|
||||||
const result = await formState.save(masterDetail.mode);
|
const result = await formState.save(masterDetail.mode);
|
||||||
|
|
||||||
toast('Location Created!');
|
if (result.status === 'success') {
|
||||||
masterDetail?.exitForm(true);
|
toast('Location Created!');
|
||||||
|
masterDetail?.exitForm(true);
|
||||||
|
} else {
|
||||||
|
console.error('Failed to save location');
|
||||||
|
const errorMessages = result.messages ? Object.values(result.messages).join('\n') : 'Failed to save location';
|
||||||
|
toast.error(errorMessages)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const primaryAction = $derived({
|
const primaryAction = $derived({
|
||||||
|
|||||||
@ -63,7 +63,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function handleInsertDetail() {
|
function handleInsertDetail() {
|
||||||
console.log('object');
|
|
||||||
const row = {
|
const row = {
|
||||||
id: ++idCounter,
|
id: ++idCounter,
|
||||||
...snapshotForm()
|
...snapshotForm()
|
||||||
|
|||||||
@ -79,7 +79,7 @@ export const detailSections = [
|
|||||||
},
|
},
|
||||||
{ key: "isDeadLabel", label: "Deceased" },
|
{ key: "isDeadLabel", label: "Deceased" },
|
||||||
{ key: "CreateDate", label: "Create Date", isUTCDate: true },
|
{ key: "CreateDate", label: "Create Date", isUTCDate: true },
|
||||||
{ key: "DelDate", label: "Disabled Date" },
|
{ key: "DelDate", label: "Delete Date" },
|
||||||
{ key: "TimeOfDeath", label: "Time of Death", isUTCDate: true },
|
{ key: "TimeOfDeath", label: "Time of Death", isUTCDate: true },
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
@ -12,12 +12,13 @@ export const patientSchema = z.object({
|
|||||||
),
|
),
|
||||||
EmailAddress1: z.string().trim().optional().refine((val) => !val || /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(val),"Invalid email format"),
|
EmailAddress1: z.string().trim().optional().refine((val) => !val || /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(val),"Invalid email format"),
|
||||||
EmailAddress2: z.string().trim().optional().refine((val) => !val || /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(val),"Invalid email format"),
|
EmailAddress2: z.string().trim().optional().refine((val) => !val || /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(val),"Invalid email format"),
|
||||||
Phone: z.string().max(14, "Max 14 chars").regex(/^$|^[0-9]+$/, "Can only contain numbers"),
|
Phone: z.string().max(14, "Max 14 chars").regex(/^$|^[0-9]+$/, "Can only contain numbers").optional(),
|
||||||
MobilePhone: z.string().max(14, "Max 14 chars").regex(/^$|^[0-9]+$/, "Can only contain numbers"),
|
MobilePhone: z.string().max(14, "Max 14 chars").regex(/^$|^[0-9]+$/, "Can only contain numbers"),
|
||||||
TimeOfDeath: z.string().optional().refine(
|
TimeOfDeath: z.string().optional().refine(
|
||||||
(date) => new Date(date) <= new Date(),
|
(date) => new Date(date) <= new Date(),
|
||||||
"Cannot exceed today's date"
|
"Cannot exceed today's date"
|
||||||
),
|
),
|
||||||
|
ZIP: z.string().max(7, "Max 7 chars").regex(/^$|^[0-9]+$/, "Can only contain numbers"),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const patientInitialForm = {
|
export const patientInitialForm = {
|
||||||
@ -55,7 +56,7 @@ export const patientInitialForm = {
|
|||||||
Phone: "",
|
Phone: "",
|
||||||
EmailAddress2: "",
|
EmailAddress2: "",
|
||||||
MobilePhone: "",
|
MobilePhone: "",
|
||||||
DeathIndicator: "",
|
isDead: "",
|
||||||
TimeOfDeath: "",
|
TimeOfDeath: "",
|
||||||
LinkTo: [],
|
LinkTo: [],
|
||||||
PatCom: "",
|
PatCom: "",
|
||||||
@ -73,6 +74,7 @@ export const patientDefaultErrors = {
|
|||||||
Phone: null,
|
Phone: null,
|
||||||
MobilePhone: null,
|
MobilePhone: null,
|
||||||
TimeOfDeath: null,
|
TimeOfDeath: null,
|
||||||
|
ZIP: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const patientFormFields = [
|
export const patientFormFields = [
|
||||||
@ -236,7 +238,7 @@ export const patientFormFields = [
|
|||||||
{
|
{
|
||||||
type: "group",
|
type: "group",
|
||||||
columns: [
|
columns: [
|
||||||
{ key: "ZIP", label: "ZIP", required: false, type: "number" },
|
{ key: "ZIP", label: "ZIP", required: false, type: "text", validateOn: ["input"] },
|
||||||
{
|
{
|
||||||
key: "Country",
|
key: "Country",
|
||||||
label: "Country",
|
label: "Country",
|
||||||
@ -257,7 +259,7 @@ export const patientFormFields = [
|
|||||||
type: "row",
|
type: "row",
|
||||||
columns: [
|
columns: [
|
||||||
{ key: "EmailAddress1", label: "Email Address 1", required: false, type: "email", validateOn: ["input", "blur"] },
|
{ key: "EmailAddress1", label: "Email Address 1", required: false, type: "email", validateOn: ["input", "blur"] },
|
||||||
{ key: "Phone", label: "Phone", required: false, type: "text", validateOn: ["input"] },
|
{ key: "Phone", label: "Phone", required: false, type: "text", validateOn: ["input", "blur"] },
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -273,13 +275,23 @@ export const patientFormFields = [
|
|||||||
{
|
{
|
||||||
type: "group",
|
type: "group",
|
||||||
columns: [
|
columns: [
|
||||||
|
// {
|
||||||
|
// key: "isDead",
|
||||||
|
// label: "Deceased",
|
||||||
|
// required: false,
|
||||||
|
// type: "select",
|
||||||
|
// optionsEndpoint: `${API.BASE_URL}${API.VALUESET}/death_indicator`,
|
||||||
|
// defaultValue: 'N'
|
||||||
|
// },
|
||||||
{
|
{
|
||||||
key: "isDead",
|
key: "isDead",
|
||||||
label: "Deceased",
|
label: "Deceased",
|
||||||
required: false,
|
required: false,
|
||||||
type: "select",
|
type: "toggle",
|
||||||
optionsEndpoint: `${API.BASE_URL}${API.VALUESET}/death_indicator`,
|
optionsToggle: [
|
||||||
defaultValue: 'N'
|
{ value: 0, label: 'No' },
|
||||||
|
{ value: 1, label: 'Yes' }
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{ key: "TimeOfDeath", label: "Time of Death", required: false, type: "datetime", validateOn: ["input"] }
|
{ key: "TimeOfDeath", label: "Time of Death", required: false, type: "datetime", validateOn: ["input"] }
|
||||||
]
|
]
|
||||||
|
|||||||
@ -68,7 +68,7 @@
|
|||||||
disabled: formState.isSaving.current
|
disabled: formState.isSaving.current
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
// $inspect(formState.selectOptions)
|
$inspect(formState.errors)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<FormPageContainer title="Create Patient" {primaryAction} {secondaryActions} {actions}>
|
<FormPageContainer title="Create Patient" {primaryAction} {secondaryActions} {actions}>
|
||||||
|
|||||||
@ -68,17 +68,18 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
let isDeathDateDisabled = $derived(
|
let isDeathDateDisabled = $derived(
|
||||||
formState.form.isDead !== 'Y'
|
formState.form.isDead !== 1 && formState.form.isDead !== "1"
|
||||||
);
|
);
|
||||||
|
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
if (isDeathDateDisabled && formState.form.TimeOfDeath) {
|
if (isDeathDateDisabled && formState.form.TimeOfDeath) {
|
||||||
formState.form.TimeOfDeath = "";
|
formState.form.TimeOfDeath = "";
|
||||||
|
formState.errors.TimeOfDeath = null;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#snippet Fieldset({ key, label, required, type, optionsEndpoint, options, validateOn, dependsOn, endpointParamKey, valueKey, labelKey })}
|
{#snippet Fieldset({ key, label, required, type, optionsEndpoint, options, optionsToggle, validateOn, dependsOn, endpointParamKey, valueKey, labelKey })}
|
||||||
<div class="flex w-full flex-col gap-1.5">
|
<div class="flex w-full flex-col gap-1.5">
|
||||||
<div class="flex justify-between items-center w-full">
|
<div class="flex justify-between items-center w-full">
|
||||||
<Label>{label}</Label>
|
<Label>{label}</Label>
|
||||||
@ -283,22 +284,27 @@
|
|||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{:else if type === "toggle"}
|
{:else if type === "toggle"}
|
||||||
<div class="flex items-center w-full">
|
{@const toggleOff = optionsToggle?.[0] ?? { value: false, label: 'Off' }}
|
||||||
<Toggle
|
{@const toggleOn = optionsToggle?.[1] ?? { value: true, label: 'On' }}
|
||||||
aria-label="Toggle discharge"
|
{@const isOn = String(formState.form[key]) === String(toggleOn.value)}
|
||||||
variant="outline"
|
<div class="flex items-center w-full">
|
||||||
class="w-full transition-all data-[state=on]:text-primary"
|
<Toggle
|
||||||
bind:pressed={formState.form.isDischarge}
|
aria-label="Toggle"
|
||||||
>
|
variant="outline"
|
||||||
|
class="w-full transition-all data-[state=on]:text-primary"
|
||||||
{#if formState.form.isDischarge}
|
pressed={isOn}
|
||||||
<XIcon class="mr-2 h-4 w-4" />
|
onPressedChange={(pressed) => {
|
||||||
{:else}
|
formState.form[key] = pressed ? toggleOn.value : toggleOff.value;
|
||||||
<CheckIcon class="mr-2 h-4 w-4" />
|
}}
|
||||||
{/if}
|
>
|
||||||
{formState.form.isDischarge ? "Discharged" : "Active"}
|
{#if isOn}
|
||||||
</Toggle>
|
<CheckIcon class="mr-2 h-4 w-4" />
|
||||||
</div>
|
{:else}
|
||||||
|
<XIcon class="mr-2 h-4 w-4" />
|
||||||
|
{/if}
|
||||||
|
{isOn ? toggleOn.label : toggleOff.label}
|
||||||
|
</Toggle>
|
||||||
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<Input
|
<Input
|
||||||
type="text"
|
type="text"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user