mirror of
https://github.com/hay-kot/homebox.git
synced 2024-11-22 08:35:43 +00:00
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:
parent
840d220d4f
commit
40e76bac0c
3 changed files with 95 additions and 20 deletions
|
@ -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>
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
|
@ -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>
|
||||||
|
|
Loading…
Reference in a new issue