Skip to content

Commit

Permalink
feat(components): product category section (#36)
Browse files Browse the repository at this point in the history
* feat(productcategory): style category section

* test(productcategory): fix failing tests

* fix(productcategory): error when no abstract

* feat(prodcutcategory): add caching

* fix(productcategory): missing type

* refactor(productcategory): extract product filtering to utils

* test(mocks): add missing utils function to mocks

---------

Co-authored-by: Jonas Scholz <[email protected]>
  • Loading branch information
lksmsr and Code42Cate authored Feb 23, 2023
1 parent 96e23aa commit 7f5114c
Show file tree
Hide file tree
Showing 9 changed files with 110 additions and 11 deletions.
2 changes: 1 addition & 1 deletion components/Elements/RichTextElement.vue
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const richtTextElementComponent = computed(() => {
case "link":
return resolveComponent("ElementsLink");
case "list":
return resolveComponent("ElementsList");
return resolveComponent("ElementsUnorderedList");
case "block":
return resolveComponent("ElementsRichText");
case "paragraph":
Expand Down
File renamed without changes.
6 changes: 5 additions & 1 deletion components/Section/Product.vue
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,18 @@
<h3 class="bg-black p-2 text-sm font-bold uppercase text-white">
Delivery
</h3>
<ElementsRichText :richtext="currentDataset?.data['tt_delivery']" />
<ElementsRichText
v-if="currentDataset?.data['tt_delivery']"
:richtext="currentDataset?.data['tt_delivery']"
/>
</div>

<div>
<h3 class="bg-black p-2 text-sm font-bold uppercase text-white">
Installation
</h3>
<ElementsRichText
v-if="currentDataset?.data['tt_installation']"
:richtext="currentDataset?.data['tt_installation']"
/>
</div>
Expand Down
54 changes: 47 additions & 7 deletions components/Section/ProductCategory.vue
Original file line number Diff line number Diff line change
@@ -1,13 +1,53 @@
<template>
<div
class="border bg-orange-200 p-4 font-bold"
data-testid="productCategorySection"
>
Product Category
<div data-testid="productCategorySection">
<div v-if="!pending" class="grid gap-4 sm:grid-cols-2 lg:grid-cols-4">
<NuxtLink
v-for="product in products"
:key="product.id"
class="h-40"
:to="product.route"
>
<div class="relative h-40 overflow-hidden">
<div
class="absolute inset-0 z-10 transform bg-black bg-opacity-70 p-8 text-white opacity-0 transition-opacity duration-500 ease-in-out hover:opacity-100"
>
<h3 class="text-lg font-bold">{{ product.data["tt_name"] }}</h3>
<p class="h-16 overflow-hidden text-xs text-gray-200">
{{ product.data["tt_abstract"]?.substring(0, 45) }}...
</p>
</div>
<ElementsImage
v-if="product.data['tt_teaser_image']"
class="absolute top-0 left-0 h-40 w-full object-cover"
:image="product.data['tt_teaser_image']"
/>
</div>
</NuxtLink>
</div>
</div>
</template>

<script setup lang="ts">
import { DataEntries } from "fsxa-api";
defineProps<{ data: DataEntries }>();
import { DataEntries, Dataset } from "fsxa-api";
const props = defineProps<{ data: DataEntries }>();
const { $fsxaApi } = useNuxtApp();
const { activeLocale } = useLocale();
const { findCachedProductsByRoute, addToCachedProducts } = useContent();
const currentRoute = decodeURIComponent(useRoute().path);
const { data: products, pending } = useAsyncData(async () => {
const cachedProducts = findCachedProductsByRoute(currentRoute);
if (cachedProducts) return cachedProducts;
const filterParams = props.data["filterParams"];
const items = await fetchProducts(
$fsxaApi,
activeLocale.value!,
filterParams?.category
);
addToCachedProducts(currentRoute, items);
return items as Dataset[];
});
</script>
13 changes: 13 additions & 0 deletions composables/content.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,27 @@ export function useContent() {
if (!cachedPages.value[route]) cachedPages.value[route] = data;
}

const cachedProducts = useState<{
[caasId: string]: Dataset[];
}>("cachedDatasets", () => ({}));

function findCachedProductsByRoute(route: string) {
return cachedProducts.value[route];
}
function addToCachedProducts(route: string, data: Dataset[]) {
if (!cachedProducts.value[route]) cachedProducts.value[route] = data;
}

return {
currentPage,
currentDataset,
cachedPages,
cachedDatasets,
addToCachedPages,
addToCachedDatasets,
addToCachedProducts,
findCachedPageByRoute,
findCachedDatasetByRoute,
findCachedProductsByRoute,
};
}
2 changes: 1 addition & 1 deletion tests/components/PageBodyContent/Section.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/**
* @vitest-environment jsdom
*/
import { Page, Dataset } from "fsxa-api";
import { vi, it, expect, describe, beforeEach } from "vitest";
import { render, cleanup } from "@testing-library/vue";
import Section from "../../../components/PageBodyContent/Section.vue";
Expand All @@ -9,7 +10,6 @@ import { createSection } from "../../testutils/createSection";
import { createPage } from "../../testutils/createPage";
import { renderConfig } from "../../testutils/renderConfig"; // registers custom components
import * as content from "../../../composables/content";
import { Page, Dataset } from "fsxa-api";

describe("Section", () => {
const mockedContent = {
Expand Down
7 changes: 6 additions & 1 deletion tests/testutils/nuxtMocks.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { FetchElementParams } from "fsxa-api/dist/types";
import { FetchByFilterParams, FetchElementParams } from "fsxa-api";
import appConfig from "../fixtures/appConfig.json";
import runtimeConfig from "../fixtures/runtimeConfig.json";
import toplevelDE from "../fixtures/toplevelNavigation_de_DE.json";
Expand All @@ -13,6 +13,7 @@ import {
fetchTopLevelNavigation,
fetchNavigationItemFromRoute,
fetchPageFromNavigationItem,
fetchProducts,
getLocaleFromNavigationItem,
} from "../../utils/fsxa";

Expand Down Expand Up @@ -51,6 +52,9 @@ export function useNuxtApp() {
fetchProjectProperties: (_config: { locale: string }) =>
projectProperties,
fetchElement: (_config: FetchElementParams) => page,
fetchByFilter: (_config: FetchByFilterParams) => ({
items: [],
}),
},
};
}
Expand Down Expand Up @@ -99,6 +103,7 @@ export {
fetchTopLevelNavigation,
fetchNavigationItemFromRoute,
fetchPageFromNavigationItem,
fetchProducts,
useContent,
useNavigationData,
useProjectProperties,
Expand Down
36 changes: 36 additions & 0 deletions utils/fsxa.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
LogicalQueryOperatorEnum,
Dataset,
Page,
QueryBuilderQuery,
} from "fsxa-api";

export const fetchDatasetByRoute = async (
Expand Down Expand Up @@ -169,3 +170,38 @@ export const getTranslatedRouteFromNavItem = async (

return { route, dataset };
};

export const fetchProducts = async (
api: FSXAProxyApi,
locale: string,
category?: string
) => {
const filters: QueryBuilderQuery[] = [
{
field: "entityType",
operator: ComparisonQueryOperatorEnum.EQUALS,
value: "product",
},
{
field: "schema",
operator: ComparisonQueryOperatorEnum.EQUALS,
value: "products",
},
];

if (category) {
filters.push({
field: "formData.tt_categories.value.identifier",
operator: ComparisonQueryOperatorEnum.EQUALS,
value: category,
});
}

const { items } = await api.fetchByFilter({
filters,
locale,
pagesize: 10,
});

return items as Dataset[];
};
1 change: 1 addition & 0 deletions vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export default defineConfig({
"fetchTopLevelNavigation",
"fetchNavigationItemFromRoute",
"fetchPageFromNavigationItem",
"fetchProducts",
"getLocaleFromNavigationItem",
],
},
Expand Down

0 comments on commit 7f5114c

Please sign in to comment.