Skip to content

Commit

Permalink
feat: manufacturer information (#695)
Browse files Browse the repository at this point in the history
* feat: implement manufacturer information

* fix: manufacturer updates and increase package version

* fix: trailing comma for lang json

* fix: changelog lint

* chore: lang change

* chore: add translatation labels
  • Loading branch information
doproiescu-plenty authored Sep 26, 2024
1 parent 523a769 commit b62282e
Show file tree
Hide file tree
Showing 16 changed files with 225 additions and 11 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<template>
<div v-if="manufacturerName || manufacturerExternalName">
<p v-if="manufacturerName">{{ manufacturerName }}</p>
<p v-if="manufacturerExternalName">{{ manufacturerExternalName }}</p>
</div>
<div v-else>
{{ t('manufacturer.noInformation') }}
</div>
</template>

<script setup lang="ts">
import { computed } from 'vue';
import { productGetters } from '@plentymarkets/shop-api';
import type { ManufacturerInformationProps } from '~/components/ManufacturerInformation/types';
const props = defineProps<ManufacturerInformationProps>();
const { t } = useI18n();
const manufacturerName = computed(() => productGetters.getManufacturerName(props.product));
const manufacturerExternalName = computed(() => productGetters.getManufacturerExternalName(props.product));
</script>
5 changes: 5 additions & 0 deletions apps/web/components/ManufacturerInformation/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import type { Product } from '@plentymarkets/shop-api';

export type ManufacturerInformationProps = {
product: Product;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<template>
<div v-if="hasAnyInfo">
<p v-if="manufacturerResponsibleInfo.name">{{ manufacturerResponsibleInfo.name }}</p>
<p v-if="manufacturerResponsibleInfo.street || manufacturerResponsibleInfo.houseNo">
{{ manufacturerResponsibleInfo.street }} {{ manufacturerResponsibleInfo.houseNo }}
</p>
<p
v-if="
manufacturerResponsibleInfo.postCode || manufacturerResponsibleInfo.town || manufacturerResponsibleInfo.country
"
>
{{ manufacturerResponsibleInfo.postCode }} {{ manufacturerResponsibleInfo.town }},&nbsp;
{{ manufacturerResponsibleInfo.country }}
</p>
<p v-if="manufacturerResponsibleInfo.phoneNo">{{ t('phone') }}: {{ manufacturerResponsibleInfo.phoneNo }}</p>
<p v-if="manufacturerResponsibleInfo.email">{{ t('email') }}: {{ manufacturerResponsibleInfo.email }}</p>
</div>
<div v-else>
{{ t('manufacturer.noResponsibleInformation') }}
</div>
</template>

<script setup lang="ts">
import { computed } from 'vue';
import { productGetters } from '@plentymarkets/shop-api';
import type { ManufacturerResponsibleInfoProps } from '~/components/ManufacturerResponsibleInfo/types';
const props = defineProps<ManufacturerResponsibleInfoProps>();
const { t } = useI18n();
const manufacturerResponsibleInfo = computed(() => ({
name: productGetters.getManufacturerResponsibleName(props.product),
street: productGetters.getManufacturerResponsibleStreet(props.product),
houseNo: productGetters.getManufacturerResponsibleHouseNo(props.product),
postCode: productGetters.getManufacturerResponsiblePostCode(props.product),
town: productGetters.getManufacturerResponsibleTown(props.product),
country: productGetters.getManufacturerResponsibleCountry(props.product),
email: productGetters.getManufacturerResponsibleEmail(props.product),
phoneNo: productGetters.getManufacturerResponsiblePhoneNo(props.product),
}));
const hasAnyInfo = computed(() => {
const info = manufacturerResponsibleInfo.value;
return Object.values(info).some(Boolean);
});
</script>
5 changes: 5 additions & 0 deletions apps/web/components/ManufacturerResponsibleInfo/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import type { Product } from '@plentymarkets/shop-api';

export type ManufacturerResponsibleInfoProps = {
product: Product;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
<template>
<UiOverlay :visible="open">
<SfDrawer
ref="productLegalDrawerRef"
v-model="open"
:placement="placement"
:class="[
'bg-neutral-50',
'border',
'border-gray-300',
'z-50',
{ 'min-w-[400px]': placement === 'left' || placement === 'right' },
]"
>
<header class="flex items-center justify-between px-10 py-6 bg-primary-500">
<div class="flex items-center text-white">{{ t('productLegalDetailsHeader') }}</div>
<UiButton square variant="tertiary" class="text-white" @click="open = false">
<SfIconClose />
</UiButton>
</header>

<div
ref="tablistRef"
role="tablist"
aria-label="Select tab"
aria-orientation="horizontal"
class="flex gap-2 border-b border-b-neutral-200 p-4 overflow-x-auto [&::-webkit-scrollbar]:hidden [-ms-overflow-style:none] [scrollbar-width:none]"
>
<UiButton
v-for="(tab, index) in tabs"
:key="tab.label"
type="button"
role="tab"
:variant="isActiveTab(index) ? 'primary' : 'secondary'"
:aria-selected="isActiveTab(index)"
:aria-controls="`tabpanel-${index}`"
:disabled="tab.disabled"
@click="setActiveTab(index)"
>
{{ tab.label }}
</UiButton>
</div>

<div
v-for="(tab, index) in tabs"
:key="tab.label"
role="tabpanel"
:id="`tabpanel-${index}`"
:aria-labelledby="`tab-${index}`"
v-show="isActiveTab(index)"
class="p-4"
>
<component :is="tab.component" :product="product" />
</div>
</SfDrawer>
</UiOverlay>
</template>

<script setup lang="ts">
import { SfDrawer, SfIconClose, SfDrawerPlacement, useTrapFocus } from '@storefront-ui/vue';
import { ProductLegalDetailsProps } from '~/components/ProductLegalDetailsDrawer/types';
import ManufacturerResponsibleInfo from '~/components/ManufacturerResponsibleInfo/ManufacturerResponsibleInfo.vue';
import ManufacturerInformation from '~/components/ManufacturerInformation/ManufacturerInformation.vue';
defineProps<ProductLegalDetailsProps>();
const { t } = useI18n();
const placement = ref<`${SfDrawerPlacement}`>('right');
const tabs = [
{ label: t('manufacturer.euResponsibleTabName'), component: ManufacturerResponsibleInfo, disabled: false },
{ label: t('manufacturer.manufacturerTabName'), component: ManufacturerInformation, disabled: false },
];
const activeTabIndex = ref(0);
const isActiveTab = (index: number) => activeTabIndex.value === index;
const setActiveTab = (index: number) => {
activeTabIndex.value = index;
};
const productLegalDrawerRef = ref();

Check warning on line 82 in apps/web/components/ProductLegalDetailsDrawer/ProductLegalDetailsDrawer.vue

View workflow job for this annotation

GitHub Actions / Lint

The variable `productLegalDrawerRef` should be named `productLegalDrawerReference`. A more descriptive name will do too
const { open } = useProductLegalDetailsDrawer();
useTrapFocus(productLegalDrawerRef, { activeState: open });
</script>
5 changes: 5 additions & 0 deletions apps/web/components/ProductLegalDetailsDrawer/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import type { Product } from '@plentymarkets/shop-api';

export type ProductLegalDetailsProps = {
product: Product;
};
6 changes: 1 addition & 5 deletions apps/web/components/ReviewsAccordion/ReviewsAccordion.vue
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
<template>
<div
ref="reviewArea"
class="relative col-span-5 md:sticky md:top-10 h-fit"
:class="{ 'pointer-events-none opacity-50': loadingReviews }"
>
<div ref="reviewArea" class="relative col-span-5 h-fit" :class="{ 'pointer-events-none opacity-50': loadingReviews }">
<SfLoaderCircular v-if="loadingReviews" class="absolute top-[130px] right-0 left-0 m-auto z-[999]" size="2xl" />

<div data-testid="reviews-accordion" id="customerReviewsAccordion">
Expand Down
2 changes: 2 additions & 0 deletions apps/web/composables/useProductLegalDetailsDrawer/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './types';
export * from './useProductLegalDetailsDrawer';
8 changes: 8 additions & 0 deletions apps/web/composables/useProductLegalDetailsDrawer/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export type OpenDrawer = () => void;

export interface UseProductLegalDetailsMethods {
open: Readonly<Ref<boolean>>;
openDrawer: OpenDrawer;
}

export type UseProductLegalDetailsMethodsReturn = () => UseProductLegalDetailsMethods;
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { UseProductLegalDetailsMethodsReturn } from './types';

const open = ref(false);

const openDrawer = () => {
open.value = true;
};

export const useProductLegalDetailsDrawer: UseProductLegalDetailsMethodsReturn = () => {
return { open, openDrawer };
};
10 changes: 10 additions & 0 deletions apps/web/lang/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,7 @@
"customerReviews": "Kundenrezensionen",
"createCustomerReview": "Bewertung abgeben",
"customerReviewsNone": "Es hat noch niemand eine Bewertung für dieses Produkt abgegeben",
"legalDetails": "TBD",
"loadingReviews": "Kundenrezensionen werden geladen...",
"reviewsCount": "{Anzahl} Bewertungen",
"showAllReviews": "Alle Bewertungen anzeigen",
Expand Down Expand Up @@ -692,6 +693,9 @@
"lastName": "Nachname",
"email": "E-Mail"
},
"productLegalDetailsHeader": "TBD",
"email": "E-Mail",
"phone": "Telefonnummer",
"coupon": {
"name": "Gutschein",
"title": "Haben sie einen Gutscheincode?",
Expand Down Expand Up @@ -843,5 +847,11 @@
},
"addressContainer": {
"sameAsShippingAddress": "Entspricht der Lieferadresse"
},
"manufacturer": {
"noResponsibleInformation": "TBD",
"noInformation": "TBD",
"euResponsibleTabName": "TBD",
"manufacturerTabName": "TBD"
}
}
10 changes: 10 additions & 0 deletions apps/web/lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,7 @@
"customerReviews": "Customer reviews",
"createCustomerReview": "Create review",
"customerReviewsNone": "Nobody has submitted a review for this product yet",
"legalDetails": "EU responsible person - click for details",
"loadingReviews": "Loading Reviews...",
"reviewsCount": "{count} reviews",
"showAllReviews": "Show all reviews",
Expand Down Expand Up @@ -692,6 +693,9 @@
"lastName": "Last Name",
"email": "Email"
},
"productLegalDetailsHeader": "Product Legal Details",
"email": "Email",
"phone": "Phone",
"coupon": {
"name": "Coupon",
"title": "Have a coupon code?",
Expand Down Expand Up @@ -843,5 +847,11 @@
},
"addressContainer": {
"sameAsShippingAddress": "Same as shipping address"
},
"manufacturer": {
"noResponsibleInformation": "No Information available for responsible person",
"noInformation": "No Information available for manufacturer",
"euResponsibleTabName": "EU Responsible person",
"manufacturerTabName": "Manufacturer"
}
}
9 changes: 9 additions & 0 deletions apps/web/pages/product/[slug].vue
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@
:product="product"
:total-reviews="reviewGetters.getTotalReviews(countsProductReviews)"
/>

