ChWebsiteApp/CHDataManagement/Views/Posts/PostDetailView.swift
2025-01-18 12:02:54 +01:00

136 lines
3.8 KiB
Swift

import SwiftUI
private struct DetailListItem<Content>: View where Content: View {
private let alignment: VerticalAlignment
private let spacing: CGFloat?
private let content: Content
init(alignment: VerticalAlignment = .center,
spacing: CGFloat? = nil,
@ViewBuilder content: () -> Content) {
self.alignment = alignment
self.spacing = spacing
self.content = content()
}
var body: some View {
HStack(alignment: alignment,
spacing: spacing) {
content
}
.padding(.horizontal)
.padding(.vertical)
.background(Color(NSColor.windowBackgroundColor))
.cornerRadius(8)
}
}
struct PostDetailView: View {
@Environment(\.language)
private var language
@EnvironmentObject
private var content: Content
@EnvironmentObject
private var selection: SelectedContent
@ObservedObject
private var post: Post
@State
private var showLinkedPagePicker = false
init(post: Post) {
self.post = post
}
private var transferImage: (language: ContentLanguage, image: FileResource)? {
post.localized(in: language.next).linkPreview.image.map { (language.next, $0) }
}
var body: some View {
ScrollView {
VStack(alignment: .leading) {
DetailTitle(
title: "Post",
text: "Posts capture quick updates and can link to pages")
if post.linkedPage == nil {
Button("Create page", action: createPageFromPost)
}
IdPropertyView(
id: $post.id,
footer: "The id is used to link to post and store them",
validation: post.isValid,
update: { post.update(id: $0) })
BoolPropertyView(
title: "Draft",
value: $post.isDraft,
footer: "Indicate a post as a draft to hide it from the website")
DatePropertyView(
title: "Start date",
value: $post.startDate,
footer: "The date when the post content started")
OptionalDatePropertyView(
title: "End date",
isEnabled: $post.hasEndDate,
date: $post.potentialEndDate,
footer: "The date when the post content ended")
PagePropertyView(
title: "Linked page",
selectedPage: $post.linkedPage,
footer: "The page to open when clicking on the post")
.onChange(of: post.linkedPage) { oldValue, newValue in
if newValue != nil {
post.tags = []
} else {
// Link removed, so copy tags from previous link
if let oldValue {
post.tags = oldValue.tags
}
}
}
LocalizedPostDetailView(
post: post.localized(in: language),
transferImage: transferImage)
}
.padding()
}
}
private func createPageFromPost() {
let page = post.makePage()
DispatchQueue.main.async {
content.pages.insert(page, at: 0)
post.linkedPage = page
selection.page = page
selection.tab = .pages
}
}
}
extension PostDetailView: MainContentView {
init(item: Post) {
self.init(post: item)
}
static let itemDescription = "a post"
}
#Preview(traits: .fixedLayout(width: 270, height: 500)) {
PostDetailView(post: .fullMock)
}