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

이번 주 인기 쇼츠 기능 구현 #21

Open
wants to merge 9 commits into
base: develop
Choose a base branch
from
30 changes: 11 additions & 19 deletions Climeet-iOS/Climeet-iOS.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -36,20 +36,11 @@
/* Begin PBXFileReference section */
0453294E2C5B8E3400BBE289 /* Climeet-iOSUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Climeet-iOSUITests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
0489EEF92C3BE58E00BFC55B /* Climeet-iOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Climeet-iOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
04ED90052CD3A519009B59A0 /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = "<group>"; };
B94EC2222BD13CBB00DC3FDB /* Climeet-iOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Climeet-iOS.app"; sourceTree = BUILT_PRODUCTS_DIR; };
B94EC2412BD1473E00DC3FDB /* .swiftlint.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = .swiftlint.yml; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */
041DA0422CF419B600CFDC31 /* PBXFileSystemSynchronizedBuildFileExceptionSet */ = {
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
membershipExceptions = (
Debug.xcconfig,
Shared.xcconfig,
);
target = B94EC2212BD13CBB00DC3FDB /* Climeet-iOS */;
};
604B97A62CC394F2005EDD29 /* PBXFileSystemSynchronizedBuildFileExceptionSet */ = {
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
membershipExceptions = (
Expand All @@ -60,7 +51,7 @@
/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */

/* Begin PBXFileSystemSynchronizedRootGroup section */
604B958E2CC394EF005EDD29 /* XCConfig */ = {isa = PBXFileSystemSynchronizedRootGroup; exceptions = (041DA0422CF419B600CFDC31 /* PBXFileSystemSynchronizedBuildFileExceptionSet */, ); explicitFileTypes = {}; explicitFolders = (); path = XCConfig; sourceTree = "<group>"; };
604B958E2CC394EF005EDD29 /* XCConfig */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = XCConfig; sourceTree = "<group>"; };
604B96BF2CC394F2005EDD29 /* Climeet-iOS */ = {isa = PBXFileSystemSynchronizedRootGroup; exceptions = (604B97A62CC394F2005EDD29 /* PBXFileSystemSynchronizedBuildFileExceptionSet */, ); explicitFileTypes = {}; explicitFolders = (); path = "Climeet-iOS"; sourceTree = "<group>"; };
604B97A82CC394F5005EDD29 /* Climeet-iOSTests */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = "Climeet-iOSTests"; sourceTree = "<group>"; };
604B97AC2CC394F7005EDD29 /* Climeet-iOSUITests */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = "Climeet-iOSUITests"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -208,7 +199,7 @@
attributes = {
BuildIndependentTargetsInParallel = 1;
LastSwiftUpdateCheck = 1530;
LastUpgradeCheck = 1600;
LastUpgradeCheck = 1610;
TargetAttributes = {
0453294D2C5B8E3400BBE289 = {
CreatedOnToolsVersion = 15.3;
Expand Down Expand Up @@ -336,8 +327,6 @@
/* Begin XCBuildConfiguration section */
045329572C5B8E3400BBE289 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReferenceAnchor = 604B958E2CC394EF005EDD29 /* XCConfig */;
baseConfigurationReferenceRelativePath = Debug.xcconfig;
buildSettings = {
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
Expand Down Expand Up @@ -382,8 +371,6 @@
};
0489EF002C3BE58E00BFC55B /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReferenceAnchor = 604B958E2CC394EF005EDD29 /* XCConfig */;
baseConfigurationReferenceRelativePath = Debug.xcconfig;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
Expand Down Expand Up @@ -430,6 +417,8 @@
};
B94EC22E2BD13CBD00DC3FDB /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReferenceAnchor = 604B958E2CC394EF005EDD29 /* XCConfig */;
baseConfigurationReferenceRelativePath = Release.xcconfig;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
Expand Down Expand Up @@ -493,6 +482,8 @@
};
B94EC22F2BD13CBD00DC3FDB /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReferenceAnchor = 604B958E2CC394EF005EDD29 /* XCConfig */;
baseConfigurationReferenceRelativePath = Release.xcconfig;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
Expand Down Expand Up @@ -550,15 +541,15 @@
B94EC2312BD13CBD00DC3FDB /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReferenceAnchor = 604B958E2CC394EF005EDD29 /* XCConfig */;
baseConfigurationReferenceRelativePath = Debug.xcconfig;
baseConfigurationReferenceRelativePath = Release.xcconfig;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_ASSET_PATHS = "\"Climeet-iOS/Preview Content\"";
DEVELOPMENT_TEAM = 7MJ69FU8BU;
DEVELOPMENT_TEAM = MV89SHQKF4;
ENABLE_PREVIEWS = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
GENERATE_INFOPLIST_FILE = YES;
Expand Down Expand Up @@ -586,15 +577,16 @@
};
B94EC2322BD13CBD00DC3FDB /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 04ED90052CD3A519009B59A0 /* Release.xcconfig */;
baseConfigurationReferenceAnchor = 604B958E2CC394EF005EDD29 /* XCConfig */;
baseConfigurationReferenceRelativePath = Release.xcconfig;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_ASSET_PATHS = "\"Climeet-iOS/Preview Content\"";
DEVELOPMENT_TEAM = 7MJ69FU8BU;
DEVELOPMENT_TEAM = MV89SHQKF4;
ENABLE_PREVIEWS = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
GENERATE_INFOPLIST_FILE = YES;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1600"
LastUpgradeVersion = "1610"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,6 @@ struct BannerReducer {

case .timerTick:
state.timerCount += 1
print(state.timerCount)
if state.timerCount == bannerChangeTime {
state.timerCount = 0
// TODO: banner change
Expand Down
5 changes: 5 additions & 0 deletions Climeet-iOS/Climeet-iOS/Presentation/Home/HomeReducer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@ struct HomeReducer {
var banner = BannerReducer.State()
var shortcut = HomeGymShortcutReducer.State()
var bestClimber = HomeBestClimberReducer.State()
var popularShorts = WeeklyPopularShortsReducer.State()
}

enum Action {
case banner(BannerReducer.Action)
case shortcut(HomeGymShortcutReducer.Action)
case bestClimber(HomeBestClimberReducer.Action)
case popularShorts(WeeklyPopularShortsReducer.Action)
}

var body: some ReducerOf<Self> {
Expand All @@ -33,5 +35,8 @@ struct HomeReducer {
Scope(state: \.bestClimber, action: \.bestClimber) {
HomeBestClimberReducer()
}
Scope(state: \.popularShorts, action: \.popularShorts) {
WeeklyPopularShortsReducer()
}
}
}
2 changes: 1 addition & 1 deletion Climeet-iOS/Climeet-iOS/Presentation/Home/HomeView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ struct HomeView: View {
.padding(.bottom, 48)
HomeBestClimberView(store: store.scope(state: \.bestClimber, action: \.bestClimber))
.padding(.bottom, 48)
WeeklyPopularShortsView()
WeeklyPopularShortsView(store: store.scope(state: \.popularShorts, action: \.popularShorts))
.padding(.bottom, 48)
WeeklyPopularGymView()
.padding(.bottom, 48)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//
// GymDifficulty.swift
// Climeet-iOS
//
// Created by 권승용 on 11/29/24.
//

import Foundation

struct GymDifficulty: Equatable {
let level: Int
let color: String

init(from dto: DifficultyMappingDTO.GymDifficulty.ResponseElement) throws {
guard let level = dto.difficulty,
let color = dto.gymDifficultyColor else {
throw AppError.dataParsingError("dto property nil")
}
self.level = level
self.color = color
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//
// PopularShorts.swift
// Climeet-iOS
//
// Created by 권승용 on 11/29/24.
//

import Foundation

struct PopularShorts: Equatable, Identifiable {
let id = UUID()
let gymName: String
let thumbnailImageURL: String
let difficulty: GymDifficulty

init(from dto: ShortsDTO.Shorts.Response, difficulty: GymDifficulty) throws {
guard let gymName = dto.gymName,
let thumbnailImageURL = dto.thumbnailImageURL else {
throw AppError.dataParsingError("dto property nil")
}
self.gymName = gymName
self.thumbnailImageURL = thumbnailImageURL
self.difficulty = difficulty
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
//
// WeeklyPopularShortsReducer.swift
// Climeet-iOS
//
// Created by 권승용 on 11/26/24.
//

import Foundation
import ComposableArchitecture

@Reducer
struct WeeklyPopularShortsReducer {
@ObservableState
struct State: Equatable {
var shortsItems: IdentifiedArrayOf<PopularShorts> = []
}

enum Action {
case onFirstAppear
case popularShortsResponse([PopularShorts])
}

@Dependency(\.shortsClient) var shortsClient
@Dependency(\.difficultyMappingClient) var difficultyMappingClient

var body: some ReducerOf<Self> {
Reduce { state, action in
switch action {
case .onFirstAppear:
return .run { send in
let request = ShortsDTO.List.Request(page: 0, size: 10)
let response = try await shortsClient.popularShorts(request)

let result = try await withThrowingTaskGroup(of: PopularShorts?.self) { group in
for responseItem in response.result {
group.addTask {
guard let id = responseItem.shortsDetailInfo?.gymID else {
throw AppError.dataParsingError("gymID not found")
}

let difficulty = try await difficultyMappingClient.gymDifficulty(id)

guard !difficulty.isEmpty else { return nil }

return try PopularShorts(
from: responseItem,
difficulty: try GymDifficulty(from: difficulty[0])
)
}
}

var popularShorts: [PopularShorts] = []

for try await item in group {
if let item = item {
popularShorts.append(item)
}
}

return popularShorts
}

await send(.popularShortsResponse(result))
}

case let .popularShortsResponse(response):
state.shortsItems = IdentifiedArray(uniqueElements: response)
print(state.shortsItems)
return .none
}
}
}
}
Loading