feat(sep): add form entry
This commit is contained in:
No files matched your search
@@ -2,14 +2,9 @@
|
|||||||
// types
|
// types
|
||||||
import type z from 'zod'
|
import type z from 'zod'
|
||||||
import type { MaterialFormData } from '~/schemas/material'
|
import type { MaterialFormData } from '~/schemas/material'
|
||||||
<<<<<<< HEAD:app/components/app/equipment/entry-form.vue
|
|
||||||
=======
|
|
||||||
// helpers
|
// helpers
|
||||||
import { toTypedSchema } from '@vee-validate/zod'
|
import { toTypedSchema } from '@vee-validate/zod'
|
||||||
import { useForm } from 'vee-validate'
|
import { useForm } from 'vee-validate'
|
||||||
// components
|
|
||||||
import Label from '~/components/pub/custom-ui/form/label.vue'
|
|
||||||
>>>>>>> 266d5f740b15942ca7b8845c00573640fdc9a3b2:app/components/app/material/entry-form.vue
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
schema: z.ZodSchema<any>
|
schema: z.ZodSchema<any>
|
||||||
|
|||||||
@@ -0,0 +1,123 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
// helpers
|
||||||
|
import { toTypedSchema } from '@vee-validate/zod'
|
||||||
|
import { useForm } from 'vee-validate'
|
||||||
|
import * as z from 'zod'
|
||||||
|
// components
|
||||||
|
import { Button } from '~/components/pub/ui/button'
|
||||||
|
import { Input } from '~/components/pub/ui/input'
|
||||||
|
import { Label } from '~/components/pub/ui/label'
|
||||||
|
import { Card, CardContent, CardHeader, CardTitle } from '~/components/pub/ui/card'
|
||||||
|
import { Select } from '~/components/pub/ui/select'
|
||||||
|
import { Textarea } from '~/components/pub/ui/textarea'
|
||||||
|
import { RadioGroup, RadioGroupItem } from '~/components/pub/ui/radio-group'
|
||||||
|
|
||||||
|
const items = [
|
||||||
|
{ value: 'item-1', label: 'Item 1' },
|
||||||
|
{ value: 'item-2', label: 'Item 2' },
|
||||||
|
{ value: 'item-3', label: 'Item 3' },
|
||||||
|
]
|
||||||
|
|
||||||
|
// Validation schema
|
||||||
|
const schema = z.object({
|
||||||
|
tanggalSep: z.string().min(1, 'Tanggal SEP wajib diisi'),
|
||||||
|
jalur: z.string().min(1, 'Pilih jalur'),
|
||||||
|
noRm: z.string().min(1, 'No. RM wajib diisi'),
|
||||||
|
namaPasien: z.string().min(1, 'Nama pasien wajib diisi'),
|
||||||
|
noTelp: z.string().min(1, 'Nomor telepon wajib diisi'),
|
||||||
|
klinikTujuan: z.string().min(1, 'Klinik tujuan wajib diisi'),
|
||||||
|
diagnosaAwal: z.string().min(1, 'Diagnosa awal wajib diisi'),
|
||||||
|
})
|
||||||
|
|
||||||
|
const { handleSubmit, errors, defineField } = useForm({
|
||||||
|
validationSchema: toTypedSchema(schema),
|
||||||
|
})
|
||||||
|
|
||||||
|
// Bind fields
|
||||||
|
const [tanggalSep] = defineField('tanggalSep')
|
||||||
|
const [jalur] = defineField('jalur')
|
||||||
|
const [noRm] = defineField('noRm')
|
||||||
|
const [namaPasien] = defineField('namaPasien')
|
||||||
|
const [noTelp] = defineField('noTelp')
|
||||||
|
const [klinikTujuan] = defineField('klinikTujuan')
|
||||||
|
const [diagnosaAwal] = defineField('diagnosaAwal')
|
||||||
|
|
||||||
|
// Submit handler
|
||||||
|
const onSubmit = handleSubmit((values) => {
|
||||||
|
console.log('✅ Validated form values:', values)
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Card class="mx-auto w-full max-w-5xl">
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle></CardTitle>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<form @submit.prevent="onSubmit" class="grid gap-6">
|
||||||
|
<!-- Tanggal SEP & Jalur -->
|
||||||
|
<div class="grid gap-4 md:grid-cols-2">
|
||||||
|
<div>
|
||||||
|
<Label for="tanggalSep">Tanggal SEP</Label>
|
||||||
|
<Input id="tanggalSep" type="date" v-model="tanggalSep" />
|
||||||
|
<p v-if="errors.tanggalSep" class="text-sm text-red-500">{{ errors.tanggalSep }}</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Label for="jalur">Jalur</Label>
|
||||||
|
<Select v-model="jalur" :items="items" placeholder="Pilih jalur"></Select>
|
||||||
|
<p v-if="errors.jalur" class="text-sm text-red-500">{{ errors.jalur }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Data Pasien -->
|
||||||
|
<h3 class="text-lg font-semibold">Data Pasien</h3>
|
||||||
|
<div class="grid gap-4 md:grid-cols-2">
|
||||||
|
<div>
|
||||||
|
<Label>No. RM*</Label>
|
||||||
|
<Input v-model="noRm" />
|
||||||
|
<p v-if="errors.noRm" class="text-sm text-red-500">{{ errors.noRm }}</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Label>Nama Pasien*</Label>
|
||||||
|
<Input v-model="namaPasien" />
|
||||||
|
<p v-if="errors.namaPasien" class="text-sm text-red-500">{{ errors.namaPasien }}</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Label>No. Telepon*</Label>
|
||||||
|
<Input v-model="noTelp" />
|
||||||
|
<p v-if="errors.noTelp" class="text-sm text-red-500">{{ errors.noTelp }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Data SEP -->
|
||||||
|
<h3 class="text-lg font-semibold">Data SEP</h3>
|
||||||
|
<div class="grid gap-4 md:grid-cols-2">
|
||||||
|
<div>
|
||||||
|
<Label>Klinik Tujuan*</Label>
|
||||||
|
<Select v-model="klinikTujuan" :items="items" placeholder="Pilih klinik"></Select>
|
||||||
|
<p v-if="errors.klinikTujuan" class="text-sm text-red-500">{{ errors.klinikTujuan }}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<Label>Diagnosa Awal*</Label>
|
||||||
|
<Input v-model="diagnosaAwal" />
|
||||||
|
<p v-if="errors.diagnosaAwal" class="text-sm text-red-500">{{ errors.diagnosaAwal }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Catatan -->
|
||||||
|
<div>
|
||||||
|
<Label>Catatan</Label>
|
||||||
|
<Textarea placeholder="Masukkan catatan opsional" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Actions -->
|
||||||
|
<div class="mt-6 flex justify-end gap-4">
|
||||||
|
<Button type="button" variant="outline">Riwayat SEP</Button>
|
||||||
|
<Button type="button" variant="outline">Preview</Button>
|
||||||
|
<Button type="submit">Simpan</Button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</template>
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
|
||||||
|
const isLoading = ref(false)
|
||||||
|
|
||||||
|
function onBack() {
|
||||||
|
navigateTo('/bpjs/sep')
|
||||||
|
}
|
||||||
|
|
||||||
|
async function onSubmit(data: any) {
|
||||||
|
console.log(data)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="mb-5 border-b border-b-slate-300 pb-3 text-lg xl:text-xl">
|
||||||
|
<Icon name="i-lucide-panel-bottom" class="me-2" />
|
||||||
|
<span class="font-semibold">Tambah</span> SEP
|
||||||
|
</div>
|
||||||
|
<AppSepEntryForm />
|
||||||
|
</template>
|
||||||
@@ -91,13 +91,15 @@ const headerPrep: HeaderPrep = {
|
|||||||
icon: 'i-lucide-panel-bottom',
|
icon: 'i-lucide-panel-bottom',
|
||||||
addNav: {
|
addNav: {
|
||||||
label: 'Tambah',
|
label: 'Tambah',
|
||||||
onClick: () => {},
|
onClick: () => {
|
||||||
|
navigateTo('/bpjs/sep/add')
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getSepList() {
|
async function getSepList() {
|
||||||
isLoading.dataListLoading = true
|
isLoading.dataListLoading = true
|
||||||
data.value = [...rows];
|
data.value = [...rows]
|
||||||
isLoading.dataListLoading = false
|
isLoading.dataListLoading = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import type { PagePermission } from '~/models/role'
|
||||||
|
import Error from '~/components/pub/base/error/error.vue'
|
||||||
|
import { PAGE_PERMISSIONS } from '~/lib/page-permission'
|
||||||
|
|
||||||
|
definePageMeta({
|
||||||
|
middleware: [],
|
||||||
|
roles: ['doctor', 'nurse', 'admisi', 'pharmacy', 'billing', 'management'],
|
||||||
|
title: 'Tambah SEP',
|
||||||
|
contentFrame: 'cf-full-width',
|
||||||
|
})
|
||||||
|
|
||||||
|
const route = useRoute()
|
||||||
|
|
||||||
|
useHead({
|
||||||
|
title: () => route.meta.title as string,
|
||||||
|
})
|
||||||
|
|
||||||
|
const roleAccess: PagePermission = PAGE_PERMISSIONS['/doctor']
|
||||||
|
|
||||||
|
const { checkRole, hasCreateAccess } = useRBAC()
|
||||||
|
|
||||||
|
// Check if user has access to this page
|
||||||
|
const hasAccess = checkRole(roleAccess)
|
||||||
|
if (!hasAccess) {
|
||||||
|
throw createError({
|
||||||
|
statusCode: 403,
|
||||||
|
statusMessage: 'Access denied',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define permission-based computed properties
|
||||||
|
const canCreate = true // hasCreateAccess(roleAccess)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div v-if="canCreate">
|
||||||
|
<ContentSepEntry />
|
||||||
|
</div>
|
||||||
|
<Error v-else :status-code="403" />
|
||||||
|
</template>
|
||||||
Reference in New Issue
Block a user