first commit

This commit is contained in:
2025-05-23 15:36:39 +07:00
commit 692ffdf2f1
129 changed files with 12232 additions and 0 deletions

View File

@@ -0,0 +1,164 @@
<script setup>
import HumanName from './HumanName.vue'
const delay = ref(null)
delay.value = 10
async function getItemsSearch(query, el$) {
const { data } = await useFetch('/api/address?search=' + query, {
lazy: true,
server: false,
})
return data.value.map((d) => {
return {
value: d,
label: d.display,
}
})
// const addressesString = data.value.map((value) => {
// var result = value.villages ? 'Desa/Kel ' + value.villages + ', ' : ''
// result += value.districts ? 'Kec ' + value.districts + ', ' : ''
// result += value.cities ? 'Kota/Kab ' + value.cities + ', ' : ''
// result += value.states ? 'Prov ' + value.states + ', ' : ''
// result += value.countries ? value.countries : ''
// return { value: value, label: result }
// })
// return addressesString
}
async function getPostal(query) {
const { data } = await useFetch('/api/address?search=' + query, {
lazy: true,
server: false,
})
return data.value
}
function onSelectSearch(option, el$) {
const postal = getPostal(option.value.states.regencies.districts)
el$.$parent.$parent.children$.country.update(option.value)
el$.$parent.$parent.children$.state.update(option.value.states)
el$.$parent.$parent.children$.city.update(option.value.states.regencies)
el$.$parent.$parent.children$.district.update(
option.value.states.regencies.districts,
)
el$.$parent.$parent.children$.village.update(
option.value.states.regencies.districts.villages,
)
el$.$parent.$parent.children$.postalCode.update(postal[0])
}
function onSelectCountry(option, el$) {
el$.$parent.$parent.children$.state.clear()
el$.$parent.$parent.children$.city.clear()
el$.$parent.$parent.children$.district.clear()
el$.$parent.$parent.children$.village.clear()
el$.$parent.$parent.children$.postalCode.clear()
}
function onSelectState(option, el$) {
el$.$parent.$parent.children$.city.clear()
el$.$parent.$parent.children$.district.clear()
el$.$parent.$parent.children$.village.clear()
el$.$parent.$parent.children$.postalCode.clear()
}
function onSelectCity(option, el$) {
el$.$parent.$parent.children$.district.clear()
el$.$parent.$parent.children$.village.clear()
el$.$parent.$parent.children$.postalCode.clear()
}
function onSelectDistrict(option, el$) {
el$.$parent.$parent.children$.village.clear()
el$.$parent.$parent.children$.postalCode.clear()
console.log(el$)
}
function onSelectVillage(option, el$) {
el$.$parent.$parent.children$.postalCode.clear()
}
async function onChange(input, el$) {
delay.value = input.length > 0 ? 5000 : 10
}
function formatData(name, value) {
return { [name]: value.name }
}
function formatLine(name, value) {
return { [name]: value.split('\n') }
}
</script>
<template>
<ListElement name="address">
<template #default="{ index }">
<ObjectElement :name="index" :columns="{
sm: {
container: 12,
},
}">
<TextareaElement name="line" placeholder="Alamat" :format-data="formatLine" />
<SelectElement name="search" @select="onSelectSearch" :search="true" :native="false" input-type="search"
autocomplete="off" placeholder="🔎 Cari Alamat" :resolve-on-load="false" :delay="20" :items="getItemsSearch"
:submit="false" no-results-text="Alamat Tidak Ditemukan" :object="true" :filter-results="false"
:caret="false" />
<SelectElement name="country" allow-absent @select="onSelectCountry" items="/api/address/countries"
:format-data="formatData" :search="true" :native="false" :object="true" :resolve-on-load="true"
autocomplete="on" value-prop="_id" label-prop="name" input-type="search" placeholder="Negara" :conditions="[
[
['address.*.line', 'not_empty'],
['address.*.search', 'not_empty'],
],
]" :columns="{
sm: {
container: 6,
},
}" />
<SelectElement name="state" allow-absent @select="onSelectState" @search-change="onChange"
items="/api/address/states?parent={address.*.country}" :format-data="formatData" :search="true"
:native="false" :object="true" :delay="delay" :resolve-on-load="false" autocomplete="on" value-prop="_id"
label-prop="name" input-type="search" placeholder="Provinsi"
:conditions="[['address.*.country', 'not_empty']]" :columns="{
sm: {
container: 6,
},
}" />
<SelectElement name="city" allow-absent @select="onSelectCity" @search-change="onChange"
items="/api/address/cities?parent={address.*.state}" :format-data="formatData" :search="true" :native="false"
:object="true" :delay="delay" :resolve-on-load="false" autocomplete="on" value-prop="_id" label-prop="name"
input-type="search" placeholder="Kota / Kabupaten" :conditions="[['address.*.state', 'not_empty']]" :columns="{
sm: {
container: 6,
},
}" />
<SelectElement name="district" allow-absent @select="onSelectDistrict" @search-change="onChange"
items="/api/address/districts?parent={address.*.city}" :format-data="formatData" :search="true"
:native="false" :object="true" :delay="delay" :resolve-on-load="false" autocomplete="on" value-prop="_id"
label-prop="name" input-type="search" placeholder="Kecamatan" :conditions="[['address.*.city', 'not_empty']]"
:columns="{
sm: {
container: 6,
},
}" />
<SelectElement name="village" allow-absent @select="onSelectVillage" @search-change="onChange"
items="/api/address/villages?parent={address.*.district}" :format-data="formatData" :search="true"
:native="false" :object="true" :delay="delay" :resolve-on-load="false" autocomplete="on" value-prop="_id"
label-prop="name" input-type="search" placeholder="Desa / Kelurahan"
:conditions="[['address.*.district', 'not_empty']]" :columns="{
sm: {
container: 6,
},
}" />
<SelectElement name="postalCode" allow-absent @search-change="onChange"
items="/api/address/postal?parent={address.*.district}" :native="false" :object="false" :delay="delay"
:resolve-on-load="false" autocomplete="off" placeholder="Kode Pos"
:conditions="[['address.*.district', 'not_empty']]" :columns="{
sm: {
container: 6,
},
}" />
</ObjectElement>
</template>
</ListElement>
</template>

