-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
2fd90f8
commit 241a71a
Showing
4 changed files
with
340 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,241 @@ | ||
--- | ||
import { Image } from "@unpic/astro" | ||
import BaseLayout from "@layouts/BaseLayout.astro" | ||
import Button from "@components/Button.astro" | ||
import LocalisedPrice from "@components/LocalisedPrice.astro" | ||
import { getActivePrices, type StripePrice } from "@utils/stripe" | ||
export async function getStaticPaths() { | ||
const prices = await getActivePrices() | ||
return prices.map(price => ({ | ||
params: { | ||
slug: price.product.metadata.slug, | ||
category: price.product.metadata.category, | ||
}, | ||
props: { price }, | ||
})) | ||
} | ||
const { price } = Astro.props | ||
const sizeToDescription: Record< | ||
StripePrice["product"]["metadata"]["size"], | ||
string | ||
> = { | ||
A3: "A3 (297 x 420 mm)", | ||
A2: "A2 (420 x 594 mm)", | ||
A1: "A1 (594 x 841 mm)", | ||
} | ||
--- | ||
|
||
<BaseLayout | ||
title={`${price.product.metadata.displayName} | Giclée Fine Art Print | Andrea Diotallevi Art`} | ||
description={price.product.description} | ||
image={price.product.images[0]} | ||
type="product" | ||
amount={(price.unit_amount / 100).toFixed(2)} | ||
currency="gbp" | ||
tags={[ | ||
price.product.metadata.displayName, | ||
"Generative Art", | ||
"p5.js", | ||
"Processing", | ||
"Procedural", | ||
"Prints", | ||
"Fine Art", | ||
"Giclee", | ||
"Hahnemühle photo rag", | ||
]} | ||
> | ||
<div | ||
class="flex flex-col md:flex-row items-center md:items-start px-4 py-8 max-w-screen-xl mx-auto" | ||
> | ||
<div class="w-full md:w-1/2 mb-6 md:mb-0 md:mr-8"> | ||
<div class="mb-5 relative"> | ||
{ | ||
price.product.images.map((src, index) => ( | ||
<Image | ||
id={`main-image-${index}`} | ||
width={1000} | ||
height={1414} | ||
src={src} | ||
alt={price.product.name} | ||
class={`w-full h-auto ${index === 0 ? "" : "absolute top-0 opacity-0"}`} | ||
/> | ||
)) | ||
} | ||
</div> | ||
<div class="grid grid-cols-4 gap-4"> | ||
{ | ||
price.product.images.map((img, index) => ( | ||
<Image | ||
id={`thumbnail-${index}`} | ||
src={img} | ||
width={1000} | ||
height={1414} | ||
alt={`Thumbnail ${index + 1}`} | ||
class={`w-full h-auto cursor-pointer border border-white border-dashed`} | ||
/> | ||
)) | ||
} | ||
</div> | ||
</div> | ||
|
||
<form id="price-form" class="w-full md:w-1/2"> | ||
<h1 class="text-5xl font-bold mb-5"> | ||
{price.product.metadata.displayName} | ||
</h1> | ||
|
||
<div class="space-y-6"> | ||
<div> | ||
<h2 class="text-2xl font-semibold mb-2">Size</h2> | ||
<select | ||
id="price-id" | ||
name="price-id" | ||
class="w-full px-3 py-3 border border-gray-800 rounded-md mb-2" | ||
> | ||
<option value={price.id}> | ||
{sizeToDescription[price.product.metadata.size]} | ||
</option> | ||
</select> | ||
<p>The image is printed full bleed with no border.</p> | ||
</div> | ||
<div> | ||
<h2 class="text-2xl font-semibold mb-2"> | ||
100% cotton paper | ||
</h2> | ||
<p> | ||
The artwork is printed on a white cotton paper called | ||
Hahnemühle photo rag 308gsm. With its characteristic, | ||
wonderfully soft feel, it boasts a lightly defined felt | ||
structure, lending each artwork a three-dimensional | ||
appearance and impressive pictorial depth. | ||
</p> | ||
</div> | ||
<div> | ||
<h2 class="text-2xl font-semibold mb-2"> | ||
Premium print quality | ||
</h2> | ||
<p> | ||
The print is crafted using premium, pigment-based inks | ||
that are fade-resistant and can endure for up to 200 | ||
years. This technique, called Giclée, makes the print | ||
stand apart with its extremely high level of quality, | ||
longevity and value compared to a standard print. | ||
</p> | ||
</div> | ||
<div> | ||
<h2 class="text-2xl font-semibold mb-2">Free shipping</h2> | ||
<p> | ||
Shipping is handled by The Print Space in London through | ||
First Class Tracked Mail (typically 6-10 days). This is | ||
an extremely more secure option than regular post for | ||
sending art prints. | ||
</p> | ||
</div> | ||
<div> | ||
<h2 class="text-2xl font-semibold mb-2"> | ||
No custom charges for UK, EU and US orders | ||
</h2> | ||
<p> | ||
With production in the UK, USA & Germany, The Print | ||
Space guarantees no extra customs charges on UK-EU-US | ||
orders. | ||
</p> | ||
</div> | ||
<div> | ||
<h2 class="text-2xl font-semibold mb-2"> | ||
<LocalisedPrice | ||
priceCurrencyOptions={price.currency_options} | ||
/> | ||
</h2> | ||
<p>Apply promotion codes at checkout.</p> | ||
</div> | ||
<Button | ||
id="submit-button" | ||
buttonText="Continue to checkout" | ||
errorMessage="There was an error creating your session. Please try again." | ||
/> | ||
</div> | ||
</form> | ||
</div> | ||
</BaseLayout> | ||
|
||
<script> | ||
import { sendGA4BeginCheckoutEvent } from "@utils/ga4" | ||
import { createCheckoutSession, getLocaleCurrency } from "@utils/serverless" | ||
|
||
document.addEventListener("astro:page-load", async () => { | ||
const priceForm = document.querySelector("#price-form") as HTMLElement | ||
|
||
if (!priceForm) return | ||
|
||
const button = document.querySelector( | ||
"#submit-button" | ||
) as HTMLButtonElement | ||
|
||
const spinner = document.getElementById("loading-spinner")! | ||
const errorMessage = document.getElementById("error-message")! | ||
|
||
priceForm.addEventListener("submit", async e => { | ||
e.preventDefault() | ||
|
||
button.disabled = true | ||
spinner.classList.remove("hidden") | ||
errorMessage.classList.add("hidden") | ||
|
||
const priceId = ( | ||
document.getElementById("price-id") as HTMLInputElement | ||
).value | ||
|
||
const session = await createCheckoutSession({ | ||
line_items: [{ price: priceId, quantity: 1 }], | ||
success_url: `${window.location.origin}/shop/checkout/success`, | ||
currency: await getLocaleCurrency(), | ||
}) | ||
|
||
if (!session) { | ||
errorMessage.classList.remove("hidden") | ||
spinner.classList.add("hidden") | ||
button.disabled = false | ||
return | ||
} | ||
|
||
sendGA4BeginCheckoutEvent({ session }) | ||
window.location.href = `/shop/checkout?clientSecret=${session.client_secret}` | ||
}) | ||
}) | ||
</script> | ||
|
||
<script> | ||
document.addEventListener("astro:page-load", () => { | ||
const mainImages = document.querySelectorAll('[id^="main-image-"]') | ||
const thumbnails = document.querySelectorAll('[id^="thumbnail-"]') | ||
|
||
if (!mainImages.length || !thumbnails.length) return | ||
|
||
let selectedThumbnail = thumbnails[0] | ||
selectedThumbnail.classList.replace("border-white", "border-black") | ||
|
||
thumbnails.forEach((thumbnail, index) => { | ||
thumbnail.addEventListener("click", () => { | ||
mainImages.forEach((img, i) => { | ||
if (i === index) { | ||
img.classList.remove("absolute", "top-0", "opacity-0") | ||
} else { | ||
img.classList.add("absolute", "top-0", "opacity-0") | ||
} | ||
}) | ||
|
||
selectedThumbnail.classList.replace( | ||
"border-black", | ||
"border-white" | ||
) | ||
thumbnail.classList.replace("border-white", "border-black") | ||
selectedThumbnail = thumbnail | ||
}) | ||
}) | ||
}) | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
--- | ||
import { Image } from "@unpic/astro" | ||
import BaseLayout from "@layouts/BaseLayout.astro" | ||
import LocalisedPrice from "@components/LocalisedPrice.astro" | ||
import { getActivePrices } from "@utils/stripe" | ||
const prices = await getActivePrices() | ||
--- | ||
|
||
<BaseLayout | ||
title="Shop | Giclée Fine Art Prints | Andrea Diotallevi Art" | ||
description="Archival quality giclée generative art prints, on vegan certified Hahnemühle photo rag 308gsm matte paper, delivered in a cardboard tube with recycled plastic ends." | ||
image={prices[0].product.images[0]} | ||
tags={[ | ||
"Generative Art", | ||
"p5.js", | ||
"Processing", | ||
"Procedural", | ||
"Prints", | ||
"Fine Art", | ||
"Giclee", | ||
"Hahnemühle photo rag", | ||
]} | ||
> | ||
<div class="max-w-screen-xl mx-auto px-4 py-8"> | ||
<div class="text-center mb-8"> | ||
<h1 class="text-5xl font-bold mb-6">Shop</h1> | ||
<p class="max-w-[600px] mx-auto"> | ||
Archival quality giclée generative art prints, on vegan | ||
certified Hahnemühle photo rag 308gsm matte paper, delivered in | ||
recycled packaging | ||
</p> | ||
</div> | ||
|
||
<div class="grid grid-cols-2 md:grid-cols-4 gap-4 md:gap-6"> | ||
{ | ||
prices.map(price => ( | ||
<a | ||
href={`/shop/${price.product.metadata.category}/${price.product.metadata.slug}`} | ||
class="flex flex-col no-underline text-black hover:underline" | ||
data-astro-prefetch | ||
> | ||
<Image | ||
alt={price.product.name} | ||
src={price.product.images[0]} | ||
width={1000} | ||
height={1414} | ||
class="w-full h-auto object-contain" | ||
/> | ||
<h2 class="text-2xl font-semibold mt-4"> | ||
{price.product.metadata.displayName} | ||
</h2> | ||
<p class="text-lg font-medium mt-2"> | ||
<LocalisedPrice | ||
priceCurrencyOptions={price.currency_options} | ||
/> | ||
</p> | ||
</a> | ||
)) | ||
} | ||
</div> | ||
</div> | ||
</BaseLayout> |
Oops, something went wrong.