dev: hotfix, pubs
+ my-ui/confirmation/confirmation noTrueSlot from record-confirmation + my-ui/confirmation/confirmation additional message + my-ui/confirmation/record-confirmation supplies noTrueSlot + my-ui/modal/modal text size + my-ui/doc-entry semicolon export
This commit is contained in:
@@ -8,6 +8,8 @@ interface ConfirmationProps {
|
|||||||
message?: string
|
message?: string
|
||||||
confirmText?: string
|
confirmText?: string
|
||||||
cancelText?: string
|
cancelText?: string
|
||||||
|
noTrueSlot?: boolean
|
||||||
|
skipClosingMessage?: boolean
|
||||||
variant?: 'default' | 'destructive' | 'warning'
|
variant?: 'default' | 'destructive' | 'warning'
|
||||||
size?: 'sm' | 'md' | 'lg' | 'xl'
|
size?: 'sm' | 'md' | 'lg' | 'xl'
|
||||||
}
|
}
|
||||||
@@ -71,20 +73,22 @@ function handleCancel() {
|
|||||||
<Dialog v-model:open="isOpen" :title="title" :size="size">
|
<Dialog v-model:open="isOpen" :title="title" :size="size">
|
||||||
<div class="space-y-4">
|
<div class="space-y-4">
|
||||||
<!-- Icon dan pesan -->
|
<!-- Icon dan pesan -->
|
||||||
<div class="flex items-center gap-3">
|
<div class="flex items-start gap-3">
|
||||||
<div :class="[variantClasses.icon, variantClasses.iconColor]" class="w-6 h-6 mt-1 flex-shrink-0" />
|
<div :class="[variantClasses.icon, variantClasses.iconColor]" class="w-4 h-4 2xl:h-5 2xl:h-6 flex-shrink-0" />
|
||||||
<div class="flex-1">
|
<div class="flex-1">
|
||||||
<p class="text-sm text-muted-foreground leading-relaxed">
|
{{ message }} {{ !noTrueSlot ? ' dengan informasi sebagai berikut:' : '.' }}
|
||||||
{{ message }}
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Slot untuk konten custom -->
|
<!-- Slot untuk konten custom -->
|
||||||
<div v-if="$slots.default">
|
<div>
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div v-if="!skipClosingMessage" class="">
|
||||||
|
Lanjutkan Proses?
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Footer buttons -->
|
<!-- Footer buttons -->
|
||||||
<div class="flex justify-end gap-3 pt-4">
|
<div class="flex justify-end gap-3 pt-4">
|
||||||
<Button variant="outline" @click="handleCancel">
|
<Button variant="outline" @click="handleCancel">
|
||||||
|
|||||||
@@ -46,31 +46,31 @@ const actionConfig = computed(() => {
|
|||||||
const configs = {
|
const configs = {
|
||||||
delete: {
|
delete: {
|
||||||
title: 'Hapus Data',
|
title: 'Hapus Data',
|
||||||
message: 'Apakah Anda yakin ingin menghapus data ini? Tindakan ini tidak dapat dibatalkan.',
|
message: 'Akan dilakukan penghapusan data',
|
||||||
confirmText: 'Hapus',
|
confirmText: 'Hapus',
|
||||||
variant: 'destructive' as const,
|
variant: 'destructive' as const,
|
||||||
},
|
},
|
||||||
deactivate: {
|
deactivate: {
|
||||||
title: 'Nonaktifkan Data',
|
title: 'Nonaktifkan Data',
|
||||||
message: 'Apakah Anda yakin ingin menonaktifkan data ini?',
|
message: 'Akan dilakukan peng-nonaktifkan data',
|
||||||
confirmText: 'Nonaktifkan',
|
confirmText: 'Nonaktifkan',
|
||||||
variant: 'warning' as const,
|
variant: 'warning' as const,
|
||||||
},
|
},
|
||||||
activate: {
|
activate: {
|
||||||
title: 'Aktifkan Data',
|
title: 'Aktifkan Data',
|
||||||
message: 'Apakah Anda yakin ingin mengaktifkan data ini?',
|
message: 'Akan dilakukan pengaktifkan data',
|
||||||
confirmText: 'Aktifkan',
|
confirmText: 'Aktifkan',
|
||||||
variant: 'default' as const,
|
variant: 'default' as const,
|
||||||
},
|
},
|
||||||
archive: {
|
archive: {
|
||||||
title: 'Arsipkan Data',
|
title: 'Arsipkan Data',
|
||||||
message: 'Apakah Anda yakin ingin mengarsipkan data ini?',
|
message: 'Akan dilakukan pengarsipan data',
|
||||||
confirmText: 'Arsipkan',
|
confirmText: 'Arsipkan',
|
||||||
variant: 'warning' as const,
|
variant: 'warning' as const,
|
||||||
},
|
},
|
||||||
restore: {
|
restore: {
|
||||||
title: 'Pulihkan Data',
|
title: 'Pulihkan Data',
|
||||||
message: 'Apakah Anda yakin ingin memulihkan data ini?',
|
message: 'Akan dilakukan pemulihan data',
|
||||||
confirmText: 'Pulihkan',
|
confirmText: 'Pulihkan',
|
||||||
variant: 'default' as const,
|
variant: 'default' as const,
|
||||||
},
|
},
|
||||||
@@ -107,6 +107,8 @@ const finalCancelText = computed(() => {
|
|||||||
function handleConfirm() {
|
function handleConfirm() {
|
||||||
if (props.record) {
|
if (props.record) {
|
||||||
emit('confirm', props.record, props.action)
|
emit('confirm', props.record, props.action)
|
||||||
|
} else {
|
||||||
|
emit('confirm', { id: 0 }, 'confirmed')
|
||||||
}
|
}
|
||||||
emit('update:open', false)
|
emit('update:open', false)
|
||||||
}
|
}
|
||||||
@@ -119,11 +121,13 @@ function handleCancel() {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Confirmation
|
<Confirmation
|
||||||
v-model:open="isOpen" :title="finalTitle" :message="finalMessage" :confirm-text="finalConfirmText"
|
v-model:open="isOpen" :variant="actionConfig.variant" size="md"
|
||||||
:cancel-text="finalCancelText" :variant="actionConfig.variant" size="md" @confirm="handleConfirm"
|
:title="finalTitle" :message="finalMessage"
|
||||||
|
:confirm-text="finalConfirmText" :cancel-text="finalCancelText"
|
||||||
|
:no-true-slot="$slots.default ? false : true"
|
||||||
|
@confirm="handleConfirm"
|
||||||
@cancel="handleCancel"
|
@cancel="handleCancel"
|
||||||
>
|
>
|
||||||
<!-- Slot untuk informasi tambahan record -->
|
|
||||||
<div v-if="record && $slots.default" class="mt-4 p-3 bg-muted rounded-md">
|
<div v-if="record && $slots.default" class="mt-4 p-3 bg-muted rounded-md">
|
||||||
<slot :record="record" :action="action" />
|
<slot :record="record" :action="action" />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -0,0 +1,95 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import type { LinkItem, ListItemDto } from './types'
|
||||||
|
import { ActionEvents } from './types'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
rec: ListItemDto
|
||||||
|
size?: 'default' | 'sm' | 'lg'
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
|
size: 'lg',
|
||||||
|
})
|
||||||
|
|
||||||
|
const recId = inject<Ref<number>>('rec_id')!
|
||||||
|
const recAction = inject<Ref<string>>('rec_action')!
|
||||||
|
const recItem = inject<Ref<any>>('rec_item')!
|
||||||
|
const activeKey = ref<string | null>(null)
|
||||||
|
const linkItems: LinkItem[] = [
|
||||||
|
{
|
||||||
|
label: 'Detail',
|
||||||
|
onClick: () => {
|
||||||
|
detail()
|
||||||
|
},
|
||||||
|
icon: 'i-lucide-eye',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Submit',
|
||||||
|
onClick: () => {
|
||||||
|
submit()
|
||||||
|
},
|
||||||
|
icon: 'i-lucide-check',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Hapus',
|
||||||
|
onClick: () => {
|
||||||
|
del()
|
||||||
|
},
|
||||||
|
icon: 'i-lucide-trash',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
function detail() {
|
||||||
|
recId.value = props.rec.id || 0
|
||||||
|
recAction.value = ActionEvents.showDetail
|
||||||
|
recItem.value = props.rec
|
||||||
|
}
|
||||||
|
|
||||||
|
function submit() {
|
||||||
|
recId.value = props.rec.id || 0
|
||||||
|
recAction.value = ActionEvents.showConfirmSubmit
|
||||||
|
recItem.value = props.rec
|
||||||
|
}
|
||||||
|
|
||||||
|
function del() {
|
||||||
|
recId.value = props.rec.id || 0
|
||||||
|
recAction.value = ActionEvents.showConfirmDelete
|
||||||
|
recItem.value = props.rec
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<DropdownMenu>
|
||||||
|
<DropdownMenuTrigger as-child>
|
||||||
|
<SidebarMenuButton
|
||||||
|
:size="size"
|
||||||
|
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"
|
||||||
|
/>
|
||||||
|
</SidebarMenuButton>
|
||||||
|
</DropdownMenuTrigger>
|
||||||
|
<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"
|
||||||
|
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="activeKey === item.label ? 'text-sidebar-accent-foreground' : ''">{{ item.label }}</span>
|
||||||
|
</DropdownMenuItem>
|
||||||
|
</DropdownMenuGroup>
|
||||||
|
</DropdownMenuContent>
|
||||||
|
</DropdownMenu>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@@ -42,12 +42,6 @@ export interface RefSearchNav {
|
|||||||
onClear: () => void
|
onClear: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface RefExportNav {
|
|
||||||
onExportPdf?: () => void
|
|
||||||
onExportCsv?: () => void
|
|
||||||
onExportExcel?: () => void
|
|
||||||
}
|
|
||||||
|
|
||||||
// prepared header for relatively common usage
|
// prepared header for relatively common usage
|
||||||
export interface HeaderPrep {
|
export interface HeaderPrep {
|
||||||
title?: string
|
title?: string
|
||||||
@@ -79,6 +73,7 @@ export interface LinkItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const ActionEvents = {
|
export const ActionEvents = {
|
||||||
|
showConfirmSubmit: 'showConfirmSubmit',
|
||||||
showConfirmDelete: 'showConfirmDel',
|
showConfirmDelete: 'showConfirmDel',
|
||||||
showEdit: 'showEdit',
|
showEdit: 'showEdit',
|
||||||
showDetail: 'showDetail',
|
showDetail: 'showDetail',
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ const settingClass = computed(() => {
|
|||||||
}
|
}
|
||||||
cls += ' [&:not(.preview)_.height-default]:pt-2 [&:not(.preview)_.height-default]:2xl:!pt-1.5 [&:not(.preview)_.height-compact]:!pt-1 '
|
cls += ' [&:not(.preview)_.height-default]:pt-2 [&:not(.preview)_.height-default]:2xl:!pt-1.5 [&:not(.preview)_.height-compact]:!pt-1 '
|
||||||
cls += '[&_textarea]:md:text-xs [&_textarea]:2xl:!text-sm '
|
cls += '[&_textarea]:md:text-xs [&_textarea]:2xl:!text-sm '
|
||||||
cls += '[&_label]:md:text-xs [&_label]:md:text-xs [&_label]:2xl:!text-sm'
|
cls += '[&_label]:md:text-xs [&_label]:2xl:!text-sm '
|
||||||
return cls
|
return cls
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
export { default as Block } from './block.vue'
|
export { default as Block } from './block.vue'
|
||||||
|
export { default as Colon } from './colon.vue'
|
||||||
export { default as Cell } from './cell.vue'
|
export { default as Cell } from './cell.vue'
|
||||||
export { default as Label } from './label.vue'
|
export { default as Label } from './label.vue'
|
||||||
export { default as Field } from './field.vue'
|
export { default as Field } from './field.vue'
|
||||||
|
|||||||
@@ -52,8 +52,8 @@ const isOpen = computed({
|
|||||||
>
|
>
|
||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
<DialogTitle :class="`text-sm 2xl:text-base font-semibold flex ${titleClass || ''}`">
|
<DialogTitle :class="`text-sm 2xl:text-base font-semibold flex ${titleClass || ''}`">
|
||||||
<div class="me-2 pt-0.5">
|
<div v-if="props.titleIcon" class="me-2 pt-0.5">
|
||||||
<Icon v-if="props.titleIcon" :name="props.titleIcon" :class="`!pt-2`" />
|
<Icon :name="props.titleIcon" :class="`!pt-2`" />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
{{ props.title }}
|
{{ props.title }}
|
||||||
@@ -61,7 +61,7 @@ const isOpen = computed({
|
|||||||
</DialogTitle>
|
</DialogTitle>
|
||||||
<DialogDescription v-if="props.description">{{ props.description }}</DialogDescription>
|
<DialogDescription v-if="props.description">{{ props.description }}</DialogDescription>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
<DialogDescription :class="sizeClass">
|
<DialogDescription :class="`${sizeClass} md:text-xs 2xl:text-sm`">
|
||||||
<slot />
|
<slot />
|
||||||
</DialogDescription>
|
</DialogDescription>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
|
|||||||
Reference in New Issue
Block a user