View File

@@ -0,0 +1,60 @@
<template>
<ListElement name="communication">
<template #default="{ index }">
<ObjectElement :name="index">
<GroupElement name="container2_2">
<GroupElement name="column1" :columns="{
container: 1,
}">
<ToggleElement name="preferred" :labels="{
on: 'Aktif',
off: 'Pasif',
}" :default="true" size="lg" align="right" />
</GroupElement>
<GroupElement name="column2" :columns="{
container: 11,
}">
<ListElement name="language" :controls="{
add: false,
remove: false,
}">
<template #default="{ index }">
<ObjectElement :name="index">
<SelectElement name="text" :items="[
{
value: 'id',
label: 'Indonesia',
},
{
value: 'en',
label: 'Inggris',
},
{
value: 'jawa',
label: 'Jawa',
},
{
value: 'sunda',
label: 'Sunda',
},
{
value: 'ch',
label: 'China',
},
]" :search="true" :native="false" input-type="search" autocomplete="off" placeholder="Bahasa"
:create="true" :append-new-option="false" />
</ObjectElement>
</template>
</ListElement>
</GroupElement>
</GroupElement>
</ObjectElement>
</template>
</ListElement>
</template>
<script lang="ts" setup>
</script>
<style></style>

View File

@@ -0,0 +1,26 @@
<script setup>
</script>
<template>
<ListElement name="contact" :rules="['min:1']" :min="1" :max="1" :initial="1">
<template #default="{ index }">
<ObjectElement :name="index">
<GroupElement name="container2">
<GroupElement name="column1" :columns="{
container: 6,
}">
<FormLibRelationship />
</GroupElement>
<GroupElement name="column_2" :columns="{
container: 6,
}">
<FormLibHumanName />
</GroupElement>
</GroupElement>
<FormLibTelecom />
<FormLibAddress />
<FormLibGender />
</ObjectElement>
</template>
</ListElement>
</template>

