159 lines
4.6 KiB
Swift
159 lines
4.6 KiB
Swift
import Foundation
|
|||
|
|
|
||
|
|
/// A `Sendable` snapshot of one copy for sale, with the shop selling it.
|
||
|
|
public struct Listing: Sendable, Equatable {
|
||
|
|
|
||
|
|
// MARK: Properties
|
||
|
|
|
||
|
|
/// The listing's URL slug.
|
||
|
|
public let slug: String
|
||
|
|
/// The shop selling the copy.
|
||
|
|
public let shop: Shop
|
||
|
|
/// The listing's title, e.g. `Nightward #1`.
|
||
|
|
public let title: String
|
||
|
|
/// The series the copy belongs to, e.g. `Nightward (2019 series)`.
|
||
|
|
public let seriesTitle: String
|
||
|
|
/// The issue or volume, e.g. `#1, cover A`.
|
||
|
|
public let issueLabel: String
|
||
|
|
/// The publisher's name.
|
||
|
|
public let publisher: String
|
||
|
|
/// The cover year.
|
||
|
|
public let year: Int
|
||
|
|
/// The format token, e.g. `single-issues`.
|
||
|
|
public let format: String
|
||
|
|
/// The printing in a few words, e.g. `1st print`.
|
||
|
|
public let printing: String
|
||
|
|
/// The printing in full, e.g. `First printing, direct edition`.
|
||
|
|
public let printingDetail: String
|
||
|
|
/// Whether the copy is a first printing.
|
||
|
|
public let isFirstPrint: Bool
|
||
|
|
/// The company that graded and slabbed the copy, or `nil` for a raw copy.
|
||
|
|
public let grader: String?
|
||
|
|
/// The numeric grade, or `nil` for formats that are not graded.
|
||
|
|
public let grade: Double?
|
||
|
|
/// The condition as the seller states it, e.g. `NM` or `Like new`.
|
||
|
|
public let condition: String
|
||
|
|
/// The grader's certificate number, or `nil` for a raw copy.
|
||
|
|
public let certNumber: String?
|
||
|
|
/// The page quality, or `nil` when not stated.
|
||
|
|
public let pageQuality: String?
|
||
|
|
/// Why the issue is a key, or `nil` when it is not one.
|
||
|
|
public let keyNotes: String?
|
||
|
|
/// The seller's notes on the copy.
|
||
|
|
public let sellerNotes: String
|
||
|
|
/// The asking price, in euro cents.
|
||
|
|
public let priceCents: Int
|
||
|
|
/// The shipping cost to the Netherlands, in euro cents.
|
||
|
|
public let shippingCents: Int
|
||
|
|
/// Whether the seller takes offers on the copy.
|
||
|
|
public let acceptsOffers: Bool
|
||
|
|
/// The placeholder cover shown until listings carry photos.
|
||
|
|
public let cover: Cover
|
||
|
|
/// When the copy was listed.
|
||
|
|
public let listedAt: Date
|
||
|
|
|
||
|
|
// MARK: Initializers
|
||
|
|
|
||
|
|
public init(
|
||
|
|
slug: String,
|
||
|
|
shop: Shop,
|
||
|
|
title: String,
|
||
|
|
seriesTitle: String,
|
||
|
|
issueLabel: String,
|
||
|
|
publisher: String,
|
||
|
|
year: Int,
|
||
|
|
format: String,
|
||
|
|
printing: String,
|
||
|
|
printingDetail: String,
|
||
|
|
isFirstPrint: Bool,
|
||
|
|
grader: String?,
|
||
|
|
grade: Double?,
|
||
|
|
condition: String,
|
||
|
|
certNumber: String?,
|
||
|
|
pageQuality: String?,
|
||
|
|
keyNotes: String?,
|
||
|
|
sellerNotes: String,
|
||
|
|
priceCents: Int,
|
||
|
|
shippingCents: Int,
|
||
|
|
acceptsOffers: Bool,
|
||
|
|
cover: Cover,
|
||
|
|
listedAt: Date
|
||
|
|
) {
|
||
|
|
self.slug = slug
|
||
|
|
self.shop = shop
|
||
|
|
self.title = title
|
||
|
|
self.seriesTitle = seriesTitle
|
||
|
|
self.issueLabel = issueLabel
|
||
|
|
self.publisher = publisher
|
||
|
|
self.year = year
|
||
|
|
self.format = format
|
||
|
|
self.printing = printing
|
||
|
|
self.printingDetail = printingDetail
|
||
|
|
self.isFirstPrint = isFirstPrint
|
||
|
|
self.grader = grader
|
||
|
|
self.grade = grade
|
||
|
|
self.condition = condition
|
||
|
|
self.certNumber = certNumber
|
||
|
|
self.pageQuality = pageQuality
|
||
|
|
self.keyNotes = keyNotes
|
||
|
|
self.sellerNotes = sellerNotes
|
||
|
|
self.priceCents = priceCents
|
||
|
|
self.shippingCents = shippingCents
|
||
|
|
self.acceptsOffers = acceptsOffers
|
||
|
|
self.cover = cover
|
||
|
|
self.listedAt = listedAt
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
// MARK: - Extensions
|
||
|
|
|
||
|
|
public extension Listing {
|
||
|
|
|
||
|
|
// MARK: Computed
|
||
|
|
|
||
|
|
/// Whether the issue is a key.
|
||
|
|
var isKey: Bool {
|
||
|
|
keyNotes != nil
|
||
|
|
}
|
||
|
|
|
||
|
|
/// Whether the copy is graded and slabbed by a grading company.
|
||
|
|
var isSlabbed: Bool {
|
||
|
|
grader != nil
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
// MARK: - Structs
|
||
|
|
|
||
|
|
public extension Listing {
|
||
|
|
/// A placeholder cover: lettering on a toned ground.
|
||
|
|
struct Cover: Sendable, Equatable {
|
||
|
|
|
||
|
|
// MARK: Properties
|
||
|
|
|
||
|
|
/// The tone token naming the cover's colours, e.g. `navy`.
|
||
|
|
public let tone: String
|
||
|
|
/// The title lettering, one line per newline.
|
||
|
|
public let title: String
|
||
|
|
/// The publisher's imprint line.
|
||
|
|
public let imprint: String
|
||
|
|
/// The issue number or volume marker.
|
||
|
|
public let number: String
|
||
|
|
|
||
|
|
// MARK: Initializers
|
||
|
|
|
||
|
|
public init(
|
||
|
|
tone: String,
|
||
|
|
title: String,
|
||
|
|
imprint: String,
|
||
|
|
number: String
|
||
|
|
) {
|
||
|
|
self.tone = tone
|
||
|
|
self.title = title
|
||
|
|
self.imprint = imprint
|
||
|
|
self.number = number
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
}
|