Merge branch 'dev' of github.com:dikstub-rssa/simrs-fe into feat/patient-63
This commit is contained in:
No files matched your search
+13
-7
@@ -1,11 +1,12 @@
|
||||
<script setup lang="ts">
|
||||
import type { SelectItem } from '~/components/pub/my-ui/form/select.vue'
|
||||
import { cn } from '~/lib/utils'
|
||||
|
||||
import { type Item } from './index'
|
||||
|
||||
const props = defineProps<{
|
||||
id: string
|
||||
id?: string
|
||||
modelValue?: string
|
||||
items: SelectItem[]
|
||||
items: Item[]
|
||||
placeholder?: string
|
||||
searchPlaceholder?: string
|
||||
emptyMessage?: string
|
||||
@@ -22,12 +23,17 @@ const open = ref(false)
|
||||
const selectedItem = computed(() => props.items.find((item) => item.value === props.modelValue))
|
||||
|
||||
const displayText = computed(() => {
|
||||
console.log(selectedItem)
|
||||
if (selectedItem.value?.label) {
|
||||
return selectedItem.value.label
|
||||
}
|
||||
return props.placeholder || 'Pilih item'
|
||||
})
|
||||
|
||||
watch(props, () => {
|
||||
console.log(props.modelValue)
|
||||
})
|
||||
|
||||
const searchableItems = computed(() => {
|
||||
const itemsWithSearch = props.items.map((item) => ({
|
||||
...item,
|
||||
@@ -49,7 +55,7 @@ const searchableItems = computed(() => {
|
||||
})
|
||||
})
|
||||
|
||||
function onSelect(item: SelectItem) {
|
||||
function onSelect(item: Item) {
|
||||
emit('update:modelValue', item.value)
|
||||
open.value = false
|
||||
}
|
||||
@@ -68,10 +74,10 @@ function onSelect(item: SelectItem) {
|
||||
:aria-describedby="`${props.id}-search`"
|
||||
:class="
|
||||
cn(
|
||||
'w-full justify-between rounded-md border px-3 py-2 text-sm font-normal focus:outline-none focus:ring-1 focus:ring-black dark:focus:ring-white',
|
||||
'h-8 w-full justify-between rounded-md border px-3 font-normal focus:outline-none focus:ring-1 focus:ring-black dark:!border-slate-400 dark:focus:ring-white md:text-xs 2xl:h-9 2xl:text-sm',
|
||||
{
|
||||
'cursor-not-allowed border-gray-300 bg-gray-100 text-gray-500 opacity-50': props.isDisabled,
|
||||
'border-gray-400 bg-white text-black hover:bg-gray-50 dark:border-gray-600 dark:bg-gray-800 dark:text-white dark:hover:bg-gray-700':
|
||||
'border-gray-400 bg-white text-black hover:bg-gray-50 dark:border-gray-600 dark:bg-slate-950 dark:text-white dark:hover:bg-gray-700':
|
||||
!props.isDisabled,
|
||||
'text-gray-400 dark:text-gray-500': !modelValue && !props.isDisabled,
|
||||
},
|
||||
@@ -116,7 +122,7 @@ function onSelect(item: SelectItem) {
|
||||
:value="item.searchValue"
|
||||
:class="
|
||||
cn(
|
||||
'flex w-full cursor-pointer items-center justify-between rounded-sm px-2 py-1.5 text-sm',
|
||||
'flex w-full cursor-pointer items-center justify-between rounded-sm px-2 py-1.5 md:text-xs xl:text-sm',
|
||||
'text-black focus:outline-none dark:text-white',
|
||||
'hover:bg-primary hover:text-white focus:bg-primary focus:text-white',
|
||||
'data-[highlighted]:bg-primary data-[highlighted]:text-white',
|
||||
@@ -0,0 +1,23 @@
|
||||
export interface Item {
|
||||
value: string
|
||||
label: string
|
||||
code?: string
|
||||
priority?: number
|
||||
}
|
||||
|
||||
export function recStrToItem(input: Record<string, string>): Item[] {
|
||||
const items: Item[] = []
|
||||
let idx = 0;
|
||||
for (const key in input) {
|
||||
if (input.hasOwnProperty(key)) {
|
||||
items.push({
|
||||
value: key || ('unknown-' + idx),
|
||||
label: input[key] || ('unknown-' + idx),
|
||||
})
|
||||
}
|
||||
idx++
|
||||
}
|
||||
return items
|
||||
}
|
||||
|
||||
export { default as Combobox } from './combobox.vue'
|
||||
@@ -19,7 +19,7 @@ function changeTab(value: string) {
|
||||
|
||||
<template>
|
||||
<!-- Tabs -->
|
||||
<div class="mt-4 flex flex-wrap gap-2 rounded-md border bg-white p-4 shadow-sm">
|
||||
<div class="mt-4 flex flex-wrap gap-2 rounded-md border bg-white dark:bg-neutral-950 p-4 shadow-sm">
|
||||
<Button
|
||||
v-for="tab in data"
|
||||
:key="tab.value"
|
||||
|
||||
@@ -9,19 +9,7 @@ const props = defineProps<{
|
||||
const recId = inject<Ref<number>>('rec_id')!
|
||||
const recAction = inject<Ref<string>>('rec_action')!
|
||||
const recItem = inject<Ref<any>>('rec_item')!
|
||||
|
||||
function detail() {
|
||||
recId.value = props.rec.id || 0
|
||||
recAction.value = ActionEvents.showDetail
|
||||
recItem.value = props.rec
|
||||
}
|
||||
|
||||
function edit() {
|
||||
recId.value = props.rec.id || 0
|
||||
recAction.value = ActionEvents.showEdit
|
||||
recItem.value = props.rec
|
||||
}
|
||||
|
||||
const activeKey = ref<string | null>(null)
|
||||
const linkItems: LinkItem[] = [
|
||||
{
|
||||
label: 'Detail',
|
||||
@@ -38,6 +26,18 @@ const linkItems: LinkItem[] = [
|
||||
icon: 'i-lucide-pencil',
|
||||
},
|
||||
]
|
||||
|
||||
function detail() {
|
||||
recId.value = props.rec.id || 0
|
||||
recAction.value = ActionEvents.showDetail
|
||||
recItem.value = props.rec
|
||||
}
|
||||
|
||||
function edit() {
|
||||
recId.value = props.rec.id || 0
|
||||
recAction.value = ActionEvents.showEdit
|
||||
recItem.value = props.rec
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -46,22 +46,29 @@ const linkItems: LinkItem[] = [
|
||||
<DropdownMenuTrigger as-child>
|
||||
<SidebarMenuButton
|
||||
size="lg"
|
||||
class="data-[state=open]:text-sidebar-accent-foreground data-[state=open]:bg-white"
|
||||
class="data-[state=open]:text-sidebar-accent-foreground data-[state=open]:bg-white dark:data-[state=open]:bg-slate-800"
|
||||
>
|
||||
<Icon name="i-lucide-chevrons-up-down" class="ml-auto size-4" />
|
||||
<Icon
|
||||
name="i-lucide-chevrons-up-down"
|
||||
class="ml-auto size-4"
|
||||
/>
|
||||
</SidebarMenuButton>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent class="w-[--radix-dropdown-menu-trigger-width] min-w-40 rounded-lg bg-white" align="end">
|
||||
<DropdownMenuContent
|
||||
class="w-[--radix-dropdown-menu-trigger-width] min-w-40 rounded-lg border border-slate-200 bg-white text-black dark:border-slate-700 dark:bg-slate-800 dark:text-white"
|
||||
align="end"
|
||||
>
|
||||
<DropdownMenuGroup>
|
||||
<DropdownMenuItem
|
||||
v-for="item in linkItems"
|
||||
:key="item.label"
|
||||
v-slot="{ active }"
|
||||
class="hover:bg-gray-100"
|
||||
class="hover:bg-gray-100 dark:hover:bg-slate-700"
|
||||
@click="item.onClick"
|
||||
@mouseenter="activeKey = item.label"
|
||||
@mouseleave="activeKey = null"
|
||||
>
|
||||
<Icon :name="item.icon" />
|
||||
<span :class="active ? 'text-sidebar-accent-foreground' : ''">{{ item.label }}</span>
|
||||
<Icon :name="item.icon ?? ''" />
|
||||
<span :class="activeKey === item.label ? 'text-sidebar-accent-foreground' : ''">{{ item.label }}</span>
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuGroup>
|
||||
</DropdownMenuContent>
|
||||
|
||||
@@ -9,25 +9,7 @@ const props = defineProps<{
|
||||
const recId = inject<Ref<number>>('rec_id')!
|
||||
const recAction = inject<Ref<string>>('rec_action')!
|
||||
const recItem = inject<Ref<any>>('rec_item')!
|
||||
|
||||
function detail() {
|
||||
recId.value = props.rec.id || 0
|
||||
recAction.value = ActionEvents.showDetail
|
||||
recItem.value = props.rec
|
||||
}
|
||||
|
||||
function edit() {
|
||||
recId.value = props.rec.id || 0
|
||||
recAction.value = ActionEvents.showEdit
|
||||
recItem.value = props.rec
|
||||
}
|
||||
|
||||
function del() {
|
||||
recId.value = props.rec.id || 0
|
||||
recAction.value = ActionEvents.showConfirmDelete
|
||||
recItem.value = props.rec
|
||||
}
|
||||
|
||||
const activeKey = ref<string | null>(null)
|
||||
const linkItems: LinkItem[] = [
|
||||
{
|
||||
label: 'Detail',
|
||||
@@ -58,6 +40,24 @@ const linkItems: LinkItem[] = [
|
||||
icon: 'i-lucide-trash',
|
||||
},
|
||||
]
|
||||
|
||||
function detail() {
|
||||
recId.value = props.rec.id || 0
|
||||
recAction.value = ActionEvents.showDetail
|
||||
recItem.value = props.rec
|
||||
}
|
||||
|
||||
function edit() {
|
||||
recId.value = props.rec.id || 0
|
||||
recAction.value = ActionEvents.showEdit
|
||||
recItem.value = props.rec
|
||||
}
|
||||
|
||||
function del() {
|
||||
recId.value = props.rec.id || 0
|
||||
recAction.value = ActionEvents.showConfirmDelete
|
||||
recItem.value = props.rec
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -66,22 +66,29 @@ const linkItems: LinkItem[] = [
|
||||
<DropdownMenuTrigger as-child>
|
||||
<SidebarMenuButton
|
||||
size="lg"
|
||||
class="data-[state=open]:text-sidebar-accent-foreground data-[state=open]:bg-white"
|
||||
class="data-[state=open]:text-sidebar-accent-foreground data-[state=open]:bg-white dark:data-[state=open]:bg-slate-800"
|
||||
>
|
||||
<Icon name="i-lucide-chevrons-up-down" class="ml-auto size-4" />
|
||||
<Icon
|
||||
name="i-lucide-chevrons-up-down"
|
||||
class="ml-auto size-4"
|
||||
/>
|
||||
</SidebarMenuButton>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent class="w-[--radix-dropdown-menu-trigger-width] min-w-40 rounded-lg bg-white" align="end">
|
||||
<DropdownMenuContent
|
||||
class="w-[--radix-dropdown-menu-trigger-width] min-w-40 rounded-lg border border-slate-200 bg-white text-black dark:border-slate-700 dark:bg-slate-800 dark:text-white"
|
||||
align="end"
|
||||
>
|
||||
<DropdownMenuGroup>
|
||||
<DropdownMenuItem
|
||||
v-for="item in linkItems"
|
||||
:key="item.label"
|
||||
v-slot="{ active }"
|
||||
class="hover:bg-gray-100"
|
||||
class="hover:bg-gray-100 dark:hover:bg-slate-700"
|
||||
@click="item.onClick"
|
||||
@mouseenter="activeKey = item.label"
|
||||
@mouseleave="activeKey = null"
|
||||
>
|
||||
<Icon :name="item.icon" />
|
||||
<span :class="active ? 'text-sidebar-accent-foreground' : ''">{{ item.label }}</span>
|
||||
<Icon :name="item.icon ?? ''" />
|
||||
<span :class="activeKey === item.label ? 'text-sidebar-accent-foreground' : ''">{{ item.label }}</span>
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuGroup>
|
||||
</DropdownMenuContent>
|
||||
|
||||
@@ -9,25 +9,7 @@ const props = defineProps<{
|
||||
const recId = inject<Ref<number>>('rec_id')!
|
||||
const recAction = inject<Ref<string>>('rec_action')!
|
||||
const recItem = inject<Ref<any>>('rec_item')!
|
||||
|
||||
function detail() {
|
||||
recId.value = props.rec.id || 0
|
||||
recAction.value = ActionEvents.showDetail
|
||||
recItem.value = props.rec
|
||||
}
|
||||
|
||||
function edit() {
|
||||
recId.value = props.rec.id || 0
|
||||
recAction.value = ActionEvents.showEdit
|
||||
recItem.value = props.rec
|
||||
}
|
||||
|
||||
function del() {
|
||||
recId.value = props.rec.id || 0
|
||||
recAction.value = ActionEvents.showConfirmDelete
|
||||
recItem.value = props.rec
|
||||
}
|
||||
|
||||
const activeKey = ref<string | null>(null)
|
||||
const linkItems: LinkItem[] = [
|
||||
{
|
||||
label: 'Detail',
|
||||
@@ -51,6 +33,24 @@ const linkItems: LinkItem[] = [
|
||||
icon: 'i-lucide-trash',
|
||||
},
|
||||
]
|
||||
|
||||
function detail() {
|
||||
recId.value = props.rec.id || 0
|
||||
recAction.value = ActionEvents.showDetail
|
||||
recItem.value = props.rec
|
||||
}
|
||||
|
||||
function edit() {
|
||||
recId.value = props.rec.id || 0
|
||||
recAction.value = ActionEvents.showEdit
|
||||
recItem.value = props.rec
|
||||
}
|
||||
|
||||
function del() {
|
||||
recId.value = props.rec.id || 0
|
||||
recAction.value = ActionEvents.showConfirmDelete
|
||||
recItem.value = props.rec
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -59,22 +59,29 @@ const linkItems: LinkItem[] = [
|
||||
<DropdownMenuTrigger as-child>
|
||||
<SidebarMenuButton
|
||||
size="lg"
|
||||
class="data-[state=open]:text-sidebar-accent-foreground data-[state=open]:bg-white"
|
||||
class="data-[state=open]:text-sidebar-accent-foreground data-[state=open]:bg-white dark:data-[state=open]:bg-slate-800"
|
||||
>
|
||||
<Icon name="i-lucide-chevrons-up-down" class="ml-auto size-4" />
|
||||
<Icon
|
||||
name="i-lucide-chevrons-up-down"
|
||||
class="ml-auto size-4"
|
||||
/>
|
||||
</SidebarMenuButton>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent class="w-[--radix-dropdown-menu-trigger-width] min-w-40 rounded-lg bg-white" align="end">
|
||||
<DropdownMenuContent
|
||||
class="w-[--radix-dropdown-menu-trigger-width] min-w-40 rounded-lg border border-slate-200 bg-white text-black dark:border-slate-700 dark:bg-slate-800 dark:text-white"
|
||||
align="end"
|
||||
>
|
||||
<DropdownMenuGroup>
|
||||
<DropdownMenuItem
|
||||
v-for="item in linkItems"
|
||||
:key="item.label"
|
||||
v-slot="{ active }"
|
||||
class="hover:bg-gray-100"
|
||||
class="hover:bg-gray-100 dark:hover:bg-slate-700"
|
||||
@click="item.onClick"
|
||||
@mouseenter="activeKey = item.label"
|
||||
@mouseleave="activeKey = null"
|
||||
>
|
||||
<Icon :name="item.icon" />
|
||||
<span :class="active ? 'text-sidebar-accent-foreground' : ''">{{ item.label }}</span>
|
||||
<Icon :name="item.icon ?? ''" />
|
||||
<span :class="activeKey === item.label ? 'text-sidebar-accent-foreground' : ''">{{ item.label }}</span>
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuGroup>
|
||||
</DropdownMenuContent>
|
||||
|
||||
@@ -9,31 +9,7 @@ const props = defineProps<{
|
||||
const recId = inject<Ref<number>>('rec_id')!
|
||||
const recAction = inject<Ref<string>>('rec_action')!
|
||||
const recItem = inject<Ref<any>>('rec_item')!
|
||||
|
||||
function detail() {
|
||||
recId.value = props.rec.id || 0
|
||||
recAction.value = ActionEvents.showDetail
|
||||
recItem.value = props.rec
|
||||
}
|
||||
|
||||
function process() {
|
||||
recId.value = props.rec.id || 0
|
||||
recAction.value = ActionEvents.showProcess
|
||||
recItem.value = props.rec
|
||||
}
|
||||
|
||||
function edit() {
|
||||
recId.value = props.rec.id || 0
|
||||
recAction.value = ActionEvents.showEdit
|
||||
recItem.value = props.rec
|
||||
}
|
||||
|
||||
function del() {
|
||||
recId.value = props.rec.id || 0
|
||||
recAction.value = ActionEvents.showConfirmDelete
|
||||
recItem.value = props.rec
|
||||
}
|
||||
|
||||
const activeKey = ref<string | null>(null)
|
||||
const linkItems: LinkItem[] = [
|
||||
{
|
||||
label: 'Proses',
|
||||
@@ -64,6 +40,30 @@ const linkItems: LinkItem[] = [
|
||||
icon: 'i-lucide-trash',
|
||||
},
|
||||
]
|
||||
|
||||
function detail() {
|
||||
recId.value = props.rec.id || 0
|
||||
recAction.value = ActionEvents.showDetail
|
||||
recItem.value = props.rec
|
||||
}
|
||||
|
||||
function process() {
|
||||
recId.value = props.rec.id || 0
|
||||
recAction.value = ActionEvents.showProcess
|
||||
recItem.value = props.rec
|
||||
}
|
||||
|
||||
function edit() {
|
||||
recId.value = props.rec.id || 0
|
||||
recAction.value = ActionEvents.showEdit
|
||||
recItem.value = props.rec
|
||||
}
|
||||
|
||||
function del() {
|
||||
recId.value = props.rec.id || 0
|
||||
recAction.value = ActionEvents.showConfirmDelete
|
||||
recItem.value = props.rec
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -72,22 +72,29 @@ const linkItems: LinkItem[] = [
|
||||
<DropdownMenuTrigger as-child>
|
||||
<SidebarMenuButton
|
||||
size="lg"
|
||||
class="data-[state=open]:text-sidebar-accent-foreground data-[state=open]:bg-white"
|
||||
class="data-[state=open]:text-sidebar-accent-foreground data-[state=open]:bg-white dark:data-[state=open]:bg-slate-800"
|
||||
>
|
||||
<Icon name="i-lucide-chevrons-up-down" class="ml-auto size-4" />
|
||||
<Icon
|
||||
name="i-lucide-chevrons-up-down"
|
||||
class="ml-auto size-4"
|
||||
/>
|
||||
</SidebarMenuButton>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent class="w-[--radix-dropdown-menu-trigger-width] min-w-40 rounded-lg bg-white" align="end">
|
||||
<DropdownMenuContent
|
||||
class="w-[--radix-dropdown-menu-trigger-width] min-w-40 rounded-lg border border-slate-200 bg-white text-black dark:border-slate-700 dark:bg-slate-800 dark:text-white"
|
||||
align="end"
|
||||
>
|
||||
<DropdownMenuGroup>
|
||||
<DropdownMenuItem
|
||||
v-for="item in linkItems"
|
||||
:key="item.label"
|
||||
v-slot="{ active }"
|
||||
class="hover:bg-gray-100"
|
||||
class="hover:bg-gray-100 dark:hover:bg-slate-700"
|
||||
@click="item.onClick"
|
||||
@mouseenter="activeKey = item.label"
|
||||
@mouseleave="activeKey = null"
|
||||
>
|
||||
<Icon :name="item.icon" />
|
||||
<span :class="active ? 'text-sidebar-accent-foreground' : ''">{{ item.label }}</span>
|
||||
<Icon :name="item.icon ?? ''" />
|
||||
<span :class="activeKey === item.label ? 'text-sidebar-accent-foreground' : ''">{{ item.label }}</span>
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuGroup>
|
||||
</DropdownMenuContent>
|
||||
|
||||
@@ -14,19 +14,7 @@ const props = withDefaults(defineProps<Props>(), {
|
||||
const recId = inject<Ref<number>>('rec_id')!
|
||||
const recAction = inject<Ref<string>>('rec_action')!
|
||||
const recItem = inject<Ref<any>>('rec_item')!
|
||||
|
||||
function edit() {
|
||||
recId.value = props.rec.id || 0
|
||||
recAction.value = ActionEvents.showEdit
|
||||
recItem.value = props.rec
|
||||
}
|
||||
|
||||
function del() {
|
||||
recId.value = props.rec.id || 0
|
||||
recAction.value = ActionEvents.showConfirmDelete
|
||||
recItem.value = props.rec
|
||||
}
|
||||
|
||||
const activeKey = ref<string | null>(null)
|
||||
const linkItems: LinkItem[] = [
|
||||
{
|
||||
label: 'Edit',
|
||||
@@ -43,6 +31,18 @@ const linkItems: LinkItem[] = [
|
||||
icon: 'i-lucide-trash',
|
||||
},
|
||||
]
|
||||
|
||||
function edit() {
|
||||
recId.value = props.rec.id || 0
|
||||
recAction.value = ActionEvents.showEdit
|
||||
recItem.value = props.rec
|
||||
}
|
||||
|
||||
function del() {
|
||||
recId.value = props.rec.id || 0
|
||||
recAction.value = ActionEvents.showConfirmDelete
|
||||
recItem.value = props.rec
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -51,22 +51,29 @@ const linkItems: LinkItem[] = [
|
||||
<DropdownMenuTrigger as-child>
|
||||
<SidebarMenuButton
|
||||
:size="size"
|
||||
class="data-[state=open]:text-sidebar-accent-foreground data-[state=open]:bg-white"
|
||||
class="data-[state=open]:text-sidebar-accent-foreground data-[state=open]:bg-white dark:data-[state=open]:bg-slate-800"
|
||||
>
|
||||
<Icon name="i-lucide-chevrons-up-down" class="ml-auto size-4" />
|
||||
<Icon
|
||||
name="i-lucide-chevrons-up-down"
|
||||
class="ml-auto size-4"
|
||||
/>
|
||||
</SidebarMenuButton>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent class="w-[--radix-dropdown-menu-trigger-width] min-w-40 rounded-lg bg-white" align="end">
|
||||
<DropdownMenuContent
|
||||
class="w-[--radix-dropdown-menu-trigger-width] min-w-40 rounded-lg border border-slate-200 bg-white text-black dark:border-slate-700 dark:bg-slate-800 dark:text-white"
|
||||
align="end"
|
||||
>
|
||||
<DropdownMenuGroup>
|
||||
<DropdownMenuItem
|
||||
v-for="item in linkItems"
|
||||
:key="item.label"
|
||||
v-slot="{ active }"
|
||||
class="hover:bg-gray-100"
|
||||
class="hover:bg-gray-100 dark:hover:bg-slate-700"
|
||||
@click="item.onClick"
|
||||
@mouseenter="activeKey = item.label"
|
||||
@mouseleave="activeKey = null"
|
||||
>
|
||||
<Icon :name="item.icon" />
|
||||
<span :class="active ? 'text-sidebar-accent-foreground' : ''">{{ item.label }}</span>
|
||||
<Icon :name="item.icon ?? ''" />
|
||||
<span :class="activeKey === item.label ? 'text-sidebar-accent-foreground' : ''">{{ item.label }}</span>
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuGroup>
|
||||
</DropdownMenuContent>
|
||||
|
||||
@@ -60,11 +60,11 @@ const settingClass = computed(() => {
|
||||
'[&_.label]:md:w-44 [&_.label]:xl:w-52',
|
||||
][getLabelSizeIdx(props.labelSize)]
|
||||
} else {
|
||||
cls += ' [&_.label]:pb-1 ';
|
||||
cls += ' [&_.label]:pb-1 [&_.label]:!pt-0 ';
|
||||
}
|
||||
cls += ' [&:not(.preview)_.height-default]:pt-2 [&:not(.preview)_.height-default]:2xl:!pt-1.5 [&:not(.preview)_.height-compact]:!pt-1 '
|
||||
cls += '[&_textarea]:text-xs [&_textarea]:xl:text-sm '
|
||||
cls += '[&_label]:text-xs [&_label]:xl:text-sm'
|
||||
cls += '[&_textarea]:text-xs [&_textarea]:2xl:!text-sm '
|
||||
cls += '[&_label]:text-xs [&_label]:2xl:!text-sm'
|
||||
return cls
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -9,6 +9,6 @@ const props = defineProps({
|
||||
<template>
|
||||
<div :class="`field ${props.defaultClass} ${props.class}`">
|
||||
<slot />
|
||||
<div v-if="props.errMessage" class="mt-1 text-xs font-medium text-red-500">{{ props.errMessage }}</div>
|
||||
<div v-if="props.errMessage" class="mt-1 md:text-xs 2xl:text-sm font-medium text-red-500">{{ props.errMessage }}</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -32,7 +32,7 @@ const settingClass = computed(() => {
|
||||
|
||||
<template>
|
||||
<div :class="settingClass">
|
||||
<label>
|
||||
<label v-bind="$attrs">
|
||||
<slot />
|
||||
</label>
|
||||
</div>
|
||||
|
||||
@@ -20,7 +20,12 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits)
|
||||
<template>
|
||||
<ComboboxItem
|
||||
v-bind="forwarded"
|
||||
:class="cn('relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm font-normal outline-none hover:bg-accent data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&>*]:text-sm [&>*]:font-normal', props.class)"
|
||||
:class="
|
||||
cn(
|
||||
'relative flex cursor-default select-none items-center rounded-sm bg-white px-2 py-1.5 text-sm font-normal text-black outline-none hover:bg-accent data-[disabled]:pointer-events-none data-[disabled]:opacity-50 dark:bg-slate-800 dark:text-white dark:hover:bg-slate-700 [&>*]:text-sm [&>*]:font-normal',
|
||||
props.class,
|
||||
)
|
||||
"
|
||||
>
|
||||
<slot />
|
||||
</ComboboxItem>
|
||||
|
||||
@@ -20,11 +20,11 @@ function handleSelect(value: string) {
|
||||
<div class="leaf-node min-w-max">
|
||||
<CommandItem
|
||||
:value="item.value"
|
||||
class="flex items-center justify-between p-2 w-full text-sm font-normal hover:text-primary cursor-pointer rounded-md"
|
||||
class="flex items-center justify-between p-2 w-full text-sm font-normal hover:text-primary cursor-pointer rounded-md bg-white dark:bg-transparent"
|
||||
:class="{ 'pl-8': shouldAlign }"
|
||||
@select="() => handleSelect(item.value)"
|
||||
>
|
||||
<span class="text-sm font-normal text-gray-400">{{ item.label }}</span>
|
||||
<span class="text-sm font-normal text-gray-400 dark:text-gray-300">{{ item.label }}</span>
|
||||
<Check
|
||||
v-if="selectedValue === item.value"
|
||||
class="w-4 h-4 text-primary ml-2 flex-shrink-0"
|
||||
|
||||
@@ -52,19 +52,27 @@ watch(isOpen, async (newValue) => {
|
||||
|
||||
<template>
|
||||
<div class="tree-node min-w-max">
|
||||
<Collapsible v-model:open="isOpen" class="w-full">
|
||||
<Collapsible
|
||||
v-model:open="isOpen"
|
||||
class="w-full"
|
||||
>
|
||||
<!-- Node Header -->
|
||||
<div class="flex items-center justify-start w-full p-2 rounded-md hover:bg-accent gap-2">
|
||||
<div
|
||||
class="flex w-full items-center justify-start gap-2 rounded-md bg-white p-2 hover:bg-accent dark:bg-transparent dark:hover:bg-slate-700"
|
||||
>
|
||||
<!-- Chevron Toggle Button -->
|
||||
<CollapsibleTrigger as-child>
|
||||
<Button
|
||||
variant="ghost"
|
||||
class="h-4 w-4 p-0 flex items-center justify-center"
|
||||
class="flex h-4 w-4 items-center justify-center p-0"
|
||||
>
|
||||
<Loader2 v-if="isLoading" class="w-4 h-4 animate-spin text-muted-foreground" />
|
||||
<Loader2
|
||||
v-if="isLoading"
|
||||
class="h-4 w-4 animate-spin text-muted-foreground"
|
||||
/>
|
||||
<ChevronRight
|
||||
v-else
|
||||
class="w-4 h-4 transition-transform duration-200 ease-in-out text-muted-foreground"
|
||||
class="h-4 w-4 text-muted-foreground transition-transform duration-200 ease-in-out"
|
||||
:class="{
|
||||
'rotate-90': isChevronRotated,
|
||||
}"
|
||||
@@ -74,21 +82,24 @@ watch(isOpen, async (newValue) => {
|
||||
|
||||
<!-- Node Label -->
|
||||
<span
|
||||
class="text-sm font-normal cursor-pointer hover:text-primary flex-1 flex items-center justify-between"
|
||||
class="flex flex-1 cursor-pointer items-center justify-between text-sm font-normal text-black hover:text-primary dark:text-white"
|
||||
@click="handleLabelClick"
|
||||
>
|
||||
{{ item.label }}
|
||||
<!-- Check Icon untuk selected state -->
|
||||
<Check
|
||||
v-if="selectedValue === item.value"
|
||||
class="w-4 h-4 text-primary ml-2 flex-shrink-0"
|
||||
class="ml-2 h-4 w-4 flex-shrink-0 text-primary"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Children Container -->
|
||||
<CollapsibleContent class="pl-6">
|
||||
<div v-if="!hasChildren" class="text-sm text-muted-foreground p-2">
|
||||
<div
|
||||
v-if="!hasChildren"
|
||||
class="p-2 text-sm text-muted-foreground"
|
||||
>
|
||||
{{ isLoading ? 'Memuat...' : 'Tidak ada data' }}
|
||||
</div>
|
||||
<TreeView
|
||||
@@ -106,7 +117,7 @@ watch(isOpen, async (newValue) => {
|
||||
|
||||
<style scoped>
|
||||
.tree-node {
|
||||
@apply w-full;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Animasi tambahan untuk smooth transition */
|
||||
|
||||
@@ -37,7 +37,7 @@ const filteredData = computed(() => {
|
||||
// recursive filter
|
||||
function filterTree(items: TreeItem[]): TreeItem[] {
|
||||
return items
|
||||
.map(item => {
|
||||
.map((item) => {
|
||||
const match = item.label.toLowerCase().includes(searchValue.value.toLowerCase())
|
||||
let children: TreeItem[] | undefined = undefined
|
||||
if (item.children) {
|
||||
@@ -57,22 +57,28 @@ const filteredData = computed(() => {
|
||||
<template>
|
||||
<Popover v-model:open="open">
|
||||
<PopoverTrigger as-child>
|
||||
<Button variant="outline" role="combobox" class="w-full justify-between bg-white border-1 border-gray-400">
|
||||
<Button
|
||||
variant="outline"
|
||||
role="combobox"
|
||||
class="w-full justify-between border border-slate-200 bg-white text-black dark:border-slate-700 dark:bg-slate-800 dark:text-white"
|
||||
>
|
||||
<span
|
||||
class="font-normal text-muted-foreground" :class="cn(
|
||||
'font-normal',
|
||||
!modelValue && 'text-muted-foreground',
|
||||
modelValue && 'text-black',
|
||||
)"
|
||||
class="font-normal text-muted-foreground"
|
||||
:class="cn('font-normal', !modelValue && 'text-muted-foreground', modelValue && 'text-black')"
|
||||
>
|
||||
{{ selectedLabel }}
|
||||
</span>
|
||||
<ChevronsUpDown class="w-4 h-4 ml-2 opacity-50 shrink-0" />
|
||||
<ChevronsUpDown class="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent class="min-w-full max-w-[350px] p-0">
|
||||
<PopoverContent
|
||||
class="min-w-full max-w-[350px] border border-slate-200 bg-white p-0 text-black dark:border-slate-700 dark:bg-slate-800 dark:text-white"
|
||||
>
|
||||
<Command>
|
||||
<CommandInput placeholder="Cari item..." v-model="searchValue" />
|
||||
<CommandInput
|
||||
placeholder="Cari item..."
|
||||
v-model="searchValue"
|
||||
/>
|
||||
<CommandEmpty>Item tidak ditemukan.</CommandEmpty>
|
||||
<CommandList class="max-h-[300px] overflow-x-auto overflow-y-auto">
|
||||
<CommandGroup>
|
||||
|
||||
Reference in New Issue
Block a user