tethys.backend/resources/js/Components/CardBox.vue

82 lines
2.3 KiB
Vue
Raw Permalink Normal View History

2023-03-03 15:54:28 +00:00
<script setup>
2023-03-17 15:13:37 +00:00
import { mdiCog } from '@mdi/js';
import { computed, useSlots } from 'vue';
import BaseIcon from '@/Components/BaseIcon.vue';
2023-03-03 15:54:28 +00:00
const props = defineProps({
2023-03-17 15:13:37 +00:00
title: {
type: String,
default: null,
},
icon: {
type: String,
default: null,
},
headerIcon: {
type: String,
default: null,
},
rounded: {
type: String,
default: 'rounded-xl',
},
hasFormData: Boolean,
empty: Boolean,
form: Boolean,
hoverable: Boolean,
modal: Boolean,
});
2023-03-03 15:54:28 +00:00
2023-03-17 15:13:37 +00:00
const emit = defineEmits(['header-icon-click', 'submit']);
2023-03-03 15:54:28 +00:00
2023-03-17 15:13:37 +00:00
const is = computed(() => (props.form ? 'form' : 'div'));
2023-03-03 15:54:28 +00:00
2023-03-17 15:13:37 +00:00
const slots = useSlots();
2023-03-03 15:54:28 +00:00
2023-03-17 15:13:37 +00:00
const footer = computed(() => slots.footer && !!slots.footer());
2023-03-03 15:54:28 +00:00
const componentClass = computed(() => {
2023-03-17 15:13:37 +00:00
const base = [props.rounded, props.modal ? 'dark:bg-slate-900' : 'dark:bg-slate-900/70'];
2023-03-03 15:54:28 +00:00
2023-03-17 15:13:37 +00:00
if (props.hoverable) {
base.push('hover:shadow-lg transition-shadow duration-500');
}
2023-03-03 15:54:28 +00:00
2023-03-17 15:13:37 +00:00
return base;
});
2023-03-03 15:54:28 +00:00
2023-03-17 15:13:37 +00:00
const computedHeaderIcon = computed(() => props.headerIcon ?? mdiCog);
2023-03-03 15:54:28 +00:00
const headerIconClick = () => {
2023-03-17 15:13:37 +00:00
emit('header-icon-click');
};
2023-03-03 15:54:28 +00:00
2023-03-17 15:13:37 +00:00
const submit = (e) => {
emit('submit', e);
};
2023-03-03 15:54:28 +00:00
</script>
<template>
2023-03-17 15:13:37 +00:00
<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}"> -->
<div v-else class="flex-1" :class="[!hasFormData && 'p-6']">
<slot />
</div>
<div v-if="footer" class="p-6 border-t border-gray-100 dark:border-slate-800">
<slot name="footer" />
</div>
</component>
2023-03-03 15:54:28 +00:00
</template>