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
@@ -18,6 +18,9 @@ struct SeriesPage {
|
||||
/// Every listing of the series still for sale.
|
||||
let listings: [Listing]
|
||||
|
||||
/// The issues the viewer owns of the series, or `nil` signed out.
|
||||
let owned: Set<Int>?
|
||||
|
||||
/// The series shown.
|
||||
let series: Series
|
||||
|
||||
@@ -31,6 +34,7 @@ struct SeriesPage {
|
||||
/// - series: the series shown.
|
||||
/// - listings: every listing of the series still for sale.
|
||||
/// - issue: the issue whose copies are listed, or `nil` (the default) for none.
|
||||
/// - owned: the issues the viewer owns of the series, or `nil` (the default) signed out.
|
||||
/// - 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.
|
||||
@@ -38,6 +42,7 @@ struct SeriesPage {
|
||||
series: Series,
|
||||
listings: [Listing],
|
||||
issue: Int? = nil,
|
||||
owned: Set<Int>? = nil,
|
||||
viewer: Viewer? = nil,
|
||||
assetVersion: String? = nil,
|
||||
analytics: Analytics? = nil
|
||||
@@ -47,6 +52,7 @@ struct SeriesPage {
|
||||
self.issue = issue
|
||||
self.listings = listings
|
||||
self.locale = .init(identifier: "en")
|
||||
self.owned = owned
|
||||
self.series = series
|
||||
self.viewer = viewer
|
||||
}
|
||||
@@ -104,6 +110,19 @@ extension SeriesPage: Page {
|
||||
p(.class("type-lead")) {
|
||||
"\(series.blurb)\(series.blurb.isEmpty ? "" : " ")\(listings.count) \(listings.count == 1 ? "copy" : "copies") listed across CCN right now."
|
||||
}
|
||||
if let owned, series.issueCount > 0 {
|
||||
div(.class("card series__collection")) {
|
||||
p(.class("type-eyebrow")) {
|
||||
"Your collection"
|
||||
}
|
||||
p(.class("type-panel")) {
|
||||
"\(owned.count) of \(series.issueCount) owned"
|
||||
}
|
||||
p(.class("type-small")) {
|
||||
"\(gaps.count) missing · \(gaps.filter { !$0.copies.isEmpty }.count) of them listed now"
|
||||
}
|
||||
}
|
||||
}
|
||||
ul(.class("series__keys")) {
|
||||
ForEach(keys) { key in
|
||||
li(.class("chip chip--warn")) {
|
||||
@@ -125,7 +144,7 @@ extension SeriesPage: Page {
|
||||
}
|
||||
ol(.class("series__issues")) {
|
||||
ForEach(issues) { entry in
|
||||
li(.class(entry.copies.isEmpty ? "series__issue series__issue--gap" : "series__issue")) {
|
||||
li(.class(issueClass(entry))) {
|
||||
span(.class("series__number")) {
|
||||
"#\(entry.number)"
|
||||
}
|
||||
@@ -143,6 +162,25 @@ extension SeriesPage: Page {
|
||||
"None listed · alert me"
|
||||
}
|
||||
}
|
||||
if let owned {
|
||||
form(
|
||||
.action("\(String.Route.series(series.slug))/own"),
|
||||
.method(.post)
|
||||
) {
|
||||
input(
|
||||
.type(.hidden),
|
||||
.name("issue"),
|
||||
.value("\(entry.number)")
|
||||
)
|
||||
button(
|
||||
.class("series__own"),
|
||||
.type(.submit),
|
||||
.custom(name: "aria-pressed", value: owned.contains(entry.number) ? "true" : "false")
|
||||
) {
|
||||
owned.contains(entry.number) ? "Owned ✓" : "I own this"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -274,6 +312,24 @@ extension SeriesPage: Page {
|
||||
|
||||
private extension SeriesPage {
|
||||
|
||||
/// The issues of the run the viewer does not own.
|
||||
var gaps: [(number: Int, copies: [Listing])] {
|
||||
issues.filter { !(owned ?? []).contains($0.number) }
|
||||
}
|
||||
|
||||
/// An issue's tile: a gap reads quieter, and an owned issue is dimmed.
|
||||
func issueClass(
|
||||
_ entry: (number: Int, copies: [Listing])
|
||||
) -> String {
|
||||
[
|
||||
"series__issue",
|
||||
entry.copies.isEmpty ? "series__issue--gap" : nil,
|
||||
owned?.contains(entry.number) == true ? "series__issue--owned" : nil,
|
||||
]
|
||||
.compactMap(\.self)
|
||||
.joined(separator: " ")
|
||||
}
|
||||
|
||||
/// The series' manga, trade paperbacks, and hardcovers.
|
||||
var collected: [Listing] {
|
||||
listings.filter { $0.issueNumber == nil }
|
||||
|
||||
Reference in new issue
Block a user