almost all ready
This commit is contained in:
@@ -0,0 +1,157 @@
|
||||
package templates
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"git.ma-al.com/goc_marek/ps_shop/internal/viewmodel"
|
||||
)
|
||||
|
||||
templ CartPage(data viewmodel.CartPageData, cssPath string, jsPath string) {
|
||||
@Layout("Cart", cssPath, jsPath, data.Menu, data.Locale, data.Cart.TotalItems) {
|
||||
<main class="min-h-screen overflow-hidden bg-[radial-gradient(circle_at_top,_rgba(245,158,11,0.22),_transparent_34%),radial-gradient(circle_at_bottom_left,_rgba(120,53,15,0.22),_transparent_36%),linear-gradient(180deg,#0c0a09,#1c1917)]">
|
||||
<div class="pointer-events-none absolute inset-x-0 top-0 h-72 bg-[linear-gradient(145deg,rgba(251,191,36,0.12),transparent_58%)]"></div>
|
||||
<div class="mx-auto flex w-full max-w-[104rem] flex-col gap-10 px-6 py-10 lg:px-8">
|
||||
<header class="relative overflow-hidden rounded-[2.2rem] border border-amber-500/20 bg-[linear-gradient(135deg,rgba(28,25,23,0.96),rgba(120,53,15,0.34))] p-8 shadow-[0_32px_120px_rgba(41,24,10,0.48)] lg:p-10">
|
||||
<div class="absolute -right-14 top-[-3.5rem] h-44 w-44 rounded-full bg-amber-300/10 blur-3xl"></div>
|
||||
<div class="absolute bottom-[-4rem] left-[-2rem] h-40 w-40 rounded-full bg-orange-500/10 blur-3xl"></div>
|
||||
<div class="relative flex flex-col gap-8 lg:flex-row lg:items-end lg:justify-between">
|
||||
<div class="max-w-2xl">
|
||||
<p class="text-xs uppercase tracking-[0.38em] text-amber-300/80">Cart overview</p>
|
||||
<h1 class="mt-4 font-serif text-4xl text-stone-50 lg:text-5xl">Everything ready for checkout.</h1>
|
||||
<p class="mt-4 max-w-xl text-sm leading-7 text-stone-300 lg:text-base">Review quantities, adjust variants, and keep the final order state visible before handing off checkout to PrestaShop.</p>
|
||||
</div>
|
||||
<div class="grid gap-3 sm:grid-cols-2 lg:min-w-[20rem]">
|
||||
<div class="rounded-[1.4rem] border border-white/10 bg-white/5 px-5 py-4 backdrop-blur">
|
||||
<p class="text-[0.68rem] uppercase tracking-[0.28em] text-stone-500">Line items</p>
|
||||
<p class="mt-2 text-3xl font-semibold text-stone-50">{ fmt.Sprintf("%d", len(data.Cart.Items)) }</p>
|
||||
</div>
|
||||
<div class="rounded-[1.4rem] border border-amber-400/20 bg-amber-300/10 px-5 py-4 backdrop-blur">
|
||||
<p class="text-[0.68rem] uppercase tracking-[0.28em] text-amber-100/80">Units total</p>
|
||||
<p class="mt-2 text-3xl font-semibold text-stone-50">{ fmt.Sprintf("%d", data.Cart.TotalItems) }</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="relative mt-8 flex flex-wrap items-center gap-3 text-sm text-stone-300">
|
||||
if data.Customer != nil {
|
||||
<span class="rounded-full border border-white/10 bg-black/15 px-4 py-2">{ fmt.Sprintf("%s %s", data.Customer.FirstName, data.Customer.LastName) }</span>
|
||||
} else {
|
||||
<span class="rounded-full border border-white/10 bg-black/15 px-4 py-2">Guest session</span>
|
||||
}
|
||||
<span class="rounded-full border border-white/10 bg-black/15 px-4 py-2">{ "Subtotal " + moneyWithCurrency(data.Cart.SubtotalTaxIncl, cartCurrencySign(data), cartCurrencyCode(data)) }</span>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<section class="grid gap-8 xl:grid-cols-[minmax(0,1.55fr)_24rem]">
|
||||
<div class="rounded-[2rem] border border-stone-800 bg-stone-900/72 p-5 shadow-[0_24px_80px_rgba(0,0,0,0.35)] lg:p-6">
|
||||
if len(data.Cart.Items) == 0 {
|
||||
<div class="rounded-[1.75rem] border border-dashed border-amber-400/30 bg-[linear-gradient(180deg,rgba(245,158,11,0.08),rgba(28,25,23,0.32))] p-12 text-center">
|
||||
<p class="text-sm uppercase tracking-[0.28em] text-amber-300">Empty</p>
|
||||
<p class="mt-4 text-3xl font-semibold text-stone-50">Your cart is empty.</p>
|
||||
<p class="mx-auto mt-3 max-w-md text-sm leading-7 text-stone-300">Browse categories or return to a product page to add items and build a full order before checkout.</p>
|
||||
</div>
|
||||
} else {
|
||||
<div class="mb-4 hidden grid-cols-[minmax(0,1fr)_11rem] gap-4 px-4 text-[0.68rem] uppercase tracking-[0.28em] text-stone-500 md:grid">
|
||||
<div>Product</div>
|
||||
<div class="text-right">Summary</div>
|
||||
</div>
|
||||
<div class="space-y-4">
|
||||
for _, item := range data.Cart.Items {
|
||||
<article class="group overflow-hidden rounded-[1.7rem] border border-stone-800 bg-[linear-gradient(180deg,rgba(41,37,36,0.88),rgba(28,25,23,0.96))] p-5 shadow-[inset_0_1px_0_rgba(255,255,255,0.04)] transition duration-300 hover:border-amber-400/30 hover:bg-[linear-gradient(180deg,rgba(120,53,15,0.22),rgba(28,25,23,0.98))] md:p-6">
|
||||
<div class="flex flex-col gap-5 md:flex-row md:items-start md:justify-between">
|
||||
if item.ImageURL != "" {
|
||||
<div class="overflow-hidden rounded-[1.35rem] border border-stone-800 bg-stone-950/70 shadow-[0_16px_40px_rgba(0,0,0,0.24)] md:w-32 md:shrink-0">
|
||||
<img class="block h-32 w-full object-cover" src={ item.ImageURL } alt={ item.Name }/>
|
||||
</div>
|
||||
}
|
||||
<div class="min-w-0 flex-1">
|
||||
<div class="flex flex-wrap items-center gap-2">
|
||||
<p class="text-[0.68rem] uppercase tracking-[0.3em] text-amber-300">Product</p>
|
||||
if cartItemAttributeLabel(item) != "" {
|
||||
<span class="rounded-full border border-amber-300/20 bg-amber-300/10 px-2.5 py-1 text-[0.65rem] uppercase tracking-[0.16em] text-amber-100/80">{ cartItemAttributeLabel(item) }</span>
|
||||
}
|
||||
</div>
|
||||
if item.URL != "" {
|
||||
<a class="mt-3 block truncate text-2xl font-semibold text-stone-50 underline-offset-4 transition group-hover:text-amber-100 hover:underline" href={ item.URL }>{ item.Name }</a>
|
||||
} else {
|
||||
<h2 class="mt-3 text-2xl font-semibold text-stone-50">{ item.Name }</h2>
|
||||
}
|
||||
<div class="mt-4 flex flex-wrap gap-2 text-xs text-stone-400">
|
||||
<span class="rounded-full border border-white/10 bg-black/20 px-3 py-1.5">{ fmt.Sprintf("Qty %d", item.Quantity) }</span>
|
||||
<span class="rounded-full border border-white/10 bg-black/20 px-3 py-1.5">{ "Net " + moneyWithCurrency(item.UnitPrice, item.CurrencySign, item.CurrencyCode) }</span>
|
||||
<span class="rounded-full border border-white/10 bg-black/20 px-3 py-1.5">{ taxLabel(item.TaxRate) }</span>
|
||||
</div>
|
||||
if cartItemAttributeLabel(item) != "" {
|
||||
<p class="mt-3 text-sm text-stone-300">{ cartItemAttributeLabel(item) }</p>
|
||||
}
|
||||
</div>
|
||||
<div class="rounded-[1.25rem] border border-stone-800 bg-stone-950/70 px-4 py-4 text-left md:min-w-[11rem] md:text-right">
|
||||
<p class="text-[0.68rem] uppercase tracking-[0.24em] text-stone-500">Line total</p>
|
||||
<p class="mt-2 text-2xl font-semibold text-stone-50">{ moneyWithCurrency(item.LineTotalTaxIncl, item.CurrencySign, item.CurrencyCode) }</p>
|
||||
<p class="mt-1 text-xs uppercase tracking-[0.2em] text-stone-500">{ conversionRateLabel(item.ConversionRate, item.CurrencyCode) }</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-6 flex flex-col gap-3 border-t border-stone-800 pt-5 md:flex-row md:items-center md:justify-between">
|
||||
<form class="flex flex-wrap items-center gap-3" method="post" action={ localizedCartPath(data.Locale) }>
|
||||
<input type="hidden" name="action" value="update"/>
|
||||
<input type="hidden" name="id_product" value={ fmt.Sprintf("%d", item.ProductID) }/>
|
||||
<input type="hidden" name="id_product_attribute" value={ fmt.Sprintf("%d", item.ProductAttributeID) }/>
|
||||
<input type="hidden" name="id_customization" value={ fmt.Sprintf("%d", item.CustomizationID) }/>
|
||||
<label class="text-[0.75rem] uppercase tracking-[0.24em] text-stone-400" for={ fmt.Sprintf("qty-%d-%d", item.ProductID, item.ProductAttributeID) }>Quantity</label>
|
||||
<div class="flex items-center overflow-hidden rounded-full border border-stone-700 bg-stone-950">
|
||||
<input class="w-20 bg-transparent px-4 py-2.5 text-center text-sm text-stone-100 outline-none ring-0" id={ fmt.Sprintf("qty-%d-%d", item.ProductID, item.ProductAttributeID) } type="number" min="1" name="qty" value={ fmt.Sprintf("%d", item.Quantity) }/>
|
||||
</div>
|
||||
<button class="rounded-full border border-amber-300/40 bg-amber-300/10 px-4 py-2.5 text-xs font-semibold uppercase tracking-[0.22em] text-amber-100 transition hover:bg-amber-300 hover:text-stone-950" type="submit">
|
||||
Update line
|
||||
</button>
|
||||
</form>
|
||||
<form method="post" action={ localizedCartPath(data.Locale) }>
|
||||
<input type="hidden" name="action" value="delete"/>
|
||||
<input type="hidden" name="id_product" value={ fmt.Sprintf("%d", item.ProductID) }/>
|
||||
<input type="hidden" name="id_product_attribute" value={ fmt.Sprintf("%d", item.ProductAttributeID) }/>
|
||||
<input type="hidden" name="id_customization" value={ fmt.Sprintf("%d", item.CustomizationID) }/>
|
||||
<button class="rounded-full border border-stone-700 bg-stone-950 px-4 py-2.5 text-xs font-semibold uppercase tracking-[0.22em] text-stone-200 transition hover:border-rose-300/30 hover:bg-rose-300 hover:text-stone-950" type="submit">
|
||||
Remove
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</article>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<aside class="xl:sticky xl:top-8 xl:self-start">
|
||||
<div class="overflow-hidden rounded-[2rem] border border-amber-500/20 bg-[linear-gradient(180deg,rgba(245,158,11,0.12),rgba(28,25,23,0.92)_34%,rgba(28,25,23,0.98))] p-8 shadow-[0_24px_80px_rgba(41,24,10,0.4)]">
|
||||
<p class="text-xs uppercase tracking-[0.3em] text-amber-200">Summary</p>
|
||||
<p class="mt-3 text-sm leading-7 text-stone-300">A compact snapshot of the current order before checkout moves to the native Presta flow.</p>
|
||||
<div class="mt-8 space-y-3">
|
||||
<div class="flex items-center justify-between rounded-2xl border border-white/10 bg-black/15 px-4 py-3 text-sm text-stone-200">
|
||||
<span>Total items</span>
|
||||
<span class="font-semibold text-stone-50">{ fmt.Sprintf("%d", data.Cart.TotalItems) }</span>
|
||||
</div>
|
||||
<div class="flex items-center justify-between rounded-2xl border border-white/10 bg-black/15 px-4 py-3 text-sm text-stone-200">
|
||||
<span>Unique lines</span>
|
||||
<span class="font-semibold text-stone-50">{ fmt.Sprintf("%d", len(data.Cart.Items)) }</span>
|
||||
</div>
|
||||
<div class="flex items-center justify-between rounded-2xl border border-white/10 bg-black/15 px-4 py-3 text-sm text-stone-200">
|
||||
<span>Subtotal net</span>
|
||||
<span class="font-semibold text-stone-50">{ moneyWithCurrency(data.Cart.Subtotal, cartCurrencySign(data), cartCurrencyCode(data)) }</span>
|
||||
</div>
|
||||
<div class="flex items-center justify-between rounded-[1.4rem] border border-amber-300/20 bg-amber-300/10 px-5 py-4 text-lg font-semibold text-stone-50">
|
||||
<span>Subtotal gross</span>
|
||||
<span>{ moneyWithCurrency(data.Cart.SubtotalTaxIncl, cartCurrencySign(data), cartCurrencyCode(data)) }</span>
|
||||
</div>
|
||||
</div>
|
||||
<a class="mt-8 inline-flex w-full items-center justify-center rounded-full bg-amber-300 px-5 py-3.5 text-sm font-semibold uppercase tracking-[0.22em] text-stone-950 transition hover:bg-amber-200" href={ data.ShopBaseURL + "/order" }>
|
||||
Checkout in PrestaShop
|
||||
</a>
|
||||
<a class="mt-3 inline-flex w-full items-center justify-center rounded-full border border-white/10 px-5 py-3 text-xs font-semibold uppercase tracking-[0.24em] text-stone-200 transition hover:border-amber-300/40 hover:text-stone-50" href="/">
|
||||
Continue browsing
|
||||
</a>
|
||||
</div>
|
||||
</aside>
|
||||
</section>
|
||||
</div>
|
||||
</main>
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user