<p @click="openDrawer()" class="font-bold leading-6 w-full p-4 flex cursor-pointer">
<span>{{ t('legalDetails') }}</span>
<SfIconChevronRight />
</p>
</section>
</div>
<section class="mx-4 mt-28 mb-20">
Expand All @@ -34,17 +39,20 @@
</NarrowContainer>

<UiReviewModal />
<ProductLegalDetailsDrawer v-if="open" :product="product" />
</NuxtLayout>
</template>

<script setup lang="ts">
import { SfIconChevronRight } from '@storefront-ui/vue';
import { Product, productGetters, reviewGetters, categoryTreeGetters } from '@plentymarkets/shop-api';
definePageMeta({
layout: false,
path: '/:slug*_:itemId',
});
const { t } = useI18n();
const route = useRoute();
const { setCurrentProduct } = useProducts();
const { setProductMetaData } = useStructuredData();
Expand All @@ -54,6 +62,7 @@ const { productParams, productId } = createProductParams(route.params);
const { data: product, fetchProduct, setProductMeta, setBreadcrumbs, breadcrumbs } = useProduct(productId);
const { data: productReviews, fetchProductReviews } = useProductReviews(Number(productId));
const { data: categoryTree } = useCategoryTree();
const { open, openDrawer } = useProductLegalDetailsDrawer();
const countsProductReviews = computed(() => reviewGetters.getReviewCounts(productReviews.value));
Expand Down
1 change: 1 addition & 0 deletions docs/changelog/changelog_en.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
- Added PayPal pay later banners on product, cart, checkout and quick checkout.
- Updated the PayPal form for credit card information.
- It is possible to disable api caching with query param `noCache=1` for debugging purposes.
- Added Manufacturer and EU Responsible information to product page.