View File

@@ -0,0 +1,17 @@
<template>
<RadiogroupElement
name="gender"
view="tabs"
label="Jenis Kelamin"
:items="[
{
value: 'male',
label: 'Laki-Laki',
},
{
value: 'female',
label: 'female',
},
]"
/>
</template>

View File

@@ -0,0 +1,45 @@
<script setup>
const parsedName = ref({})
const onChange = (newValue, oldValue, el$) => {
const i = parseInt(el$.$parent.$parent.path.split('.')[1])
parsedName.value[i] = parseName(el$.$parent.$parent.children$.text.value)
el$.$parent.$parent.children$.prefix.update(parsedName.value[i].prefix)
el$.$parent.$parent.children$.given.update(parsedName.value[i].given)
el$.$parent.$parent.children$.family.update(parsedName.value[i].family)
el$.$parent.$parent.children$.suffix.update(parsedName.value[i].suffix)
console.log(el$.$parent.$parent.children$.text.value)
}
</script>
<template>
<ListElement name="name" :controls="{
add: true,
remove: false,
}" :rules="['min:1']" :min="1" :max="1" :initial="1">
<template #default="{ index }">
<ObjectElement :name="index" :columns="{
sm: {
container: 12,
},
}">
<TextElement @change="onChange" name="text" placeholder="Nama Lengkap" />
<HiddenElement name="prefix" :meta="true" />
<HiddenElement name="given" :meta="true" />
<HiddenElement name="family" :meta="true" />
<HiddenElement name="suffix" :meta="true" />
<!-- <FormLibParsedName :name="parsedName" :path="'address.0'" /> -->
<StaticElement name="parsed-name" size="m">
<div v-if="parsedName[index]" class="d-flex flex-row">
<v-chip v-for="(prefix, index) in parsedName[index].prefix" :key="`prefix-${index}`" size="x-small"
class="mr-1 bg-indigo-lighten-3">{{ prefix }}</v-chip>
<v-chip v-for="(given, index) in parsedName[index].given" :key="`given-${index}`" size="x-small"
class="mr-1 bg-blue-darken-3">{{ given }}</v-chip>
<v-chip v-show="parsedName[index].family" size="x-small" class="mr-1 bg-blue">{{ parsedName[index].family
}}</v-chip>
<v-chip v-for="(suffix, index) in parsedName[index].suffix" :key="`suffix-${index}`" size="x-small"
class="mr-1 bg-indigo-lighten-3">{{ suffix }}</v-chip>
</div>
</StaticElement>
</ObjectElement>
</template>
</ListElement>
</template>

View File

@@ -0,0 +1,30 @@
<script setup>
import items from '~/data/practitioner.json'
function onChange(oldValue, newValue, el$) {
el$.$parent.$parent.children$.value.update(el$.value)
}
</script>
<template>
<ListElement name="identifier" :rules="['min:1']">
<template #default="{ index }">
<ObjectElement :name="index">
<GroupElement name="type">
<SelectElement name="name" :search="true" :items="items" data-key="option" :native="false" default="ktp"
:columns="{
container: 3,
}" :can-clear="false" :can-deselect="false" />
<TextElement v-for="item in items" :conditions="[['identifier.*.type.name', item.value]]" name="value_element"
@change="onChange" :rules="['nullable', item.regex]" :messages="{
regex: 'Format Nomor ID salah!',
}" :placeholder="item.placeholder" :columns="{
container: 9,
}" :submit="false" />
<HiddenElement name="value" :meta="true" />
</GroupElement>
</ObjectElement>
</template>
</ListElement>
</template>

View File

