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 :: [#365] 자세 - 개발 완료 #366

Merged
merged 27 commits into from
Jul 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
1b8a82b
FEAT :: [#365] 라이트 모드 고정
Eunho0922 Jul 20, 2024
db81a09
FEAT :: [#365] 자세 - 탭(어깨, 팔, 하체) 파일 추가
Eunho0922 Jul 25, 2024
d0ef341
REFACT :: [#365] 마음가짐 앱 이름 수정
Eunho0922 Jul 25, 2024
57f5e2e
FEAT :: [#365] 자세 - 부분별 검색 API 연동
Eunho0922 Jul 25, 2024
9b51e6d
FEAT :: [#365] 자세 - 부위별 model 추가
Eunho0922 Jul 25, 2024
67b40a0
REFACT :: [#365] 자세 - 추천 Model 변경
Eunho0922 Jul 25, 2024
141f9d5
FEAT :: [#365] 자세 - 부분별 검색 API 연동
Eunho0922 Jul 25, 2024
ba95d19
REFACT :: [#365] PoseDTO 리펙
Eunho0922 Jul 25, 2024
bc02c7c
FEAT :: [#365] 자세 - 카테고리별 조회 추가
Eunho0922 Jul 25, 2024
8791d91
REFACT :: [#365] 자세 - 디테일 리펙토링
Eunho0922 Jul 25, 2024
ced7620
FEAT :: [#365] 자세 - MainVC 탭 전환 기능 추가
Eunho0922 Jul 25, 2024
7652cac
FEAT :: [#365] 자세 - 검색 기능 구현
Eunho0922 Jul 25, 2024
a69b087
FEAT :: [#365] 자세 - 팔 탭 추가
Eunho0922 Jul 25, 2024
28d6ded
FEAT :: [#365] 자세 - 하체 탭 추가
Eunho0922 Jul 25, 2024
0ddb294
FEAT :: [#365] 자세 - 어깨 탭 추가
Eunho0922 Jul 25, 2024
163be2c
FEAT :: [#365] 자세 - 가슴 탭 서버 연동
Eunho0922 Jul 25, 2024
97079af
FEAT :: [#365] 자세 - 가슴 탭 서버 연동
Eunho0922 Jul 25, 2024
84c4af1
FEAT :: [#365] 자세 - 등 탭 서버 연동
Eunho0922 Jul 25, 2024
217273d
FEAT :: [#365] 자세 - 등 탭 서버 연동
Eunho0922 Jul 25, 2024
8b2d975
FEAT :: [#365] 자세 - 검색 기능 구현
Eunho0922 Jul 25, 2024
e60e9f0
FEAT :: [#365] 자세 - 추천 탭 서버 연동
Eunho0922 Jul 25, 2024
fb73bcc
FEAT :: [#365] 자세 - 추천 탭 서버 연동
Eunho0922 Jul 25, 2024
bb115f1
FEAT :: [#365] 자세 - 추천 탭 서버 연동
Eunho0922 Jul 25, 2024
37e1ed2
REFACT :: [#365] 자세 - 리펙토링
Eunho0922 Jul 25, 2024
9d66412
REFACT :: [#365] 자세 - Service 리펙
Eunho0922 Jul 25, 2024
9a11d2b
BURN :: [#365] 불필요한 코드 삭제
Eunho0922 Jul 25, 2024
06d1d1d
REFACT :: [#365] 마음가짐 - scenedelgate 리펙
Eunho0922 Jul 25, 2024
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
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ public extension Project {
"CFBundleDevelopmentRegion": "ko",
"CFBundleVersion": "1",
"CFBundleIdentifier": "com.maeumGaGym-health-iOS.release",
"CFBundleDisplayName": "Maeumgajim",
"CFBundleDisplayName": "마음가짐",
"UILaunchStoryboardName": "LaunchScreen",
"UIApplicationSceneManifest": [
"UIApplicationSupportsMultipleScenes": false,
Expand Down
1 change: 1 addition & 0 deletions Projects/Core/Sources/Base/BaseViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ open class BaseViewController<T>: UIViewController {
/// View가 메모리에 로드된 후 호출됩니다.
open override func viewDidLoad() {
super.viewDidLoad()
overrideUserInterfaceStyle = .light
bindActions()
bindViewModel()
layout()
Expand Down
10 changes: 4 additions & 6 deletions Projects/Data/Sources/Repository/PostureRepository.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@ public class PostureRepository: PostureRepositoryInterface {
.map { $0.toDomain() }
}

public func getPartData(type: PosturePartType) -> Single<PosturePartModel> {
return networkService.requestPartData(type: type)
public func getPartData(accessToken: String, category: String) -> Single<PosePartModel> {
return networkService.requestPartData(category: category, accessToken: accessToken)
.map(PosePartDTO.self)
.map { $0.toDomain() }
}

public func getDetailData(accessToken: String, id: Int) -> Single<PostureDetailModel> {
Expand All @@ -23,10 +25,6 @@ public class PostureRepository: PostureRepositoryInterface {
.map { $0.toDomain() }
}

public func getSearchData() -> Single<PostureSearchModel> {
return networkService.requestSearchData()
}

public func getAllPoseData(accessToken: String, lastUpdated: String) -> Single<PostureAllModel> {
return networkService.getAllPoseData(accessToken: accessToken, lastUpdated: lastUpdated)
.map(PostureAllDTO.self)
Expand Down
42 changes: 19 additions & 23 deletions Projects/Domain/Sources/Model/Posture/PosturePartModel.swift
Original file line number Diff line number Diff line change
@@ -1,33 +1,29 @@
import UIKit
import Foundation

public struct PosturePartModel {
public var exerciseType: [PosturePartExerciseTypeModel]
public var allExerciseData: [PosturePartExerciseModel]
public var bodyExerciseData: [PosturePartExerciseModel]
public var machineExerciseData: [PosturePartExerciseModel]

public init(exerciseType: [PosturePartExerciseTypeModel], allExerciseData: [PosturePartExerciseModel], bodyExerciseData: [PosturePartExerciseModel], machineExerciseData: [PosturePartExerciseModel]) {
self.exerciseType = exerciseType
self.allExerciseData = allExerciseData
self.bodyExerciseData = bodyExerciseData
self.machineExerciseData = machineExerciseData
public struct PosePartModel {
public var responses: [PosePartResponseModel]

public init(responses: [PosePartResponseModel]) {
self.responses = responses
}
}

public struct PosturePartExerciseModel {
public var image: UIImage
public struct PosePartResponseModel {
public var id: Int
public var category: [String]
public var needMachine: Bool
public var name: String
public var simplePart, exactPart: [String]
public var thumbnail: String

public init(image: UIImage, name: String) {
self.image = image
init(id: Int, category: [String], needMachine: Bool, name: String, simplePart: [String], exactPart: [String], thumbnail: String) {
self.id = id
self.category = category
self.needMachine = needMachine
self.name = name
self.simplePart = simplePart
self.exactPart = exactPart
self.thumbnail = thumbnail
}
}

public struct PosturePartExerciseTypeModel {
public var exerciseName: String

public init(exerciseName: String) {
self.exerciseName = exerciseName
}
}
Original file line number Diff line number Diff line change
@@ -1,30 +1,20 @@
import UIKit

public struct PoseRecommandModel {
public var poses: PoseRecommandPartModel
public var responses: [PoseRecommandPartModel]

public init(poses: PoseRecommandPartModel) {
self.poses = poses
public init(responses: [PoseRecommandPartModel]) {
self.responses = responses
}
}

public struct PoseRecommandPartModel {
public var 어깨, 복근, 등, 가슴, 팔: PoseRecommandPartResponseModel
public var category: String
public var poses: [PoseRecommandResponseModel]

public init(어깨: PoseRecommandPartResponseModel, 복근: PoseRecommandPartResponseModel, 등: PoseRecommandPartResponseModel, 가슴: PoseRecommandPartResponseModel, 팔: PoseRecommandPartResponseModel) {
self.어깨 = 어깨
self.복근 = 복근
self.등 = 등
self.가슴 = 가슴
self.팔 = 팔
}
}

public struct PoseRecommandPartResponseModel {
public var responses: [PoseRecommandResponseModel]

public init(responses: [PoseRecommandResponseModel]) {
self.responses = responses
public init(category: String, poses: [PoseRecommandResponseModel]) {
self.category = category
self.poses = poses
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ public enum PosturePartType {

public protocol PostureRepositoryInterface {
func getRecommandData(accessToken: String) -> Single<PoseRecommandModel>
func getPartData(type: PosturePartType) -> Single<PosturePartModel>
func getPartData(accessToken: String, category: String) -> Single<PosePartModel>
func getDetailData(accessToken: String, id: Int) -> Single<PostureDetailModel>
func getSearchData() -> Single<PostureSearchModel>
func getAllPoseData(accessToken: String, lastUpdated: String) -> Single<PostureAllModel>
}
83 changes: 57 additions & 26 deletions Projects/Domain/Sources/Response/PoseDTO.swift
Original file line number Diff line number Diff line change
Expand Up @@ -77,25 +77,27 @@ public extension PoseDetailDTO {
}
}

public struct PoseRecommandDTO: Decodable {
public let poses: PoseRecommandPart
protocol DomainConvertible {
associatedtype DomainType
func toDomain() -> DomainType
}

public struct PoseRecommandPart: Decodable {
public let 어깨, 복근, 등, 가슴, 팔: PoseRecommandPartResponse
public struct PoseRecommandDTO: Codable {
let responses: [PoseRecommandPart]
}

public struct PoseRecommandPartResponse: Decodable {
public let responses: [PoseRecommandResponse]
public struct PoseRecommandPart: Codable {
let category: String
let poses: [PoseRecommandResponse]
}

public struct PoseRecommandResponse: Decodable {
public let id: Int
public let category: [String]
public let needMachine: Bool
public let name: String
public let simplePart, exactPart: [String]
public let thumbnail: String
public struct PoseRecommandResponse: Codable {
let id: Int
let category: [String]
let needMachine: Bool
let name: String
let simplePart, exactPart: [String]
let thumbnail: String

enum CodingKeys: String, CodingKey {
case id, category
Expand All @@ -107,32 +109,61 @@ public struct PoseRecommandResponse: Decodable {
}
}

extension PoseRecommandDTO {
extension PoseRecommandDTO: DomainConvertible {
public func toDomain() -> PoseRecommandModel {
return .init(poses: poses.toDomain())
return .init(responses: responses.toDomain())
}
}

extension PoseRecommandPart {
extension PoseRecommandPart: DomainConvertible {
public func toDomain() -> PoseRecommandPartModel {
return .init(어깨: 어깨.toDomain(), 복근: 복근.toDomain(), 등: 등.toDomain(), 가슴: 가슴.toDomain(), 팔: 팔.toDomain())
return .init(category: category, poses: poses.toDomain())
}
}

extension PoseRecommandPartResponse {
public func toDomain() -> PoseRecommandPartResponseModel {
return .init(responses: responses.toDomain())
}
}

extension PoseRecommandResponse {
extension PoseRecommandResponse: DomainConvertible {
public func toDomain() -> PoseRecommandResponseModel {
return .init(id: id, category: category, needMachine: needMachine, name: name, simplePart: simplePart, exactPart: exactPart, thumbnail: thumbnail)
}
}

extension Array where Element == PoseRecommandResponse {
public func toDomain() -> [PoseRecommandResponseModel] {

extension Array where Element: DomainConvertible {
func toDomain() -> [Element.DomainType] {
return self.map { $0.toDomain() }
}
}

public struct PosePartDTO: Codable {
let responses: [PosePartResponse]
}

public struct PosePartResponse: Codable {
let id: Int
let category: [String]
let needMachine: Bool
let name: String
let simplePart, exactPart: [String]
let thumbnail: String

enum CodingKeys: String, CodingKey {
case id, category
case needMachine = "need_machine"
case name
case simplePart = "simple_part"
case exactPart = "exact_part"
case thumbnail
}
}

extension PosePartDTO: DomainConvertible {
public func toDomain() -> PosePartModel {
return .init(responses: responses.toDomain())
}
}

extension PosePartResponse: DomainConvertible {
public func toDomain() -> PosePartResponseModel {
return .init(id: id, category: category, needMachine: needMachine, name: name, simplePart: simplePart, exactPart: exactPart, thumbnail: thumbnail)
}
}
88 changes: 72 additions & 16 deletions Projects/Domain/Sources/UseCase/PostureUseCase.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,26 @@ import TokenManager

public protocol PostureUseCase {
var recommandData: PublishSubject<PoseRecommandModel> { get }
var partData: PublishSubject<PosturePartModel> { get }
var categoryChestData: PublishSubject<PosePartModel> { get }
var categoryBackData: PublishSubject<PosePartModel> { get }
var categoryShoulderData: PublishSubject<PosePartModel> { get }
var categoryArmData: PublishSubject<PosePartModel> { get }
var categoryLegData: PublishSubject<PosePartModel> { get }


var detailData: PublishSubject<PostureDetailModel> { get }
var searchData: PublishSubject<PostureSearchModel> { get }
var searchData: PublishSubject<PosePartModel> { get }
var poseAllData: PublishSubject<PostureAllModel> { get }

func getRecommandData()
func getPartData(type: PosturePartType)
func getChestData()
func getBackData()
func getShoulderData()
func getArmData()
func getLegData()

func getDetailData(id: Int)
func getSearchData()
func getSearchData(category: String)
func getAllPoseData()
}

Expand All @@ -29,9 +40,15 @@ public class DefaultPostureUseCase {

private let accessToken = TokenManagerImpl().get(key: .accessToken)
public let recommandData = PublishSubject<PoseRecommandModel>()
public let partData = PublishSubject<PosturePartModel>()
public let categoryChestData = PublishSubject<PosePartModel>()
public let categoryBackData = PublishSubject<PosePartModel>()
public let categoryShoulderData = PublishSubject<PosePartModel>()
public let categoryArmData = PublishSubject<PosePartModel>()
public let categoryLegData = PublishSubject<PosePartModel>()


public let detailData = PublishSubject<PostureDetailModel>()
public let searchData = PublishSubject<PostureSearchModel>()
public let searchData = PublishSubject<PosePartModel>()
public let poseAllData = PublishSubject<PostureAllModel>()

public init(repository: PostureRepositoryInterface) {
Expand All @@ -52,16 +69,56 @@ extension DefaultPostureUseCase: PostureUseCase {
}).disposed(by: disposeBag)
}

public func getPartData(type: PosturePartType) {
repository.getPartData(type: type)
public func getChestData() {
repository.getPartData(accessToken: accessToken ?? "", category: "가슴")
.subscribe(onSuccess: { [weak self] partData in
self?.partData.onNext(partData)
self?.categoryChestData.onNext(partData)
},
onFailure: { error in
print("PostureUseCase getPartData error occurred: \(error)")
print("PostureUseCase getChestData error occurred: \(error)")
}).disposed(by: disposeBag)
}


public func getBackData() {
repository.getPartData(accessToken: accessToken ?? "", category: "등")
.subscribe(onSuccess: { [weak self] partData in
self?.categoryBackData.onNext(partData)
},
onFailure: { error in
print("PostureUseCase getBacktData error occurred: \(error)")
}).disposed(by: disposeBag)
}

public func getShoulderData() {
repository.getPartData(accessToken: accessToken ?? "", category: "어깨")
.subscribe(onSuccess: { [weak self] partData in
self?.categoryShoulderData.onNext(partData)
},
onFailure: { error in
print("PostureUseCase getShoulderData error occurred: \(error)")
}).disposed(by: disposeBag)
}

public func getArmData() {
repository.getPartData(accessToken: accessToken ?? "", category: "팔")
.subscribe(onSuccess: { [weak self] partData in
self?.categoryArmData.onNext(partData)
},
onFailure: { error in
print("PostureUseCase getArmData error occurred: \(error)")
}).disposed(by: disposeBag)
}

public func getLegData() {
repository.getPartData(accessToken: accessToken ?? "", category: "하체")
.subscribe(onSuccess: { [weak self] partData in
self?.categoryLegData.onNext(partData)
},
onFailure: { error in
print("PostureUseCase getLegData error occurred: \(error)")
}).disposed(by: disposeBag)
}

public func getDetailData(id: Int) {
repository.getDetailData(accessToken: accessToken ?? "", id: id)
.subscribe(onSuccess: { [weak self] detailData in
Expand All @@ -72,13 +129,12 @@ extension DefaultPostureUseCase: PostureUseCase {
}).disposed(by: disposeBag)
}

public func getSearchData() {
repository.getSearchData()
public func getSearchData(category: String) {
repository.getPartData(accessToken: accessToken ?? "", category: category)
.subscribe(onSuccess: { [weak self] searchData in
self?.searchData.onNext(searchData)
},
onFailure: { error in
print("PostureUseCase getSearchData error occurred: \(error)")
}, onFailure: { _ in
self.searchData.onNext(PosePartModel(responses: []))
}).disposed(by: disposeBag)
}

Expand Down
Loading
Loading