Implemented phase 6 for the POC prototype in the Website service.
This commit is contained in:
1 parent
256d22df40
commit
f2f445827b
40 files changed
+1906
-37
No files matched your search
@@ -0,0 +1,137 @@
|
||||
import Elementary
|
||||
import Foundation
|
||||
import Infrastructure
|
||||
import Persistence
|
||||
|
||||
/// The events where shops trade in person: agree on the site, skip shipping, collect the copy at the con.
|
||||
struct EventsPage {
|
||||
|
||||
// MARK: Properties
|
||||
|
||||
let analytics: Analytics?
|
||||
let assetVersion: String?
|
||||
let locale: Locale
|
||||
|
||||
/// The events still to come, soonest first, each with the number of listings that can be picked up there.
|
||||
let events: [(event: Event, listingCount: Int)]
|
||||
|
||||
/// The moment "this weekend" is judged from.
|
||||
let now: Date
|
||||
|
||||
/// The signed-in viewer, or `nil` when signed out.
|
||||
let viewer: Viewer?
|
||||
|
||||
// MARK: Initializers
|
||||
|
||||
/// Creates the events screen.
|
||||
/// - Parameters:
|
||||
/// - events: the events still to come, soonest first.
|
||||
/// - listings: every listing for sale, counted per event by the shops trading there.
|
||||
/// - viewer: the signed-in viewer, or `nil` (the default) when signed out.
|
||||
/// - now: the moment "this weekend" is judged from; the present by default.
|
||||
/// - 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(
|
||||
events: [Event],
|
||||
listings: [Listing],
|
||||
viewer: Viewer? = nil,
|
||||
now: Date = .init(),
|
||||
assetVersion: String? = nil,
|
||||
analytics: Analytics? = nil
|
||||
) {
|
||||
self.analytics = analytics
|
||||
self.assetVersion = assetVersion
|
||||
self.events = events.map { event in
|
||||
let shops = Set(event.shops.map(\.slug))
|
||||
|
||||
return (event, listings.count { shops.contains($0.shop.slug) })
|
||||
}
|
||||
self.locale = .init(identifier: "en")
|
||||
self.now = now
|
||||
self.viewer = viewer
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: - Page
|
||||
|
||||
extension EventsPage: Page {
|
||||
|
||||
// MARK: Computed
|
||||
|
||||
var content: some HTML {
|
||||
SiteLayout(viewer: viewer) {
|
||||
div(.class("page wants")) {
|
||||
div(.class("events__intro")) {
|
||||
h1(.class("type-h1")) {
|
||||
"Pick up at a con"
|
||||
}
|
||||
p(.class("type-lead")) {
|
||||
"Sellers mark which events they'll trade at. Agree on CCN, skip shipping, collect it in person."
|
||||
}
|
||||
}
|
||||
if events.isEmpty {
|
||||
div(.class("empty")) {
|
||||
h2(.class("type-panel")) {
|
||||
"No events coming up"
|
||||
}
|
||||
p(.class("type-body-sm")) {
|
||||
"Every copy still ships, tracked."
|
||||
}
|
||||
}
|
||||
}
|
||||
ul(.class("wants__list")) {
|
||||
ForEach(events) { entry in
|
||||
li {
|
||||
a(
|
||||
.class("card events__event"),
|
||||
.href(.Route.pickup(at: entry.event.slug))
|
||||
) {
|
||||
span(.class("wants__top")) {
|
||||
span(.class("events__name")) {
|
||||
strong {
|
||||
entry.event.name
|
||||
}
|
||||
span(.class("type-small")) {
|
||||
Date.span(from: entry.event.startsOn, to: entry.event.endsOn)
|
||||
}
|
||||
}
|
||||
if entry.event.startsOn.isWithinAWeek(of: now) {
|
||||
Chip("This weekend", tone: .warn)
|
||||
}
|
||||
}
|
||||
span(.class("type-small")) {
|
||||
entry.event.venue
|
||||
}
|
||||
span(.class("events__chips")) {
|
||||
Chip("\(entry.event.shops.count) \(entry.event.shops.count == 1 ? "shop" : "shops") trading")
|
||||
Chip("\(entry.listingCount) \(entry.listingCount == 1 ? "listing" : "listings") for pickup")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
p(.class("type-small wants__note")) {
|
||||
"Selling? Pick the events you'll trade at on your seller dashboard."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var scripts: [any Asset] {
|
||||
[StaticFile.shared]
|
||||
}
|
||||
|
||||
var stylesheets: [any Asset] {
|
||||
[StaticFile.shared, StaticFile.trade]
|
||||
}
|
||||
|
||||
var summary: String? {
|
||||
"Comic cons where CCN shops trade in person: agree on a copy online, collect it at the event."
|
||||
}
|
||||
|
||||
var title: String {
|
||||
"Events — CCN"
|
||||
}
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user