Implemented phase 2 for the POC prototype in the Website service.

This commit is contained in:
javier committed 2026-09-21 11:44:58 +02:00
1 parent 09c7b8a1a7
commit 43dcc03da6
28 files changed
+1468 -65

No files matched your search

@@ -27,6 +27,9 @@ struct ShopPage {
/// The shop shown.
let shop: Shop
/// The signed-in viewer, or `nil` when signed out.
let viewer: Viewer?
// MARK: Initializers
/// Creates the public screen of a shop.
@@ -35,6 +38,7 @@ struct ShopPage {
/// - inventory: every listing of the shop, counted per format on the tabs.
/// - matches: the shop's listings matching the parameters; the screen shows the page they ask for.
/// - parameters: the tab, quick filters, and sort order applied.
/// - viewer: the signed-in viewer, or `nil` (the default) when signed out.
/// - assetVersion: the version token appended to the page's asset URLs, or `nil` (the default) to leave them unversioned.
/// - analytics: the analytics tracker embedded in the document head, or `nil` (the default) to omit it.
init(
@@ -42,9 +46,11 @@ struct ShopPage {
inventory: [Listing],
matches: [Listing],
parameters: SearchParameters,
viewer: Viewer? = nil,
assetVersion: String? = nil,
analytics: Analytics? = nil
) {
self.viewer = viewer
let slice = Pagination.slice(
matches,
page: parameters.page,
@@ -78,7 +84,7 @@ extension ShopPage: Page {
// MARK: Computed
var content: some HTML {
SiteLayout {
SiteLayout(viewer: viewer) {
div(.class("page shop")) {
section(.class("shop__head")) {
span(.class("monogram monogram--xl")) {
@@ -116,20 +122,24 @@ extension ShopPage: Page {
div(.class("shop__actions")) {
a(
.class("button button--primary"),
.href(signIn)
.href(.Route.gated(.Route.message(shop: shop.slug), from: shop.path, viewer: viewer))
) {
Icon(.message, size: 16)
"Message shop"
}
a(
.class("button button--outline"),
.href(signIn)
) {
"Follow shop"
}
span(.class("type-small shop__gate")) {
Icon(.key, size: 13)
"Both need a passkey sign-in"
if viewer == nil {
a(
.class("button button--outline"),
.href(.Route.signIn(returningTo: shop.path))
) {
"Follow shop"
}
span(.class("type-small shop__gate")) {
Icon(.key, size: 13)
"Both need a passkey sign-in"
}
} else {
Unavailable("Follow shop", modifier: "button--outline")
}
}
}
@@ -286,11 +296,6 @@ private extension ShopPage {
// MARK: Computed
/// The sign-in screen, returning to this shop.
var signIn: String {
.Route.signIn(returningTo: shop.path)
}
var stats: [(value: String, label: String)] {
[
("\(counts.values.reduce(0, +))", "listings"),