Skip to content
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

[FEAT] 마이페이지 > 프로필 편집 기능 구현 #266

Merged
merged 13 commits into from
Apr 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions PLUB.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,10 @@
C316051B2997936200D27488 /* GuestQuestionViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C316051A2997936200D27488 /* GuestQuestionViewModel.swift */; };
C316051F2997F92200D27488 /* EditMeetingPostRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C316051E2997F92200D27488 /* EditMeetingPostRequest.swift */; };
C31605212997F9C800D27488 /* EditMeetingQuestionRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C31605202997F9C800D27488 /* EditMeetingQuestionRequest.swift */; };
C31D577429E16DBD00E056BA /* MyInfoRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C31D577329E16DBD00E056BA /* MyInfoRequest.swift */; };
C32AB19029DDB9000045B919 /* ProfileEditViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C32AB18F29DDB9000045B919 /* ProfileEditViewModel.swift */; };
C332DFD52976E5440023B70B /* PhotoBottomSheetViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C332DFD42976E5440023B70B /* PhotoBottomSheetViewController.swift */; };
C3394CB929E177D2005EECD7 /* UpdateImageRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3394CB829E177D2005EECD7 /* UpdateImageRequest.swift */; };
C33952EF29B6577B0029FF7F /* ScheduleParticipantCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33952EE29B6577B0029FF7F /* ScheduleParticipantCollectionViewCell.swift */; };
C33EF37D29A1DFD100D7A5CA /* ScheduleAlarmView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33EF37C29A1DFD100D7A5CA /* ScheduleAlarmView.swift */; };
C33FB0722993F84A00BEB15B /* EditMeetingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33FB0712993F84A00BEB15B /* EditMeetingViewController.swift */; };
Expand Down Expand Up @@ -320,6 +323,7 @@
C3B3435B29BE3E5100935B73 /* MyPlubbingResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3B3435A29BE3E5100935B73 /* MyPlubbingResponse.swift */; };
C3B3435D29BE4A3000935B73 /* MyPlubbingParameter.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3B3435C29BE4A3000935B73 /* MyPlubbingParameter.swift */; };
C3C24CD3298FBA6D00056313 /* PeopleNumberToolTip.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3C24CD2298FBA6D00056313 /* PeopleNumberToolTip.swift */; };
C3C7197C29DC81C700A6DFD9 /* ProfileEditViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3C7197B29DC81C700A6DFD9 /* ProfileEditViewController.swift */; };
C3CD674A29B4B37C0052087E /* ScheduleParticipantViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3CD674929B4B37C0052087E /* ScheduleParticipantViewController.swift */; };
C3CD674E29B4DD9C0052087E /* ScheduleParticipantTopView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3CD674D29B4DD9C0052087E /* ScheduleParticipantTopView.swift */; };
C3CD675029B4E5970052087E /* ScheduleParticipantViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3CD674F29B4E5970052087E /* ScheduleParticipantViewModel.swift */; };
Expand Down Expand Up @@ -567,7 +571,10 @@
C316051A2997936200D27488 /* GuestQuestionViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GuestQuestionViewModel.swift; sourceTree = "<group>"; };
C316051E2997F92200D27488 /* EditMeetingPostRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditMeetingPostRequest.swift; sourceTree = "<group>"; };
C31605202997F9C800D27488 /* EditMeetingQuestionRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditMeetingQuestionRequest.swift; sourceTree = "<group>"; };
C31D577329E16DBD00E056BA /* MyInfoRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyInfoRequest.swift; sourceTree = "<group>"; };
C32AB18F29DDB9000045B919 /* ProfileEditViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileEditViewModel.swift; sourceTree = "<group>"; };
C332DFD42976E5440023B70B /* PhotoBottomSheetViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotoBottomSheetViewController.swift; sourceTree = "<group>"; };
C3394CB829E177D2005EECD7 /* UpdateImageRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UpdateImageRequest.swift; sourceTree = "<group>"; };
C33952EE29B6577B0029FF7F /* ScheduleParticipantCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScheduleParticipantCollectionViewCell.swift; sourceTree = "<group>"; };
C33EF37C29A1DFD100D7A5CA /* ScheduleAlarmView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScheduleAlarmView.swift; sourceTree = "<group>"; };
C33FB0712993F84A00BEB15B /* EditMeetingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditMeetingViewController.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -647,6 +654,7 @@
C3B3435A29BE3E5100935B73 /* MyPlubbingResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyPlubbingResponse.swift; sourceTree = "<group>"; };
C3B3435C29BE4A3000935B73 /* MyPlubbingParameter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyPlubbingParameter.swift; sourceTree = "<group>"; };
C3C24CD2298FBA6D00056313 /* PeopleNumberToolTip.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PeopleNumberToolTip.swift; sourceTree = "<group>"; };
C3C7197B29DC81C700A6DFD9 /* ProfileEditViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileEditViewController.swift; sourceTree = "<group>"; };
C3CD674929B4B37C0052087E /* ScheduleParticipantViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScheduleParticipantViewController.swift; sourceTree = "<group>"; };
C3CD674D29B4DD9C0052087E /* ScheduleParticipantTopView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScheduleParticipantTopView.swift; sourceTree = "<group>"; };
C3CD674F29B4E5970052087E /* ScheduleParticipantViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScheduleParticipantViewModel.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -991,6 +999,7 @@
isa = PBXGroup;
children = (
70CF332F299793220077FF47 /* RegisterInterestRequest.swift */,
C31D577329E16DBD00E056BA /* MyInfoRequest.swift */,
);
path = Request;
sourceTree = "<group>";
Expand Down Expand Up @@ -1429,6 +1438,7 @@
C3100CBA29BD8A96005FCCAD /* Component */,
C3E0390629C2087000C4744C /* Recruiting */,
C3EC027B29D958070024C962 /* Waiting */,
C3C7197A29DC81A100A6DFD9 /* ProfileEdit */,
);
path = MyPage;
sourceTree = "<group>";
Expand Down Expand Up @@ -1783,6 +1793,7 @@
isa = PBXGroup;
children = (
C3B04E452981788800188E60 /* UploadImageRequest.swift */,
C3394CB829E177D2005EECD7 /* UpdateImageRequest.swift */,
);
path = Request;
sourceTree = "<group>";
Expand Down Expand Up @@ -1860,6 +1871,15 @@
path = Response;
sourceTree = "<group>";
};
C3C7197A29DC81A100A6DFD9 /* ProfileEdit */ = {
isa = PBXGroup;
children = (
C3C7197B29DC81C700A6DFD9 /* ProfileEditViewController.swift */,
C32AB18F29DDB9000045B919 /* ProfileEditViewModel.swift */,
);
path = ProfileEdit;
sourceTree = "<group>";
};
C3CD675229B4FB3E0052087E /* ScheduleParticipant */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -2122,6 +2142,7 @@
70BD5F3729657E3E002CBA89 /* ApplyQuestionViewModel.swift in Sources */,
C332DFD52976E5440023B70B /* PhotoBottomSheetViewController.swift in Sources */,
70197B812955A68C000503F6 /* CategoryInfoListView.swift in Sources */,
C31D577429E16DBD00E056BA /* MyInfoRequest.swift in Sources */,
70BD5F2C2963204D002CBA89 /* DetailRecruitmentViewController.swift in Sources */,
BAE0AC7629B5D67D00F46F3D /* BoardDetailViewController.swift in Sources */,
C34F048429C715A800E5B67E /* SettingSubview.swift in Sources */,
Expand Down Expand Up @@ -2217,11 +2238,13 @@
C36CE39F29731A0700E3A68C /* PhotoSelectView.swift in Sources */,
BA784FAE297937DA00E8B06F /* CalendarControl.swift in Sources */,
C31605192997935100D27488 /* MeetingInfoViewModel.swift in Sources */,
C32AB19029DDB9000045B919 /* ProfileEditViewModel.swift in Sources */,
70A420AB298FAD000026E9F9 /* TopTabCollectionViewCell.swift in Sources */,
70A420BF29914B690026E9F9 /* RequestBookmarkResponse.swift in Sources */,
BAE1AD952944775C00CE36B9 /* PolicyViewController.swift in Sources */,
BA5DEB302974D8E200650788 /* NetworkResult.swift in Sources */,
70A420C029914B690026E9F9 /* SearchRecruitmentResponse.swift in Sources */,
C3C7197C29DC81C700A6DFD9 /* ProfileEditViewController.swift in Sources */,
70F1DFDE297A8A6C00F9BC83 /* MeetingRouter.swift in Sources */,
70727A3B29D32E4C003DE956 /* InquireAllTodolistResponse.swift in Sources */,
C34F71C329799B1C003DB376 /* TimeControl.swift in Sources */,
Expand Down Expand Up @@ -2278,6 +2301,7 @@
70F1DFE8297D969000F9BC83 /* RecruitmentRouter.swift in Sources */,
BA784FAA2978EB9900E8B06F /* SignUpViewModel.swift in Sources */,
702876C229A3751400E57509 /* ArchiveViewController.swift in Sources */,
C3394CB929E177D2005EECD7 /* UpdateImageRequest.swift in Sources */,
BA340E2229782311002BAF2C /* MeetingIntroduceView.swift in Sources */,
C38D65622987F0990052013F /* CategoryHeaderView.swift in Sources */,
C3EB29CB29A91CC600615B6B /* MeetingScheduleViewModel.swift in Sources */,
Expand Down
21 changes: 21 additions & 0 deletions PLUB/Sources/Models/Account/Request/MyInfoRequest.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//
// MyInfoRequest.swift
// PLUB
//
// Created by 김수빈 on 2023/04/08.
//

