init doctor base feature

This commit is contained in:
Khafid Prayoga
2025-08-13 14:43:49 +07:00
parent d5c453450f
commit 1b6c161448
9 changed files with 691 additions and 555 deletions
+6
View File
@@ -0,0 +1,6 @@
<script setup lang="ts">
</script>
<template>
<AppPatientEntryForm />
</template>
+116
View File
@@ -0,0 +1,116 @@
<script setup lang="ts">
import type { Summary } from '~/components/pub/base/summary-card.type'
import type { HeaderPrep, RefSearchNav } from '~/components/pub/nav/types'
import { Calendar, Hospital, UserCheck, UsersRound } from 'lucide-vue-next'
const data = ref([])
const refSearchNav: RefSearchNav = {
onClick: () => {
// open filter modal
},
onInput: (_val: string) => {
// filter patient list
},
onClear: () => {
// clear url param
},
}
// Loading state management
const isLoading = reactive({
summary: false,
table: false,
})
const recId = ref<number>(0)
const recAction = ref<string>('')
const recItem = ref<any>(null)
const hreaderPrep: HeaderPrep = {
title: 'Pasien',
icon: 'i-lucide-add',
addNav: {
label: 'Tambah',
onClick: () => navigateTo('/patient/add'),
},
}
// Initial/default data structure
const summaryData: Summary[] = [
{
title: 'Total Pasien',
icon: UsersRound,
metric: 23,
trend: 15,
timeframe: 'daily',
},
{
title: 'Pasien Aktif',
icon: UserCheck,
metric: 100,
trend: 9,
timeframe: 'daily',
},
{
title: 'Kunjungan Hari Ini',
icon: Calendar,
metric: 52,
trend: 1,
timeframe: 'daily',
},
{
title: 'Peserta BPJS',
icon: Hospital,
metric: 71,
trend: -3,
timeframe: 'daily',
},
]
// API call function
async function getPatientSummary() {
try {
isLoading.summary = true
await new Promise((resolve) => setTimeout(resolve, 500))
} catch (error) {
console.error('Error fetching patient summary:', error)
// Keep default/existing data on error
} finally {
isLoading.summary = false
}
}
async function getPatientList() {
const resp = await xfetch('/api/v1/patient')
console.log('data patient', resp)
if (resp.success) {
data.value = (resp.body as Record<string, any>).data
}
}
onMounted(() => {
getPatientSummary()
getPatientList()
})
provide('rec_id', recId)
provide('rec_action', recAction)
provide('rec_item', recItem)
</script>
<template>
<PubNavHeaderPrep :prep="{ ...hreaderPrep }" :ref-search-nav="refSearchNav" />
<div class="flex flex-1 flex-col gap-4 md:gap-8">
<div class="grid gap-4 md:grid-cols-2 md:gap-8 lg:grid-cols-4">
<template v-if="isLoading.summary">
<PubBaseSummaryCard v-for="n in 4" :key="n" is-skeleton />
</template>
<template v-else>
<PubBaseSummaryCard v-for="card in summaryData" :key="card.title" :stat="card" />
</template>
</div>
<AppPatientList :data="data" />
</div>
</template>
+15 -20
View File
@@ -13,6 +13,11 @@ const navMenu: any[] = [
icon: 'i-lucide-users',
link: '/patient',
},
{
title: 'Doctor',
icon: 'i-lucide-cross',
link: '/doctor',
},
{
title: 'Rehabilitasi Medik',
icon: 'i-lucide-heart',
@@ -78,12 +83,12 @@ const teams: {
logo: string
plan: string
}[] = [
{
name: 'SIMRS - RSSA',
logo: '/rssa-logo.png',
plan: 'Saiful Anwar Hospital',
},
]
{
name: 'SIMRS - RSSA',
logo: '/rssa-logo.png',
plan: 'Saiful Anwar Hospital',
},
]
// const user: {
// name: string
@@ -114,22 +119,12 @@ const sidebar = {
<SidebarGroupLabel v-if="nav.heading">
{{ nav.heading }}
</SidebarGroupLabel>
<component
:is="resolveNavItemComponent(item)"
v-for="(item, index) in nav.items"
:key="index"
:item="item"
class="mb-2"
/>
<component :is="resolveNavItemComponent(item)" v-for="(item, index) in nav.items" :key="index" :item="item"
class="mb-2" />
</SidebarGroup>
<SidebarGroup class="mt-auto">
<component
:is="resolveNavItemComponent(item)"
v-for="(item, index) in navMenuBottom"
:key="index"
:item="item"
size="sm"
/>
<component :is="resolveNavItemComponent(item)" v-for="(item, index) in navMenuBottom" :key="index" :item="item"
size="sm" />
</SidebarGroup>
</SidebarContent>
<SidebarFooter>
@@ -0,0 +1,9 @@
<script setup lang="ts">
definePageMeta({
roles: ['sys', 'doc'],
})
</script>
<template>
<div>detail pasien</div>
</template>
@@ -0,0 +1,9 @@
<script setup lang="ts">
definePageMeta({
roles: ['sys', 'doc'],
})
</script>
<template>
<div>edit detail pasien</div>
</template>
+9
View File
@@ -0,0 +1,9 @@
<script setup lang="ts">
definePageMeta({
roles: ['sys', 'doc'],
})
</script>
<template>
<div>add pasien</div>
</template>
+9
View File
@@ -0,0 +1,9 @@
<script setup lang="ts">
definePageMeta({
roles: ['sys', 'doc'],
})
</script>
<template>
<div>list pasien</div>
</template>
+5 -4
View File
@@ -28,10 +28,10 @@
"devDependencies": {
"@antfu/eslint-config": "^4.10.1",
"@nuxt/eslint": "^1.2.0",
"@nuxt/icon": "^1.11.0",
"@nuxt/icon": "^1.15.0",
"@nuxt/test-utils": "^3.19.2",
"@nuxtjs/color-mode": "^3.5.2",
"@pinia/nuxt": "^0.5.1",
"@pinia/nuxt": "^0.11.2",
"@unocss/eslint-plugin": "^66.0.0",
"@unocss/nuxt": "^66.0.0",
"@vee-validate/zod": "^4.15.0",
@@ -46,7 +46,7 @@
"eslint-plugin-format": "^1.0.1",
"happy-dom": "^18.0.1",
"lucide-vue-next": "^0.482.0",
"nuxt": "^4.0.1",
"nuxt": "^4.0.3",
"playwright-core": "^1.54.2",
"prettier": "^3.6.2",
"prettier-plugin-tailwindcss": "^0.5.14",
@@ -65,5 +65,6 @@
"vue-sonner": "^1.3.0",
"vue-tsc": "^2.1.10",
"zod": "^3.24.2"
}
},
"packageManager": "pnpm@8.15.9+sha512.499434c9d8fdd1a2794ebf4552b3b25c0a633abcee5bb15e7b5de90f32f47b513aca98cd5cfd001c31f0db454bc3804edccd578501e4ca293a6816166bbd9f81"
}
+513 -531
View File
File diff suppressed because it is too large Load Diff