Skip to content

Commit

Permalink
Merge pull request #64 from zerosome-dev/feature/home
Browse files Browse the repository at this point in the history
✨[Feat] add logout, revoke, mypage api
  • Loading branch information
syss220211 authored Aug 29, 2024
2 parents 3bfb77c + 65b9e01 commit b83702b
Show file tree
Hide file tree
Showing 16 changed files with 353 additions and 61 deletions.
2 changes: 2 additions & 0 deletions Projects/App/Sources/Data/Constants/Response.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,5 @@ struct Response<T: Decodable>: Decodable {
let status: Bool
let data: T?
}

struct NoneDecodeResponse: Decodable { }
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//
// MemberBasicInfoResponseDTO.swift
// App
//
// Created by 박서연 on 2024/08/29.
// Copyright © 2024 iOS. All rights reserved.
//

import Foundation

struct MemberBasicInfoResponseDTO: Decodable {
var nickname: String?
var rivewCnt: Int?
}
22 changes: 21 additions & 1 deletion Projects/App/Sources/Data/EndPoint/EndPoint.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ struct APIEndPoint {
case join = "/api/v1/auth/join"
case refreshToken = "/api/v1/auth/refresh"
case logout = "/api/v1/auth/logout"
case revoke = "/api/v1/auth/reovke" // ??미정
}

enum Home: String {
Expand All @@ -35,6 +34,17 @@ struct APIEndPoint {
case zeroTagList = "/api/app/v1/filter/zero-category"
}

enum Review: String {
case changeNickname = "/api/app/v1/member/nickname"
case modifierReview = "/api/app/v1/member"
case deleteReview = "/api/app/v1/review"
}

enum Mypage: String {
case userInfo = "/api/app/v1/member"
case userReviewList = "/api/app/v1/review/member"
}

enum Detail: String {
case detail = "/api/app/v1/product/detail"
}
Expand All @@ -58,6 +68,16 @@ struct APIEndPoint {
let base = baseURL + endPoint.rawValue
return build(url: base, parameters: parameters)
}

static func url(for endPoint: Review, with parameters: [String: Any]? = nil) -> String {
let base = baseURL + endPoint.rawValue
return build(url: base, parameters: parameters)
}

static func url(for endPoint: Mypage, with parameters: [String: Any]? = nil) -> String {
let base = baseURL + endPoint.rawValue
return build(url: base, parameters: parameters)
}
}