import Foundation

struct MyInfoRequest: Codable {
let nickname: String
let introduce: String
let profileImage: String?
}

extension MyInfoRequest {
enum CodingKeys: String, CodingKey {
case nickname, introduce
case profileImage = "profileImageUrl"
}
}
16 changes: 16 additions & 0 deletions PLUB/Sources/Models/Image/Request/UpdateImageRequest.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//
// UpdateImageRequest.swift
// PLUB
//
// Created by 김수빈 on 2023/04/08.
//

struct UpdateImageRequest: Codable {
let type: ImageType
let deleteURL: String

enum CodingKeys: String, CodingKey {
case type
case deleteURL = "toDeleteUrls"
}
}
9 changes: 7 additions & 2 deletions PLUB/Sources/Network/Routers/AccountRouter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,15 @@ enum AccountRouter {
case validateNickname(String)
case inquireInterest
case registerInterest(RegisterInterestRequest)
case updateMyInfo(MyInfoRequest)
}

extension AccountRouter: Router {
var method: HTTPMethod {
switch self {
case .inquireMyInfo, .validateNickname, .inquireInterest:
return .get
case .registerInterest:
case .registerInterest, .updateMyInfo:
return .post
}
}
Expand All @@ -34,14 +35,16 @@ extension AccountRouter: Router {
return "/accounts/me/interest"
case .registerInterest:
return "/accounts/interest"
case .updateMyInfo:
return "/accounts/me/profile"
}
}

