tethys.backend/resources/js/Components/CardBox.vue
2023-03-03 16:54:28 +01:00

112 lines
2.2 KiB
Vue

<script setup>
import { mdiCog } from '@mdi/js'
import { computed, useSlots } from 'vue'
import BaseIcon from '@/Components/BaseIcon.vue'
const props = defineProps({
title: {
type: String,
default: null
},
icon: {
type: String,
default: null
},
headerIcon: {
type: String,
default: null
},
rounded: {
type: String,
default: 'rounded-xl'
},
hasTable: Boolean,
empty: Boolean,
form: Boolean,
hoverable: Boolean,
modal: Boolean
})
const emit = defineEmits(['header-icon-click', 'submit'])
const is = computed(() => props.form ? 'form' : 'div')
const slots = useSlots()
const footer = computed(() => slots.footer && !!slots.footer())
const componentClass = computed(() => {
const base = [
props.rounded,
props.modal ? 'dark:bg-slate-900' : 'dark:bg-slate-900/70'
]
if (props.hoverable) {
base.push('hover:shadow-lg transition-shadow duration-500')
}
return base
})
const computedHeaderIcon = computed(() => props.headerIcon ?? mdiCog)
const headerIconClick = () => {
emit('header-icon-click')
}
const submit = e => {
emit('submit', e)
}
</script>
<template>
<component
:is="is"
:class="componentClass"
class="bg-white flex flex-col"
@submit="submit"
>
<header
v-if="title"
class="flex items-stretch border-b border-gray-100 dark:border-slate-800"
>
<div
class="flex items-center py-3 grow font-bold"
:class="[ icon ? 'px-4' : 'px-6' ]"
>
<BaseIcon
v-if="icon"
:path="icon"
class="mr-3"
/>
{{ title }}
</div>
<button
class="flex items-center py-3 px-4 justify-center ring-blue-700 focus:ring"
@click="headerIconClick"
>
<BaseIcon :path="computedHeaderIcon" />
</button>
</header>
<div
v-if="empty"
class="text-center py-24 text-gray-500 dark:text-slate-400"
>
<p>Nothing's here…</p>
</div>
<div
v-else
class="flex-1"
:class="{'p-6':!hasTable}"
>
<slot />
</div>
<div
v-if="footer"
class="p-6 border-t border-gray-100 dark:border-slate-800"
>
<slot name="footer" />
</div>
</component>
</template>