dashersupply/src/components/Product.astro

253 lines
13 KiB
Plaintext

---
import type { ContentsDto } from "../data/internals/ContentsDtoT";
import type { Localized } from "../data/internals/LocalizedT";
import type { Product } from "../data/models/multis/Product";
import { getAssetById, getBrandsByIds, getMarketplacesByIds, getOffersByListingId } from "../data/api-client";
import path from "node:path";
import * as core from "../data/core/client";
import { renderMarkdown } from "../lib/rendering";
import { SCHEMAS } from "../data/models/schemas";
import type { Listing } from "../data/models/multis/Listing";
import type { Offer } from "../data/models/multis/Offer";
import type { Marketplace } from "../data/models/multis/Marketplace";
import ImageCarousel from "./ImageCarousel.astro";
import type { AmazonMarketplaceConnection } from "../data/models/components/AmazonMarketplaceConnection";
import { getSellersByIds } from "../data/api-client";
import { DateTime } from "luxon";
import type { Multilingual, SquidexEditable } from "./SharedProperties";
interface Props extends Multilingual, SquidexEditable {
productDto: ContentsDto<Product>,
}
let category={ } as unknown as any;let site={ } as unknown as any
const formatAsCurrency = (amount: number) => amount.toLocaleString(locale, { style: 'currency', currency: 'USD' });
const { productDto, editToken, locale } = Astro.props;
const product = productDto.items[0].data!;
let amazonConnectorSchemaId = (await core.client.schemas.getSchema({ schema: 'product-marketplace-connection-amazon' })).id;
let brandDto = (await getBrandsByIds(product.brand.iv[0]));
let possibleAmazonConnectors = product.marketplaceConnections.iv.filter((connection) => connection.connection.schemaId === amazonConnectorSchemaId);
let amazonConnector = possibleAmazonConnectors.length > 0 ? possibleAmazonConnectors[0].connection as AmazonMarketplaceConnection : undefined;
const listingsDto = await core.getContentsUsingJsonQuery<Listing>(SCHEMAS.LISTINGS, JSON.stringify({
filter: {
path: "data.product.iv",
op: "eq",
value: productDto.items[0].id,
}
}));
const listingOffersDtos = listingsDto.items.map(async (listingDto) => await core.getContentsUsingJsonQuery<Offer>(SCHEMAS.OFFERS, JSON.stringify({
filter: {
path: "data.listing.iv",
op: "eq",
value: listingDto.id
}
})));
// listingsDto.items.forEach(async (listing) => {
// let marketplaceId = listing.data?.marketplace.iv[0]!;
// const marketplaceDto = await core.getContentsByIds<Marketplace>(SCHEMAS.MARKETPLACES, marketplaceId);
// const marketplace = marketplaceDto.items[0].data!;
// pushDisclaimer({ renderedText: renderMarkdown(marketplace.disclaimer[locale]), marketplaceEditToken: marketplaceDto.items[0].editToken! });
// });
let productListingImages: string[] = [];
for (let listingDto of listingsDto.items) {
for (let assetId of listingDto.data?.marketplaceImages?.iv||[]) {
let assetDto = await getAssetById(assetId);
let assetUrl = path.posix.join('/img', assetDto.links['content']
.href
.split('/')
.reverse()
.filter((_value, index, array) => index < (array.length - index - 2))
.reverse()
.join('/'));
productListingImages.push(assetUrl);
}
}
let i18n: { [key: string]: Localized<string> } = {
'Brand:': {
'en-US': "Brand:",
'es-US': "Marca :",
'fr-CA': "Marque :",
},
'New from': {
'en-US': "New from",
'es-US': "Nuevo desde",
'fr-CA': "Nouveau depuis",
},
'Used from': {
'en-US': "Used from",
'es-US': "Usado desde",
'fr-CA': "Utilisé depuis",
},
'on': {
'en-US': "on",
'es-US': "en",
'fr-CA': "sur",
},
'Price information updated as of': {
'en-US': "Price information updated as of",
'es-US': "Información de precio actualizada a partir de",
'fr-CA': "Information sur le prix mise à jour jusqu\'à",
},
'Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon.com at the time of purchase will apply to the purchase of this product.': {
'en-US': "Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon.com at the time of purchase will apply to the purchase of this product.",
'es-US': "Precios de los productos y disponibilidad son exactos a la fecha/hora indicada y están sujetos a cambios. Cualquier información sobre precios y disponibilidad que se muestre en Amazon.com al momento del pago se aplicará a la compra de este producto.",
'fr-CA': "Les prix des produits et la disponibilité sont exacts à la date/heure indiquée et peuvent varier. Toute information sur les prix et la disponibilité affichés sur Amazon.com au moment de l'achat s'appliqueront à l'achat de ce produit."
}
}
---
<div class="callout">
<!-- <Fragment content={product.callout||category.description||site.categoriesCallout} /> -->
</div>
<div class="row">
<div class="col-sm-12 col-md-6 col-lg-4">
{ productListingImages.length == 1 &&
<img src={productListingImages[0]} alt={product.productName[locale]} style="max-width: 100%;" />
}
{ productListingImages.length > 1 &&
<ImageCarousel showDots={true} images={productListingImages.map((productUrl: string) => { return { src: productUrl }; } )||[]} />
}
</div>
<div class="col-sm-12 col-md-6 col-lg-8">
<h3 class="card-title">
<a href={amazonConnector?.siteStripeUrl||''}>{product?.productName[locale]}</a>
</h3>
<p>
<!-- <StarRating value={product?.amazonProductDetails?.reviewRating||0} max={5} overlayColor="#13151a" /> {product?.amazonProductDetails?.reviewCount} Reviews -->
{ brandDto && brandDto.items.length &&
// <span>&#x2022;</span>
<span class="item-metadata-key">{i18n['Brand:'][locale].toUpperCase()}</span> <span class="item-metadata-value"><a href={`/${brandDto.items[0].data!.slug[locale]}`}>{brandDto.items[0].data!.brandName[locale]}</a></span>
}
</p>
<div class="navbar">
{ listingsDto.items.map(async (listingDto) => {
let marketplacesDto = await getMarketplacesByIds(listingDto.data?.marketplace.iv[0]!);
let offersDto = await getOffersByListingId(listingDto.id);
return (
<Fragment>
{ offersDto.items.map(async (offerDto) => {
let sellersDto = await getSellersByIds(offerDto.data?.seller.iv[0]!);
return (
<span class="custom-btn-container">
{ offerDto.data?.newPrice.iv !== null &&
<a href={amazonConnector?.siteStripeUrl||''}>
{offerDto.data!.newPrice.iv ? formatAsCurrency(offerDto.data!.newPrice.iv||0) : 'See Price'} {i18n['New from'][locale]} {sellersDto.items[0].data?.sellerName[locale]} {i18n['on'][locale]} {marketplacesDto.items[0].data?.marketplaceName[locale]}
<span>&rarr;</span>
<br />
<small><small><i>{i18n['Price information updated as of'][locale]} {DateTime.fromISO(offerDto.data!.offerDate.iv).setLocale(locale).toFormat('D, t ZZZZ')}.</i></small></small>
</a>
}
{ offerDto.data?.usedPrice.iv &&
<a href={amazonConnector?.siteStripeUrl||''}>
{offerDto.data!.usedPrice.iv ? formatAsCurrency(offerDto.data!.usedPrice.iv||0) : 'See Price'} {i18n['Used from'][locale]} {sellersDto.items[0].data?.sellerName[locale]} {i18n['on'][locale]} {marketplacesDto.items[0].data?.marketplaceName[locale]}
<span>&rarr;</span><br />
<small><small><i>{i18n['Price information updated as of'][locale]} {DateTime.fromISO(offerDto.data!.offerDate.iv).setLocale(locale).toFormat('D, t ZZZZ')}.</i></small></small>
</a>
}
</span>
);
})}
{ marketplacesDto.items[0].data?.marketplaceName["en-US"] === 'Amazon' && locale === 'en-US' &&
<p><small><small><i>{i18n['Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon.com at the time of purchase will apply to the purchase of this product.']['en-US']}</i></small></small></p>
}
{ marketplacesDto.items[0].data?.marketplaceName["en-US"] === 'Amazon' && locale !== 'en-US' &&
<p><small><small><i>{i18n['Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon.com at the time of purchase will apply to the purchase of this product.']['en-US']}</i></small></small></p>
<p><small><small><i>{i18n['Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon.com at the time of purchase will apply to the purchase of this product.'][locale]}</i></small></small></p>
}
</Fragment>
)
})}
</div>
{ product?.description &&
<Fragment set:html={renderMarkdown(product.description[locale])} />
}
<!-- { !product?.description &&
<ul>
{product?.amazonProductDetails?.featureBullets?.map(featureBullet => (
<li>{featureBullet}</li>
))}
</ul>
<p>
{product?.amazonProductDetails?.description && product?.amazonProductDetails?.description}
</p>
} -->
<div class="navbar">
{ listingsDto.items.map(async (listingDto) => {
let marketplacesDto = await getMarketplacesByIds(listingDto.data?.marketplace.iv[0]!);
let offersDto = await getOffersByListingId(listingDto.id);
return (
<Fragment>
{ offersDto.items.map(async (offerDto) => {
let sellersDto = await getSellersByIds(offerDto.data?.seller.iv[0]!);
return (
<span class="custom-btn-container">
{ offerDto.data?.newPrice.iv !== null &&
<a href={amazonConnector?.siteStripeUrl||''}>
{offerDto.data!.newPrice.iv ? formatAsCurrency(offerDto.data!.newPrice.iv||0) : 'See Price'} {i18n['New from'][locale]} {sellersDto.items[0].data?.sellerName[locale]} {i18n['on'][locale]} {marketplacesDto.items[0].data?.marketplaceName[locale]}
<span>&rarr;</span><br />
<small>{i18n['Price information updated as of'][locale]} {DateTime.fromISO(offerDto.data!.offerDate.iv).setLocale(locale).toFormat('D, t ZZZZ')}.</small>
</a>
}
{ offerDto.data?.usedPrice.iv &&
<a href={amazonConnector?.siteStripeUrl||''}>
{offerDto.data!.usedPrice.iv ? formatAsCurrency(offerDto.data!.usedPrice.iv||0) : 'See Price'} {i18n['Used from'][locale]} {sellersDto.items[0].data?.sellerName[locale]} {i18n['on'][locale]} {marketplacesDto.items[0].data?.marketplaceName[locale]}
<span>&rarr;</span><br />
<small>{i18n['Price information updated as of'][locale]} {DateTime.fromISO(offerDto.data!.offerDate.iv).setLocale(locale).toFormat('D, t ZZZZ')}.</small>
</a>
}
</span>
);
})}
{ marketplacesDto.items[0].data?.marketplaceName["en-US"] === 'Amazon' && locale === 'en-US' &&
<p><small><small><i>{i18n['Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon.com at the time of purchase will apply to the purchase of this product.']['en-US']}</i></small></small></p>
}
{ marketplacesDto.items[0].data?.marketplaceName["en-US"] === 'Amazon' && locale !== 'en-US' &&
<p><small><small><i>{i18n['Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon.com at the time of purchase will apply to the purchase of this product.'][locale]}</i></small></small></p>
<p><small><small><i>{i18n['Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon.com at the time of purchase will apply to the purchase of this product.']['en-US']}</i></small></small></p>
}
</Fragment>
)
})}
</div>
</div>
</div>
<style>
.custom-btn-container {
background-color: #23262d;
background-image: none;
background-size: 400%;
border-radius: 8px;
background-position: 100%;
padding: 1px;
transition: background-position 0.6s cubic-bezier(0.22, 1, 0.36, 1);
box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.1);
text-align: center;
display: flex;
align-items: center;
}
.custom-btn-container > a {
width: 100%;
border-radius: 8px;
text-decoration: none;
line-height: 1.4;
/* padding: calc(0.5rem - 1px); */
color: white;
padding: 1rem;
background-color: #23262d;
opacity: 0.8;
}
.custom-btn-container:is(:hover, :focus-within) {
background-position: 0;
background-image: var(--accent-gradient);
}
.navbar {
display: flex;
/* grid-template: auto; */
}
</style>