diff --git a/Pickle/Pickle/Screen/Home/TimerReportView.swift b/Pickle/Pickle/Screen/Home/TimerReportView.swift index 7b9d0da..dfff733 100644 --- a/Pickle/Pickle/Screen/Home/TimerReportView.swift +++ b/Pickle/Pickle/Screen/Home/TimerReportView.swift @@ -11,8 +11,12 @@ struct TimerReportView: View { @Environment(\.dismiss) private var dismiss + @Binding var isShowingReportSheet: Bool + @Binding var isComplete: Bool + @Binding var isShowingTimerView: Bool + var todo: Todo - var spendTime: Int + var spendTime: TimeInterval var body: some View { VStack { @@ -30,7 +34,7 @@ struct TimerReportView: View { HStack { Text("총 소요 시간") Spacer() - Text(convertSecondsToTime(timeInSecond: spendTime)) + Text(convertSecondsToTime(timeInSecond: Int(spendTime))) } } .font(.pizzaTitle2Bold) @@ -71,11 +75,16 @@ struct TimerReportView: View { } Button(action: { - + isShowingTimerView = false + isShowingReportSheet = false + dismiss() }, label: { Text("확인") }) } + .onAppear { + isComplete = true + } } func convertSecondsToTime(timeInSecond: Int) -> String { let hours = timeInSecond / 3600 // 시 @@ -92,7 +101,7 @@ struct TimerReportView: View { struct TimerReportView_Previews: PreviewProvider { static var previews: some View { - TimerReportView(todo: Todo(id: UUID().uuidString, + TimerReportView(isShowingReportSheet: .constant(false), isComplete: .constant(false), isShowingTimerView: .constant(false), todo: Todo(id: UUID().uuidString, content: "이력서 작성하기", startTime: Date(), targetTime: 60, diff --git a/Pickle/Pickle/Screen/Home/TimerView.swift b/Pickle/Pickle/Screen/Home/TimerView.swift index 5980af4..a436bbc 100644 --- a/Pickle/Pickle/Screen/Home/TimerView.swift +++ b/Pickle/Pickle/Screen/Home/TimerView.swift @@ -13,163 +13,184 @@ struct TimerView: View { var todo: Todo let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect() - @State var targetTime: TimeInterval = 1 // 목표소요시간 - @State var timeRemaining: TimeInterval = 0 // 남은 시간 - @State var spendTime: TimeInterval = 0 // 실제 소요시간 - @State var timeExtra: TimeInterval = 0 // 추가소요시간 - @State var settingTime: TimeInterval = 0 // 원형 타이머 설정용 시간 + @State private var targetTime: TimeInterval = 1 // 목표소요시간 + @State private var timeRemaining: TimeInterval = 0 // 남은 시간 + @State private var spendTime: TimeInterval = 0 // 실제 소요시간 + @State private var timeExtra: TimeInterval = 0 // 추가소요시간 + @State private var settingTime: TimeInterval = 0 // 원형 타이머 설정용 시간 + @State private var completeLimit: TimeInterval = 10 // 5분 이후 + @State private var isDisabled: Bool = true // 완료버튼 활성화 용도 - @State var isShowGiveupAlert: Bool = false - @State var isDecresing: Bool = true - @State var isStart: Bool = true + @State private var isGiveupSign: Bool = false + @State private var isShowGiveupAlert: Bool = false + @State private var isDecresing: Bool = true + @State private var isStart: Bool = true + @State private var isShowingReportSheet: Bool = false + @State private var isComplete: Bool = false // '완료'버튼 누를때 시간 멈추기 확인용 + @Binding var isShowingTimerView: Bool var body: some View { VStack { - // TODO: RegisterView처럼 랜덤으로 바꿔주기 // 멘트부분 if isStart { Text("따라 읽어봐요!") .font(Font.pizzaTitleBold) .padding(.top) - .padding(.bottom, 50) + + Text("") + .foregroundColor(.secondary) + .padding(.top, 10) + .padding(.bottom, 40) } else { - Text("시작이 반이다! 시작했네유~") + Text(todo.content) .font(Font.pizzaTitleBold) .padding(.top) - .padding(.bottom, 50) + + // TODO: RegisterView처럼 랜덤으로 바꿔주기 + Text("🍕 굽는 중") + .foregroundColor(.secondary) + .padding(.top, 10) + .padding(.bottom, 40) } - // 타이머 부분 + // MARK: 타이머 부분 ZStack { Circle() - .fill(Color.lightGray) + .fill(.clear) .frame(width: CGFloat.screenWidth * 0.75) - .overlay(Circle().stroke(Color.defaultGray, lineWidth: 20)) + .overlay(Circle().stroke(.tertiary, lineWidth: 5)) Circle() .trim(from: 0, to: progress()) - .stroke(Color.black, style: StrokeStyle(lineWidth: 19, lineCap: .round)) + .stroke(Color.primary, style: StrokeStyle(lineWidth: 5, lineCap: .round)) .frame(width: CGFloat.screenWidth * 0.75) .rotationEffect(.degrees(-90)) - VStack { - if isStart { - if timeRemaining != 0 { - Text(String(format: "%g", timeRemaining)) - .font(Font.system(size: 40)) - .fontWeight(.heavy) - .onReceive(timer) { _ in - timeRemaining -= 1 - } - } else { - Text("시작") - .font(Font.system(size: 40)) - .fontWeight(.heavy) - .onReceive(timer) { _ in - calcRemain() - } - } + + if isStart { + if timeRemaining != 0 { + Text(String(format: "%g", timeRemaining)) + .font(Font.system(size: 40)) + .fontWeight(.heavy) + .onReceive(timer) { _ in + timeRemaining -= 1 + } } else { - Image("smilePizza") - .resizable() - .aspectRatio(contentMode: .fit) - .frame(width: CGFloat.screenWidth * 0.5) - - if isDecresing { - // 남은시간 줄어드는 타이머 - Text(convertSecondsToTime(timeInSecond: timeRemaining)) - .font(Font.pizzaTitleBold) - .onReceive(timer) { _ in + Text("시작") + .font(Font.system(size: 40)) + .fontWeight(.heavy) + .onReceive(timer) { _ in + calcRemain() + } + } + } else { + + if isDecresing { + // 남은시간 줄어드는 타이머 + Text(convertSecondsToTime(timeInSecond: timeRemaining)) + .font(Font.pizzaTitleBold) + .onReceive(timer) { _ in + if !isComplete { timeRemaining -= 1 + spendTime += 1 if timeRemaining == 0 { turnMode() } + if spendTime >= completeLimit { + isDisabled = false + } } - } else { - // 추가시간 늘어나는 타이머 - HStack { - Text("+ \(convertSecondsToTime(timeInSecond: timeExtra))") - .font(Font.pizzaTitleBold) - .onReceive(timer) { _ in + } + } else { + // 추가시간 늘어나는 타이머 + HStack { + Text("+ \(convertSecondsToTime(timeInSecond: timeExtra))") + .font(Font.pizzaTitleBold) + .onReceive(timer) { _ in + if !isStart && !isComplete { timeExtra += 1 - if timeExtra.truncatingRemainder(dividingBy: 600) == 0 { - turnMode() - } + spendTime += 1 } - } + } } - - // 실제 소요시간 타이머 - Text(convertSecondsToTime(timeInSecond: spendTime)) - .foregroundColor(Color.textGray) - .onReceive(timer) { _ in - spendTime += 1 - } } + + // 목표시간 명시 + Text(convertTargetTimeToString(timeInSecond: todo.targetTime)) + .foregroundColor(.secondary) + .offset(y: 40) } } - // 완료, 포기 버튼 + // MARK: 완료, 포기 버튼 HStack { - NavigationLink { + // TimerReportView Sheet 로 하기 + Button { // TODO: spendTime 업데이트하기 - TimerReportView(todo: todo, spendTime: Int(spendTime)) + if isDisabled { + isShowGiveupAlert = true + isComplete = true + } else { + isShowingReportSheet = true + isComplete = true + } } label: { - Image(systemName: "checkmark.seal") + Text("완료") + .font(.pizzaHeadlineBold) + .frame(width: 75, height: 75) + .foregroundColor(.green) + .background(Color(hex: 0xDAFFD9)) + .clipShape(Circle()) } + .padding([.leading, .trailing], 75) Button(action: { // 포기 alert띄우기 + isGiveupSign = true isShowGiveupAlert = true }, label: { - HStack { - Image(systemName: "trash.fill") - Text("포기") - } + Text("포기") + .font(.pizzaHeadlineBold) + .frame(width: 75, height: 75) + .foregroundColor(.red) + .background(Color(hex: 0xFFDBDB)) + .clipShape(Circle()) + }) + .padding([.leading, .trailing], 75) } - .buttonStyle(.bordered) - .tint(Color.black) .padding(.top, 10) - // 지금 하는 일 - HStack { - VStack(alignment: .leading) { - Text(todo.content) - .font(Font.pizzaHeadline) - .padding(.bottom) - // TODO: 날짜 불러오기 date extension - Text("오후 5:00") - .font(Font.pizzaFootnote) - } - Spacer() - } - .padding() - .background(Color.lightGray) - .cornerRadius(15) - .padding([.leading, .trailing, .top], 30) - Spacer() } .onAppear { startTodo() } .navigationBarBackButtonHidden(true) - .toolbar { - ToolbarItem(placement: .navigationBarLeading) { - Button { + .alert(isPresented: $isShowGiveupAlert) { + if isDisabled && !isGiveupSign { + Alert(title: Text("시작 후 5분은 피자조각을 얻지 못해요"), + message: Text(""), + primaryButton: .destructive(Text("완료")) { + // 포기하기 함수 + isShowGiveupAlert = true + isShowingReportSheet = true + }, secondaryButton: .cancel(Text("취소")) { + isComplete = false + }) + + } else { + Alert(title: Text("정말 포기하시겠습니까?"), + message: Text("지금 포기하면 피자조각을 얻지 못해요"), + primaryButton: .destructive(Text("포기하기")) { + // 포기하기 함수 dismiss() - } label: { - Image(systemName: "chevron.backward") - } - + }, secondaryButton: .cancel(Text("취소")) { + isGiveupSign = false + }) } } - .alert(isPresented: $isShowGiveupAlert) { - Alert(title: Text("정말 포기하시겠습니까?"), - message: Text("지금 포기하면 피자조각을 얻지 못해요"), - primaryButton: .destructive(Text("포기하기")) { - // 포기하기 함수 - dismiss() - }, secondaryButton: .cancel(Text("취소"))) + // TimerReportView Sheet로! + .sheet(isPresented: $isShowingReportSheet) { + TimerReportView(isShowingReportSheet: $isShowingReportSheet, isComplete: $isComplete, isShowingTimerView: $isShowingTimerView, todo: todo, spendTime: spendTime) } } @@ -187,6 +208,18 @@ struct TimerView: View { } } + // 목표시간 초 -> H시간 M분으로 보여주기 + func convertTargetTimeToString(timeInSecond: TimeInterval) -> String { + let hours: Int = Int(timeInSecond / 3600) + let minutes: Int = Int(timeInSecond - Double(hours) * 3600) / 60 + + if timeInSecond >= 3600 { + return String(format: "%i시간 %i분", hours, minutes) + } else { + return String(format: "%i분", minutes) + } + } + func startTodo() { self.settingTime = 3 self.timeRemaining = settingTime @@ -197,16 +230,15 @@ struct TimerView: View { func calcRemain() { isStart = false // TODO: targetTime 초? or 분? + // TODO: 여기서 시작시간 update self.settingTime = todo.targetTime self.timeRemaining = settingTime } func turnMode() { self.isDecresing = false - self.settingTime = 600 } - - + func progress() -> CGFloat { if isStart { return CGFloat(0) @@ -214,7 +246,7 @@ struct TimerView: View { if isDecresing { return (CGFloat(settingTime - timeRemaining) / CGFloat(settingTime)) } else { - return (CGFloat(timeExtra.truncatingRemainder(dividingBy: 60)) / CGFloat(settingTime)) + return 1 } } } @@ -228,7 +260,7 @@ struct TimerView_Previews: PreviewProvider { startTime: Date(), targetTime: 60, spendTime: Date() + 5400, - status: .ready)) + status: .ready), isShowingTimerView: .constant(false)) } } } diff --git a/Pickle/Pickle/Screen/Home/TodoCellView.swift b/Pickle/Pickle/Screen/Home/TodoCellView.swift index 9679c6d..c205cb0 100644 --- a/Pickle/Pickle/Screen/Home/TodoCellView.swift +++ b/Pickle/Pickle/Screen/Home/TodoCellView.swift @@ -10,9 +10,11 @@ import SwiftUI struct TodoCellView: View { - + var todo: Todo + @State var isShowingTimerView: Bool = false + var body: some View { ZStack { RoundedRectangle(cornerRadius: 8) @@ -34,8 +36,10 @@ struct TodoCellView: View { Spacer() - NavigationLink { - TimerView(todo: todo) + Button { + isShowingTimerView = true +// TimerView(todo: todo) +// .backKeyModifier(visible: false) } label: { ZStack { Rectangle() @@ -51,7 +55,11 @@ struct TodoCellView: View { } .padding(.horizontal, 40) } + .fullScreenCover(isPresented: $isShowingTimerView) { + TimerView(todo: todo, isShowingTimerView: $isShowingTimerView) + } } + } struct TodoCellView_Previews: PreviewProvider {