-
Remi PLANEL authoredRemi PLANEL authored
GenericItem.vue 5.24 KiB
<template>
<v-card :flat="flat">
<error-alert v-if="hasError" :error-message="error"></error-alert>
<template v-if="hasItem">
<v-skeleton-loader
v-if="loading"
elevation="2"
:type="skeletonLoaderType"
></v-skeleton-loader>
<v-card v-else flat class="mt-3" :color="color">
<v-toolbar flat :color="toolbarColor">
<v-btn nuxt x-small text class="mr-3" @click="goToItemListLocation()"
><v-icon left>mdi-arrow-left</v-icon>{{ itemListLabel }}</v-btn
>
<v-divider vertical inset></v-divider>
<v-toolbar-title class="text-uppercase ml-3">
<v-btn
v-if="item.title"
text
class="text-h5"
@click="goToItemLocation()"
>
{{ item.title }}</v-btn
><small v-if="item.subtitle" class="text--secondary">
{{ item.subtitle }}</small
>
</v-toolbar-title>
<v-spacer></v-spacer>
<template v-if="itemActions">
<template v-if="$vuetify.breakpoint.mobile">
<v-menu bottom left>
<template v-slot:activator="{ on, attrs }">
<v-btn icon v-bind="attrs" v-on="on" @click.stop>
<v-icon>mdi-dots-vertical</v-icon>
</v-btn>
</template>
<v-list>
<template v-for="itemAction in itemActions">
<v-list-item
v-if="itemAction.can(item)"
:key="itemAction.title"
@click.stop="itemAction.action(item)"
>
<v-list-item-title
><v-icon left>{{ itemAction.icon }}</v-icon>
{{ itemAction.title }}</v-list-item-title
>
</v-list-item>
</template>
</v-list>
</v-menu>
</template>
<template v-else>
<v-tooltip
v-for="itemAction in itemActions"
:key="itemAction.id"
bottom
>
<template v-slot:activator="{ on, attrs }">
<v-btn
v-if="itemAction.can(item)"
:color="$vuetify.theme.dark ? null : 'secondary'"
icon
large
v-bind="attrs"
v-on="on"
@click.stop="itemAction.action(item)"
>
<v-icon>{{ itemAction.icon }}</v-icon>
</v-btn>
</template>
<span>{{ itemAction.title }}</span></v-tooltip
>
</template>
</template>
<!-- chips -->
<template v-if="!$vuetify.breakpoint.mobile">
<v-spacer></v-spacer>
<v-chip
v-if="item.creation_date"
class="ma-2"
color="secondary"
small
>
{{ item.creation_date.toDateString() }}
</v-chip>
<v-chip small color="accent">{{ itemType }}</v-chip>
</template>
</v-toolbar>
<v-card-text>
<v-card flat :color="color">
<v-toolbar dense flat :color="color"
><v-toolbar-title>Description</v-toolbar-title>
</v-toolbar>
<v-card-text v-if="item.description">
<slot name="description">
{{ item.description }}
</slot>
</v-card-text>
</v-card>
</v-card-text>
<slot name="content"></slot>
</v-card>
</template>
</v-card>
</template>
<script>
import ErrorAlert from '@/components/ErrorAlert'
export default {
components: {
ErrorAlert,
},
props: {
itemListLocation: { type: Object, default: () => null },
itemLocation: { type: Object, default: () => null },
itemType: { type: String, default: 'item' },
itemActions: { type: Array, default: () => null },
item: { type: Object, default: () => null },
loading: { type: Boolean, default: false },
skeletonLoaderType: {
type: String,
default:
'card-heading, list-item-avatar-two-line@3, article, table-heading, table-thead, table-tfoot',
},
color: { type: String, default: null },
flat: { type: Boolean, default: false },
},
data() {
return {
error: null,
}
},
computed: {
hasError() {
return this.error !== null
},
hasItem() {
return this.item !== null
},
itemListLabel() {
return this?.itemListLocation?.label || 'items'
},
// TODO : choose color for toolbar
toolbarColor() {
return this.$vuetify.theme.dark ? null : this.color
},
},
methods: {
goToItemListLocation() {
if (this.itemListLocation) {
this.$router.push(this.itemListLocation)
} else {
this.error = `There is no ${this.itemType} list location defined`
}
},
goToItemLocation() {
if (this.itemLocation) {
this.$router.push(this.itemLocation)
} else {
this.error = 'There is no location defined for the current item'
}
},
},
}
</script>