#### SEO

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
"lhci:mobile": "lhci autorun"
},
"dependencies": {
"@plentymarkets/shop-api": "^0.62.0",
"@plentymarkets/shop-api": "^0.64.0",
"@types/applepayjs": "^14.0.8",
"@vee-validate/nuxt": "^4.13.2",
"@vee-validate/yup": "^4.13.2",
Expand Down
10 changes: 5 additions & 5 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4237,7 +4237,7 @@ __metadata:
"@nuxt/test-utils": ^3.13.1
"@nuxtjs/turnstile": ^0.8.0
"@paypal/paypal-js": 8.1.0
"@plentymarkets/shop-api": ^0.62.0
"@plentymarkets/shop-api": ^0.64.0
"@types/applepayjs": ^14.0.8
"@types/uuid": ^9.0.8
"@vee-validate/nuxt": ^4.13.2
Expand Down Expand Up @@ -4269,14 +4269,14 @@ __metadata:
languageName: unknown
linkType: soft

"@plentymarkets/shop-api@npm:^0.62.0":
version: 0.62.0
resolution: "@plentymarkets/shop-api@npm:0.62.0::__archiveUrl=https%3A%2F%2Fnpm.pkg.github.com%2Fdownload%2F%40plentymarkets%2Fshop-api%2F0.62.0%2Fa224326ec09b4da3e60ea38cb77d069bb947425b"
"@plentymarkets/shop-api@npm:^0.64.0":
version: 0.64.0
resolution: "@plentymarkets/shop-api@npm:0.64.0::__archiveUrl=https%3A%2F%2Fnpm.pkg.github.com%2Fdownload%2F%40plentymarkets%2Fshop-api%2F0.64.0%2Fec04299ace9c7413367291f892907f2776ba6f8a"
dependencies:
"@vue-storefront/middleware": ^3.10.0
axios: ^1.7.5
consola: ^3.2.3
checksum: 2080c4c19d0f513f9d81c1e8cdfa8533bdce7f1daa7364b04b22425b0e5a415a2104612875090acf2096ee64af5521ab341c73a1611fa3b25a8ed246de1bf8f7
checksum: 3570b77d1e2c29dcd577bda60db1adc64ecd9a8454a387f1452760276a64a56f427bf2cf87e2091b7bc0bbcd1fd2185c0697206a71a453903c3b89e0c04e35a2
languageName: node
linkType: hard

Expand Down

0 comments on commit b62282e

Please sign in to comment.