adding country flags, html meta stuff, web routes file, js components
This commit is contained in:
59
src/resources/js/Components/Modals/Cofnirm.vue
Normal file
59
src/resources/js/Components/Modals/Cofnirm.vue
Normal file
@@ -0,0 +1,59 @@
|
||||
<script setup>
|
||||
import { reactive } from 'vue'
|
||||
import Modal from './Modal.vue'
|
||||
|
||||
const emit = defineEmits(['close'])
|
||||
|
||||
const props = defineProps({
|
||||
show: {
|
||||
default: false
|
||||
},
|
||||
maxWidth: {
|
||||
default: '2xl'
|
||||
},
|
||||
closeable: {
|
||||
default: true
|
||||
},
|
||||
})
|
||||
|
||||
// computed properties
|
||||
|
||||
// watchers
|
||||
|
||||
// lifecycle hooks
|
||||
|
||||
// methods
|
||||
function close() {
|
||||
emit('close')
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<modal :show="show" :max-width="maxWidth" :closeable="closeable" @close="close">
|
||||
<div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
|
||||
<div class="sm:flex sm:items-start">
|
||||
<div class="mx-auto shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-red-100 sm:mx-0 sm:h-10 sm:w-10">
|
||||
<svg class="h-6 w-6 text-red-600" stroke="currentColor" fill="none" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"/>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
|
||||
<h3 class="text-lg">
|
||||
<slot name="title"></slot>
|
||||
</h3>
|
||||
|
||||
<div class="mt-2">
|
||||
<slot name="content"></slot>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-row justify-end px-6 py-4 bg-gray-100 text-right">
|
||||
<slot name="footer">
|
||||
</slot>
|
||||
</div>
|
||||
</modal>
|
||||
</template>
|
||||
101
src/resources/js/Components/Modals/ConfirmPassword.vue
Normal file
101
src/resources/js/Components/Modals/ConfirmPassword.vue
Normal file
@@ -0,0 +1,101 @@
|
||||
<script setup>
|
||||
import { reactive, ref } from 'vue'
|
||||
|
||||
const emit = defineEmits(['confirmed'])
|
||||
|
||||
const props = defineProps({
|
||||
title: {
|
||||
default: 'Confirm Password',
|
||||
},
|
||||
content: {
|
||||
default: 'For your security, please confirm your password to continue.',
|
||||
},
|
||||
button: {
|
||||
default: 'Confirm',
|
||||
},
|
||||
})
|
||||
|
||||
let confirmingPassword = false
|
||||
let form = {
|
||||
password: '',
|
||||
error: '',
|
||||
}
|
||||
|
||||
// computed properties
|
||||
|
||||
// watchers
|
||||
|
||||
// lifecycle hooks
|
||||
|
||||
// methods
|
||||
function startConfirmingPassword() {
|
||||
axios.get(route('password.confirmation')).then(resp => {
|
||||
if (resp.data.confirmed) {
|
||||
emit('confirmed')
|
||||
} else {
|
||||
confirmingPassword = true
|
||||
setTimeout(() => $refs.password.focus(), 250)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function confirmPassword() {
|
||||
form.processing = true;
|
||||
|
||||
axios.post(route('password.confirm'), {
|
||||
password: form.password,
|
||||
}).then(() => {
|
||||
form.processing = false
|
||||
closeModal()
|
||||
$nextTick(() => emit('confirmed'))
|
||||
}).catch(erro => {
|
||||
form.processing = false;
|
||||
form.error = erro.response.data.errors.password[0]
|
||||
$refs.password.focus()
|
||||
})
|
||||
}
|
||||
|
||||
function closeModal() {
|
||||
confirmingPassword = false
|
||||
form.password = ''
|
||||
form.error = ''
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<span @click="startConfirmingPassword">
|
||||
<slot />
|
||||
</span>
|
||||
|
||||
<jet-dialog-modal :show="confirmingPassword" @close="closeModal">
|
||||
<template #title>
|
||||
{{ title }}
|
||||
</template>
|
||||
|
||||
<template #content>
|
||||
{{ content }}
|
||||
|
||||
<div class="mt-4">
|
||||
<jet-input type="password" class="mt-1 block w-3/4" placeholder="Password"
|
||||
ref="password"
|
||||
v-model="form.password"
|
||||
@keyup.enter="confirmPassword" />
|
||||
|
||||
<jet-input-error :message="form.error" class="mt-2" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #footer>
|
||||
<jet-secondary-button @click="closeModal">
|
||||
Cancel
|
||||
</jet-secondary-button>
|
||||
|
||||
<jet-button class="ml-3" @click="confirmPassword" :class="{ 'opacity-25': form.processing }" :disabled="form.processing">
|
||||
{{ button }}
|
||||
</jet-button>
|
||||
</template>
|
||||
</jet-dialog-modal>
|
||||
</div>
|
||||
</template>
|
||||
48
src/resources/js/Components/Modals/Dialog.vue
Normal file
48
src/resources/js/Components/Modals/Dialog.vue
Normal file
@@ -0,0 +1,48 @@
|
||||
<script setup>
|
||||
import { reactive } from 'vue'
|
||||
import Modal from './Modal.vue'
|
||||
|
||||
const emit = defineEmits(['close'])
|
||||
|
||||
const props = defineProps({
|
||||
show: {
|
||||
default: false
|
||||
},
|
||||
maxWidth: {
|
||||
default: '2xl'
|
||||
},
|
||||
closeable: {
|
||||
default: true
|
||||
},
|
||||
})
|
||||
|
||||
// computed properties
|
||||
|
||||
// watchers
|
||||
|
||||
// lifecycle hooks
|
||||
|
||||
// methods
|
||||
function close() {
|
||||
emit('close')
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<modal :show="show" :max-width="maxWidth" :closeable="closeable" @close="close">
|
||||
<div class="px-6 py-4">
|
||||
<div class="text-lg">
|
||||
<slot name="title"></slot>
|
||||
</div>
|
||||
|
||||
<div class="mt-4">
|
||||
<slot name="content"></slot>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-row justify-end px-6 py-4 bg-gray-100 text-right">
|
||||
<slot name="footer"></slot>
|
||||
</div>
|
||||
</modal>
|
||||
</template>
|
||||
98
src/resources/js/Components/Modals/Modal.vue
Normal file
98
src/resources/js/Components/Modals/Modal.vue
Normal file
@@ -0,0 +1,98 @@
|
||||
<script setup>
|
||||
import { computed, watch, onBeforeMount, onMounted } from 'vue'
|
||||
|
||||
const emit = defineEmits(['close'])
|
||||
|
||||
const props = defineProps({
|
||||
show: {
|
||||
default: false
|
||||
},
|
||||
maxWidth: {
|
||||
default: '2xl'
|
||||
},
|
||||
closeable: {
|
||||
default: true
|
||||
},
|
||||
})
|
||||
|
||||
// computed properties
|
||||
const maxWidthClass = computed(() => {
|
||||
return {
|
||||
'sm': 'sm:max-w-sm',
|
||||
'md': 'sm:max-w-md',
|
||||
'lg': 'sm:max-w-lg',
|
||||
'xl': 'sm:max-w-xl',
|
||||
'2xl': 'sm:max-w-2xl',
|
||||
}[props.maxWidth]
|
||||
})
|
||||
|
||||
// watchers
|
||||
watch(() => props.show, (newShow) => {
|
||||
if (newShow) {
|
||||
document.body.style.overflow = 'hidden'
|
||||
} else {
|
||||
document.body.style.overflow = null
|
||||
}
|
||||
})
|
||||
/*watch(props.show, (newShow) => {
|
||||
if (newShow) {
|
||||
document.body.style.overflow = 'hidden'
|
||||
} else {
|
||||
document.body.style.overflow = null
|
||||
}
|
||||
})*/
|
||||
|
||||
// lifecycle hooks
|
||||
onBeforeMount(() => {
|
||||
document.removeEventListener('keydown', closeOnEscape)
|
||||
document.body.style.overflow = null
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
document.addEventListener('keydown', closeOnEscape)
|
||||
})
|
||||
|
||||
// methods
|
||||
function close() {
|
||||
if (props.closeable) {
|
||||
emit('close')
|
||||
}
|
||||
}
|
||||
|
||||
function closeOnEscape(e) {
|
||||
if (e.key === 'Escape' && props.show) {
|
||||
close()
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<teleport to="body">
|
||||
<transition leave-active-class="duration-200">
|
||||
<div v-show="show" class="fixed inset-0 overflow-y-auto px-4 py-6 sm:px-0 z-50" scroll-region>
|
||||
<transition enter-active-class="ease-out duration-300"
|
||||
enter-from-class="opacity-0"
|
||||
enter-to-class="opacity-100"
|
||||
leave-active-class="ease-in duration-200"
|
||||
leave-from-class="opacity-100"
|
||||
leave-to-class="opacity-0">
|
||||
<div v-show="show" class="fixed inset-0 transform transition-all" @click="close">
|
||||
<div class="absolute inset-0 bg-gray-500 opacity-75"></div>
|
||||
</div>
|
||||
</transition>
|
||||
|
||||
<transition enter-active-class="ease-out duration-300"
|
||||
enter-from-class="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
||||
enter-to-class="opacity-100 translate-y-0 sm:scale-100"
|
||||
leave-active-class="ease-in duration-200"
|
||||
leave-from-class="opacity-100 translate-y-0 sm:scale-100"
|
||||
leave-to-class="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95">
|
||||
<div v-show="show" class="mb-6 bg-white rounded-lg overflow-hidden shadow-xl transform transition-all sm:w-full sm:mx-auto" :class="maxWidthClass">
|
||||
<slot v-if="show"></slot>
|
||||
</div>
|
||||
</transition>
|
||||
</div>
|
||||
</transition>
|
||||
</teleport>
|
||||
</template>
|
||||
Reference in New Issue
Block a user