diff --git a/KisaniCal/Models/ExerciseModels.swift b/KisaniCal/Models/ExerciseModels.swift index 6d1eadd..f600299 100644 --- a/KisaniCal/Models/ExerciseModels.swift +++ b/KisaniCal/Models/ExerciseModels.swift @@ -527,7 +527,7 @@ class WorkoutViewModel: ObservableObject { ]) // ── Wednesday: Shoulders, Triceps & Biceps ─────────────────────────── - let wed = WorkoutProgram(name: "Shoulders & Arms", emoji: "🔥", colorIndex: 2, sections: [ + let wed = WorkoutProgram(name: "Shoulders & Arms", emoji: "🔄", colorIndex: 2, sections: [ warmUp, WorkoutSection(name: "Shoulders", exercises: [ Exercise(name: "Reverse Fly", sfSymbol: "dumbbell.fill", colorIndex: 2, sets: s(3)), @@ -580,7 +580,7 @@ class WorkoutViewModel: ObservableObject { ]) // ── Saturday: Full Body ────────────────────────────────────────────── - let sat = WorkoutProgram(name: "Full Body", emoji: "💥", colorIndex: 1, sections: [ + let sat = WorkoutProgram(name: "Full Body", emoji: "🏋️", colorIndex: 1, sections: [ warmUp, WorkoutSection(name: "Upper Body", exercises: [ Exercise(name: "Incline Bench Press",sfSymbol: "figure.strengthtraining.traditional", colorIndex: 0, sets: s(3)), diff --git a/KisaniCal/Views/TodayView.swift b/KisaniCal/Views/TodayView.swift index d2e3e4f..de8c965 100644 --- a/KisaniCal/Views/TodayView.swift +++ b/KisaniCal/Views/TodayView.swift @@ -307,62 +307,61 @@ struct WorkoutTodayBanner: View { var body: some View { VStack(alignment: .leading, spacing: 0) { - // ── Header row — taps open session ── - HStack(spacing: 6) { - Image(systemName: isDone ? "checkmark.seal.fill" : "dumbbell.fill") - .font(.system(size: 10)) - Text(isDone ? "WORKOUT COMPLETE" : "TODAY'S WORKOUT") - .font(AppFonts.mono(9, weight: .bold)) - Spacer() - Text(setsText).font(AppFonts.mono(9)).foregroundColor(AppColors.text3(cs)) - Image(systemName: "chevron.right") - .font(.system(size: 9, weight: .semibold)) - .foregroundColor(accent.opacity(0.5)) - } - .foregroundColor(accent) - .padding(.horizontal, 13).padding(.top, 10).padding(.bottom, 8) - .contentShape(Rectangle()) - .onTapGesture { onTap() } + // ── Main row — progress ring leads ── + HStack(spacing: 13) { + // Progress ring (or idle ring when not active) + ZStack { + Circle() + .stroke(AppColors.borderHi(cs), lineWidth: 3) + .frame(width: 44, height: 44) + if isActiveProgram && vm.totalSets > 0 { + Circle() + .trim(from: 0, to: CGFloat(min(vm.progress, 1))) + .stroke(accent, style: StrokeStyle(lineWidth: 3, lineCap: .round)) + .frame(width: 44, height: 44) + .rotationEffect(.degrees(-90)) + .animation(KisaniSpring.entrance, value: vm.progress) + } + if isDone { + Image(systemName: "checkmark") + .font(.system(size: 11, weight: .semibold)) + .foregroundColor(accent) + } else if isActiveProgram && vm.totalSets > 0 { + Text("\(Int(vm.progress * 100))%") + .font(AppFonts.mono(9, weight: .bold)) + .foregroundColor(accent) + } else { + Image(systemName: "dumbbell") + .font(.system(size: 13, weight: .regular)) + .foregroundColor(AppColors.text3(cs)) + } + } - Divider().background(accent.opacity(0.15)) - - // ── Program identity row — taps open session ── - HStack(spacing: 10) { - Text(program.emoji).font(.system(size: 18)) - .frame(width: 36, height: 36) - .background(isDone ? AppColors.greenSoft : AppColors.blueSoft) - .clipShape(RoundedRectangle(cornerRadius: 9)) - - VStack(alignment: .leading, spacing: 2) { + VStack(alignment: .leading, spacing: 3) { + HStack(spacing: 5) { + Text(isDone ? "DONE" : "TODAY") + .font(AppFonts.mono(8, weight: .bold)) + .foregroundColor(accent) + Text("·") + .font(AppFonts.mono(8)) + .foregroundColor(AppColors.text3(cs)) + Text(setsText) + .font(AppFonts.mono(8)) + .foregroundColor(AppColors.text3(cs)) + } Text(program.name) - .font(AppFonts.sans(13, weight: .semibold)) + .font(AppFonts.sans(14, weight: .semibold)) .foregroundColor(AppColors.text(cs)) Text("\(program.sections.count) section\(program.sections.count == 1 ? "" : "s") · \(program.totalExercises) exercise\(program.totalExercises == 1 ? "" : "s")") - .font(AppFonts.mono(9.5)) + .font(AppFonts.mono(9)) .foregroundColor(AppColors.text3(cs)) } Spacer() - - if isActiveProgram && vm.totalSets > 0 { - ZStack { - Circle().stroke(AppColors.borderHi(cs), lineWidth: 2.5).frame(width: 34, height: 34) - Circle().trim(from: 0, to: CGFloat(vm.progress)) - .stroke(accent, style: StrokeStyle(lineWidth: 2.5, lineCap: .round)) - .frame(width: 34, height: 34).rotationEffect(.degrees(-90)) - .animation(KisaniSpring.entrance, value: vm.progress) - if isDone { - Image(systemName: "checkmark") - .font(.system(size: 10, weight: .bold)) - .foregroundColor(AppColors.green) - } else { - Text("\(Int(vm.progress * 100))%") - .font(AppFonts.mono(8.5, weight: .bold)) - .foregroundColor(accent) - } - } - } + Image(systemName: "chevron.right") + .font(.system(size: 10, weight: .semibold)) + .foregroundColor(AppColors.text3(cs)) } - .padding(.horizontal, 13).padding(.vertical, 10) + .padding(.horizontal, 13).padding(.vertical, 12) .contentShape(Rectangle()) .onTapGesture { onTap() } @@ -408,9 +407,9 @@ struct WorkoutTodayBanner: View { } } } - .background(accent.opacity(0.07)) + .background(AppColors.surface(cs)) .clipShape(RoundedRectangle(cornerRadius: AppRadius.large)) - .overlay(RoundedRectangle(cornerRadius: AppRadius.large).stroke(accent.opacity(0.2), lineWidth: 1)) + .overlay(RoundedRectangle(cornerRadius: AppRadius.large).stroke(AppColors.border(cs), lineWidth: 1)) .animation(KisaniSpring.entrance, value: isDone) } } diff --git a/KisaniCal/Views/WorkoutView.swift b/KisaniCal/Views/WorkoutView.swift index 8dbc9b3..aeb9033 100644 --- a/KisaniCal/Views/WorkoutView.swift +++ b/KisaniCal/Views/WorkoutView.swift @@ -374,7 +374,7 @@ struct ProgressRingCard: View { VStack(alignment: .leading, spacing: 2) { Text("\(done) / \(total) sets done") .font(AppFonts.sans(12.5, weight: .semibold)).foregroundColor(AppColors.text(cs)) - Text(total == 0 ? "Add exercises to get started" : done == total && total > 0 ? "Workout complete! 🎉" : "Keep going 🔥") + Text(total == 0 ? "Add exercises to get started" : done == total && total > 0 ? "All sets done" : "\(total - done) sets remaining") .font(AppFonts.sans(10)).foregroundColor(AppColors.text3(cs)) } Spacer() @@ -387,24 +387,31 @@ struct ProgressRingCard: View { struct StreakBannerView: View { @Environment(\.colorScheme) private var cs let streak: Int + var body: some View { - HStack(spacing: 10) { - Text("\(streak)").font(AppFonts.mono(26, weight: .bold)).foregroundColor(AppColors.accent) - VStack(alignment: .leading, spacing: 1) { - Text("Day Streak").font(AppFonts.sans(12, weight: .semibold)).foregroundColor(AppColors.text(cs)) - Text("Don't break the chain").font(AppFonts.sans(10)).foregroundColor(AppColors.text3(cs)) + HStack(spacing: 0) { + VStack(alignment: .leading, spacing: 2) { + Text("\(streak)") + .font(AppFonts.mono(28, weight: .bold)) + .foregroundColor(AppColors.text(cs)) + Text("day streak") + .font(AppFonts.sans(11)) + .foregroundColor(AppColors.text3(cs)) } Spacer() - HStack(spacing: 4) { + // 7-day tick bar — current week progress + HStack(spacing: 3) { ForEach(0..<7, id: \.self) { i in - Circle().fill(i < streak ? AppColors.accent : AppColors.borderHi(cs)).frame(width: 7, height: 7) + let filled = streak > 0 && i < (streak % 7 == 0 ? 7 : streak % 7) + RoundedRectangle(cornerRadius: 1.5) + .fill(filled ? AppColors.accent : AppColors.borderHi(cs)) + .frame(width: 18, height: 3) } } } - .padding(11) - .background(LinearGradient(colors: [AppColors.accent.opacity(0.12), AppColors.yellow.opacity(0.08)], startPoint: .topLeading, endPoint: .bottomTrailing)) - .clipShape(RoundedRectangle(cornerRadius: AppRadius.large)) - .overlay(RoundedRectangle(cornerRadius: AppRadius.large).stroke(AppColors.accent.opacity(0.18), lineWidth: 1)) + .padding(.horizontal, 14) + .padding(.vertical, 13) + .cardStyle() } } @@ -1116,7 +1123,7 @@ struct RenameProgramSheet: View { @State private var name: String @State private var selectedEmoji: String @FocusState private var nameFocused: Bool - private let emojis = ["💪", "🦵", "🔄", "🏃", "🤸", "🏋️", "🧘", "🚴", "🥊", "🎯", "⚡️", "🔥"] + private let emojis = ["💪", "🦵", "🔄", "🏃", "🤸", "🏋️", "🧘", "🚴", "🥊", "🎯", "⚡️", "🫀"] init(program: WorkoutProgram) { self.program = program @@ -1190,7 +1197,7 @@ struct AddProgramSheet: View { @State private var name = "" @State private var selectedEmoji = "💪" @FocusState private var nameFocused: Bool - private let emojis = ["💪", "🦵", "🔄", "🏃", "🤸", "🏋️", "🧘", "🚴", "🥊", "🎯", "⚡️", "🔥"] + private let emojis = ["💪", "🦵", "🔄", "🏃", "🤸", "🏋️", "🧘", "🚴", "🥊", "🎯", "⚡️", "🫀"] var body: some View { VStack(spacing: 0) {