import PromptGarageCore import SwiftUI struct PromptDetailView: View { @Bindable var model: AppModel var body: some View { Group { if let prompt = model.selectedPrompt { PromptDetailContent(model: model, prompt: prompt) } else { ContentUnavailableView { Label("Prompt auswählen", systemImage: "text.quote") } description: { Text("Wähle links einen Prompt aus, um Inhalt und Metadaten zu sehen.") } } } .navigationTitle(model.selectedPrompt?.title ?? "Details") } } private struct PromptDetailContent: View { @Bindable var model: AppModel let prompt: PromptRecord var body: some View { VStack(spacing: 0) { ScrollView { VStack(alignment: .leading, spacing: 22) { header metadata Divider() Text(prompt.content) .font(.body) .textSelection(.enabled) .frame(maxWidth: .infinity, alignment: .leading) .padding(.bottom, 16) } .padding(24) .frame(maxWidth: 820, alignment: .leading) .frame(maxWidth: .infinity) } Divider() actionBar } .background(Color(nsColor: .textBackgroundColor).opacity(0.38)) .toolbar { ToolbarItemGroup { Button { Task { await model.toggleStar(prompt) } } label: { Label( prompt.isStarred ? "Favorit entfernen" : "Favorit", systemImage: prompt.isStarred ? "star.fill" : "star" ) } .disabled(!model.canMutatePrompts) Menu { Button("Nur kopieren") { Task { await model.copy(prompt, countAsUse: false) } } Button("Bearbeiten …") { model.presentEditPrompt(prompt) } .disabled(!model.canMutatePrompts) Divider() Button("Löschen …", role: .destructive) { model.requestDelete(prompt) } .disabled(!model.canMutatePrompts) } label: { Label("Weitere Aktionen", systemImage: "ellipsis.circle") } } } } private var header: some View { VStack(alignment: .leading, spacing: 12) { Text(prompt.title) .font(.largeTitle.weight(.semibold)) .textSelection(.enabled) HStack(spacing: 12) { RatingControl(rating: prompt.rating) { rating in Task { await model.setRating(rating, for: prompt) } } .disabled(!model.canMutatePrompts) if prompt.isStarred { StatusChip(title: "Favorit", systemImage: "star.fill", tint: AppUI.accent) } StatusChip( title: "\(prompt.useCount)× verwendet", systemImage: "arrow.up.forward.circle" ) } } } private var metadata: some View { VStack(alignment: .leading, spacing: 10) { if !prompt.tagList.isEmpty { HStack(spacing: 6) { ForEach(prompt.tagList, id: \.self) { tag in StatusChip(title: tag, systemImage: "tag", tint: .primary) } } } Grid(alignment: .leading, horizontalSpacing: 18, verticalSpacing: 6) { GridRow { Text("Quelle").foregroundStyle(.secondary) Text(prompt.source ?? "Unbekannt").textSelection(.enabled) } if let modelName = prompt.model, !modelName.isEmpty { GridRow { Text("Modell").foregroundStyle(.secondary) Text(modelName).textSelection(.enabled) } } GridRow { Text("Aktualisiert").foregroundStyle(.secondary) Text(prompt.updatedAt).textSelection(.enabled) } if let promptedAt = prompt.promptedAt, !promptedAt.isEmpty { GridRow { Text("Prompt-Datum").foregroundStyle(.secondary) Text(promptedAt).textSelection(.enabled) } } else { GridRow { Text("Prompt-Datum").foregroundStyle(.secondary) Label( "Legacy · Originaldatum unbekannt", systemImage: "clock.badge.questionmark" ) .foregroundStyle(.secondary) } } } .font(.caption) } } private var actionBar: some View { HStack(spacing: 10) { Button("Bearbeiten") { model.presentEditPrompt(prompt) } .disabled(!model.canMutatePrompts) Spacer() Button { Task { await model.copy(prompt, countAsUse: model.canMutatePrompts) } } label: { Label( model.canMutatePrompts ? "Kopieren & als verwendet zählen" : "Prompt kopieren", systemImage: "doc.on.doc.fill" ) } .buttonStyle(.borderedProminent) .keyboardShortcut(.return, modifiers: [.command]) } .padding(14) .background(.bar) } }