extension APIEndPoint {
Expand Down
18 changes: 18 additions & 0 deletions Projects/App/Sources/Data/Mapper/Mypage/MypageMapper.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//
// MypageMapper.swift
// App
//
// Created by 박서연 on 2024/08/29.
// Copyright © 2024 iOS. All rights reserved.
//

import Foundation

class MypageMapper {
static func toMemberBasicInfo(response: MemberBasicInfoResponseDTO) -> MemberBasicInfoResult {
return MemberBasicInfoResult(
nickname: response.nickname ?? "",
rivewCnt: response.rivewCnt ?? 0
)
}
}
79 changes: 79 additions & 0 deletions Projects/App/Sources/Data/Repository/Mypage/MypageRepository.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
//
// MypageRepository.swift
// App
//
// Created by 박서연 on 2024/08/30.
// Copyright © 2024 iOS. All rights reserved.
//

import Combine

final class MypageRepository: MypageRepositoryProtocol {

private let apiService: ApiService

init(apiService: ApiService) {
self.apiService = apiService
}

func getUserBasicInfo() -> Future<MemberBasicInfoResult, NetworkError> {
return Future { promise in
Task {
let response: Result<MemberBasicInfoResponseDTO, NetworkError> = await self.apiService.request(
httpMethod: .get,
endPoint: APIEndPoint.url(for: .userInfo),
header: AccountStorage.shared.accessToken
)

switch response {
case .success(let success):
let mappedResult = MypageMapper.toMemberBasicInfo(response: success)
promise(.success(mappedResult))
case .failure(let failure):
debugPrint("Mypage UserInfo failed \(failure.localizedDescription)")
promise(.failure(NetworkError.badRequest))
}
}
}
}

func logout() -> Future<Bool, NetworkError> {
return Future { promise in
Task {
let response: Result<NoneDecodeResponse, NetworkError> = await self.apiService.request(
httpMethod: .delete,
endPoint: APIEndPoint.url(for: .logout),
header: AccountStorage.shared.accessToken
)

switch response {
case .success(let success):
promise(.success(true))
case .failure(let failure):
debugPrint("Failure to Logout!! \(failure.localizedDescription)")
promise(.failure(NetworkError.badRequest))
}
}
}
}

func revoke() -> Future<Bool, NetworkError> {
return Future { promise in
Task {
let response: Result<NoneDecodeResponse, NetworkError> = await self.apiService.request(
httpMethod: .delete,
endPoint: APIEndPoint.url(for: .signIn),
header: AccountStorage.shared.accessToken
)

switch response {
case .success(let success):
promise(.success(true))
case .failure(let failure):
debugPrint("Failure to Revoke!! \(failure.localizedDescription)")
promise(.failure(NetworkError.badRequest))
}
}
}
}
}
5 changes: 5 additions & 0 deletions Projects/App/Sources/Data/Service/ApiService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,11 @@ final class ApiService {

do {
let result = try JSONDecoder().decode(Response<T>.self, from: data)

if T.self == Void.self {
return .success(() as! T)
}

debugPrint("🚨🚨 <<<Network Data>>> 🚨🚨 \(result)")

guard let data = result.data else {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//
// MemberBasicInfoResult.swift
// App
//
// Created by 박서연 on 2024/08/29.
// Copyright © 2024 iOS. All rights reserved.
//

import Foundation

struct MemberBasicInfoResult {
var nickname: String
var rivewCnt: Int
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//
// MypageRepositoryProtocol.swift
// App
//
// Created by 박서연 on 2024/08/30.
// Copyright © 2024 iOS. All rights reserved.
//

import Combine

protocol MypageRepositoryProtocol {
func getUserBasicInfo() -> Future<MemberBasicInfoResult, NetworkError>
func logout() -> Future<Bool, NetworkError>
func revoke() -> Future<Bool, NetworkError>
}
25 changes: 25 additions & 0 deletions Projects/App/Sources/Domain/Usecase/MypageUsecase.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//
// MypageUsecase.swift
// App
//
// Created by 박서연 on 2024/08/30.
// Copyright © 2024 iOS. All rights reserved.
//

import Combine

struct MypageUsecase {
let mypageRepoProtocol: MypageRepositoryProtocol

func getUserBasicInfo() -> Future<MemberBasicInfoResult, NetworkError> {
return mypageRepoProtocol.getUserBasicInfo()
}

func logout() -> Future<Bool, NetworkError> {
return mypageRepoProtocol.logout()
}

func revoke() -> Future<Bool, NetworkError> {
return mypageRepoProtocol.revoke()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ struct CategoryMainView: View {
.tapTitle { // 전체 필터로 이동
viewModel.send(action: .tapCategoryTitle(d1Category))
viewModel.send(action: .getBrandNameForCafe(d1Category))
print("main 🏪🏪🏪 \(viewModel.entirCode)")

router.navigateTo(.categoryFilter(
viewModel.filteredTitle,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@ extension CategoryViewModel {

case .getBrandNameForCafe(let d1Category):
self.brandFilter = d1Category.d2Category.filter { $0.d2CategoryName != "전체" }.map { $0.d2CategoryName }
print("🩵🩵🩵🩵brandFilterbrandFilter: \(self.brandFilter)🩵🩵🩵🩵")
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,25 @@ import SwiftUI
import DesignSystem

struct UserInfoView: View {
@ObservedObject var viewModel: MypageViewModel
let reviewCount: Int = 1
var nickname: (() -> Void)?
var action: (() -> Void)?

init(
viewModel: MypageViewModel,
nickname: (() -> Void)? = nil,
action: (() -> Void)? = nil
) {
self.viewModel = viewModel
self.nickname = nickname
self.action = action
}

var body: some View {
VStack(spacing: 30) {
HStack {
ZSText("닉네임닉네임닉네임닉네임", fontType: .subtitle1)
ZSText(viewModel.userInfo.nickname, fontType: .subtitle1)
Spacer()
ZSText("닉네임 변경", fontType: .body3, color: Color.neutral600)
.padding(.init(top: 6,leading: 10, bottom: 6, trailing: 10))
Expand All @@ -36,12 +39,12 @@ struct UserInfoView: View {
}
}

Text(reviewCount == 0 ? "아직 작성한 리뷰가 없어요" : "작성한 리뷰 (reviewCount)")
Text(viewModel.userInfo.rivewCnt == 0 ? "아직 작성한 리뷰가 없어요" : "작성한 리뷰 (reviewCount)")
.applyFont(font: .subtitle2)
.foregroundStyle(reviewCount == 0 ? Color.neutral800 : Color.white)
.foregroundStyle(viewModel.userInfo.rivewCnt == 0 ? Color.neutral800 : Color.white)
.padding(.vertical, 16)
.frame(maxWidth: .infinity)
.background(reviewCount == 0 ? Color.negative.opacity(0.1) : Color.primaryFF6972)
.background(viewModel.userInfo.rivewCnt == 0 ? Color.primaryFF6972.opacity(0.1) : Color.primaryFF6972)
.clipShape(RoundedRectangle(cornerRadius: 8))
.onTapGesture {
action?()
Expand All @@ -66,5 +69,5 @@ extension UserInfoView {
}

#Preview {
UserInfoView()
UserInfoView(viewModel: MypageViewModel(mypageUseCase: MypageUsecase(mypageRepoProtocol: MypageRepository(apiService: ApiService()))))
}
53 changes: 53 additions & 0 deletions Projects/App/Sources/Presentation/Mypage/Main/MypageInfoView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
//
// MypageInfoView.swift
// App
//
// Created by 박서연 on 2024/08/30.
// Copyright © 2024 iOS. All rights reserved.
//

import SwiftUI
import DesignSystem

struct MypageInfoView: View {
var body: some View {
VStack {
ForEach(MypageCenter.allCases, id: \.self) { center in
Text(center.rawValue)
.applyFont(font: .body3)
.foregroundStyle(Color.neutral300)
.frame(maxWidth: .infinity, alignment: .leading)
.padding(.bottom, 10)
.padding(.top, 20)

ForEach(center.type, id: \.self) { type in
HStack {
Text(type)
.applyFont(font: .body2)
.foregroundStyle(Color.neutral900)
.frame(maxWidth: .infinity, alignment: .leading)

Spacer()

if type == MypageCenter.service.type.last! {
Text("앱 버전1.201.23")
.applyFont(font: .body2)
.foregroundStyle(Color.neutral500)
} else {
ZerosomeAsset.ic_arrow_after
.resizable()
.frame(width: 24, height: 24)
}

}
.onTapGesture {
print("case 별로 이동 처리 추가 예정")
}
}
.padding(.bottom, 10)
DivideRectangle(height: 1, color: Color.neutral100)
}
}
.padding(.horizontal, 22)
}
}
Loading

0 comments on commit b83702b

Please sign in to comment.