import SwiftUI struct AtBatTimelineView: View { let pitches: [LiveFeedPlayEvent] var body: some View { VStack(alignment: .leading, spacing: 10) { Text("AT-BAT") .font(.system(size: 12, weight: .bold, design: .rounded)) .foregroundStyle(.white.opacity(0.5)) .kerning(1.2) HStack(spacing: 6) { ForEach(Array(pitches.enumerated()), id: \.offset) { index, pitch in let isLatest = index == pitches.count - 1 let code = pitchCallLetter(pitch.callCode) let color = pitchCallColor(pitch.callCode) Text(code) .font(.system(size: isLatest ? 14 : 13, weight: .black, design: .rounded)) .foregroundStyle(color) .padding(.horizontal, isLatest ? 12 : 10) .padding(.vertical, isLatest ? 7 : 6) .background(color.opacity(isLatest ? 0.25 : 0.15)) .clipShape(Capsule()) .overlay { if isLatest { Capsule() .strokeBorder(color.opacity(0.5), lineWidth: 1) } } } } if let last = pitches.last?.count { Text("\(last.balls)-\(last.strikes), \(last.outs) out\(last.outs == 1 ? "" : "s")") .font(.system(size: 14, weight: .semibold, design: .rounded)) .foregroundStyle(.white.opacity(0.6)) } } } } func pitchCallLetter(_ code: String) -> String { switch code { case "B": return "B" case "C": return "S" case "S": return "S" case "F": return "F" case "X", "D", "E": return "X" default: return "ยท" } } func pitchCallColor(_ code: String) -> Color { switch code { case "B": return .green case "C": return .red case "S": return .orange case "F": return .yellow case "X", "D", "E": return .blue default: return .white.opacity(0.5) } } func shortPitchType(_ code: String) -> String { switch code { case "FF": return "4SM" case "SI": return "SNK" case "FC": return "CUT" case "SL": return "SLD" case "CU", "KC": return "CRV" case "CH": return "CHG" case "FS": return "SPL" case "KN": return "KNK" case "ST": return "SWP" case "SV": return "SLV" default: return code } }