first commit
This commit is contained in:
202
src/components/Dialogs/ActionDialog.vue
Normal file
202
src/components/Dialogs/ActionDialog.vue
Normal file
@ -0,0 +1,202 @@
|
||||
<script setup lang="ts">
|
||||
import { Dialog, DialogPanel, DialogTitle, TransitionChild, TransitionRoot } from '@headlessui/vue';
|
||||
import {
|
||||
CheckIcon,
|
||||
ExclamationTriangleIcon, InformationCircleIcon, QuestionMarkCircleIcon,
|
||||
} from '@heroicons/vue/24/outline'
|
||||
import { ref, watch } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
open: Boolean,
|
||||
title: String,
|
||||
message: String,
|
||||
cancelText: {
|
||||
type: String,
|
||||
default: 'Batal',
|
||||
},
|
||||
confirmText: {
|
||||
type: String,
|
||||
default: 'Oke',
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: 'normal',
|
||||
},
|
||||
});
|
||||
const emits = defineEmits(['onClose', 'onCancel', 'onConfirm']);
|
||||
const open = ref(props.open)
|
||||
const title = ref(props.title)
|
||||
const message = ref(props.message)
|
||||
const cancelText = ref(props.cancelText)
|
||||
const confirmText = ref(props.confirmText)
|
||||
const type = ref(props.type)
|
||||
|
||||
function close() {
|
||||
open.value = false;
|
||||
emits('onClose', false);
|
||||
}
|
||||
|
||||
function handleOnCancel() {
|
||||
emits('onCancel');
|
||||
close();
|
||||
}
|
||||
|
||||
function handleOnConfirm() {
|
||||
emits('onConfirm');
|
||||
close();
|
||||
}
|
||||
|
||||
watch(() => props.open, (value) => {
|
||||
open.value = value;
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- Log Out Dialog -->
|
||||
<TransitionRoot as="template" :show="open">
|
||||
<Dialog as="div" class="relative z-20" @close="close">
|
||||
<TransitionChild as="template" enter="ease-out duration-300" enter-from="opacity-0" enter-to="opacity-100"
|
||||
leave="ease-in duration-200" leave-from="opacity-100" leave-to="opacity-0">
|
||||
<div class="fixed inset-0 transition-opacity bg-gray-500 bg-opacity-75" />
|
||||
</TransitionChild>
|
||||
|
||||
<div class="fixed inset-0 z-10 overflow-y-auto">
|
||||
<div class="flex items-center justify-center min-h-full p-4 text-center sm:p-0">
|
||||
<TransitionChild as="template" enter="ease-out duration-300"
|
||||
enter-from="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
||||
enter-to="opacity-100 translate-y-0 sm:scale-100" leave="ease-in duration-200"
|
||||
leave-from="opacity-100 translate-y-0 sm:scale-100"
|
||||
leave-to="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95">
|
||||
<DialogPanel
|
||||
:class="[type === 'error' || type === 'warning' ? 'sm:max-w-lg' : 'sm:max-w-sm sm:p-6', 'relative overflow-hidden text-left transition-all transform bg-white rounded-lg shadow-xl sm:my-8 sm:w-full']">
|
||||
<!-- Body Section -->
|
||||
<div v-if="type === 'error'" class="px-4 pt-5 pb-4 bg-white sm:p-6 sm:pb-4">
|
||||
<div class="sm:flex sm:items-start">
|
||||
<div
|
||||
class="flex items-center justify-center flex-shrink-0 w-12 h-12 mx-auto bg-red-100 rounded-full sm:mx-0 sm:h-10 sm:w-10">
|
||||
<ExclamationTriangleIcon class="w-6 h-6 text-red-600" aria-hidden="true" />
|
||||
</div>
|
||||
<div class="mt-3 text-center sm:ml-4 sm:mt-0 sm:text-left">
|
||||
<DialogTitle as="h3" class="text-base font-semibold leading-6 text-gray-900">
|
||||
{{ title }}
|
||||
</DialogTitle>
|
||||
<div class="mt-2">
|
||||
<p class="text-sm text-gray-500">
|
||||
{{ message }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else-if="type === 'warning'" class="px-4 pt-5 pb-4 bg-white sm:p-6 sm:pb-4">
|
||||
<div class="sm:flex sm:items-start">
|
||||
<div
|
||||
class="flex items-center justify-center flex-shrink-0 w-12 h-12 mx-auto bg-orange-100 rounded-full sm:mx-0 sm:h-10 sm:w-10">
|
||||
<QuestionMarkCircleIcon class="w-6 h-6 text-orange-600" aria-hidden="true" />
|
||||
</div>
|
||||
<div class="mt-3 text-center sm:ml-4 sm:mt-0 sm:text-left">
|
||||
<DialogTitle as="h3" class="text-base font-semibold leading-6 text-gray-900">
|
||||
{{ title }}
|
||||
</DialogTitle>
|
||||
<div class="mt-2">
|
||||
<p class="text-sm text-gray-500">
|
||||
{{ message }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else-if="type === 'info'">
|
||||
<div class="flex items-center justify-center w-12 h-12 mx-auto bg-blue-100 rounded-full">
|
||||
<InformationCircleIcon class="w-6 h-6 text-blue-600" aria-hidden="true" />
|
||||
</div>
|
||||
<div class="mt-3 text-center sm:mt-5">
|
||||
<DialogTitle as="h3" class="text-lg font-medium leading-6 text-gray-900">
|
||||
{{ title }}
|
||||
</DialogTitle>
|
||||
<div class="mt-2">
|
||||
<p class="text-sm text-gray-500">
|
||||
{{ message }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else-if="type === 'success'">
|
||||
<div class="flex items-center justify-center w-12 h-12 mx-auto bg-green-100 rounded-full">
|
||||
<CheckIcon class="w-6 h-6 text-green-600" aria-hidden="true" />
|
||||
</div>
|
||||
<div class="mt-3 text-center sm:mt-5">
|
||||
<DialogTitle as="h3" class="text-lg font-medium leading-6 text-gray-900">
|
||||
{{ title }}
|
||||
</DialogTitle>
|
||||
<div class="mt-2">
|
||||
<p class="text-sm text-gray-500">
|
||||
{{ message }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div class="mt-3 text-center sm:mt-5">
|
||||
<DialogTitle as="h3" class="text-lg font-medium leading-6 text-gray-900">
|
||||
{{ title }}
|
||||
</DialogTitle>
|
||||
<div class="mt-2">
|
||||
<p class="text-sm text-gray-500">
|
||||
{{ message }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Footer Section -->
|
||||
<div v-if="type === 'error'" class="px-4 py-3 bg-gray-50 sm:flex sm:flex-row-reverse sm:px-6">
|
||||
<button type="button"
|
||||
class="inline-flex justify-center w-full px-3 py-2 text-sm font-semibold text-white bg-red-600 rounded-md shadow-sm hover:bg-red-500 sm:ml-3 sm:w-auto"
|
||||
@click="handleOnConfirm()">{{ confirmText }}</button>
|
||||
<button type="button"
|
||||
class="inline-flex justify-center w-full px-3 py-2 mt-3 text-sm font-semibold text-gray-900 bg-white rounded-md shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50 sm:mt-0 sm:w-auto"
|
||||
@click="handleOnCancel()" ref="cancelButtonRef">
|
||||
{{ cancelText }}
|
||||
</button>
|
||||
</div>
|
||||
<div v-else-if="type === 'warning'"
|
||||
class="px-4 py-3 bg-gray-50 sm:flex sm:flex-row-reverse sm:px-6">
|
||||
<button type="button"
|
||||
class="inline-flex justify-center w-full px-3 py-2 text-sm font-semibold text-white bg-orange-600 rounded-md shadow-sm hover:bg-orange-500 sm:ml-3 sm:w-auto"
|
||||
@click="handleOnConfirm()">{{ confirmText }}</button>
|
||||
<button type="button"
|
||||
class="inline-flex justify-center w-full px-3 py-2 mt-3 text-sm font-semibold text-gray-900 bg-white rounded-md shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50 sm:mt-0 sm:w-auto"
|
||||
@click="handleOnCancel()" ref="cancelButtonRef">
|
||||
{{ cancelText }}
|
||||
</button>
|
||||
</div>
|
||||
<div v-else-if="type === 'info'" class="mt-5 sm:mt-6">
|
||||
<button type="button"
|
||||
class="inline-flex justify-center w-full px-4 py-2 text-base font-medium text-white bg-blue-600 border border-transparent rounded-md shadow-sm hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 sm:text-sm"
|
||||
@click="handleOnConfirm()">
|
||||
{{ confirmText }}
|
||||
</button>
|
||||
</div>
|
||||
<div v-else-if="type === 'success'" class="mt-5 sm:mt-6">
|
||||
<button type="button"
|
||||
class="inline-flex justify-center w-full px-4 py-2 text-base font-medium text-white bg-indigo-600 border border-transparent rounded-md shadow-sm hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 sm:text-sm"
|
||||
@click="handleOnConfirm()">
|
||||
{{ confirmText }}
|
||||
</button>
|
||||
</div>
|
||||
<div v-else class="mt-5 sm:mt-6 sm:grid sm:grid-flow-row-dense sm:grid-cols-2 sm:gap-3">
|
||||
<button type="button"
|
||||
class="inline-flex justify-center w-full px-4 py-2 text-base font-medium text-white bg-indigo-600 border border-transparent rounded-md shadow-sm hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 sm:col-start-2 sm:text-sm"
|
||||
@click="handleOnConfirm()">{{ confirmText }}</button>
|
||||
<button type="button"
|
||||
class="inline-flex justify-center w-full px-4 py-2 mt-3 text-base font-medium text-gray-700 bg-white border border-gray-300 rounded-md shadow-sm hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 sm:col-start-1 sm:mt-0 sm:text-sm"
|
||||
@click="handleOnCancel()" ref="cancelButtonRef">{{ cancelText }}</button>
|
||||
</div>
|
||||
</DialogPanel>
|
||||
</TransitionChild>
|
||||
</div>
|
||||
</div>
|
||||
</Dialog>
|
||||
</TransitionRoot>
|
||||
</template>
|
148
src/components/Dialogs/ChangePasswordDialog.vue
Normal file
148
src/components/Dialogs/ChangePasswordDialog.vue
Normal file
@ -0,0 +1,148 @@
|
||||
<script setup lang="ts">
|
||||
import { Dialog, DialogPanel, DialogTitle, TransitionChild, TransitionRoot } from '@headlessui/vue';
|
||||
import {
|
||||
CheckIcon,
|
||||
ExclamationTriangleIcon, InformationCircleIcon, QuestionMarkCircleIcon,
|
||||
} from '@heroicons/vue/24/outline'
|
||||
import { XMarkIcon } from '@heroicons/vue/24/solid';
|
||||
import { ref, watch } from 'vue';
|
||||
import InputText from '../InputText.vue';
|
||||
import ButtonPrimary from '../ButtonPrimary.vue';
|
||||
import { dispatchNotification } from '../Notification';
|
||||
|
||||
const props = defineProps({ open: Boolean });
|
||||
const emits = defineEmits(['onClose']);
|
||||
const open = ref(props.open)
|
||||
const oldPassword = ref('');
|
||||
const password = ref('');
|
||||
const passwordConfirmation = ref('');
|
||||
const isLoading = ref(false);
|
||||
|
||||
function close() {
|
||||
open.value = false;
|
||||
emits('onClose', false);
|
||||
}
|
||||
|
||||
function showLoading() {
|
||||
isLoading.value = true;
|
||||
}
|
||||
|
||||
function hideLoading() {
|
||||
isLoading.value = false;
|
||||
}
|
||||
|
||||
function handleOnChangePassword() {
|
||||
if (oldPassword.value == '') {
|
||||
dispatchNotification({
|
||||
title: 'Peringatan',
|
||||
content: 'Password lama tidak boleh kosong',
|
||||
type: 'error',
|
||||
})
|
||||
} else if (password.value == '') {
|
||||
dispatchNotification({
|
||||
title: 'Peringatan',
|
||||
content: 'Password baru tidak boleh kosong',
|
||||
type: 'error',
|
||||
})
|
||||
} else if (passwordConfirmation.value == '') {
|
||||
dispatchNotification({
|
||||
title: 'Peringatan',
|
||||
content: 'Konfirmasi password tidak boleh kosong',
|
||||
type: 'error',
|
||||
})
|
||||
} else if (password.value != passwordConfirmation.value) {
|
||||
dispatchNotification({
|
||||
title: 'Peringatan',
|
||||
content: 'Password baru dan konfirmasi password tidak sama',
|
||||
type: 'error',
|
||||
})
|
||||
} else if (oldPassword.value == password.value) {
|
||||
dispatchNotification({
|
||||
title: 'Peringatan',
|
||||
content: 'Password baru tidak boleh sama dengan password lama',
|
||||
type: 'error',
|
||||
})
|
||||
} else {
|
||||
showLoading();
|
||||
setTimeout(() => {
|
||||
hideLoading();
|
||||
close();
|
||||
}, 15000);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
watch(() => props.open, (value) => {
|
||||
open.value = value;
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- Log Out Dialog -->
|
||||
<TransitionRoot as="template" :show="open">
|
||||
<Dialog as="div" class="relative z-20" @close="close">
|
||||
<TransitionChild as="template" enter="ease-out duration-300" enter-from="opacity-0" enter-to="opacity-100"
|
||||
leave="ease-in duration-200" leave-from="opacity-100" leave-to="opacity-0">
|
||||
<div class="fixed inset-0 transition-opacity bg-gray-500 bg-opacity-75" />
|
||||
</TransitionChild>
|
||||
|
||||
<div class="fixed inset-0 z-10 overflow-y-auto">
|
||||
<div class="flex items-center justify-center min-h-full p-4 text-center sm:p-0">
|
||||
<TransitionChild as="template" enter="ease-out duration-300"
|
||||
enter-from="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
||||
enter-to="opacity-100 translate-y-0 sm:scale-100" leave="ease-in duration-200"
|
||||
leave-from="opacity-100 translate-y-0 sm:scale-100"
|
||||
leave-to="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95">
|
||||
<DialogPanel
|
||||
class="relative p-4 overflow-hidden text-left transition-all transform bg-white rounded-lg shadow-xl sm:max-w-sm sm:p-6 sm:my-8 sm:w-full">
|
||||
<form @submit.prevent="handleOnChangePassword" class="flex flex-col">
|
||||
<div class="absolute top-0 right-0 pt-4 pr-4 ">
|
||||
<button type="button"
|
||||
class="text-gray-400 bg-white rounded-md hover:text-gray-500 focus:outline-none focus:ring-0"
|
||||
@click="close">
|
||||
<span class="sr-only">Close</span>
|
||||
<XMarkIcon class="w-6 h-6" aria-hidden="true" />
|
||||
</button>
|
||||
</div>
|
||||
<div>
|
||||
<DialogTitle as="h4" class="font-medium leading-6 text-gray-900 text-md">
|
||||
Ubah Password
|
||||
</DialogTitle>
|
||||
<div class="flex flex-col mt-2">
|
||||
<label for="password" class="mb-2 text-xs font-medium text-dark">
|
||||
Password Lama
|
||||
</label>
|
||||
<InputText type="password" class-name="mb-3 text-sm placeholder:text-sm"
|
||||
placeholder="Masukan Password lama" :value="oldPassword"
|
||||
@update:value="oldPassword = $event" />
|
||||
|
||||
<label for="password" class="mb-2 text-xs font-medium text-dark">
|
||||
Password Baru
|
||||
</label>
|
||||
<InputText class-name="mb-3 text-sm placeholder:text-sm" type="password"
|
||||
placeholder="Masukan Password baru" :value="password"
|
||||
@update:value="password = $event" />
|
||||
|
||||
<label for="password" class="mb-2 text-xs font-medium text-dark">
|
||||
Konfirmasi Password
|
||||
</label>
|
||||
<InputText class-name="mb-3 text-sm placeholder:text-sm" type="password"
|
||||
placeholder="Konfirmasi Password" :value="passwordConfirmation"
|
||||
@update:value="passwordConfirmation = $event" />
|
||||
</div>
|
||||
</div>
|
||||
<!-- Footer Section -->
|
||||
<div class="mt-2">
|
||||
<ButtonPrimary
|
||||
class-name="inline-flex justify-center w-full px-4 py-2 font-medium text-white bg-indigo-600 border border-transparent rounded-md shadow-sm text-md focus:outline-none focus:ring-0 sm:text-sm"
|
||||
type="submit" label="Ubah Password" :disabled="isLoading" :is-loading="isLoading" />
|
||||
</div>
|
||||
</form>
|
||||
</DialogPanel>
|
||||
</TransitionChild>
|
||||
</div>
|
||||
</div>
|
||||
</Dialog>
|
||||
</TransitionRoot>
|
||||
</template>
|
Reference in New Issue
Block a user