import SwiftUI struct BookmarkDetailView: View { let bookmarkId: String @State private var viewModel = BookmarkDetailViewModel() @State private var webViewHeight: CGFloat = 300 var body: some View { ScrollView { VStack(alignment: .leading, spacing: 16) { // Header mit Bild if !viewModel.bookmarkDetail.imageUrl.isEmpty { AsyncImage(url: URL(string: viewModel.bookmarkDetail.imageUrl)) { image in image .resizable() .aspectRatio(contentMode: .fill) } placeholder: { Rectangle() .fill(Color.gray.opacity(0.3)) .frame(height: 200) } .frame(height: 200) .clipped() } VStack(alignment: .leading, spacing: 6) { // Titel Text(viewModel.bookmarkDetail.title) .font(.largeTitle) .fontWeight(.bold) // Meta-Informationen metaInfoSection Divider() // Artikel-Inhalt mit WebView if !viewModel.articleContent.isEmpty { WebView(htmlContent: viewModel.articleContent) { height in webViewHeight = height } .frame(height: webViewHeight) } else if viewModel.isLoadingArticle { ProgressView("Lade Artikel...") .frame(maxWidth: .infinity, alignment: .center) .padding() } } .padding() } } .navigationBarTitleDisplayMode(.inline) .task { await viewModel.loadBookmarkDetail(id: bookmarkId) await viewModel.loadArticleContent(id: bookmarkId) } } private var metaInfoSection: some View { VStack(alignment: .leading, spacing: 8) { if !viewModel.bookmarkDetail.authors.isEmpty { HStack { Image(systemName: "person") Text(viewModel.bookmarkDetail.authors.joined(separator: ", ")) .font(.subheadline) .foregroundColor(.secondary) } } HStack { Image(systemName: "calendar") Text("Erstellt: \(formatDate(viewModel.bookmarkDetail.created))") .font(.subheadline) .foregroundColor(.secondary) } HStack { Image(systemName: "textformat") Text("\(viewModel.bookmarkDetail.wordCount) Wörter • \(viewModel.bookmarkDetail.readingTime) min Lesezeit") .font(.subheadline) .foregroundColor(.secondary) } } } private func formatDate(_ dateString: String) -> String { // Erstelle einen Formatter für das ISO8601-Format mit Millisekunden let isoFormatter = ISO8601DateFormatter() isoFormatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds] // Fallback für Format ohne Millisekunden let isoFormatterNoMillis = ISO8601DateFormatter() isoFormatterNoMillis.formatOptions = [.withInternetDateTime] // Versuche beide Formate var date: Date? if let parsedDate = isoFormatter.date(from: dateString) { date = parsedDate } else if let parsedDate = isoFormatterNoMillis.date(from: dateString) { date = parsedDate } if let date = date { let displayFormatter = DateFormatter() displayFormatter.dateStyle = .medium displayFormatter.timeStyle = .short displayFormatter.locale = Locale(identifier: "de_DE") return displayFormatter.string(from: date) } return dateString } } #Preview { NavigationView { BookmarkDetailView(bookmarkId: "sample-id") } }