mirror of
https://github.com/KevinMidboe/planetposen-frontend.git
synced 2025-12-08 20:28:42 +00:00
* Generates JSON ld structured metadata from a product & appends to head * Updated IProduct & IVariation interface * Added IProductResponse & IProductsResponse interfaces * Fixed sitemap urls having to many protocols * Implemented jsonld for product w/ variations * Aligned Product responses between backend & frontend * PageMeta for updating head meta values: title & description Use on any page where we want to display a unique meta page title & description * Set document language to norwegian * Linting
118 lines
2.8 KiB
Svelte
118 lines
2.8 KiB
Svelte
<script lang="ts">
|
|
import ProductTile from '../ProductTile.svelte';
|
|
import ProductVariationSelect from '$lib/components/ProductVariationSelect.svelte';
|
|
import QuantitySelect from '$lib/components/QuantitySelect.svelte';
|
|
import SizesSection from './SizesSection.svelte';
|
|
import Button from '$lib/components/Button.svelte';
|
|
import type { PageData } from './$types';
|
|
import type { IProduct, IVariation } from '$lib/interfaces/IProduct';
|
|
|
|
export let data: PageData;
|
|
const product = data.product as IProduct;
|
|
import { addProductToCart } from '$lib/websocketCart';
|
|
|
|
function setSelectedVariation(event: CustomEvent) {
|
|
selectedVariation = event.detail;
|
|
}
|
|
|
|
function addProductClicked() {
|
|
cooldownInputs = true;
|
|
addProductToCart(product.product_no, selectedVariation.sku_id, quantity);
|
|
setTimeout(() => reset(), 2300);
|
|
}
|
|
|
|
function reset() {
|
|
quantity = 1;
|
|
cooldownInputs = false;
|
|
}
|
|
|
|
function defaultVariation() {
|
|
return product.variations?.find((variation) => variation.default_price);
|
|
}
|
|
|
|
let cooldownInputs = false;
|
|
let quantity = 1;
|
|
let selectedVariation: IVariation | undefined = defaultVariation();
|
|
|
|
$: addProductButtonText = cooldownInputs
|
|
? `${quantity} produkt${quantity > 1 ? 'er' : ''} lagt til`
|
|
: `Legg til ${quantity} i handlekurven`;
|
|
|
|
onMount(() => document.head.appendChild(generateProductJsonLd(product)))
|
|
</script>
|
|
|
|
<div class="product-container">
|
|
<ProductTile product="{product}" large="{true}" />
|
|
|
|
<div class="details">
|
|
<h2 class="name">{product.name}</h2>
|
|
<p class="subtext">{product.subtext}</p>
|
|
<p class="subtext">{product.description}</p>
|
|
<p class="price">NOK {selectedVariation?.price} (Ink. Moms)</p>
|
|
|
|
<ProductVariationSelect
|
|
variations="{product.variations}"
|
|
on:selected="{setSelectedVariation}"
|
|
/>
|
|
|
|
<QuantitySelect bind:value="{quantity}" disabled="{cooldownInputs}" />
|
|
|
|
<div class="button">
|
|
<Button
|
|
on:click="{() => addProductClicked()}"
|
|
text="{addProductButtonText}"
|
|
active="{cooldownInputs}"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<SizesSection />
|
|
|
|
{#if data?.jsonld}
|
|
{@html data.jsonld}
|
|
{/if}
|
|
|
|
<style lang="scss" module="scoped">
|
|
@import '../../../styles/media-queries.scss';
|
|
|
|
.product-container {
|
|
display: grid;
|
|
max-width: 1200px;
|
|
margin: 2rem auto 4rem;
|
|
|
|
grid-template-columns: 1fr;
|
|
|
|
@include tablet {
|
|
margin: 8rem auto 2rem;
|
|
grid-template-columns: 1fr 1fr;
|
|
}
|
|
|
|
> * {
|
|
margin: 1rem;
|
|
}
|
|
|
|
.details {
|
|
.name {
|
|
font-size: 2rem;
|
|
}
|
|
|
|
.price {
|
|
margin-top: 3rem;
|
|
font-size: 1.5rem;
|
|
}
|
|
|
|
p {
|
|
font-size: 1.2rem;
|
|
}
|
|
|
|
.button {
|
|
margin-top: 3rem;
|
|
}
|
|
|
|
@include desktop {
|
|
margin-left: 4rem;
|
|
}
|
|
}
|
|
}
|
|
</style>
|