Untitled
unknown
plain_text
2 years ago
8.5 kB
14
Indexable
<template>
<transition name="modal">
<div :style="`z-index: ${zIndex}`" class="modal-mask">
<div class="modal-wrapper">
<template v-if="modalType === 'custom-slot'">
<div class="modal-container" :style="{ width: width }">
<div class="modal-header font-16 font-weight-bold" v-if="!noHeader">
<slot name="header">
{{ title }}
</slot>
<slot name="close">
<img
@click="closeModal()"
class="icon-close icon-close-custom-slot"
style="cursor: pointer"
src="/assets/frontend/images/symbols/icon-close.png"
alt="close"
/>
</slot>
</div>
<div class="modal-body">
<slot name="body"> default body </slot>
</div>
<div class="modal-footer" v-if="!noFooter">
<slot name="footer">
<!-- Default Footer -->
<button @click="handleConfirm()"
class="w-100 modal-button-footer"
:style="`background-color: ${confirmButtonColor}`"
>
{{ buttonTitle }}
</button>
</slot>
</div>
</div>
</template>
<template v-else>
<div class="modals-wrapper" :style="`width: ${customWidth};`">
<div class="header" v-if="!noHeader">
<div @click.prevent="closeModal()" class="close-wrapper">
<slot name="close">
<img
class="icon-close"
src="/assets/frontend/images/symbols/icon-close.png"
alt="close"
/>
</slot>
</div>
</div>
<template v-if="modalType != 'information'">
<slot name="icon">
<div
class="icon-modal d-flex justify-content-center"
>
<img
v-if="modalType === 'success'"
src="/assets/frontend/images/symbols/icon-success.png"
alt="success"
/>
<img
v-else-if="modalType === 'retry'"
src="/assets/frontend/images/symbols/icon-warning.png"
alt="retry"
>
<img
v-else-if="modalType === 'failed'"
src="/assets/frontend/images/symbols/icon-failed.png"
alt="failed"
>
</div>
</slot>
<slot name="title">
<div
class="title d-flex justify-content-center"
>
<p>{{ title }}</p>
</div>
</slot>
</template>
<slot name="description">
<div
class="description d-flex justify-content-center"
:class="modalType === 'information' ? 'font-14 text-btg' : ''"
>
<p v-html="description"></p>
</div>
</slot>
<slot name="button">
<div v-if="modalType != 'information'" class="modal-buttons">
<button
v-if="
modalType === 'retry' ||
modalType === 'failed' ||
modalType === 'success'
"
@click="handleConfirm()"
class="w-100 modal-button-warning"
:style="`background-color: ${confirmButtonColor}`"
>
{{ buttonTitle }}
</button>
<div
v-else-if="modalType === 'confirm'"
class="d-flex justify-content-center"
style="gap: 20px"
>
<button
@click="handleCancel()"
class="button-no"
:style="`background-color: ${cancelButtonColor}`"
>
{{ cancelButtonTitle }}
</button>
<button
@click="handleConfirm()"
class="button-yes"
:style="`background-color: ${confirmButtonColor}`"
>
{{ confirmButtonTitle }}
</button>
</div>
</div>
</slot>
</div>
</template>
</div>
</div>
</transition>
</template>
<script>
export default {
props: {
title: {
type: String,
default: "",
},
description: {
type: String,
default: "",
},
buttonTitle: {
type: String,
default: "Coba Lagi",
},
confirmButtonColor: {
type: String,
default: "#ff8136"
},
cancelButtonColor: {
type: String,
default: "rgb(221, 51, 51)"
},
modalType: {
type: String,
default: "failed",
required: true
// retry => Try Again => handleConfirm()
// failed => OK => handleConfirm()
// success => OK => handleConfirm()
// confirm => Yes and No => handleConfirm() dan handleCancel()
// information => without button => -
// custom-slot => Modal Custom With Slot => if(noFooter == false) handleConfirm()
// if (noFooter === true) => without button
},
noFooter: {
type: Boolean,
default: false,
},
noHeader: {
type: Boolean,
default: false,
},
width: {
type: String,
default: "520px",
},
customWidth: {
type: String,
default: "282px",
},
cancelButtonTitle: {
type: String,
default: "Batal"
},
confirmButtonTitle: {
type: String,
default: "Ok"
},
zIndex: {
type: Number,
default: 1060
}
},
methods: {
closeModal() {
this.$emit("close");
},
handleConfirm() {
this.$emit("handleConfirm");
},
handleCancel() {
this.$emit("handleCancel");
},
},
};
</script>
<style scoped>
/* Animation */
@keyframes fade-in {
0% {
transform: scale(70%) translate(-50%, -50%);
}
50% {
transform: scale(110%) translate(-50%, -50%);
}
100% {
transform: scale(100%) translate(-50%, -50%);
}
}
@keyframes fade-out {
0% {
transform: scale(100%) translate(-50%, -50%);
}
50% {
transform: scale(110%) translate(-50%, -50%);
}
100% {
transform: scale(70%) translate(-50%, -50%);
}
}
@keyframes bounce {
0% {
transform: scale(70%);
}
50% {
transform: scale(110%);
}
100% {
transform: scale(100%);
}
}
/* Animation */
.modal-container {
animation: bounce .4s ease-in;
}
.modal-header,
.modal-body,
.modal-footer {
padding: 20px 40px !important;
}
.modal-body {
max-height: 600px;
overflow-y: scroll;
overflow-x: hidden;
}
.modal-header,
.modal-footer {
border: none !important;
}
.modal-footer > * {
margin: 0px;
}
.modals-wrapper {
position: fixed;
height: auto;
background-color: #fff;
box-shadow: 2px 1px 10px 0px rgba(0, 0, 0, 0.15);
border-radius: 25px;
left: 50%;
top: 50%;
z-index: 9999;
transform: translate(-50%, -50%);
padding: 20px 30px;
animation: fade-in .2s ease-in;
}
.close-wrapper {
position: absolute;
top: -11px;
right: -11px;
display: grid;
place-items: center;
background-color: #fff;
border-radius: 50%;
width: 30px;
height: 30px;
box-shadow: 2px 1px 10px 0px rgba(0, 0, 0, 0.25);
cursor: pointer;
}
.icon-close {
width: 15px;
height: 15px;
}
.title p {
color: #ff7a00;
font-size: 14px;
font-weight: 700;
margin-top: 12px;
}
.icon-modal > img {
width: 60px;
height: 60px;
}
.description {
margin-top: 10px;
font-size: 12px;
text-align: center;
color: #404040;
}
.modal-buttons button {
margin-top: 20px;
border: none;
height: 35px;
border-radius: 8px;
color: #fff;
font-size: 12px;
font-weight: 700;
}
.modal-button-warning {
background: #ff8136;
}
.button-yes,
.button-no {
padding: 0.625em 1.1em;
}
.button-no, .button-yes {
/* background-color: rgb(221, 51, 51); */
min-width: 80px;
}
.modal-button-footer {
/* background: #ff8136; */
border: none;
padding: 14px;
border-radius: 12px;
color: #fff;
font-size: 16px;
font-weight: 700;
}
.icon-close-custom-slot {
filter: brightness(0) invert(1);
}
@media screen and (max-width: 768px) {
.modal-body {
max-height: 80%;
}
.modal-header,
.modal-body,
.modal-footer {
padding: 20px 16px !important;
}
}
</style>
Editor is loading...