base_ui/components/global/BaseModalV2.vue

406 lines
10 KiB
Vue
Raw Permalink Normal View History

2025-02-01 09:34:55 +00:00
<template>
<!-- #region modal -->
<transition name="my-modal-fade">
<div class="my-modal-backdrop">
<div
class="my-modal"
@keydown.esc="close()"
tabindex="1000"
@keydown.enter.ctrl="save()"
role="dialog"
:class="modalSize"
aria-labelledby="my-modalTitle"
aria-describedby="my-modalDescription"
style="border-radius: 10px; padding: 0 5px 10px 5px"
:style="{
overflow: $attrs.overflow,
width: $attrs.width,
height: $attrs.height,
}"
>
<!-- #region header -->
<header class="my-modal-header text-dark p-3" id="my-modalTitle">
<div class="d-flex flex-grow-1 font-weight-semi-bold">
<!-- <slot name="header-title"></slot> -->
<slot></slot>
<div class="flex-grow-1 mx-3">
<button-component
@click="loadFromVuexClipboard()"
buttonText="بارگزاری از حافظه"
v-tooltip="'بارگذاری آخرین مورد کپی شده'"
classes="btn btn-primary"
v-if="showLoadButton"
>
</button-component>
<button-component
@click="copyToVuexClipboard()"
classes="btn btn-success mr-2"
buttonText="ذخیره در حافظه"
v-tooltip="'ذخیره در حافظه محلی'"
v-if="showCopyButton"
>
</button-component>
</div>
<div
v-if="showNextBtns"
class="d-flex col-3 justify-content-end pl-0"
>
<div class="main-page_date-icon-right col-auto">
<span
class="d-flex btn text-title-nextItem"
title="قبلی"
@click.prevent="prevItem()"
>
<svg class="icon icon-Component-358--1">
<use xlink:href="#icon-Component-358--1"></use>
</svg>
<span class="nextItem">قبلی</span>
</span>
</div>
<div class="main-page_date-icon-left col-auto pl-0">
<span
class="d-flex btn text-title-prevItem"
title="بعدی"
@click.prevent="nextItem()"
>
<span class="prevItem">بعدی</span>
<svg class="icon icon-Component-359--1">
<use xlink:href="#icon-Component-359--1"></use>
</svg>
</span>
</div>
</div>
<!-- <button
type="button"
class="btn-close"
@click="close"
aria-label="Close my-modal"
>
x
</button> -->
<button
@click.prevent="close"
type="button"
class="close"
data-dismiss="modal"
aria-label="Close"
>
<span aria-hidden="true">&times;</span>
</button>
</div>
</header>
<!-- #endregion header -->
<!-- #region section -->
<section
class="my-modal-body firefox-scrollbar m-2"
id="my-modalDescription"
:key="renderBody"
:style="{ maxHeight: $attrs.maxHeight, minHeight: $attrs.minHeight }"
>
<slot name="body"> </slot>
</section>
<!-- #endregion section -->
<!-- #region footer -->
<footer v-if="hasFooter" class="my-modal-footer p-1 mx-3">
<!-- <slot name="footer"> This is the default footer! </slot> -->
<div class="modal-footer">
<button
v-if="showDeleteButton"
@click.prevent="deleteEmit()"
class="btn delete-btn btn-outline-danger"
type="button"
>
حذف
</button>
<div class="w-100 d-flex justify-content-end align-items-center">
<button
v-if="showCloseButton"
@click.prevent="close()"
type="button"
class="btn btn-default"
data-dismiss="modal"
>
بستن
</button>
<button
v-if="showSaveButton"
@click.prevent="save()"
type="button"
class="btn btn-primary"
>
ذخیره
</button>
</div>
</div>
<div v-if="footerDesc">
{{ footerDesc }}
</div>
<!-- <button
type="button"
class="btn-green"
@click="close"
aria-label="Close my-modal"
>
Close me!
</button> -->
</footer>
<!-- #endregion footer -->
</div>
</div>
</transition>
<!-- #endregion modal -->
</template>
<script>
import { mapState, mapActions } from "pinia";
import { useCommonStore } from "~/stores/commonStore";
import { useAuthStore } from "~/stores/authStore";
/**
* @vue-prop {String} [modalSize="modal-xl"] - اندازه مودال
* @vue-prop {Boolean} [hasFooter=true] - نشان میدهد که آیا مودال دارای فوتر باشد یا خیر
* @vue-prop {String} [modalTitle=""] - عنوان مودال
* @vue-prop {Boolean} [showSaveButton=true] - نشان میدهد که آیا دکمه ذخیره نمایش داده شود یا خیر
* @vue-prop {Boolean} [showCloseButton=true] - نشان میدهد که آیا دکمه بستن نمایش داده شود یا خیر
*
* @vue-data {String} [sub_Title=""] - زیر عنوان
*
* @vue-computed {String} [getComponentName] - نام کامپوننت
*
* @vue-event {Function} SHOW_BASE_MODAL - نمایش مودال پایه
*/
export default {
props: {
modalSize: {
default: "modal-xl",
},
hasFooter: {
default: true,
},
modalTitle: {
default: "",
},
footerDesc: {
default: "",
},
showLoadButton: {
default: false,
},
showCopyButton: {
default: false,
},
showSaveButton: {
default: true,
},
showCloseButton: {
default: true,
},
showDeleteButton: {
default: true,
},
showNextBtns: {
default: false,
},
formData: {
default() {
return {};
},
},
entity: {
default() {
return undefined;
},
},
currentEntityContent: {
default() {
return undefined;
},
},
},
data() {
return {
sub_Title: "",
renderBody: 1,
};
},
computed: {
...mapState(useAuthStore, ["getComponentName"]),
// ...mapState("common", ["lastRecordGetter"]),
},
methods: {
...mapActions(useCommonStore, ["SHOW_BASE_MODAL"]),
// ...mapActions("common", ["lastRecordSetter"]),
prevItem() {
this.$emit("prevItem");
},
nextItem() {
this.$emit("nextItem");
},
loadFromVuexClipboard() {
this.$emit("loadFromVuexClipboard");
// let lastObj = this.lastRecordGetter[this.qruleActiveTabGetter.key];
// if(lastObj.id)
// delete lastObj.id;
// this.formData = lastObj;
// this.renderBody++;
},
copyToVuexClipboard() {
this.$emit("copyToVuexClipboard");
// this.lastRecordSetter({
// [this.qruleActiveTabGetter.key]: structuredClone(this.selectRuleObject),
// });
},
/**
* بستن مدال.
* این متد مدال را بسته و رویداد بستن را از طریق امیت به والد ارسال میکند.
*/
close() {
// this.SHOW_BASE_MODAL(false);
this.$emit("close");
},
/**
* ذخیره تغییرات و بستن مدال.
* این متد تغییرات را ذخیره کرده، مدال را بسته و رویداد ذخیره را از طریق امیت به والد ارسال میکند.
*/
save() {
// this.SHOW_BASE_MODAL(false);
if (this.showSaveButton) this.$emit("save");
},
deleteEmit() {
this.mySwalConfirm({
title: "هشدار!!!",
html: `از حذف اطلاعات جاری اطمینان دارید؟ `,
icon: "warning",
}).then((result) => {
if (result.isConfirmed) {
this.$emit("delete");
}
});
},
},
mounted() {
// window.addEventListener("keydown", this.handleKeyDown);
// this.$nextTick(() => {
// this.$el?.focus();
// });
},
};
</script>
<style lang="scss">
.my-modal-backdrop {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: rgba(0, 0, 0, 0.3);
display: flex;
justify-content: center;
align-items: center;
z-index: 99;
}
.my-modal {
background: #ffffff;
box-shadow: 2px 2px 20px 1px;
overflow-x: auto;
display: flex;
flex-direction: column;
&.modal-sm {
width: 300px;
}
&.modal-lg {
width: 800px;
}
&.modal-xl {
width: 1140px;
}
&.modal-xxl {
width: 1500px;
}
}
.my-modal-header,
.my-modal-footer {
padding: 15px;
display: flex;
}
.my-modal-header {
position: relative;
border-bottom: 1px solid #eeeeee;
color: #4aae9b;
justify-content: space-between;
margin: 0 15px;
}
.my-modal-footer {
/* border-top: 1px solid #eeeeee; */
flex-direction: column;
.modal-footer {
display: flex;
justify-content: space-between;
align-items: center;
}
}
.my-modal-body {
position: relative;
padding: 10px 10px;
overflow-y: auto;
overflow-x: hidden;
// width: 50em;
height: 100%;
min-height: auto;
max-height: 30em;
}
.close {
&:hover {
color: #ef4444 !important;
}
}
.btn-close {
position: absolute;
top: 0;
left: 0;
border: none;
font-size: 20px;
padding: 10px;
cursor: pointer;
font-weight: bold;
color: #4aae9b;
background: transparent;
}
.btn-green {
color: white;
background: #4aae9b;
border: 1px solid #4aae9b;
border-radius: 2px;
}
.my-modal-fade-enter,
.my-modal-fade-leave-to {
opacity: 0;
}
.my-modal-fade-enter-active,
.my-modal-fade-leave-active {
transition: opacity 0.5s ease;
}
</style>