// // CVFilledPreviewPageView.swift // App for Indeed // // Full-screen preview of a profile merged into the selected CV template. // import Cocoa private final class CVPreviewFlippedDocumentView: NSView { override var isFlipped: Bool { true } } /// Hosts a scrollable `CVProfileDocumentView` with a simple chrome header and back navigation. final class CVFilledPreviewPageView: NSView { var onDismiss: (() -> Void)? private let backButton = NSButton(title: "← Profiles", target: nil, action: nil) private let titleLabel = NSTextField(labelWithString: "CV preview") private let scrollView = NSScrollView() private let documentView = CVPreviewFlippedDocumentView() private let contentStack = NSStackView() private static let pageBackground = NSColor(srgbRed: 1, green: 1, blue: 1, alpha: 1) private static let secondaryText = NSColor(srgbRed: 100 / 255, green: 116 / 255, blue: 139 / 255, alpha: 1) private static let brandBlue = NSColor(srgbRed: 37 / 255, green: 87 / 255, blue: 167 / 255, alpha: 1) override init(frame frameRect: NSRect) { super.init(frame: frameRect) wantsLayer = true layer?.backgroundColor = Self.pageBackground.cgColor userInterfaceLayoutDirection = .leftToRight backButton.translatesAutoresizingMaskIntoConstraints = false backButton.bezelStyle = .rounded backButton.isBordered = false backButton.font = .systemFont(ofSize: 13, weight: .semibold) backButton.contentTintColor = Self.brandBlue backButton.target = self backButton.action = #selector(didTapBack) titleLabel.font = .systemFont(ofSize: 18, weight: .semibold) titleLabel.textColor = NSColor(srgbRed: 31 / 255, green: 41 / 255, blue: 55 / 255, alpha: 1) let subtitle = NSTextField(wrappingLabelWithString: "Your profile fields are laid out using the template you chose in CV Maker.") subtitle.font = .systemFont(ofSize: 12, weight: .regular) subtitle.textColor = Self.secondaryText subtitle.maximumNumberOfLines = 0 let headerCol = NSStackView(views: [backButton, titleLabel, subtitle]) headerCol.orientation = .vertical headerCol.alignment = .leading headerCol.spacing = 6 headerCol.setCustomSpacing(14, after: backButton) headerCol.translatesAutoresizingMaskIntoConstraints = false contentStack.orientation = .vertical contentStack.alignment = .leading contentStack.spacing = 20 contentStack.translatesAutoresizingMaskIntoConstraints = false documentView.translatesAutoresizingMaskIntoConstraints = false documentView.addSubview(contentStack) scrollView.translatesAutoresizingMaskIntoConstraints = false scrollView.drawsBackground = false scrollView.hasVerticalScroller = true scrollView.hasHorizontalScroller = false scrollView.autohidesScrollers = true scrollView.borderType = .noBorder scrollView.documentView = documentView addSubview(headerCol) addSubview(scrollView) NSLayoutConstraint.activate([ headerCol.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 32), headerCol.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -32), headerCol.topAnchor.constraint(equalTo: topAnchor, constant: 16), scrollView.leadingAnchor.constraint(equalTo: leadingAnchor), scrollView.trailingAnchor.constraint(equalTo: trailingAnchor), scrollView.topAnchor.constraint(equalTo: headerCol.bottomAnchor, constant: 16), scrollView.bottomAnchor.constraint(equalTo: bottomAnchor), documentView.leadingAnchor.constraint(equalTo: scrollView.contentView.leadingAnchor), documentView.widthAnchor.constraint(equalTo: scrollView.contentView.widthAnchor), documentView.topAnchor.constraint(equalTo: scrollView.contentView.topAnchor), documentView.bottomAnchor.constraint(equalTo: contentStack.bottomAnchor, constant: 40), contentStack.leadingAnchor.constraint(equalTo: documentView.leadingAnchor, constant: 32), contentStack.trailingAnchor.constraint(lessThanOrEqualTo: documentView.trailingAnchor, constant: -32), contentStack.topAnchor.constraint(equalTo: documentView.topAnchor, constant: 8), contentStack.widthAnchor.constraint(lessThanOrEqualTo: documentView.widthAnchor, constant: -64) ]) } @available(*, unavailable) required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } func configure(profile: SavedProfile, template: CVTemplate) { for v in contentStack.arrangedSubviews { contentStack.removeArrangedSubview(v) v.removeFromSuperview() } let doc = CVProfileDocumentView(profile: profile, template: template) contentStack.addArrangedSubview(doc) let profileTitle = profile.profileDisplayName.isEmpty ? "Untitled profile" : profile.profileDisplayName titleLabel.stringValue = "\(template.name) · \(profileTitle)" } @objc private func didTapBack() { onDismiss?() } }