var headers: HeaderType {
switch self {
case .validateNickname:
return .default
case .inquireMyInfo, .inquireInterest, .registerInterest:
case .inquireMyInfo, .inquireInterest, .registerInterest, .updateMyInfo:
return .withAccessToken
}
}
Expand All @@ -52,6 +55,8 @@ extension AccountRouter: Router {
return .plain
case .registerInterest(let request):
return .body(request)
case .updateMyInfo(let request):
return .body(request)
}
}
}
4 changes: 4 additions & 0 deletions PLUB/Sources/Network/Services/AccountService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,8 @@ extension AccountService {
func registerInterest(request: RegisterInterestRequest) -> PLUBResult<EmptyModel> {
return sendRequest(AccountRouter.registerInterest(request))
}

func updateMyInfo(request: MyInfoRequest) -> PLUBResult<MyInfoResponse> {
return sendRequest(AccountRouter.updateMyInfo(request), type: MyInfoResponse.self)
}
}
25 changes: 23 additions & 2 deletions PLUB/Sources/Network/Services/ImageService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ import Alamofire
import RxCocoa
import RxSwift

enum ImageServiceType {
case upload
case update
}

final class ImageService: BaseService {
static let shared = ImageService()

Expand All @@ -32,17 +37,33 @@ extension ImageService {
)
}

func updateImage(
images: [UIImage],
params: UpdateImageRequest
) -> PLUBResult<UploadImageResponse> {
return sendRequestWithImage(
setUpImageData(
images: images,
params: params.toDictionary,
type: .update
),
ImageRouter.updateImage,
type: UploadImageResponse.self
)
}

private func setUpImageData(
images: [UIImage],
params: [String: Any]
params: [String: Any],
type: ImageServiceType = .upload
) -> MultipartFormData {
let formData = MultipartFormData()

for image in images {
guard let imageData = image.jpegData(compressionQuality: 0.1) else { continue }
formData.append(
imageData,
withName: "files",
withName: type == .upload ? "files" : "newFiles",
fileName: "\(image).jpeg",
mimeType: "image/jpeg"
)
Expand Down
5 changes: 3 additions & 2 deletions PLUB/Sources/Views/Meeting/MeetingViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -197,8 +197,9 @@ extension MeetingViewController: UICollectionViewDelegate, UICollectionViewDataS
}

guard let previousIndex = previousIndex,
previousIndex != index
else { return }
previousIndex != index,
previousIndex < meetingList.count else { return }

meetingList[previousIndex].isDimmed = true
}
}
Expand Down
4 changes: 2 additions & 2 deletions PLUB/Sources/Views/MyPage/Cell/MyPageSectionHeaderView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ final class MyPageSectionHeaderView: UITableViewHeaderFooterView {
}

