-
Notifications
You must be signed in to change notification settings - Fork 6
[Feat] #136 - 마이페이지 러닝 기록 상세뷰 UI와 삭제 api 연결 #138
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
The head ref may contain hidden characters: "feat/#136-\uB9C8\uC774\uD398\uC774\uC9C0-\uB7EC\uB2DD-\uAE30\uB85D-\uC0C1\uC138\uBDF0-UI\uC640-\uC11C\uBC84-\uC5F0\uACB0"
Changes from all commits
610947c
20f4b18
870a070
87dbcb6
be22beb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -16,6 +16,8 @@ final class RNAlertVC: UIViewController { | |
|
|
||
| var rightButtonTapAction: (() -> Void)? | ||
|
|
||
| var deleteRecordDelegate: deleteRecordDelegate? | ||
|
|
||
| // MARK: - UI Components | ||
|
|
||
| private let containerView = UIView().then { | ||
|
|
@@ -30,7 +32,7 @@ final class RNAlertVC: UIViewController { | |
| } | ||
|
|
||
| private lazy var yesButton = UIButton(type: .custom).then { | ||
| $0.setTitle("네", for: .normal) | ||
| $0.setTitle("예", for: .normal) | ||
| $0.titleLabel?.font = .h5 | ||
| $0.setTitleColor(.w1, for: .normal) | ||
| $0.layer.backgroundColor = UIColor.m1.cgColor | ||
|
|
@@ -78,6 +80,13 @@ extension RNAlertVC { | |
| self.noButton.addTarget(self, action: #selector(touchUpNoButton), for: .touchUpInside) | ||
| self.yesButton.addTarget(self, action: #selector(touchYesButton), for: .touchUpInside) | ||
| } | ||
|
|
||
| @discardableResult | ||
| func setButtonTitle(_ leftButtonTitle: String, _ rightButtonTitle: String) -> Self { | ||
| self.yesButton.setTitle(rightButtonTitle, for: .normal) | ||
| self.noButton.setTitle(leftButtonTitle, for: .normal) | ||
| return self | ||
| } | ||
|
Comment on lines
+84
to
+89
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
| } | ||
|
|
||
| // MARK: - @objc Function | ||
|
|
@@ -89,6 +98,7 @@ extension RNAlertVC { | |
|
|
||
| @objc private func touchYesButton() { | ||
| self.rightButtonTapAction?() | ||
| deleteRecordDelegate?.wantsToDelete() | ||
| } | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -12,6 +12,7 @@ import Moya | |
| enum RecordRouter { | ||
| case recordRunning(param: RunningRecordRequestDto) | ||
| case getActivityRecordInfo | ||
| case deleteRecord(recordIdList: [Int]) | ||
| } | ||
|
|
||
| extension RecordRouter: TargetType { | ||
|
|
@@ -25,7 +26,7 @@ extension RecordRouter: TargetType { | |
|
|
||
| var path: String { | ||
| switch self { | ||
| case .recordRunning: | ||
| case .recordRunning, .deleteRecord: | ||
| return "/record" | ||
| case .getActivityRecordInfo: | ||
| return "/record/user" | ||
|
|
@@ -38,6 +39,8 @@ extension RecordRouter: TargetType { | |
| return .post | ||
| case .getActivityRecordInfo: | ||
| return .get | ||
| case .deleteRecord: | ||
| return .put | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -51,12 +54,14 @@ extension RecordRouter: TargetType { | |
| } | ||
| case .getActivityRecordInfo: | ||
| return .requestPlain | ||
| case .deleteRecord(let recordIdList): | ||
| return .requestParameters(parameters: ["recordIdList": recordIdList], encoding: JSONEncoding.default) | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍👍 |
||
| } | ||
| } | ||
|
|
||
| var headers: [String: String]? { | ||
| switch self { | ||
| case .recordRunning, .getActivityRecordInfo: | ||
| case .recordRunning, .getActivityRecordInfo, .deleteRecord: | ||
| return Config.defaultHeader | ||
| } | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,19 +9,16 @@ import UIKit | |
|
|
||
| import SnapKit | ||
| import Then | ||
| import Moya | ||
|
|
||
| final class ActivityRecordDetailVC: UIViewController { | ||
|
|
||
| // MARK: - Properties | ||
|
|
||
| private let recordProvider = Providers.recordProvider | ||
|
|
||
| private var activityRecordList = [ActivityRecord]() | ||
|
|
||
| private var courseId: Int? | ||
|
|
||
| private var publicCourseId: Int? | ||
|
|
||
|
|
||
| private var recordId: Int? | ||
|
|
||
| // MARK: - UI Components | ||
|
|
||
| private lazy var navibar = CustomNavigationBar(self, type: .titleWithLeftButton) | ||
|
|
@@ -44,9 +41,9 @@ final class ActivityRecordDetailVC: UIViewController { | |
| $0.font = .h4 | ||
| } | ||
|
|
||
| private let recordDateInfoView = CourseDetailInfoView(title: "날짜", description: "0000.00.00") | ||
| private let recordDateInfoView = CourseDetailInfoView(title: "날짜", description: String()) | ||
|
|
||
| private let recordDepartureInfoView = CourseDetailInfoView(title: "출발지", description: "서울시 영등포구") | ||
| private let recordDepartureInfoView = CourseDetailInfoView(title: "출발지", description: String()) | ||
|
|
||
| private lazy var recordInfoStackView = UIStackView(arrangedSubviews: [recordDateInfoView, recordDepartureInfoView]).then { | ||
| $0.axis = .vertical | ||
|
|
@@ -70,17 +67,11 @@ final class ActivityRecordDetailVC: UIViewController { | |
| $0.text = "평균 페이스" | ||
| } | ||
|
|
||
| private lazy var recordDistanceValueLabel = setBlackTitle().then { | ||
| $0.text = "5.1km" | ||
| } | ||
| private lazy var recordDistanceValueLabel = setBlackTitle() | ||
|
|
||
| private lazy var recordRunningTimeValueLabel = setBlackTitle().then { | ||
| $0.text = "00:28:07" | ||
| } | ||
| private lazy var recordRunningTimeValueLabel = setBlackTitle() | ||
|
|
||
| private lazy var recordAveragePaceValueLabel = setBlackTitle().then { | ||
| $0.text = "5’31’’" | ||
| } | ||
| private lazy var recordAveragePaceValueLabel = setBlackTitle() | ||
|
|
||
| private lazy var recordDistanceStackView = setDetailInfoStakcView(title: recordDistanceLabel, value: recordDistanceValueLabel) | ||
|
|
||
|
|
@@ -105,33 +96,101 @@ final class ActivityRecordDetailVC: UIViewController { | |
| setNavigationBar() | ||
| setUI() | ||
| setLayout() | ||
| setAddTarget() | ||
| } | ||
| } | ||
|
|
||
| // MARK: - @objc Function | ||
|
|
||
| extension ActivityRecordDetailVC { | ||
| @objc func moreButtonDidTap() { | ||
| let alertController = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet) | ||
| let editAction = UIAlertAction(title: "수정하기", style: .default, handler: {(_: UIAlertAction!) in | ||
| //self.navigationController?.pushViewController(courseEditVC, animated: false) | ||
| }) | ||
| let deleteVC = RNAlertVC(description: "러닝 기록을 정말로 삭제하시겠어요?").setButtonTitle("취소", "삭제하기") | ||
| deleteVC.modalPresentationStyle = .overFullScreen | ||
| let deleteAction = UIAlertAction(title: "삭제하기", style: .destructive, handler: {(_: UIAlertAction!) in | ||
| self.present(deleteVC, animated: false, completion: nil)}) | ||
|
|
||
| deleteVC.rightButtonTapAction = { [weak self] in | ||
| deleteVC.dismiss(animated: false) | ||
| self?.deleteRecord() | ||
| } | ||
|
|
||
| [ editAction, deleteAction ].forEach { alertController.addAction($0) } | ||
| present(alertController, animated: true, completion: nil) | ||
| } | ||
| } | ||
|
|
||
| // MARK: - Methods | ||
|
|
||
| extension ActivityRecordDetailVC { | ||
| func setCourseId(courseId: Int?, publicCourseId: Int?) { | ||
| self.courseId = courseId | ||
| self.publicCourseId = publicCourseId | ||
| func setRecordId(recordId: Int?) { | ||
| self.recordId = recordId | ||
| } | ||
|
Comment on lines
+129
to
+131
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이 작업을 외부 VC에서 실행시키고 있는 것 같은데 그냥 바로 빝에 있는 setData함수에서 어차피 ActivityRecord 모델을 받아오고 있고 이 모델에 Id가 있기 때문에 함수를 분리한 것은 좋지만 호출은 바로 밑에 있는 setData에서 하면 될 거 같아요~!
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 수정하겠습니다! |
||
|
|
||
| func setData(model: ActivityRecord) { | ||
| self.mapImageView.setImage(with: model.image) | ||
| self.courseTitleLabel.text = model.title | ||
|
|
||
| let location = "\(model.departure.region) \(model.departure.city)" | ||
| self.recordDepartureInfoView.setDescriptionText(description: location) | ||
|
|
||
| // 날짜 바꾸기 | ||
| let recordDate = model.createdAt.prefix(10) | ||
| let resultDate = RNTimeFormatter.changeDateSplit(date: String(recordDate)) | ||
| self.recordDateInfoView.setDescriptionText(description: resultDate) | ||
|
|
||
| // 이동 시간 바꾸기 | ||
| let recordRunningTime = model.time.suffix(7) | ||
| self.recordRunningTimeValueLabel.text = String(recordRunningTime) | ||
|
|
||
| // 평균 페이스 바꾸기 | ||
| let array = spiltRecordAveragePace(model: model) | ||
| setUpRecordAveragePaceValueLabel(array: array, label: recordAveragePaceValueLabel) | ||
| setUpRecordDistanceValueLabel(model: model, label: recordDistanceValueLabel) | ||
| } | ||
|
|
||
| private func setAddTarget() { | ||
| self.moreButton.addTarget(self, action: #selector(moreButtonDidTap), for: .touchUpInside) | ||
| } | ||
|
|
||
| func setDetailInfoStakcView(title: UIView, value: UIView) -> UIStackView { | ||
| let stackView = UIStackView(arrangedSubviews: [title, value]) | ||
| stackView.axis = .vertical | ||
| stackView.alignment = .center | ||
| stackView.spacing = 2 | ||
| stackView.spacing = 8 | ||
| return stackView | ||
| } | ||
|
|
||
| func setBlackTitle() -> UILabel { | ||
| private func spiltRecordAveragePace(model: ActivityRecord) -> [String] { | ||
| let recordAveragePace = model.pace | ||
| let array = recordAveragePace.split(separator: ":").map { String($0) } | ||
| return array | ||
| } | ||
|
|
||
| private func setUpRecordAveragePaceValueLabel(array: [String], label: UILabel) { | ||
| let numberArray = array.compactMap { Int($0) } // 페이스에서 첫번째 인덱스 두번째 값만 가져오기 위해 | ||
| let attributedString = NSMutableAttributedString(string: String(numberArray[1]) + "’", attributes: [.font: UIFont.h3, .foregroundColor: UIColor.g1]) | ||
| attributedString.append(NSAttributedString(string: String(array[2]) + "”", attributes: [.font: UIFont.h3, .foregroundColor: UIColor.g1])) | ||
| label.attributedText = attributedString | ||
| } | ||
|
|
||
| private func setUpRecordDistanceValueLabel(model: ActivityRecord, label: UILabel) { | ||
| let attributedString = NSMutableAttributedString(string: String(model.distance) + " ", attributes: [.font: UIFont.h3, .foregroundColor: UIColor.g1]) | ||
| attributedString.append(NSAttributedString(string: "km", attributes: [.font: UIFont.b4, .foregroundColor: UIColor.g2])) | ||
| label.attributedText = attributedString | ||
| } | ||
|
|
||
| private func setBlackTitle() -> UILabel { | ||
| let label = UILabel() | ||
| label.textColor = .g1 | ||
| label.font = .h3 | ||
| return label | ||
| } | ||
|
|
||
| func setGreyTitle() -> UILabel { | ||
| private func setGreyTitle() -> UILabel { | ||
| let label = UILabel() | ||
| label.textColor = .g2 | ||
| label.font = .b4 | ||
|
|
@@ -142,6 +201,7 @@ extension ActivityRecordDetailVC { | |
| // MARK: - Layout Helpers | ||
|
|
||
| extension ActivityRecordDetailVC { | ||
|
|
||
| private func setUI() { | ||
| view.backgroundColor = .w1 | ||
| middleScorollView.backgroundColor = .w1 | ||
|
|
@@ -162,7 +222,7 @@ extension ActivityRecordDetailVC { | |
| } | ||
|
|
||
| moreButton.snp.makeConstraints { make in | ||
| make.trailing.equalTo(self.view.safeAreaLayoutGuide).inset(16) | ||
| make.trailing.equalTo(self.view.safeAreaLayoutGuide) | ||
| make.centerY.equalTo(navibar) | ||
| } | ||
| } | ||
|
|
@@ -173,7 +233,7 @@ extension ActivityRecordDetailVC { | |
| middleScorollView.snp.makeConstraints { make in | ||
| make.top.equalTo(navibar.snp.bottom) | ||
| make.leading.trailing.equalTo(view.safeAreaLayoutGuide) | ||
| make.bottom.equalToSuperview() | ||
| make.bottom.equalTo(view.safeAreaLayoutGuide) | ||
| } | ||
|
|
||
| middleScorollView.addSubviews(mapImageView, courseTitleLabel, firstHorizontalDivideLine, recordInfoStackView, secondHorizontalDivideLine) | ||
|
|
@@ -197,7 +257,7 @@ extension ActivityRecordDetailVC { | |
|
|
||
| recordInfoStackView.snp.makeConstraints { make in | ||
| make.top.equalTo(firstHorizontalDivideLine.snp.bottom).offset(20) | ||
| make.leading.trailing.equalToSuperview().inset(16) | ||
| make.leading.trailing.equalTo(view.safeAreaLayoutGuide).inset(16) | ||
| } | ||
|
|
||
| firstVerticalDivideLine.snp.makeConstraints { make in | ||
|
|
@@ -239,29 +299,29 @@ extension ActivityRecordDetailVC { | |
| recordSubInfoStackView.snp.makeConstraints { make in | ||
| make.top.equalTo(secondHorizontalDivideLine.snp.bottom).offset(23) | ||
| make.centerX.equalToSuperview() | ||
| make.bottom.equalToSuperview().inset(30) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // MARK: - Network | ||
|
|
||
| extension ActivityRecordDetailVC { | ||
| func getActivityRecordDetailWithPath() { | ||
| private func deleteRecord() { | ||
| guard let recordId = self.recordId else { return } | ||
| print(recordId) | ||
| LoadingIndicator.showLoading() | ||
| recordProvider.request(.getActivityRecordInfo) { [weak self] response in | ||
| recordProvider.request(.deleteRecord(recordIdList: [recordId])) { [weak self] response in | ||
| LoadingIndicator.hideLoading() | ||
| guard let self = self else { return } | ||
| switch response { | ||
| case .success(let result): | ||
| print("result:", result) | ||
| let status = result.statusCode | ||
| if 200..<300 ~= status { | ||
| do { | ||
| let responseDto = try result.map(BaseResponse<ActivityRecordInfoDto>.self) | ||
| guard let data = responseDto.data else { return } | ||
| //self.setData(activityRecordList: data.records) | ||
| } catch { | ||
| print(error.localizedDescription) | ||
| } | ||
| print("삭제 성공") | ||
| self.navigationController?.popViewController(animated: false) | ||
|
|
||
| } | ||
| if status >= 400 { | ||
| print("400 error") | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rightButtonTapAction 이라는 클로저로 터치 이벤트 발생 시 처리할 액션을 지정해줄 수 있도록 했는데 delegate를 추가로 구현하셨네요..?
rightButtonTapAction으로 전체 검색해서 사용 예시 한번 확인해보세요
하위뷰에서 이벤트 발생시 처리할 동작을 지정해줄 때에는 늘 하던대로 delegate-protocol을 사용할 수도 있지만 이렇게 클로저로 액션일 미리 지정해줄 수도 있습니다.
둘 다 사용할 줄 알아야해요!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
delegate-protocol을 쓴 이유가 deleteVC에서 버튼이 눌렸을 때, ActivityRecordVC에 있는 테이블뷰 -> 선택된 셀들을 가져와야 하는데, rightButtonTapAction 클로저 안에서 이 ActivityRecordVC 테이블뷰에 접근하는 법을 모르겠어서 였어요..! 제가 클로저에 대한 이해가 낮아서 그런 것 같은데.. 잘 모르겠어서 일단은 수정하지 말아볼게요...!