331 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Swift
		
	
	
	
	
	
			
		
		
	
	
			331 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Swift
		
	
	
	
	
	
//
 | 
						|
//  ProfileUpdateViewModel.swift
 | 
						|
//  SodaLive
 | 
						|
//
 | 
						|
//  Created by klaus on 2023/08/19.
 | 
						|
//
 | 
						|
 | 
						|
import UIKit
 | 
						|
import Combine
 | 
						|
 | 
						|
import Moya
 | 
						|
 | 
						|
final class ProfileUpdateViewModel: ObservableObject {
 | 
						|
    
 | 
						|
    private let repository = UserRepository()
 | 
						|
    private var subscription = Set<AnyCancellable>()
 | 
						|
    
 | 
						|
    @Published var isLoading = false
 | 
						|
    @Published var errorMessage = ""
 | 
						|
    @Published var isShowPopup = false
 | 
						|
    
 | 
						|
    @Published var email = ""
 | 
						|
    @Published var nickname = ""
 | 
						|
    @Published var youtubeUrl = ""
 | 
						|
    @Published var instagramUrl = ""
 | 
						|
    @Published var websiteUrl = ""
 | 
						|
    @Published var blogUrl = ""
 | 
						|
    @Published var gender: Gender = .NONE
 | 
						|
    @Published var introduce = ""
 | 
						|
    
 | 
						|
    @Published var currentPassword = ""
 | 
						|
    @Published var newPassword = ""
 | 
						|
    @Published var newPasswordConfirm = ""
 | 
						|
    
 | 
						|
    @Published var tags = [String]()
 | 
						|
    @Published var insertTags = [String]()
 | 
						|
    @Published var removeTags = [String]()
 | 
						|
    
