Files
boursecu_admin/src/components/BasicActionSheet.vue
T

189 lines
4.2 KiB
Vue
Raw Normal View History

2026-05-31 11:51:52 +03:30
<template>
<BasicModal
v-if="!isMobileView"
:key="`action-sheet-modal-${overlayKey}`"
v-model:visible="visibleProxy"
:title="title"
:width="modalWidth"
:loading="loading"
custom-footer
@close="handleCancel"
@ok="$emit('ok')"
>
<slot />
<template #footer>
<div
v-if="showButton && (showCancel || showOk)"
class="grid gap-3"
:class="[!showOk || !showCancel ? 'grid-cols-1' : 'grid-cols-12']"
>
<AButton
v-if="showCancel"
type="primary"
:class="[{ 'col-span-4': showOk }]"
size="large"
ghost
block
@click="handleCancel"
>
{{ cancelText }}
</AButton>
<AButton
v-if="showOk"
type="primary"
:class="[{ 'col-span-8': showCancel }]"
size="large"
block
@click="$emit('ok')"
>
{{ okText }}
</AButton>
</div>
</template>
</BasicModal>
<ADrawer
v-else-if="isMobileView"
:key="`action-sheet-drawer-${overlayKey}`"
v-model:visible="visibleProxy"
placement="bottom"
:closable="false"
:destroy-on-close="true"
:height="drawerHeight"
2026-06-03 17:51:27 +03:30
:z-index="ACTION_SHEET_Z_INDEX"
2026-05-31 11:51:52 +03:30
class="basic-action-sheet"
>
<div class="basic-action-sheet__container">
<div class="flex cursor-pointer justify-center pt-2" @click="visibleProxy = false">
<span class="w-12 rounded-sm border-t-2 border-t-solid border-t-gray-500"></span>
</div>
<div class="basic-action-sheet__content">
<slot />
</div>
<div
v-if="showButton && (showCancel || showOk)"
class="basic-action-sheet__footer grid gap-3"
:class="[!showOk || !showCancel ? 'grid-cols-1' : 'grid-cols-12']"
>
<AButton
v-if="showCancel"
type="primary"
:class="[{ 'col-span-4': showOk }]"
size="large"
ghost
block
@click="handleCancel"
>
{{ cancelText }}
</AButton>
<AButton
v-if="showOk"
type="primary"
:class="[{ 'col-span-8': showCancel }]"
size="large"
block
@click="$emit('ok')"
>
{{ okText }}
</AButton>
</div>
</div>
</ADrawer>
</template>
<script lang="ts" setup>
import { computed } from 'vue'
import BasicModal from '@/components/BasicModal.vue'
import { ACTION_SHEET_HEIGHT } from '@/constants/actionSheet'
2026-06-03 17:51:27 +03:30
import { ACTION_SHEET_Z_INDEX } from '@/constants/overlayZIndex'
2026-05-31 11:51:52 +03:30
import { isMobile } from '@core/utils/is'
interface Props {
visible?: boolean
title?: string
modalWidth?: string
loading?: boolean
drawerHeight?: string
cancelText?: string
showButton?: boolean
showCancel?: boolean
showOk?: boolean
okText?: string
}
const props = withDefaults(defineProps<Props>(), {
visible: false,
title: '',
modalWidth: '36rem',
loading: false,
drawerHeight: ACTION_SHEET_HEIGHT,
cancelText: 'بازگشت',
showButton: false,
showCancel: true,
showOk: true,
okText: 'ثبت'
})
const emit = defineEmits<{
(e: 'update:visible', value: boolean): void
(e: 'update:show', value: boolean): void
(e: 'ok'): void
(e: 'cancel'): void
(e: 'close'): void
}>()
const isMobileView = computed(() => isMobile.value)
const overlayKey = computed(() => (isMobileView.value ? 'drawer' : 'modal'))
const visibleProxy = computed({
get: () => props.visible,
set: (value: boolean) => {
emit('update:visible', value)
emit('update:show', value)
}
})
function handleCancel() {
emit('cancel')
emit('close')
visibleProxy.value = false
}
</script>
<style lang="less">
.basic-action-sheet {
.ant-drawer-content {
border-radius: 16px 16px 0 0;
overflow: hidden;
}
.ant-drawer-body {
padding: 0;
height: 100%;
}
}
.basic-action-sheet__container {
height: 100%;
min-height: 100%;
display: flex;
flex-direction: column;
}
.basic-action-sheet__content {
flex: 1;
overflow-y: auto;
padding: 0 16px 12px;
}
.basic-action-sheet__footer {
position: sticky;
bottom: 0;
z-index: 2;
background: #fff;
padding: 8px 16px calc(16px + env(safe-area-inset-bottom));
border-top: 1px solid #f0f0f0;
}
</style>