Dev cleaning (#106)
This commit is contained in:
@@ -0,0 +1,102 @@
|
||||
<script lang="ts" setup>
|
||||
definePageMeta({
|
||||
layout: 'blank',
|
||||
public: true,
|
||||
})
|
||||
|
||||
const route = useRoute()
|
||||
const contentFrame = computed(() => route.meta.contentFrame)
|
||||
const contentContent = computed(() => {
|
||||
switch (contentFrame.value) {
|
||||
case 'cf-container-lg':
|
||||
return 'cf-frame cf-container-lg-content'
|
||||
case 'cf-container-md':
|
||||
return 'cf-frame cf-container-md-content'
|
||||
case 'cf-container-sm':
|
||||
return 'cf-frame cf-container-sm-content'
|
||||
case 'cf-full-width':
|
||||
return 'cf-frame-width'
|
||||
default:
|
||||
return 'cf-frame'
|
||||
}
|
||||
})
|
||||
|
||||
const teams: {
|
||||
name: string
|
||||
logo: string
|
||||
plan: string
|
||||
}[] = [
|
||||
{
|
||||
name: 'SIMRS - RSSA',
|
||||
logo: '/rssa-logo.png',
|
||||
plan: 'Saiful Anwar Hospital',
|
||||
},
|
||||
]
|
||||
const sidebar = {
|
||||
collapsible: 'offcanvas', // 'offcanvas' | 'icon' | 'none'
|
||||
side: 'left', // 'left' | 'right'
|
||||
variant: 'sidebar', // 'sidebar' | 'floating' | 'inset'
|
||||
}
|
||||
|
||||
const navMenu = ref({
|
||||
heading: 'Main Menu',
|
||||
items: [
|
||||
{
|
||||
title: 'Test User List',
|
||||
icon: 'i-lucide-user',
|
||||
component: defineAsyncComponent(() => import('~/pages/_dev/user/list.vue')),
|
||||
},
|
||||
{
|
||||
title: 'Test Medicine List',
|
||||
icon: 'i-lucide-user',
|
||||
component: defineAsyncComponent(() => import('~/components/content/item/list.vue')),
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
const activeComponent = ref<any>(null)
|
||||
|
||||
function selectComponent(item: any) {
|
||||
activeComponent.value = item.component
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<SidebarProvider>
|
||||
<Sidebar :collapsible="sidebar.collapsible" :side="sidebar.side" :variant="sidebar.variant">
|
||||
<SidebarHeader>
|
||||
<LayoutSidebarNavHeader :teams="teams" />
|
||||
</SidebarHeader>
|
||||
<SidebarContent>
|
||||
<SidebarGroup v-if="navMenu.items.length > 0">
|
||||
<SidebarGroupLabel>
|
||||
{{ navMenu.heading }}
|
||||
</SidebarGroupLabel>
|
||||
<button
|
||||
v-for="(item, index) in navMenu.items"
|
||||
:key="index"
|
||||
class="my-2 mb-2 flex w-full items-center gap-2 rounded px-2 py-1 hover:bg-gray-100"
|
||||
@click="selectComponent(item)"
|
||||
>
|
||||
<i :class="item.icon"></i>
|
||||
{{ item.title }}
|
||||
</button>
|
||||
</SidebarGroup>
|
||||
</SidebarContent>
|
||||
<SidebarFooter>
|
||||
<LayoutSidebarNavFooter />
|
||||
</SidebarFooter>
|
||||
<SidebarRail />
|
||||
</Sidebar>
|
||||
|
||||
<SidebarInset>
|
||||
<LayoutHeader />
|
||||
<div class="w-full min-w-0 flex-1 overflow-x-auto p-4 lg:p-6">
|
||||
<div v-if="activeComponent">
|
||||
<component :is="activeComponent" />
|
||||
</div>
|
||||
<div v-else class="text-gray-500">Playground untuk testing component</div>
|
||||
</div>
|
||||
</SidebarInset>
|
||||
</SidebarProvider>
|
||||
</template>
|
||||
@@ -0,0 +1,54 @@
|
||||
<script setup lang="ts">
|
||||
// #region Props & Emits
|
||||
const props = defineProps<{
|
||||
title: string
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'update', value: string): void
|
||||
}>()
|
||||
// #endregion
|
||||
|
||||
// #region State & Computed
|
||||
// =============================
|
||||
const count = ref(0)
|
||||
const double = computed(() => count.value * 2)
|
||||
// #endregion
|
||||
|
||||
// #region Lifecycle Hooks
|
||||
onMounted(() => {
|
||||
// init code
|
||||
fetchData()
|
||||
})
|
||||
// #endregion
|
||||
|
||||
// #region Functions
|
||||
async function fetchData() {
|
||||
console.log('fetched')
|
||||
}
|
||||
// #endregion region
|
||||
|
||||
// #region Utilities & event handlers
|
||||
function increment() {
|
||||
count.value++
|
||||
}
|
||||
// #endregion
|
||||
|
||||
// #region Watchers
|
||||
watch(count, (newVal, oldVal) => {
|
||||
console.log('count changed:', oldVal, '->', newVal)
|
||||
})
|
||||
// #endregion
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<p>Count: {{ count }}</p>
|
||||
<p>Double: {{ double }}</p>
|
||||
<button @click="increment">+1</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
/* component style */
|
||||
</style>
|
||||
@@ -0,0 +1,41 @@
|
||||
<script setup lang="ts">
|
||||
// import type { PagePermission } from '~/models/role'
|
||||
import Error from '~/components/pub/my-ui/error/error.vue'
|
||||
// import { PAGE_PERMISSIONS } from '~/lib/page-permission'
|
||||
|
||||
definePageMeta({
|
||||
// middleware: ['rbac'],
|
||||
roles: ['doctor', 'nurse', 'admisi', 'pharmacy', 'billing', 'management'],
|
||||
title: 'Daftar Divisi',
|
||||
contentFrame: 'cf-container-lg',
|
||||
})
|
||||
|
||||
const route = useRoute()
|
||||
|
||||
useHead({
|
||||
title: () => route.meta.title as string,
|
||||
})
|
||||
|
||||
// const roleAccess: PagePermission = PAGE_PERMISSIONS['/patient']
|
||||
|
||||
// const { checkRole, hasReadAccess } = useRBAC()
|
||||
|
||||
// // Check if user has access to this page
|
||||
// const hasAccess = checkRole(roleAccess)
|
||||
// if (!hasAccess) {
|
||||
// navigateTo('/403')
|
||||
// }
|
||||
|
||||
// Define permission-based computed properties
|
||||
// const canRead = hasReadAccess(roleAccess)
|
||||
const canRead = true
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<div v-if="canRead">
|
||||
<ContentPrescriptionList />
|
||||
</div>
|
||||
<Error v-else :status-code="403" />
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,10 @@
|
||||
<script setup lang="ts">
|
||||
definePageMeta({
|
||||
layout: 'blank',
|
||||
public: true,
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>test tambah user</div>
|
||||
</template>
|
||||
@@ -0,0 +1,81 @@
|
||||
<script setup lang="ts">
|
||||
import TreeSelect from '~/components/pub/my-ui/select-tree/tree-select.vue'
|
||||
|
||||
definePageMeta({
|
||||
layout: 'blank',
|
||||
})
|
||||
|
||||
// Tipe data untuk konsistensi
|
||||
interface TreeItem {
|
||||
value: string
|
||||
label: string
|
||||
hasChildren: boolean
|
||||
children?: TreeItem[]
|
||||
}
|
||||
|
||||
// State untuk data pohon. Awalnya hanya berisi data level atas.
|
||||
const treeData = ref<TreeItem[]>([
|
||||
{ value: 'frontend', label: 'Frontend', hasChildren: true },
|
||||
{ value: 'backend', label: 'Backend', hasChildren: true },
|
||||
{ value: 'devops', label: 'DevOps', hasChildren: false },
|
||||
])
|
||||
|
||||
// State untuk menampung nilai yang dipilih
|
||||
const selectedValue = ref<string>()
|
||||
|
||||
// --- INI BAGIAN PENTING: LOGIKA API DAN MANIPULASI DATA ---
|
||||
|
||||
// Helper: Fungsi rekursif untuk mencari dan menyisipkan data anak ke dalam state
|
||||
function findAndInsertChildren(nodes: TreeItem[], parentId: string, newChildren: TreeItem[]) {
|
||||
for (const node of nodes) {
|
||||
if (node.value === parentId) {
|
||||
node.children = newChildren
|
||||
return true
|
||||
}
|
||||
if (node.children && findAndInsertChildren(node.children, parentId, newChildren)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Fungsi yang akan dipanggil oleh komponen TreeSelectItem untuk mengambil data
|
||||
async function handleFetchChildren(parentId: string) {
|
||||
console.log(`Mengambil data anak untuk parent: ${parentId}`)
|
||||
|
||||
// Simulasi panggilan API ke backend Anda
|
||||
await new Promise(resolve => setTimeout(resolve, 500)) // Delay 0.5 detik
|
||||
|
||||
let childrenData: TreeItem[] = []
|
||||
if (parentId === 'frontend') {
|
||||
childrenData = [
|
||||
{ value: 'vue', label: 'Vue.js', hasChildren: true },
|
||||
{ value: 'react', label: 'React.js', hasChildren: false },
|
||||
]
|
||||
} else if (parentId === 'backend') {
|
||||
childrenData = [
|
||||
{ value: 'nodejs', label: 'Node.js', hasChildren: false },
|
||||
{ value: 'golang', label: 'Go', hasChildren: false },
|
||||
]
|
||||
} else if (parentId === 'vue') { // Contoh untuk level yang lebih dalam
|
||||
childrenData = [
|
||||
{ value: 'nuxt', label: 'Nuxt.js', hasChildren: false },
|
||||
]
|
||||
}
|
||||
// Akhir simulasi
|
||||
|
||||
// Masukkan data anak yang baru didapat ke dalam state treeData
|
||||
findAndInsertChildren(treeData.value, parentId, childrenData)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="p-10">
|
||||
<h1 class="mb-4 text-2xl font-bold">Tree Select (Lazy Loading)</h1>
|
||||
<TreeSelect v-model="selectedValue" :data="treeData" :on-fetch-children="handleFetchChildren" />
|
||||
<p class="mt-4">
|
||||
Value yang terpilih:
|
||||
<span class="p-1 font-mono text-sm rounded-md bg-slate-100">{{ selectedValue || 'Belum ada' }}</span>
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
Reference in New Issue
Block a user