feat: filter details for zero values (#364)

* filter details for zero values

* ensure exhaustive checks

* update event listener to only bind when collapsable
This commit is contained in:
Hayden 2023-03-22 19:05:13 -08:00 committed by GitHub
parent 840d220d4f
commit 40e76bac0c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 95 additions and 20 deletions

View file

@ -1,16 +1,46 @@
<template> <template>
<div class="card bg-base-100 shadow-xl sm:rounded-lg"> <div class="card bg-base-100 shadow-xl sm:rounded-lg">
<div v-if="$slots.title" class="px-4 py-5 sm:px-6"> <div v-if="$slots.title" class="px-4 py-5 sm:px-6">
<h3 class="text-lg font-medium leading-6"> <component :is="collapsable ? 'button' : 'div'" v-on="collapsable ? { click: toggle } : {}">
<slot name="title"></slot> <h3 class="text-lg font-medium leading-6 flex items-center">
</h3> <slot name="title"></slot>
<p v-if="$slots.subtitle" class="mt-1 max-w-2xl text-sm text-gray-500"> <template v-if="collapsable">
<slot name="subtitle"></slot> <span class="ml-2 swap swap-rotate" :class="`${collapsed ? 'swap-active' : ''}`">
</p> <Icon class="h-6 w-6 swap-on" name="mdi-chevron-right" />
<template v-if="$slots['title-actions']"> <Icon class="h-6 w-6 swap-off" name="mdi-chevron-down" />
<slot name="title-actions"></slot> </span>
</template> </template>
</h3>
</component>
<div>
<p v-if="$slots.subtitle" class="mt-1 max-w-2xl text-sm text-gray-500">
<slot name="subtitle"></slot>
</p>
<template v-if="$slots['title-actions']">
<slot name="title-actions"></slot>
</template>
</div>
</div>
<div
:class="{
'max-h-screen': !collapsed,
'max-h-0': collapsed,
}"
class="transition-[max-height] duration-200 overflow-hidden"
>
<slot />
</div> </div>
<slot />
</div> </div>
</template> </template>
<script setup lang="ts">
defineProps<{
collapsable?: boolean;
}>();
function toggle() {
collapsed.value = !collapsed.value;
}
const collapsed = ref(false);
</script>

View file

@ -36,3 +36,23 @@ export type Detail = BaseDetail & {
export type AnyDetail = DateDetail | CurrencyDetail | LinkDetail | MarkdownDetail | Detail; export type AnyDetail = DateDetail | CurrencyDetail | LinkDetail | MarkdownDetail | Detail;
export type Details = Array<Detail | AnyDetail>; export type Details = Array<Detail | AnyDetail>;
export function filterZeroValues(details: Details): Details {
return details.filter(detail => {
switch (detail.type) {
case "date":
return validDate(detail.text);
case "currency":
return !!detail.text;
case "link":
return !!detail.text && !!detail.href;
case undefined:
case "text":
case "markdown":
return detail.text !== null && detail.text !== "" && detail.text !== undefined;
default:
console.warn("Unknown detail type (this should never happen)", detail);
return false;
}
});
}

View file

@ -1,5 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { AnyDetail, Detail, Details } from "~~/components/global/DetailsSection/types"; import { AnyDetail, Detail, Details, filterZeroValues } from "~~/components/global/DetailsSection/types";
import { ItemAttachment } from "~~/lib/api/types/data-contracts"; import { ItemAttachment } from "~~/lib/api/types/data-contracts";
definePageMeta({ definePageMeta({
@ -121,7 +121,7 @@
return []; return [];
} }
return [ const ret: Details = [
{ {
name: "Description", name: "Description",
type: "markdown", type: "markdown",
@ -176,6 +176,12 @@
}; };
}), }),
]; ];
if (!preferences.value.showEmpty) {
return filterZeroValues(ret);
}
return ret;
}); });
const showAttachments = computed(() => { const showAttachments = computed(() => {
@ -256,6 +262,10 @@
text: item.value?.warrantyDetails || "", text: item.value?.warrantyDetails || "",
}); });
if (!preferences.value.showEmpty) {
return filterZeroValues(details);
}
return details; return details;
}); });
@ -267,7 +277,7 @@
}); });
const purchaseDetails = computed<Details>(() => { const purchaseDetails = computed<Details>(() => {
return [ const v: Details = [
{ {
name: "Purchased From", name: "Purchased From",
text: item.value?.purchaseFrom || "", text: item.value?.purchaseFrom || "",
@ -284,6 +294,12 @@
date: true, date: true,
}, },
]; ];
if (!preferences.value.showEmpty) {
return filterZeroValues(v);
}
return v;
}); });
const showSold = computed(() => { const showSold = computed(() => {
@ -294,7 +310,7 @@
}); });
const soldDetails = computed<Details>(() => { const soldDetails = computed<Details>(() => {
return [ const v: Details = [
{ {
name: "Sold To", name: "Sold To",
text: item.value?.soldTo || "", text: item.value?.soldTo || "",
@ -311,6 +327,12 @@
date: true, date: true,
}, },
]; ];
if (!preferences.value.showEmpty) {
return filterZeroValues(v);
}
return v;
}); });
const confirm = useConfirm(); const confirm = useConfirm();
@ -442,7 +464,7 @@
<section> <section>
<div class="space-y-6"> <div class="space-y-6">
<BaseCard v-if="!hasNested"> <BaseCard v-if="!hasNested" collapsable>
<template #title> Details </template> <template #title> Details </template>
<template #title-actions> <template #title-actions>
<div class="flex flex-wrap justify-between items-center mt-2 gap-4"> <div class="flex flex-wrap justify-between items-center mt-2 gap-4">
@ -469,9 +491,9 @@
</div> </div>
</BaseCard> </BaseCard>
<BaseCard v-if="showAttachments"> <BaseCard v-if="showAttachments" collapsable>
<template #title> Attachments </template> <template #title> Attachments </template>
<DetailsSection :details="attachmentDetails"> <DetailsSection v-if="attachmentDetails.length > 0" :details="attachmentDetails">
<template #manuals> <template #manuals>
<ItemAttachmentsList <ItemAttachmentsList
v-if="attachments.manuals.length > 0" v-if="attachments.manuals.length > 0"
@ -501,19 +523,22 @@
/> />
</template> </template>
</DetailsSection> </DetailsSection>
<div v-else>
<p class="text-base-content/70 px-6 pb-4">No attachments found</p>
</div>
</BaseCard> </BaseCard>
<BaseCard v-if="showPurchase"> <BaseCard v-if="showPurchase" collapsable>
<template #title> Purchase Details </template> <template #title> Purchase Details </template>
<DetailsSection :details="purchaseDetails" /> <DetailsSection :details="purchaseDetails" />
</BaseCard> </BaseCard>
<BaseCard v-if="showWarranty"> <BaseCard v-if="showWarranty" collapsable>
<template #title> Warranty Details </template> <template #title> Warranty Details </template>
<DetailsSection :details="warrantyDetails" /> <DetailsSection :details="warrantyDetails" />
</BaseCard> </BaseCard>
<BaseCard v-if="showSold"> <BaseCard v-if="showSold" collapsable>
<template #title> Sold Details </template> <template #title> Sold Details </template>
<DetailsSection :details="soldDetails" /> <DetailsSection :details="soldDetails" />
</BaseCard> </BaseCard>