Skip to content

Commit

Permalink
Merge branch 'main' into product-titles
Browse files Browse the repository at this point in the history
  • Loading branch information
doproiescu-plenty authored Oct 31, 2024
2 parents 2ae9ae3 + eb6666d commit 11ed3ac
Show file tree
Hide file tree
Showing 18 changed files with 254 additions and 253 deletions.
1 change: 1 addition & 0 deletions apps/server/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"display": "Server",
"compilerOptions": {
"resolveJsonModule": true,
"lib": ["DOM", "DOM.Iterable", "ES2019"],
"composite": false,
"declaration": false,
Expand Down
37 changes: 0 additions & 37 deletions apps/web/components/HeroContent/HeroContent.vue

This file was deleted.

51 changes: 43 additions & 8 deletions apps/web/components/ui/CartProductCard/CartProductCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,12 @@
{{ n(currentFullPrice || 0, 'currency') }}
</span>
<UiQuantitySelector
ref="quantitySelectorReference"
:disabled="disabled"
@change-quantity="debounceQuantity"
:value="cartGetters.getItemQty(cartItem)"
:value="itemQuantitySelector"
:min-value="productGetters.getMinimumOrderQuantity(cartItem.variation || ({} as Product))"
:max-value="maximumOrderQuantity"
class="mt-4 sm:mt-0"
/>
</div>
Expand All @@ -125,21 +127,25 @@
<script setup lang="ts">
import { productGetters, productBundleGetters, cartGetters } from '@plentymarkets/shop-api';
import { SfLink, SfLoaderCircular, SfIconClose } from '@storefront-ui/vue';
import _ from 'lodash';
import type { CartProductCardProps } from '~/components/ui/CartProductCard/types';
import type { Product } from '@plentymarkets/shop-api';
import _ from 'lodash';
const { cartItem, disabled = false } = defineProps<CartProductCardProps>();
const emit = defineEmits(['load']);
const { addModernImageExtension, getImageForViewport } = useModernImage();
const { setCartItemQuantity, deleteCartItem } = useCart();
const { data: cartData, setCartItemQuantity, deleteCartItem } = useCart();
const { send } = useNotification();
const { t, n } = useI18n();
const localePath = useLocalePath();
const imageLoaded = ref(false);
const img = ref();
const deleteLoading = ref(false);
const emit = defineEmits(['load']);
const { cartItem, disabled = false } = defineProps<CartProductCardProps>();
const quantitySelectorReference = ref(null as any);
const itemQuantitySelector = ref(cartGetters.getItemQty(cartItem));
const maximumOrderQuantity = ref();
onMounted(() => {
const imgElement = (img.value?.$el as HTMLImageElement) || null;
Expand All @@ -156,13 +162,41 @@ onMounted(() => {
}
});
const changeQuantity = async (quantity: string) => {
const handleMaximumQuantityCheck = async (quantityCast: number) => {
if (!cartData.value?.itemQuantity || quantityCast <= cartData.value.itemQuantity) {
maximumOrderQuantity.value = undefined;
return;
}
maximumOrderQuantity.value = cartData.value.itemQuantity;
if (quantitySelectorReference.value) {
const event = new Event('input');
Object.defineProperty(event, 'target', {
value: { value: maximumOrderQuantity.value },
writable: true,
});
quantitySelectorReference.value.handleOnChange(event);
}
await setCartItemQuantity({
quantity: Number(quantity),
quantity: maximumOrderQuantity.value,
cartItemId: cartItem.id,
productId: cartItem.variationId,
});
};
const changeQuantity = async (quantity: string) => {
const quantityCast = Number(quantity);
if (Number.isNaN(quantityCast) || quantityCast === cartData.value.itemQuantity) return;
await setCartItemQuantity({
quantity: quantityCast,
cartItemId: cartItem.id,
productId: cartItem.variationId,
}).then(async () => await handleMaximumQuantityCheck(quantityCast));
};
const deleteItem = async () => {
deleteLoading.value = true;
await deleteCartItem({
Expand All @@ -175,6 +209,7 @@ const deleteItem = async () => {
const currentFullPrice = computed(() => {
return cartGetters.getCartItemPrice(cartItem) * cartGetters.getItemQty(cartItem);
});
const cartItemImage = computed(() => {
if (cartItem && cartItem.variation) {
return getImageForViewport(cartItem.variation, 'CartProductCard');
Expand Down
4 changes: 2 additions & 2 deletions apps/web/components/ui/HeroCarousel/HeroCarousel.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
</template>

<script setup lang="ts">
import { HeroItem } from './types';
import { HeroContentProps } from './types';
import { Swiper, SwiperSlide } from 'swiper/vue';
import { Navigation, Pagination } from 'swiper/modules';
const { handleArrows, onSlideChange } = useCarousel();
Expand All @@ -25,7 +25,7 @@ import '@/assets/libraries/swiper/navigation.min.css';
import '@/assets/libraries/swiper/pagination.min.css';
const { heroItemProps } = defineProps<{
heroItemProps: HeroItem[];
heroItemProps: HeroContentProps[];
}>();
const enableModules = computed(() => heroItemProps.length > 1);
Expand Down
7 changes: 1 addition & 6 deletions apps/web/components/ui/HeroCarousel/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export type SizeKey = 'lg' | 'md' | 'sm' | 'xs';

export type Sizes = Record<SizeKey, { width: string; height: string }>;

export type HeroItem = {
export type HeroContentProps = {
image?: string;
alt?: string;
tagline?: string;
Expand All @@ -21,8 +21,3 @@ export type HeroItem = {
backgroundSizes: Sizes;
actualBackgroundSize: SizeKey;
};

export type HeroCarouselProps = {
background: { image: string; sizes: Sizes };
hero: HeroItem[];
};
4 changes: 2 additions & 2 deletions apps/web/components/ui/HeroContent/HeroContent.vue
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@
</template>

<script setup lang="ts">
import { HeroItem, SizeKey } from '../HeroCarousel/types';
import { HeroContentProps, SizeKey } from '../HeroCarousel/types';
defineProps<{
heroItemProps: HeroItem;
heroItemProps: HeroContentProps;
currentSizeKey: SizeKey;
}>();
</script>
2 changes: 1 addition & 1 deletion apps/web/components/ui/MediaCard/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export type MediaItem = {
export type MediaItemProps = {
text: string;
image: string;
alt: string;
Expand Down
2 changes: 2 additions & 0 deletions apps/web/components/ui/QuantitySelector/QuantitySelector.vue
Original file line number Diff line number Diff line change
Expand Up @@ -98,4 +98,6 @@ const handleOnChange = (event: Event) => {
const nextValue = Number.parseFloat(currentValue);
set(clamp(nextValue, minValue, maxValue));
};
defineExpose({ handleOnChange });
</script>
17 changes: 16 additions & 1 deletion apps/web/composables/useCart/useCart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
SetCartItemQuantityParams,
DeleteCartItemParams,
CartItem,
CartItemError,
} from '@plentymarkets/shop-api';
import {
type UseCartReturn,
Expand Down Expand Up @@ -38,6 +39,10 @@ const migrateVariationData = (oldCart: Cart, nextCart: Cart = {} as Cart): Cart
return nextCart;
};

const isCartItemError = (data: Cart | CartItemError): data is CartItemError => {
return 'availableStock' in data;
};

/**
* @description Composable for managing cart.
* @returns UseCartReturn
Expand Down Expand Up @@ -186,9 +191,19 @@ export const useCart: UseCartReturn = () => {
cartItemId: params.cartItemId,
}),
);

useHandleError(error.value);

state.value.data = migrateVariationData(state.value.data, data?.value?.data) ?? state.value.data;
if (isCartItemError(data.value?.data as unknown as Cart | CartItemError)) {
const { $i18n } = useNuxtApp();
const { send } = useNotification();
const responseData = data?.value?.data as CartItemError;
state.value.data.itemQuantity = responseData.availableStock;

send({ message: $i18n.t('storefrontError.cart.reachedMaximumQuantity'), type: 'warning' });
} else {
state.value.data = migrateVariationData(state.value.data, data?.value?.data as Cart) ?? state.value.data;
}

return state.value.data;
} catch (error) {
Expand Down
74 changes: 74 additions & 0 deletions apps/web/composables/useHomepageData/homepageTemplateData.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
{
"id": 100,
"hero": [
{
"image": {
"lg": "https://cdn02.plentymarkets.com/mevofvd5omld/frontend/homepage-hero-headphones.avif",
"md": "https://cdn02.plentymarkets.com/mevofvd5omld/frontend/headphones-md.avif",
"sm": "https://cdn02.plentymarkets.com/mevofvd5omld/frontend/headphones-sm.avif",
"xs": "https://cdn02.plentymarkets.com/mevofvd5omld/frontend/headphones-xs.avif",
"alt": "Headphones"
},
"tagline": "Feel the music",
"taglineColor": "#000000",
"heading": "Your Sound, Elevated",
"headingColor": "#000000",
"description": "Immerse yourself in rich, crystal-clear audio with our cutting-edge headphones. Designed for the ultimate listening experience, whether you're a casual listener or an audiophile. Discover the perfect blend of style, comfort, and sound quality that elevates your music to new heights.\n\n",
"descriptionColor": "#000000",
"callToAction": "Order Now",
"link": ""
},
{
"image": {
"lg": "https://cdn02.plentymarkets.com/mevofvd5omld/frontend/homepage-hero-headphones.avif",
"md": "https://cdn02.plentymarkets.com/mevofvd5omld/frontend/headphones-md.avif",
"sm": "https://cdn02.plentymarkets.com/mevofvd5omld/frontend/headphones-sm.avif",
"xs": "https://cdn02.plentymarkets.com/mevofvd5omld/frontend/headphones-xs.avif",
"alt": "Headphones"
},
"tagline": "Experience Sound Freedom",
"taglineColor": "#000000",
"heading": "Wireless. Effortless. Seamless.",
"headingColor": "#000000",
"description": "Unleash your audio with our state-of-the-art wireless earbuds. Designed for all-day comfort and uncompromised sound quality, these earbuds deliver crisp highs and deep bass, letting you enjoy your music without any distractions. Discover freedom with a perfect fit, long battery life, and intuitive controls.",
"descriptionColor": "#000000",
"callToAction": "Shop Earbuds",
"link": ""
},
{
"image": {
"lg": "https://cdn02.plentymarkets.com/mevofvd5omld/frontend/homepage-hero-headphones.avif",
"md": "https://cdn02.plentymarkets.com/mevofvd5omld/frontend/headphones-md.avif",
"sm": "https://cdn02.plentymarkets.com/mevofvd5omld/frontend/headphones-sm.avif",
"xs": "https://cdn02.plentymarkets.com/mevofvd5omld/frontend/headphones-xs.avif",
"alt": "Headphones"
},
"tagline": "Amplify Your Space",
"taglineColor": "#000000",
"heading": "Big Sound, Compact Design",
"headingColor": "#000000",
"description": "Transform your space with our portable speakers that pack a punch. Crafted for superior sound performance, these speakers are perfect for home or on the go. With easy connectivity and a sleek design, elevate your listening experience whether you're indoors or outdoors.",
"descriptionColor": "#000000",
"callToAction": "Browse Speakers",
"link": ""
}
],
"valueProposition": [
{
"text": "<div class='flex flex-col mt-5 sm:mt-20 mt-0 sm:p-0 p-5 text-center sm:text-left'><span class='text-xl font-bold mb-2'>Experience the Future of Sound</span><h2 class='text-2xl font-semibold mb-4'>Redefine Your Listening Experience</h2><p class='typography-text-sm md:typography-text-lg mb-6 padding-right-desktop'>Our latest collection of headphones is designed to deliver unparalleled audio precision, with deep bass, clear highs, and an immersive experience for every genre of music. Combining sleek design, comfort, and cutting-edge technology, these headphones are made for those who refuse to compromise on sound quality.</p><ul class='list-disc list-inside typography-text-sm md:typography-text-lg '><li>Premium, studio-quality sound</li><li>Comfortable fit for extended listening</li><li>Long-lasting battery life</li><li>Seamless wireless connectivity</li></ul></div>",
"image": "https://cdn02.plentymarkets.com/mevofvd5omld/frontend/headphones-mediacard.avif",
"alt": "Headphones",
"alignment": "left"
}
],
"featured": [
{
"headline": "",
"categoryId": 1
},
{
"headline": "",
"categoryId": 2
}
]
}
Loading

0 comments on commit 11ed3ac

Please sign in to comment.