@@ -0,0 +1,52 @@
<script setup>
// Define props with validation
const props = defineProps({
path: {
type: String,
required: true,
},
name: {
type: Object,
required: true,
validator: (value) => {
// Basic validation to ensure data has a name property
return value && value.name
},
},
})
</script>
<template>
<StaticElement name="parsed-name" size="m">
<div v-show="name" class="d-flex flex-row">
<span> {{ index }}</span>
<v-chip
v-for="(prefix, index) in name.value[path].prefix"
:key="`prefix-${index}`"
size="x-small"
class="mr-1 bg-indigo-lighten-3"
>{{ prefix }}</v-chip
>
<v-chip
v-for="(given, index) in name.value[path].given"
:key="`given-${index}`"
size="x-small"
class="mr-1 bg-blue-darken-3"
>{{ given }}</v-chip
>
<v-chip
v-show="name.value[path].family"
size="x-small"
class="mr-1 bg-blue"
>{{ name.family }}</v-chip
>
<v-chip
v-for="(suffix, index) in name.value[path].suffix"
:key="`suffix-${index}`"
size="x-small"
class="mr-1 bg-indigo-lighten-3"
>{{ suffix }}</v-chip
>
</div>
</StaticElement>
</template>

View File

@@ -0,0 +1,76 @@
<script setup>
// import items from '~/assets/data/contact/relationship.json'
</script>
<template>
<ListElement
name="relationship"
:rules="['min:1']"
:min="1"
:max="1"
:initial="1"
>
<template #default="{ index }">
<ObjectElement
:name="index"
>
<SelectElement
name="code"
:search="true"
:native="false"
input-type="search"
autocomplete="off"
placeholder="Hubungan Dengan Pasien"
:columns="{
container: 12,
}"
:items="[
{
value: 'BP',
label: 'Billing contact person',
},
{
value: 'CP',
label: 'Contact person',
},
{
value: 'EP',
label: 'Emergency contact person',
},
{
value: 'PR',
label: 'Person preparing referral',
},
{
value: 'E',
label: 'Employer',
},
{
value: 'C',
label: 'Emergency Contact',
},
{
value: 'F',
label: 'Federal Agency',
},
{
value: 'I',
label: 'Insurance Company',
},
{
value: 'N',
label: 'Next-of-Kin',
},
{
value: 'S',
label: 'State Agency',
},
{
value: 'U',
label: 'Unknown',
},
]"
/>
</ObjectElement>
</template>
</ListElement>
</template>

View File

@@ -0,0 +1,72 @@
<template>
<ListElement name="telecom">
<template #default="{ index }">
<ObjectElement :name="index">
<SelectElement name="system" :items="[
{
value: 'phone',
label: '📞',
},
{
value: 'email',
label: '📧',
},
{
value: 'url',
label: '🌐',
},
]" :search="true" :native="false" input-type="search" autocomplete="off" :can-deselect="false"
:can-clear="false" default="phone" :columns="{
default: {
container: 2,
},
sm: {
container: 1,
},
}" :caret="false" />
<SelectElement name="use" :items="[
{
value: 'home',
label: '🏠',
},
{
value: 'mobile',
label: '📱',
},
{
value: 'work',
label: '🏢',
},
]" :search="true" :native="false" input-type="search" autocomplete="off" :columns="{
default: {
container: 2,
},
sm: {
container: 1,
},
}" :caret="false" :can-deselect="false" :can-clear="false" default="home" />
<GroupElement name="value" :columns="{
default: {
container: 8,
},
sm: {
container: 10,
},
}">
<PhoneElement name="phone" :allow-incomplete="true" :unmask="true" default="+62"
:conditions="[['telecom.*.system', 'in', ['phone']]]" />
<TextElement name="email" input-type="email" :rules="['nullable', 'email']" placeholder="eg. example@mail.com"
:conditions="[['telecom.*.system', 'in', ['email']]]" />
<TextElement name="url" input-type="url" :rules="['nullable', 'url']" placeholder="eg. http(s)://domain.com"
:floating="false" :conditions="[['telecom.*.system', 'in', ['url']]]" />
</GroupElement>
</ObjectElement>
</template>
</ListElement>
</template>
<script lang="ts" setup>
</script>
<style></style>