diff --git a/nahbar/AftermathRatingFlowView.swift b/nahbar/AftermathRatingFlowView.swift index bca52ca..33b5c9d 100644 --- a/nahbar/AftermathRatingFlowView.swift +++ b/nahbar/AftermathRatingFlowView.swift @@ -2,18 +2,19 @@ import SwiftUI import SwiftData // MARK: - AftermathRatingFlowView -// Sheet-basierter Bewertungs-Flow für die Nachwirkungs-Bewertung (4 Fragen). -// Wird aus einer Push-Notification heraus oder aus der Momente-Liste geöffnet. +// Scrollbarer Bewertungs-Flow für die Nachwirkungs-Bewertung (4 Fragen). +// Gleiche Interaktion wie MeetingRatingFlowView – Fragen blenden nacheinander ein. struct AftermathRatingFlowView: View { @Environment(\.modelContext) private var modelContext + @Environment(\.nahbarTheme) var theme @Environment(\.dismiss) private var dismiss let moment: Moment - private let questions = RatingQuestion.aftermath // 4 Fragen - @State private var currentIndex: Int = 0 + private let questions = RatingQuestion.aftermath // 4 Fragen @State private var values: [Int?] + @State private var revealedCount: Int = 1 @State private var showSummary: Bool = false init(moment: Moment) { @@ -27,7 +28,7 @@ struct AftermathRatingFlowView: View { if showSummary { MeetingSummaryView(moment: moment, onDismiss: { dismiss() }) } else { - questionStep + questionFlow } } .navigationTitle("Nachwirkung") @@ -36,46 +37,80 @@ struct AftermathRatingFlowView: View { ToolbarItem(placement: .cancellationAction) { Button("Abbrechen") { dismiss() } } - if !showSummary { - ToolbarItem(placement: .confirmationAction) { - Button(currentIndex == questions.count - 1 ? "Fertig" : "Weiter") { - advance() - } + } + } + } + + // MARK: - Scrollbarer Fragen-Flow + + private var questionFlow: some View { + ScrollViewReader { proxy in + ScrollView { + VStack(spacing: 14) { + ForEach(0.. Void // Dot ausgewählt (nur wenn isActive) + let onSkip: () -> Void // Überspringen getippt (nur wenn isActive) + + var body: some View { + VStack(alignment: .leading, spacing: 16) { + HStack { + Text("\(index + 1) / \(total)") + .font(.caption.weight(.medium)) + .foregroundStyle(theme.contentTertiary) + Spacer() + HStack(spacing: 5) { + Image(systemName: question.category.icon) + .font(.caption.bold()) + Text(LocalizedStringKey(question.category.rawValue)) + .font(.caption.bold()) + } + .foregroundStyle(question.category.color) + .padding(.horizontal, 10) + .padding(.vertical, 5) + .background(question.category.color.opacity(0.12), in: Capsule()) + } + + Text(LocalizedStringKey(question.text)) + .font(.system(size: 16, weight: .semibold, design: theme.displayDesign)) + .foregroundStyle(theme.contentPrimary) + .fixedSize(horizontal: false, vertical: true) + + RatingDotPicker( + value: $value, + negativePole: question.negativePole, + positivePole: question.positivePole + ) + .onChange(of: value) { _, newValue in + if isActive, newValue != nil { + onAnswer() + } + } + + if isActive { + Button { + value = nil + onSkip() + } label: { + Text("Überspringen") + .font(.subheadline) + .foregroundStyle(.secondary) + } + .buttonStyle(.plain) + } + } + .padding(16) + .background(theme.surfaceCard) + .clipShape(RoundedRectangle(cornerRadius: theme.radiusCard)) + .opacity(isActive ? 1.0 : 0.75) + } +} + // MARK: - RatingQuestionView // Zeigt eine einzelne Bewertungsfrage mit Kategorie-Badge, Fragetext, // RatingDotPicker und "Überspringen"-Button. diff --git a/nahbar/VisitRatingFlowView.swift b/nahbar/VisitRatingFlowView.swift index 3142446..807d6be 100644 --- a/nahbar/VisitRatingFlowView.swift +++ b/nahbar/VisitRatingFlowView.swift @@ -2,24 +2,21 @@ import SwiftUI import SwiftData // MARK: - MeetingRatingFlowView -// Sheet-basierter Bewertungs-Flow für die Sofort-Bewertung eines Treffen-Moments. -// Erwartet einen bereits gespeicherten Moment vom Typ .meeting und ergänzt ihn -// um Ratings sowie den Nachwirkungs-Status. +// Scrollbarer Bewertungs-Flow für die Sofort-Bewertung eines Treffens. +// Fragen blenden nacheinander von unten ein, sobald die vorherige beantwortet wurde. +// Nach der letzten Frage erscheint ein "Speichern"-Button. struct MeetingRatingFlowView: View { @Environment(\.modelContext) private var modelContext + @Environment(\.nahbarTheme) var theme @Environment(\.dismiss) private var dismiss let moment: Moment - - // Nachwirkungs-Verzögerung (aus App-Einstellungen übergeben) var aftermathDelay: TimeInterval = 36 * 3600 - // MARK: State - private let questions = RatingQuestion.immediate // 5 Fragen - @State private var currentIndex: Int = 0 - @State private var values: [Int?] // [nil] × 5 + @State private var values: [Int?] + @State private var revealedCount: Int = 1 @State private var showSummary: Bool = false init(moment: Moment, aftermathDelay: TimeInterval = 36 * 3600) { @@ -34,7 +31,7 @@ struct MeetingRatingFlowView: View { if showSummary { MeetingSummaryView(moment: moment, onDismiss: { dismiss() }) } else { - questionStep + questionFlow } } .navigationTitle("Treffen bewerten") @@ -43,43 +40,75 @@ struct MeetingRatingFlowView: View { ToolbarItem(placement: .cancellationAction) { Button("Abbrechen") { dismiss() } } - if !showSummary { - ToolbarItem(placement: .confirmationAction) { - Button(currentIndex == questions.count - 1 ? "Fertig" : "Weiter") { - advance() - } + } + } + } + + // MARK: - Scrollbarer Fragen-Flow + + private var questionFlow: some View { + ScrollViewReader { proxy in + ScrollView { + VStack(spacing: 14) { + ForEach(0..