 | 
						|
    var profileImage: UIImage? = nil {
 | 
						|
        didSet {
 | 
						|
            if let _ = profileImage {
 | 
						|
                updateProfileImage()
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
    
 | 
						|
    var profileResponse: GetProfileResponse?
 | 
						|
    
 | 
						|
    var refresh: () -> Void = {}
 | 
						|
    
 | 
						|
    let placeholder = "소개글을 입력하세요"
 | 
						|
    
 | 
						|
    func getMyProfile() {
 | 
						|
        isLoading = true
 | 
						|
        repository.getMyProfile()
 | 
						|
            .sink { result in
 | 
						|
                switch result {
 | 
						|
                case .finished:
 | 
						|
                    DEBUG_LOG("finish")
 | 
						|
                case .failure(let error):
 | 
						|
                    ERROR_LOG(error.localizedDescription)
 | 
						|
                }
 | 
						|
            } receiveValue: { [unowned self] response in
 | 
						|
                self.isLoading = false
 | 
						|
                let responseData = response.data
 | 
						|
                
 | 
						|
                do {
 | 
						|
                    let jsonDecoder = JSONDecoder()
 | 
						|
                    let decoded = try jsonDecoder.decode(ApiResponse<GetProfileResponse>.self, from: responseData)
 | 
						|
                    
 | 
						|
                    if let data = decoded.data, decoded.success {
 | 
						|
                        self.profileResponse = data
 | 
						|
                        
 | 
						|
                        self.email = data.email
 | 
						|
                        self.nickname = data.nickname
 | 
						|
                        self.youtubeUrl = data.youtubeUrl ?? ""
 | 
						|
                        self.instagramUrl = data.instagramUrl ?? ""
 | 
						|
                        self.blogUrl = data.blogUrl ?? ""
 | 
						|
                        self.websiteUrl = data.websiteUrl ?? ""
 | 
						|
                        self.introduce = data.introduce
 | 
						|
                        self.gender = data.gender
 | 
						|
                        self.tags.append(contentsOf: data.tags)
 | 
						|
                        
 | 
						|
                        UserDefaults.set(data.nickname, forKey: .nickname)
 | 
						|
                    } else {
 | 
						|
                        if let message = decoded.message {
 | 
						|
                            self.errorMessage = message
 | 
						|
                        } else {
 | 
						|
                            self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
 | 
						|
                        }
 | 
						|
                        
 | 
						|
                        self.isShowPopup = true
 | 
						|
                    }
 | 
						|
                } catch {
 | 
						|
                    self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
 | 
						|
                    self.isShowPopup = true
 | 
						|
                }
 | 
						|
            }
 | 
						|
            .store(in: &subscription)
 | 
						|
    }
 | 
						|
    
 | 
						|
    func updateProfile() {
 | 
						|
        if profileResponse!.nickname != nickname ||
 | 
						|
            profileResponse!.youtubeUrl != youtubeUrl ||
 | 
						|
            profileResponse!.instagramUrl != instagramUrl ||
 | 
						|
            profileResponse!.blogUrl != blogUrl ||
 | 
						|
            profileResponse!.websiteUrl != websiteUrl ||
 | 
						|
            profileResponse!.gender != gender ||
 | 
						|
            profileResponse!.introduce != introduce ||
 | 
						|
            !insertTags.isEmpty ||
 | 
						|
            !removeTags.isEmpty {
 | 
						|
            
 | 
						|
            let request = ProfileUpdateRequest(
 | 
						|
                email: profileResponse!.email,
 | 
						|
                nickname: profileResponse!.nickname != nickname ? nickname : nil,
 | 
						|
                gender: profileResponse!.gender != gender ? gender : nil,
 | 
						|
                introduce: profileResponse!.introduce != introduce && introduce.trimmingCharacters(in: .whitespacesAndNewlines) != placeholder ? introduce : nil,
 | 
						|
                youtubeUrl: profileResponse!.youtubeUrl != youtubeUrl ? youtubeUrl : nil,
 | 
						|
                instagramUrl: profileResponse!.instagramUrl != instagramUrl ? instagramUrl : nil,
 | 
						|
                websiteUrl: profileResponse!.websiteUrl != websiteUrl ? websiteUrl : nil,
 | 
						|
                blogUrl: profileResponse!.blogUrl != blogUrl ? blogUrl : nil,
 | 
						|
                insertTags: !insertTags.isEmpty ? insertTags : nil,
 | 
						|
                removeTags: !removeTags.isEmpty ? removeTags : nil
 | 
						|
            )
 | 
						|
            
 | 
						|
            isLoading = true
 | 
						|
            repository.profileUpdate(request: request)
 | 
						|
                .sink { result in
 | 
						|
                    switch result {
 | 
						|
                    case .finished:
 | 
						|
                        DEBUG_LOG("finish")
 | 
						|
                    case .failure(let error):
 | 
						|
                        ERROR_LOG(error.localizedDescription)
 | 
						|
                    }
 | 
						|
                } receiveValue: { [unowned self] response in
 | 
						|
                    self.isLoading = false
 | 
						|
                    let responseData = response.data
 | 
						|
                    
 | 
						|
                    do {
 | 
						|
                        let jsonDecoder = JSONDecoder()
 | 
						|
                        let decoded = try jsonDecoder.decode(ApiResponse<GetProfileResponse>.self, from: responseData)
 | 
						|
                        
 | 
						|
                        if let _ = decoded.data, decoded.success {
 | 
						|
                            self.refresh()
 | 
						|
                            self.errorMessage = "프로필이 변경되었습니다."
 | 
						|
                            self.isShowPopup = true
 | 
						|
                            
 | 
						|
                            DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
 | 
						|
                                AppState.shared.back()
 | 
						|
                            }
 | 
						|
                        } else {
 | 
						|
                            if let message = decoded.message {
 | 
						|
                                self.errorMessage = message
 | 
						|
                            } else {
 | 
						|
                                self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
 | 
						|
                            }
 | 
						|
                            
 | 
						|
                            self.isShowPopup = true
 | 
						|
                        }
 | 
						|
                    } catch {
 | 
						|
                        self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
 | 
						|
                        self.isShowPopup = true
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                .store(in: &subscription)
 | 
						|
            
 | 
						|
        } else {
 | 
						|
            AppState.shared.back()
 | 
						|
        }
 | 
						|
    }
 | 
						|
    
 | 
						|
    func updatePassword() {
 | 
						|
        if currentPassword.trimmingCharacters(in: .whitespaces).isEmpty {
 | 
						|
            errorMessage = "현재 비밀번호를 입력하세요."
 | 
						|
            isShowPopup = true
 | 
						|
            return
 | 
						|
        }
 | 
						|
        
 | 
						|
        if newPassword.trimmingCharacters(in: .whitespaces).isEmpty {
 | 
						|
            errorMessage = "변경할 비밀번호를 입력하세요."
 | 
						|
            isShowPopup = true
 | 
						|
            return
 | 
						|
        }
 | 
						|
        
 | 
						|
        if newPassword != newPasswordConfirm {
 | 
						|
            errorMessage = "비밀번호가 일치하지 않습니다."
 | 
						|
            isShowPopup = true
 | 
						|
            return
 | 
						|
        }
 | 
						|
        
 | 
						|
        if !validatePassword() {
 | 
						|
            errorMessage = "영문, 숫자 포함 8자 이상의 비밀번호를 입력해 주세요."
 | 
						|
            isShowPopup = true
 | 
						|
            return
 | 
						|
        }
 | 
						|
        
 | 
						|
        let request = ProfileUpdateRequest(
 | 
						|
            email: UserDefaults.string(forKey: .email),
 | 
						|
            password: currentPassword,
 | 
						|
            modifyPassword: newPassword
 | 
						|
        )
 | 
						|
        
 | 
						|
        isLoading = true
 | 
						|
        repository.profileUpdate(request: request)
 | 
						|
            .sink { result in
 | 
						|
                switch result {
 | 
						|
                case .finished:
 | 
						|
                    DEBUG_LOG("finish")
 | 
						|
                case .failure(let error):
 | 
						|
                    ERROR_LOG(error.localizedDescription)
 | 
						|
                }
 | 
						|
            } receiveValue: { [unowned self] response in
 | 
						|
                self.isLoading = false
 | 
						|
                let responseData = response.data
 | 
						|
                
 | 
						|
                do {
 | 
						|
                    let jsonDecoder = JSONDecoder()
 | 
						|
                    let decoded = try jsonDecoder.decode(ApiResponse<GetProfileResponse>.self, from: responseData)
 | 
						|
                    
 | 
						|
                    if let _ = decoded.data, decoded.success {
 | 
						|
                        self.errorMessage = "비밀번호가 변경되었습니다."
 | 
						|
                        self.isShowPopup = true
 | 
						|
                        self.currentPassword = ""
 | 
						|
                        self.newPassword = ""
 | 
						|
                        self.newPasswordConfirm = ""
 | 
						|
                        
 | 
						|
                        DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
 | 
						|
                            AppState.shared.back()
 | 
						|
                        }
 | 
						|
                    } else {
 | 
						|
                        if let message = decoded.message {
 | 
						|
                            self.errorMessage = message
 | 
						|
                        } else {
 | 
						|
                            self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
 | 
						|
                        }
 | 
						|
                        
 | 
						|
                        self.isShowPopup = true
 | 
						|
                    }
 | 
						|
                } catch {
 | 
						|
                    self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
 | 
						|
                    self.isShowPopup = true
 | 
						|
                }
 | 
						|
            }
 | 
						|
            .store(in: &subscription)
 | 
						|
    }
 | 
						|
    
 | 
						|
    func removeTag(tag: String) {
 | 
						|
        if let index = tags.firstIndex(of: tag) {
 | 
						|
            tags.remove(at: index)
 | 
						|
        }
 | 
						|
        
 | 
						|
        if (insertTags.contains(tag)) {
 | 
						|
            if let index = insertTags.firstIndex(of: tag) {
 | 
						|
                insertTags.remove(at: index)
 | 
						|
            }
 | 
						|
        } else {
 | 
						|
            removeTags.append(tag)
 | 
						|
        }
 | 
						|
    }
 | 
						|
    
 | 
						|
    func addTag(tag: String) {
 | 
						|
        tags.append(tag)
 | 
						|
        if (removeTags.contains(tag)) {
 | 
						|
            if let index = removeTags.firstIndex(of: tag) {
 | 
						|
                removeTags.remove(at: index)
 | 
						|
            }
 | 
						|
        } else {
 | 
						|
            insertTags.append(tag)
 | 
						|
        }
 | 
						|
    }
 | 
						|
    
 | 
						|
    private func updateProfileImage() {
 | 
						|
        isLoading = false
 | 
						|
        
 | 
						|
        if let profileImage = profileImage, let imageData = profileImage.jpegData(compressionQuality: 0.8) {
 | 
						|
            repository
 | 
						|
                .profileImageUpdate(parameter: MultipartFormData(
 | 
						|
                    provider: .data(imageData),
 | 
						|
                    name: "image",
 | 
						|
                    fileName: "\(UUID().uuidString)_\(Date().timeIntervalSince1970 * 1000).jpg",
 | 
						|
                    mimeType: "image/*"
 | 
						|
                ))
 | 
						|
                .sink { result in
 | 
						|
                    switch result {
 | 
						|
                    case .finished:
 | 
						|
                        DEBUG_LOG("finish")
 | 
						|
                    case .failure(let error):
 | 
						|
                        ERROR_LOG(error.localizedDescription)
 | 
						|
                    }
 | 
						|
                } receiveValue: { [unowned self] response in
 | 
						|
                    self.isLoading = false
 | 
						|
                    let responseData = response.data
 | 
						|
                    
 | 
						|
                    do {
 | 
						|
                        let jsonDecoder = JSONDecoder()
 | 
						|
                        let decoded = try jsonDecoder.decode(ApiResponse<String>.self, from: responseData)
 | 
						|
                        
 | 
						|
                        if let profileImageUrl = decoded.data, decoded.success {
 | 
						|
                            UserDefaults.set(profileImageUrl, forKey: .profileImage)
 | 
						|
                            self.refresh()
 | 
						|
                            self.getMyProfile()
 | 
						|
                        } else {
 | 
						|
                            if let message = decoded.message {
 | 
						|
                                self.errorMessage = message
 | 
						|
                            } else {
 | 
						|
                                self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
 | 
						|
                            }
 | 
						|
                            
 | 
						|
                            self.isShowPopup = true
 | 
						|
                        }
 | 
						|
                    } catch {
 | 
						|
                        self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
 | 
						|
                        self.isShowPopup = true
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                .store(in: &subscription)
 | 
						|
        } else {
 | 
						|
            self.errorMessage = "프로필 이미지를 업데이트 하지 못했습니다.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
 | 
						|
            self.isShowPopup = true
 | 
						|
            self.isLoading = false
 | 
						|
        }
 | 
						|
    }
 | 
						|
    
 | 
						|
    private func validatePassword() -> Bool {
 | 
						|
        let passwordRegEx = "^(?=.*[A-Za-z])(?=.*\\d)[A-Za-z\\d$@!%*#?&]{8,}$"
 | 
						|
        
 | 
						|
        let predicate = NSPredicate(format:"SELF MATCHES %@", passwordRegEx)
 | 
						|
        return predicate.evaluate(with: newPassword)
 | 
						|
    }
 | 
						|
}
 |