private let foldImageView = UIImageView().then {
$0.image = UIImage(named: "foldedArrow")
$0.highlightedImage = UIImage(named: "unfoldedArrow")
$0.image = UIImage(named: "unfoldedArrow")
$0.highlightedImage = UIImage(named: "foldedArrow")
}

private let button = UIButton()
Expand Down
2 changes: 1 addition & 1 deletion PLUB/Sources/Views/MyPage/Cell/MyPageTableViewCell.swift
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ final class MyPageTableViewCell: UITableViewCell {
}

private func setupLayouts() {
addSubview(contentStackView)
contentView.addSubview(contentStackView)
[meetingImageView, textStackView].forEach {
contentStackView.addArrangedSubview($0)
}
Expand Down
4 changes: 3 additions & 1 deletion PLUB/Sources/Views/MyPage/Component/MyProfileView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@ import SnapKit
final class MyProfileView: UIView {

private let profileImageView = UIImageView().then {
$0.contentMode = .scaleAspectFill
$0.layer.cornerRadius = 32
$0.clipsToBounds = true
}

private let editButton = UIButton().then {
let editButton = UIButton().then {
$0.setImage(UIImage(named: "pencil"), for: .normal)
}

Expand Down
20 changes: 20 additions & 0 deletions PLUB/Sources/Views/MyPage/MyPageViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,20 @@ final class MyPageViewController: BaseViewController {
owner.tableView.reloadSections([index], with: .automatic)
}
.disposed(by: disposeBag)

profileView.editButton
.rx.tap
.asDriver()
.drive(with: self) { owner, _ in
guard let myInfoData = owner.viewModel.myInfoData else { return }
let vc = ProfileEditViewController(
viewModel: ProfileEditViewModel(myInfoData: myInfoData)
)
vc.delegate = owner
vc.hidesBottomBarWhenPushed = true
owner.navigationController?.pushViewController(vc, animated: true)
}
.disposed(by: disposeBag)
}
}

Expand Down Expand Up @@ -211,3 +225,9 @@ extension MyPageViewController: MyPageCellDelegate {
viewModel.removeCell(with: plubbingID)
}
}

extension MyPageViewController: ProfileEditDelegate {
func updateProfile(myInfo: MyInfoResponse) {
viewModel.updateMyInfo.onNext(myInfo)
}
}
20 changes: 17 additions & 3 deletions PLUB/Sources/Views/MyPage/MyPageViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,15 @@ final class MyPageViewModel {

// Input
let sectionTapped: AnyObserver<Int> // 섹션뷰 클릭 이벤트
let updateMyInfo: AnyObserver<MyInfoResponse> // 내 정보 데이터 갱신

// Output
var myInfo: Driver<MyInfoResponse> // 내 정보 데이터
let myInfo: Driver<MyInfoResponse> // 내 정보 데이터
let reloadData: Driver<Void> // 테이블 뷰 갱신
let reloadSection: Driver<Int> // 테이블 뷰 섹션 갱신

private let sectionTappedSubject = PublishSubject<Int>()
private let updateMyInfoSubject = PublishSubject<MyInfoResponse>()
private let myInfoSubject = PublishSubject<MyInfoResponse>()
private let reloadDataSubject = PublishSubject<Void>()
private let reloadSectionSubject = PublishSubject<Int>()
Expand All @@ -37,6 +39,7 @@ final class MyPageViewModel {

init() {
sectionTapped = sectionTappedSubject.asObserver()
updateMyInfo = updateMyInfoSubject.asObserver()

myInfo = myInfoSubject.asDriver(onErrorDriveWith: .empty())
reloadData = reloadDataSubject.asDriver(onErrorDriveWith: .empty())
Expand All @@ -49,6 +52,13 @@ final class MyPageViewModel {
owner.reloadSectionSubject.onNext(index)
})
.disposed(by: disposeBag)

updateMyInfoSubject
.withUnretained(self)
.subscribe(onNext: { owner, myInfo in
owner.setupMyInfoData(myInfo: myInfo)
})
.disposed(by: disposeBag)
}

func fetchMyInfoData() {
Expand All @@ -59,8 +69,7 @@ final class MyPageViewModel {
case .success(let model):
print(model)
guard let data = model.data else { return }
owner.myInfoData = data
owner.myInfoSubject.onNext(data)
owner.setupMyInfoData(myInfo: data)
default:
break
}
Expand Down Expand Up @@ -118,4 +127,9 @@ final class MyPageViewModel {
}
}
}

private func setupMyInfoData(myInfo: MyInfoResponse) {
myInfoData = myInfo
myInfoSubject.onNext(myInfo)
}
}
Loading