// // LiveReservationCancelView.swift // SodaLive // // Created by klaus on 2023/08/11. // import SwiftUI import Kingfisher struct LiveReservationCancelView: View { @StateObject var viewModel = LiveReservationStatusViewModel() let reservationId: Int var body: some View { BaseView(isLoading: $viewModel.isLoading) { VStack(spacing: 0) { DetailNavigationBar(title: viewModel.isCancelComplete ? "예약취소 확인" : "예약취소") ScrollView(.vertical, showsIndicators: false) { VStack(spacing: 0) { if let item = viewModel.selectedReservationStatusItem { if viewModel.isCancelComplete { Text("예약취소가 완료되었습니다.") .font(.custom(Font.bold.rawValue, size: 20)) .foregroundColor(Color(hex: "a285eb")) .frame(width: screenSize().width - 26.7, alignment: .leading) .padding(.top, 33.3) if item.price > 0 { Text("결제한 \(item.price)캔이\n환불처리 되었습니다.") .font(.custom(Font.medium.rawValue, size: 20)) .foregroundColor(Color(hex: "eeeeee")) .frame(width: screenSize().width - 26.7, alignment: .leading) .padding(.top, 20) } HStack(spacing: 13.3) { Text("다른 라이브 예약하기") .font(.custom(Font.medium.rawValue, size: 15)) .foregroundColor(Color.button) .padding(.vertical, 16) .frame(width: (screenSize().width - 40) / 2) .background(Color.button.opacity(0.2)) .cornerRadius(10) .overlay( RoundedRectangle(cornerRadius: 10) .stroke( Color.button, lineWidth: 1 ) ) .onTapGesture { AppState.shared.setAppStep(step: .main) } Text("캔내역 확인하기") .font(.custom(Font.medium.rawValue, size: 15)) .foregroundColor(.white) .padding(.vertical, 16) .frame(width: (screenSize().width - 40) / 2) .background(Color.button) .cornerRadius(10) .onTapGesture { AppState.shared.setAppStep(step: .canStatus(refresh: {})) } } .frame(width: screenSize().width - 26.7, alignment: .leading) .padding(.top, 20) } else { HStack(spacing: 20) { KFImage(URL(string: item.coverImageUrl)) .resizable() .scaledToFill() .frame(width: 80, height: 116.7, alignment: .top) .cornerRadius(4.7) VStack(alignment: .leading, spacing: 0) { Text(item.beginDateTime) .font(.custom(Font.medium.rawValue, size: 9.3)) .foregroundColor(Color(hex: "ffd300")) Text(item.masterNickname) .font(.custom(Font.medium.rawValue, size: 11.3)) .foregroundColor(Color.graybb) .padding(.top, 10) Text(item.title) .font(.custom(Font.medium.rawValue, size: 15.3)) .foregroundColor(Color(hex: "e2e2e2")) .lineLimit(2) .padding(.top, 4.3) Text( item.price > 0 ? "\(item.price)캔" : "무료" ) .font(.custom(Font.medium.rawValue, size: 12)) .foregroundColor(Color(hex: "e2e2e2").opacity(0.4)) .padding(.top, 15.3) } } .padding(.horizontal, 13.3) .frame(width: screenSize().width) .padding(.top, 20) Rectangle() .foregroundColor(Color.gray90.opacity(0.5)) .padding(.horizontal, 13.3) .frame(width: screenSize().width, height: 1) .padding(.top, 13.3) VStack(spacing: 13.3) { Text("예약을 취소하시겠습니까?") .font(.custom(Font.bold.rawValue, size: 20)) .foregroundColor(Color(hex: "a285eb")) .frame(width: screenSize().width - 26.7, alignment: .leading) Text("예약취소 이유를 선택해주세요. 서비스 개선에 중요한 자료로 활용하겠습니다.") .font(.custom(Font.medium.rawValue, size: 13.3)) .foregroundColor(Color.grayee) .frame(width: screenSize().width - 26.7, alignment: .leading) } .padding(.top, 40) VStack(alignment: .leading, spacing: 16.7) { ForEach(0..<viewModel.cancelReasons.count, id: \.self) { index in let reason = viewModel.cancelReasons[index] HStack(spacing: 13.3) { Image( viewModel.cancelReasonSelectedIndex == index ? "btn_radio_select_selected" : "btn_radio_select_normal" ) .resizable() .frame(width: 20, height: 20) Text(reason) .font(.custom(Font.medium.rawValue, size: 13.3)) .foregroundColor(Color.grayee) if index == viewModel.cancelReasons.count - 1 { VStack(spacing: 6.7) { TextField("입력해주세요", text: $viewModel.reason) .autocapitalization(.none) .disableAutocorrection(true) .font(.custom(Font.medium.rawValue, size: 13.3)) .foregroundColor(Color.grayee) .keyboardType(.webSearch) Rectangle() .frame(height: 1) .foregroundColor(Color.gray90.opacity(0.5)) } } } .onTapGesture { viewModel.cancelReasonSelectedIndex = index } } } .frame(width: screenSize().width - 53.4, alignment: .leading) .padding(.top, 20) Rectangle() .frame(width: screenSize().width, height: 6.7) .foregroundColor(Color(hex: "232323")) .padding(.vertical, 20) Text("취소요청시, 차감했던 캔은 환불처리 됩니다. 수다방 참여인원 제한에 따라 재예약이 불가할 수 있습니다.") .font(.custom(Font.medium.rawValue, size: 12)) .foregroundColor(Color(hex: "ff5c49")) .frame(width: screenSize().width - 53.4, alignment: .leading) Text("예약취소") .font(.custom(Font.bold.rawValue, size: 15)) .foregroundColor(.white) .padding(.vertical, 16) .frame(width: screenSize().width - 26.7) .background(Color.button) .cornerRadius(6.7) .padding(.top, 90) .padding(.bottom, 13.3) .onTapGesture { viewModel.cancelReservation(reservationId: self.reservationId) } } } } } } } .popup(isPresented: $viewModel.isShowPopup, type: .toast, position: .top, autohideIn: 1) { GeometryReader { geo in HStack { Spacer() Text(viewModel.errorMessage) .padding(.vertical, 13.3) .padding(.horizontal, 6.7) .frame(width: geo.size.width - 66.7, alignment: .center) .font(.custom(Font.medium.rawValue, size: 12)) .background(Color.button) .foregroundColor(Color.white) .multilineTextAlignment(.leading) .fixedSize(horizontal: false, vertical: true) .cornerRadius(20) .padding(.top, 66.7) Spacer() } .onDisappear { if reservationId <= 0 { AppState.shared.back() } } } } .onAppear { if reservationId <= 0 { viewModel.errorMessage = "잘못된 예약정보 입니다." viewModel.isShowPopup = true } else { viewModel.getReservation(reservationId: reservationId) } } } } struct LiveReservationCancelView_Previews: PreviewProvider { static var previews: some View { LiveReservationCancelView(reservationId: 0) } }