// // LiveReservationItemView.swift // SodaLive // // Created by klaus on 2023/08/10. // import SwiftUI import Kingfisher struct LiveReservationItemView: View { let item: GetRoomListResponse @State var dateDic: [String: String] = [:] var body: some View { HStack(spacing: 16) { ZStack(alignment: .topLeading) { KFImage(URL(string: item.creatorProfileImage)) .cancelOnDisappear(true) .resizable() .scaledToFill() .frame(width: 100, height: 100, alignment: .top) .cornerRadius(16) .clipped() if item.isPrivateRoom { Image("ic_lock") .resizable() .frame(width: 20, height: 20) .padding(4) .background(Color(hex: "333333").opacity(0.7)) .clipShape(Circle()) .padding(.leading, 4) .padding(.top, 4) } } VStack(alignment: .leading, spacing: 8) { Text(item.creatorNickname) .font(.custom(Font.preRegular.rawValue, size: 18)) .foregroundColor(.white) .lineLimit(1) .truncationMode(.tail) Text(item.title) .font(.custom(Font.preRegular.rawValue, size: 14)) .foregroundColor(Color(hex: "B0BEC5")) .lineLimit(1) .truncationMode(.tail) HStack(spacing: 4) { Text("\(dateDic["dayOfWeek"] ?? "")") .font(.custom(Font.preRegular.rawValue, size: 14)) .foregroundColor(Color(hex: "78909C")) Text("|") .font(.custom(Font.preRegular.rawValue, size: 14)) .foregroundColor(Color(hex: "78909C")) Text("\(dateDic["time"] ?? "")") .font(.custom(Font.preRegular.rawValue, size: 14)) .foregroundColor(Color(hex: "98A2F6")) } } Spacer() VStack(alignment: .trailing, spacing: 8) { VStack(spacing: 0) { Text("\(dateDic["month"] ?? "")월") .font(.custom(Font.preBold.rawValue, size: 14)) .foregroundColor(.white) .padding(.vertical, 6) .frame(maxWidth: .infinity) .background(Color(hex: "FF5C49")) .cornerRadius(16, corners: [.topLeft, .topRight]) Text("\(dateDic["day"] ?? "")") .font(.custom(Font.preBold.rawValue, size: 14)) .foregroundColor(Color(hex: "263238")) .padding(.vertical, 6) .frame(maxWidth: .infinity) .background(Color(hex: "FFFFFF")) .cornerRadius(16, corners: [.bottomLeft, .bottomRight]) } if item.price > 0 { HStack(spacing: 2) { Image("ic_can_circle") .resizable() .frame(width: 12, height: 12) Text("\(item.price)") .font(.custom(Font.preRegular.rawValue, size: 12)) .foregroundColor(.white) } .padding(4) .frame(maxWidth: .infinity) .background(Color(hex: "3b5ff1")) .cornerRadius(4) } else { Text("무료") .font(.custom(Font.preRegular.rawValue, size: 14)) .foregroundColor(Color(hex: "#263238")) .padding(4) .frame(maxWidth: .infinity) .background(Color.white) .cornerRadius(4) } } .frame(width: 55) } .padding(10) .background(Color(hex: "263238")) .cornerRadius(16) .onAppear { self.dateDic = parseUtcIsoLocalDateTime(item.beginDateTimeUtc) } } func parseUtcIsoLocalDateTime(_ utcString: String) -> [String: String] { // 1. 서버에서 내려온 포맷: "yyyy-MM-dd'T'HH:mm:ss" let utcFormatter = DateFormatter() utcFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss" utcFormatter.locale = Locale.current utcFormatter.timeZone = TimeZone(abbreviation: "UTC") // 2. 문자열 → Date 객체 guard let date = utcFormatter.date(from: utcString) else { return [:] // 파싱 실패 시 빈 딕셔너리 반환 } // 3~6. 출력용 Formatter (로컬 시간 기준) let localFormatter = DateFormatter() localFormatter.locale = Locale.current localFormatter.timeZone = TimeZone.current // 3. 월 (1~12) localFormatter.dateFormat = "M" let month = localFormatter.string(from: date) // 4. 일 (1~31) localFormatter.dateFormat = "d" let day = localFormatter.string(from: date) // 5. 요일 (예: "Mon", "목") localFormatter.dateFormat = "E" let dayOfWeek = localFormatter.string(from: date) // 6. 시간 (예: "AM 05:00") localFormatter.dateFormat = "a hh:mm" let time = localFormatter.string(from: date) return [ "month": month, "day": day, "dayOfWeek": dayOfWeek, "time": time ] } } struct LiveReservationItemView_Previews: PreviewProvider { static var previews: some View { LiveReservationItemView(item: GetRoomListResponse( roomId: 99, title: "test", content: "testtest", beginDateTime: "2022.05.23 Mon 03:00 PM", beginDateTimeUtc: "2025-08-10T15:00:00", numberOfParticipate: 0, numberOfPeople: 5, coverImageUrl: "https://test-cf.sodalive.net/profile/default-profile.png", isAdult: false, price: 0, tags: ["팬미팅", "힐링"], channelName: nil, creatorProfileImage: "https://test-cf.sodalive.net/profile/default-profile.png", creatorNickname: "user8", creatorId: 19, isReservation: false, isPrivateRoom: true )) } }