diff --git a/SOPT-iOS/Projects/Core/Sources/Extension/Foundation+/String+.swift b/SOPT-iOS/Projects/Core/Sources/Extension/Foundation+/String+.swift index 478876cf7..08ca1c975 100644 --- a/SOPT-iOS/Projects/Core/Sources/Extension/Foundation+/String+.swift +++ b/SOPT-iOS/Projects/Core/Sources/Extension/Foundation+/String+.swift @@ -114,7 +114,7 @@ public extension String { // 앞쪽에 띄어쓰기가 없으면, 중간 인덱스 뒷쪽의 첫번째 인덱스 if spaceIndex == nil { - spaceIndex = self[middleIndex...endIndex].firstIndex(of: " ") + spaceIndex = self[middleIndex..(key: "checkedAppVersion") public static var checkedAppVersion } + + public struct Soptamp { + @UserDefaultWrapper(key: "reportUrl") public static var reportUrl + } } extension UserDefaultKeyList { diff --git a/SOPT-iOS/Projects/Data/Sources/Repository/MainRepository.swift b/SOPT-iOS/Projects/Data/Sources/Repository/MainRepository.swift index 96df2119b..1141d6b6a 100644 --- a/SOPT-iOS/Projects/Data/Sources/Repository/MainRepository.swift +++ b/SOPT-iOS/Projects/Data/Sources/Repository/MainRepository.swift @@ -18,14 +18,21 @@ public class MainRepository { private let configService: ConfigService private let descriptionService: DescriptionService private let pokeService: PokeService + private let stampService: StampService private let cancelBag = CancelBag() - public init(userService: UserService, configService: ConfigService, descriptionService: DescriptionService, pokeService: PokeService) { + public init(userService: UserService, + configService: ConfigService, + descriptionService: DescriptionService, + pokeService: PokeService, + stampService: StampService + ) { self.userService = userService self.configService = configService self.descriptionService = descriptionService self.pokeService = pokeService + self.stampService = stampService } } @@ -98,4 +105,10 @@ extension MainRepository: MainRepositoryInterface { .map { $0.toDomain() } .eraseToAnyPublisher() } + + public func getReportUrl() -> AnyPublisher { + stampService.getReportUrl() + .map { $0.toDomain() } + .eraseToAnyPublisher() + } } diff --git a/SOPT-iOS/Projects/Data/Sources/Repository/MissionListRepository.swift b/SOPT-iOS/Projects/Data/Sources/Repository/MissionListRepository.swift index 107ff43f5..a2b168f61 100644 --- a/SOPT-iOS/Projects/Data/Sources/Repository/MissionListRepository.swift +++ b/SOPT-iOS/Projects/Data/Sources/Repository/MissionListRepository.swift @@ -31,6 +31,7 @@ public class MissionListRepository { } extension MissionListRepository: MissionListRepositoryInterface { + public func fetchMissionList(type: MissionListFetchType, userName: String?) -> AnyPublisher<[MissionListModel], Error> { guard let userName else { return fetchMissionList(type: type) diff --git a/SOPT-iOS/Projects/Data/Sources/Transform/MissionListTransform.swift b/SOPT-iOS/Projects/Data/Sources/Transform/MissionListTransform.swift index f2a50976b..8d46967af 100644 --- a/SOPT-iOS/Projects/Data/Sources/Transform/MissionListTransform.swift +++ b/SOPT-iOS/Projects/Data/Sources/Transform/MissionListTransform.swift @@ -28,3 +28,9 @@ public extension MissionListEntity { } } } + +extension SoptampReportUrlEntity { + func toDomain() -> SoptampReportUrlModel { + return SoptampReportUrlModel(reportUrl: reportUrl) + } +} diff --git a/SOPT-iOS/Projects/Demo/Sources/Dependency/RegisterDependencies.swift b/SOPT-iOS/Projects/Demo/Sources/Dependency/RegisterDependencies.swift index 4bd3ee3cb..4ee0632d3 100644 --- a/SOPT-iOS/Projects/Demo/Sources/Dependency/RegisterDependencies.swift +++ b/SOPT-iOS/Projects/Demo/Sources/Dependency/RegisterDependencies.swift @@ -40,7 +40,8 @@ extension AppDelegate { userService: DefaultUserService(), configService: DefaultConfigService(), descriptionService: DefaultDescriptionService(), - pokeService: DefaultPokeService() + pokeService: DefaultPokeService(), + stampService: DefaultStampService() ) } ) diff --git a/SOPT-iOS/Projects/Domain/Sources/Model/SoptampReportUrlModel.swift b/SOPT-iOS/Projects/Domain/Sources/Model/SoptampReportUrlModel.swift new file mode 100644 index 000000000..96560193b --- /dev/null +++ b/SOPT-iOS/Projects/Domain/Sources/Model/SoptampReportUrlModel.swift @@ -0,0 +1,19 @@ +// +// SoptampReportURLModel.swift +// Domain +// +// Created by Jae Hyun Lee on 10/14/24. +// Copyright © 2024 SOPT-iOS. All rights reserved. +// + +import Foundation + +// MARK: - SoptampReportURLModel + +public struct SoptampReportUrlModel: Codable { + public let reportUrl: String + + public init(reportUrl: String) { + self.reportUrl = reportUrl + } +} diff --git a/SOPT-iOS/Projects/Domain/Sources/RepositoryInterface/MainRepositoryInterface.swift b/SOPT-iOS/Projects/Domain/Sources/RepositoryInterface/MainRepositoryInterface.swift index 96fe51514..2a80f8416 100644 --- a/SOPT-iOS/Projects/Domain/Sources/RepositoryInterface/MainRepositoryInterface.swift +++ b/SOPT-iOS/Projects/Domain/Sources/RepositoryInterface/MainRepositoryInterface.swift @@ -18,4 +18,5 @@ public protocol MainRepositoryInterface { func checkPokeNewUser() -> AnyPublisher func appService() -> AnyPublisher<[AppServiceModel], Error> func hotBoard() -> AnyPublisher + func getReportUrl() -> AnyPublisher } diff --git a/SOPT-iOS/Projects/Domain/Sources/UseCase/MainUseCase.swift b/SOPT-iOS/Projects/Domain/Sources/UseCase/MainUseCase.swift index acb2c5810..13d39dde1 100644 --- a/SOPT-iOS/Projects/Domain/Sources/UseCase/MainUseCase.swift +++ b/SOPT-iOS/Projects/Domain/Sources/UseCase/MainUseCase.swift @@ -26,6 +26,7 @@ public protocol MainUseCase { func checkPokeNewUser() func getAppService() func getHotBoard() + func getReportUrl() } public class DefaultMainUseCase { @@ -140,4 +141,14 @@ extension DefaultMainUseCase: MainUseCase { } .store(in: cancelBag) } + + public func getReportUrl() { + repository.getReportUrl() + .withUnretained(self) + .sink { event in + print("GetReportUrl State: \(event)") + } receiveValue: { owner, resultModel in + UserDefaultKeyList.Soptamp.reportUrl = resultModel.reportUrl + }.store(in: cancelBag) + } } diff --git a/SOPT-iOS/Projects/Domain/Sources/UseCase/MissionListUseCase.swift b/SOPT-iOS/Projects/Domain/Sources/UseCase/MissionListUseCase.swift index d963c6f32..40d881993 100644 --- a/SOPT-iOS/Projects/Domain/Sources/UseCase/MissionListUseCase.swift +++ b/SOPT-iOS/Projects/Domain/Sources/UseCase/MissionListUseCase.swift @@ -18,6 +18,7 @@ public protocol MissionListUseCase { var missionListModelsFetched: PassthroughSubject<[MissionListModel], Error> { get set } var usersActiveGenerationInfo: PassthroughSubject { get set } + var errorOccurred: PassthroughSubject { get set } } public class DefaultMissionListUseCase { @@ -26,17 +27,22 @@ public class DefaultMissionListUseCase { private var cancelBag = CancelBag() public var missionListModelsFetched = PassthroughSubject<[MissionListModel], Error>() public var usersActiveGenerationInfo = PassthroughSubject() - + public var errorOccurred = PassthroughSubject() + public init(repository: MissionListRepositoryInterface) { self.repository = repository } } extension DefaultMissionListUseCase: MissionListUseCase { + public func fetchMissionList(type: MissionListFetchType) { repository.fetchMissionList(type: type, userName: nil) .sink(receiveCompletion: { event in print("completion: \(event)") + if case Subscribers.Completion.failure = event { + self.errorOccurred.send() + } }, receiveValue: { model in self.missionListModelsFetched.send(model) }) @@ -73,3 +79,4 @@ extension DefaultMissionListUseCase: MissionListUseCase { }).store(in: self.cancelBag) } } + diff --git a/SOPT-iOS/Projects/Features/BaseFeatureDependency/Sources/Alert/AlertVCTheme.swift b/SOPT-iOS/Projects/Features/BaseFeatureDependency/Sources/Alert/AlertVCTheme.swift index 93da5b422..1f566d967 100644 --- a/SOPT-iOS/Projects/Features/BaseFeatureDependency/Sources/Alert/AlertVCTheme.swift +++ b/SOPT-iOS/Projects/Features/BaseFeatureDependency/Sources/Alert/AlertVCTheme.swift @@ -68,7 +68,7 @@ extension AlertVC.AlertTheme { case .main: return isNetworkErr ? DSKitAsset.Colors.white100.color : DSKitAsset.Colors.gray600.color case .soptamp: - return isNetworkErr ? DSKitAsset.Colors.soptampError200.color : DSKitAsset.Colors.soptampGray300.color + return isNetworkErr ? DSKitAsset.Colors.black60.color : DSKitAsset.Colors.soptampGray300.color } } diff --git a/SOPT-iOS/Projects/Features/DailySoptuneFeature/Sources/Components/DailySoptuneProfileImageView.swift b/SOPT-iOS/Projects/Features/DailySoptuneFeature/Sources/Components/DailySoptuneProfileImageView.swift index 8c5f6edba..7dd8e8d90 100644 --- a/SOPT-iOS/Projects/Features/DailySoptuneFeature/Sources/Components/DailySoptuneProfileImageView.swift +++ b/SOPT-iOS/Projects/Features/DailySoptuneFeature/Sources/Components/DailySoptuneProfileImageView.swift @@ -10,14 +10,7 @@ import UIKit import DSKit extension CustomProfileImageView { - public func setImage(with url: String) { + func setImage(with url: String) { self.setImage(with: url, placeholder: DSKitAsset.Assets.iconDefaultProfile.image) } - - // 오늘의 솝마디에서는 Border가 들어가지 않는 것으로 통일 - @discardableResult - public func setBorder() -> Self { - self.layer.borderWidth = 0 - return self - } } diff --git a/SOPT-iOS/Projects/Features/DailySoptuneFeature/Sources/DailySoptuneScene/Views/DailySoptuneResultPokeView.swift b/SOPT-iOS/Projects/Features/DailySoptuneFeature/Sources/DailySoptuneScene/Views/DailySoptuneResultPokeView.swift index 3f0372727..ba2b03b0b 100644 --- a/SOPT-iOS/Projects/Features/DailySoptuneFeature/Sources/DailySoptuneScene/Views/DailySoptuneResultPokeView.swift +++ b/SOPT-iOS/Projects/Features/DailySoptuneFeature/Sources/DailySoptuneScene/Views/DailySoptuneResultPokeView.swift @@ -20,8 +20,8 @@ public final class DailySoptuneResultPokeView: UIView { .asDriver() lazy var profileTap = self.profileImageView.gesture() - .filter { _ in self.user?.isAnonymous == false } - .map { _ in self.user }.asDriver() + .filter { [weak self] _ in self?.user?.isAnonymous == false } + .map { [weak self] _ in self?.user }.asDriver() // MARK: - Properties @@ -151,7 +151,7 @@ extension DailySoptuneResultPokeView { self.nameLabel.text = model.name self.partLabel.text = "\(model.generation)기 \(model.part)" self.profileImageView.setImage(with: model.profileImage) - self.profileImageView.setBorder() + self.profileImageView.layer.borderWidth = 0 self.kokButton.isEnabled = !model.isAlreadyPoke } diff --git a/SOPT-iOS/Projects/Features/MainFeature/Sources/MainScene/ViewModel/MainViewModel.swift b/SOPT-iOS/Projects/Features/MainFeature/Sources/MainScene/ViewModel/MainViewModel.swift index 288952a25..d6bcfc853 100644 --- a/SOPT-iOS/Projects/Features/MainFeature/Sources/MainScene/ViewModel/MainViewModel.swift +++ b/SOPT-iOS/Projects/Features/MainFeature/Sources/MainScene/ViewModel/MainViewModel.swift @@ -152,6 +152,7 @@ extension MainViewModel { self.requestAuthorizationForNotification() self.useCase.getServiceState() self.trackAmplitude(event: .viewAppHome) + self.useCase.getReportUrl() }.store(in: cancelBag) input.hotBoardTapped diff --git a/SOPT-iOS/Projects/Features/StampFeature/Interface/Sources/StampFeatureViewControllable.swift b/SOPT-iOS/Projects/Features/StampFeature/Interface/Sources/StampFeatureViewControllable.swift index d652bffd9..174c21148 100644 --- a/SOPT-iOS/Projects/Features/StampFeature/Interface/Sources/StampFeatureViewControllable.swift +++ b/SOPT-iOS/Projects/Features/StampFeature/Interface/Sources/StampFeatureViewControllable.swift @@ -18,6 +18,7 @@ public protocol MissionListCoordinatable { var onCurrentGenerationRankingButtonTap: ((RankingViewType) -> Void)? { get set } var onGuideTap: (() -> Void)? { get set } var onCellTap: ((MissionListModel, _ username: String?) -> Void)? { get set } + var onReportButtonTap: (() -> Void)? { get set } } public protocol ListDetailViewControllable: ViewControllable & ListDetailCoordinatable { } public protocol ListDetailCoordinatable { diff --git a/SOPT-iOS/Projects/Features/StampFeature/Sources/Coordinator/StampCoordinator.swift b/SOPT-iOS/Projects/Features/StampFeature/Sources/Coordinator/StampCoordinator.swift index ce2da2fee..239147e07 100644 --- a/SOPT-iOS/Projects/Features/StampFeature/Sources/Coordinator/StampCoordinator.swift +++ b/SOPT-iOS/Projects/Features/StampFeature/Sources/Coordinator/StampCoordinator.swift @@ -12,6 +12,7 @@ import Core import BaseFeatureDependency import StampFeatureInterface import Domain +import SafariServices public final class StampCoordinator: DefaultCoordinator { @@ -50,6 +51,12 @@ final class StampCoordinator: DefaultCoordinator { missionList.onCellTap = { [weak self] model, username in self?.runMissionDetailFlow(model, username) } + missionList.onReportButtonTap = { [weak self] in + guard let url = UserDefaultKeyList.Soptamp.reportUrl else { return } + let safariViewController = SFSafariViewController(url: URL(string: url)!) + safariViewController.playgroundStyle() + self?.rootController?.present(safariViewController, animated: true) + } rootController = missionList.asNavigationController router.present(rootController, animated: true, modalPresentationSytle: .overFullScreen) } diff --git a/SOPT-iOS/Projects/Features/StampFeature/Sources/MissionListScene/VC/MissionListVC.swift b/SOPT-iOS/Projects/Features/StampFeature/Sources/MissionListScene/VC/MissionListVC.swift index 0ca26e41b..cae8436c3 100644 --- a/SOPT-iOS/Projects/Features/StampFeature/Sources/MissionListScene/VC/MissionListVC.swift +++ b/SOPT-iOS/Projects/Features/StampFeature/Sources/MissionListScene/VC/MissionListVC.swift @@ -43,6 +43,7 @@ public class MissionListVC: UIViewController, MissionListViewControllable { public var onCurrentGenerationRankingButtonTap: ((RankingViewType) -> Void)? public var onGuideTap: (() -> Void)? public var onCellTap: ((MissionListModel, String?) -> Void)? + public var onReportButtonTap: (() -> Void)? private var usersActiveGenerationStatus: UsersActiveGenerationStatusViewResponse? @@ -265,15 +266,22 @@ extension MissionListVC { owner.onSwiped?() }.store(in: self.cancelBag) } - + private func bindViewModels() { let input = MissionListViewModel.Input( viewDidLoad: Driver.just(()), viewWillAppear: viewWillAppear.asDriver(), missionTypeSelected: missionTypeMenuSelected ) + let output = self.viewModel.transform(from: input, cancelBag: self.cancelBag) + naviBar.reportButtonTapped + .withUnretained(self) + .sink { owner, _ in + owner.onReportButtonTap?() + }.store(in: cancelBag) + output.$missionListModel .compactMap { $0 } .sink { [weak self] model in @@ -289,6 +297,12 @@ extension MissionListVC { self?.remakeButtonConstraint() self?.configureCurrentGenerationButton(with: String(describing: generationStatus.currentGeneration)) }.store(in: self.cancelBag) + + output.needNetworkAlert + .withUnretained(self) + .sink { owner, _ in + owner.showNetworkAlert() + }.store(in: self.cancelBag) } } @@ -397,6 +411,13 @@ extension MissionListVC { attributedStr.addAttribute(NSAttributedString.Key.foregroundColor, value: UIColor.white, range: NSMakeRange(0, attributedStr.length)) self.currentGenerationRankFloatingButton.setAttributedTitle(attributedStr, for: .normal) } + + private func showNetworkAlert() { + AlertUtils.presentNetworkAlertVC( + theme: .soptamp, + animated: true + ) + } } // MARK: - UICollectionViewDelegate diff --git a/SOPT-iOS/Projects/Features/StampFeature/Sources/MissionListScene/ViewModel/MissionListViewModel.swift b/SOPT-iOS/Projects/Features/StampFeature/Sources/MissionListScene/ViewModel/MissionListViewModel.swift index 486052b36..eb8cdeb11 100644 --- a/SOPT-iOS/Projects/Features/StampFeature/Sources/MissionListScene/ViewModel/MissionListViewModel.swift +++ b/SOPT-iOS/Projects/Features/StampFeature/Sources/MissionListScene/ViewModel/MissionListViewModel.swift @@ -31,6 +31,8 @@ public class MissionListViewModel: ViewModelType { public class Output: NSObject { @Published var missionListModel: [MissionListModel]? @Published var usersActivateGenerationStatus: UsersActiveGenerationStatusViewResponse? + @Published var reportUrl: SoptampReportUrlModel? + var needNetworkAlert = PassthroughSubject() } // MARK: - init @@ -65,7 +67,7 @@ extension MissionListViewModel { .sink { owner, fetchType in owner.useCase.fetchMissionList(type: fetchType) }.store(in: cancelBag) - + return output } @@ -100,5 +102,11 @@ extension MissionListViewModel { .sink { usersActivateGenerationStatus in output.usersActivateGenerationStatus = usersActivateGenerationStatus }.store(in: self.cancelBag) + + self.useCase.errorOccurred + .asDriver() + .sink { _ in + output.needNetworkAlert.send() + }.store(in: cancelBag) } } diff --git a/SOPT-iOS/Projects/Modules/DSKit/Resources/Assets.xcassets/Soptamp/icReport.imageset/Contents.json b/SOPT-iOS/Projects/Modules/DSKit/Resources/Assets.xcassets/Soptamp/icReport.imageset/Contents.json new file mode 100644 index 000000000..62ea3ed2d --- /dev/null +++ b/SOPT-iOS/Projects/Modules/DSKit/Resources/Assets.xcassets/Soptamp/icReport.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "ic_report.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SOPT-iOS/Projects/Modules/DSKit/Resources/Assets.xcassets/Soptamp/icReport.imageset/ic_report.svg b/SOPT-iOS/Projects/Modules/DSKit/Resources/Assets.xcassets/Soptamp/icReport.imageset/ic_report.svg new file mode 100644 index 000000000..1d1b5993f --- /dev/null +++ b/SOPT-iOS/Projects/Modules/DSKit/Resources/Assets.xcassets/Soptamp/icReport.imageset/ic_report.svg @@ -0,0 +1,3 @@ + + + diff --git a/SOPT-iOS/Projects/Modules/DSKit/Sources/Components/SoptampComponents/STNavigationBar.swift b/SOPT-iOS/Projects/Modules/DSKit/Sources/Components/SoptampComponents/STNavigationBar.swift index 118da7e16..4bde90a28 100644 --- a/SOPT-iOS/Projects/Modules/DSKit/Sources/Components/SoptampComponents/STNavigationBar.swift +++ b/SOPT-iOS/Projects/Modules/DSKit/Sources/Components/SoptampComponents/STNavigationBar.swift @@ -34,12 +34,15 @@ public class STNavigationBar: UIView { private let titleButton = UIButton() private let leftButton = UIButton() private let rightButton = UIButton() + private let reportButton = UIButton() // MARK: - Properties private var naviType: NaviType! private var rightButtonClosure: (() -> Void)? private var leftButtonClosure: (() -> Void)? + private var reportButtonClosure: (() -> Void)? + public var rightButtonTapped: Driver { rightButton.publisher(for: .touchUpInside) .map { _ in () } @@ -55,6 +58,11 @@ public class STNavigationBar: UIView { .map { _ in () } .asDriver() } + public var reportButtonTapped: Driver { + reportButton.publisher(for: .touchUpInside) + .map { _ in () } + .asDriver() + } // MARK: - Initialize @@ -130,6 +138,13 @@ extension STNavigationBar { return self } + @discardableResult + public func reportButtonAction(_ closure: (() -> Void)? = nil) -> Self { + self.reportButtonClosure = closure + self.reportButton.addTarget(self, action: #selector(tappedReportButton), for: .touchUpInside) + return self + } + @discardableResult public func resetLeftButtonAction(_ closure: (() -> Void)? = nil) -> Self { self.leftButtonClosure = closure @@ -200,6 +215,11 @@ extension STNavigationBar { private func tappedLeftButton() { self.leftButtonClosure?() } + + @objc + private func tappedReportButton() { + self.reportButtonClosure?() + } } // MARK: - UI & Layout @@ -222,6 +242,7 @@ extension STNavigationBar { titleButton.setTitleColor(.black, for: .normal) titleButton.semanticContentAttribute = .forceRightToLeft titleButton.titleLabel?.adjustsFontSizeToFitWidth = true + reportButton.setImage(DSKitAsset.Assets.icReport.image, for: .normal) case .titleWithLeftButton: rightButton.isHidden = true leftButton.setImage(UIImage(asset: DSKitAsset.Assets.icArrow), for: .normal) @@ -243,18 +264,25 @@ extension STNavigationBar { } private func setTitleLayout() { - self.addSubviews(titleButton, rightButton) + self.addSubviews(titleButton, rightButton, reportButton) titleButton.snp.makeConstraints { make in make.centerY.equalToSuperview().offset(1) make.leading.equalToSuperview().inset(20) } - + rightButton.snp.makeConstraints { make in make.centerY.equalToSuperview() make.trailing.equalToSuperview().inset(20) make.width.height.equalTo(32) } + + reportButton.snp.makeConstraints { make in + make.centerY.equalToSuperview() + make.trailing.equalTo(rightButton.snp.leading).offset(-12) + make.size.equalTo(32) + } + } private func setTitleWithLeftButton() { diff --git a/SOPT-iOS/Projects/Modules/Networks/Sources/API/StampAPI.swift b/SOPT-iOS/Projects/Modules/Networks/Sources/API/StampAPI.swift index a857a753a..8297d0064 100644 --- a/SOPT-iOS/Projects/Modules/Networks/Sources/API/StampAPI.swift +++ b/SOPT-iOS/Projects/Modules/Networks/Sources/API/StampAPI.swift @@ -18,6 +18,7 @@ public enum StampAPI { case putStamp(requestModel: ListDetailRequestEntity) case deleteStamp(stampId: Int) case resetStamp + case getReportUrl } extension StampAPI: BaseAPI { @@ -27,7 +28,7 @@ extension StampAPI: BaseAPI { // MARK: - Header public var headers: [String : String]? { switch self { - case .fetchStampListDetail, .resetStamp, .postStamp, .putStamp, .deleteStamp: + case .fetchStampListDetail, .resetStamp, .postStamp, .putStamp, .deleteStamp, .getReportUrl: return HeaderType.jsonWithToken.value } } @@ -43,6 +44,8 @@ extension StampAPI: BaseAPI { return "/\(stampId)" case .resetStamp: return "/all" + case .getReportUrl: + return "/report" } } diff --git a/SOPT-iOS/Projects/Modules/Networks/Sources/Entity/SoptampReportUrlEntity.swift b/SOPT-iOS/Projects/Modules/Networks/Sources/Entity/SoptampReportUrlEntity.swift new file mode 100644 index 000000000..425414551 --- /dev/null +++ b/SOPT-iOS/Projects/Modules/Networks/Sources/Entity/SoptampReportUrlEntity.swift @@ -0,0 +1,13 @@ +// +// SoptampReportUrlEntity.swift +// Networks +// +// Created by Jae Hyun Lee on 10/14/24. +// Copyright © 2024 SOPT-iOS. All rights reserved. +// + +import Foundation + +public struct SoptampReportUrlEntity: Codable { + public let reportUrl: String +} diff --git a/SOPT-iOS/Projects/Modules/Networks/Sources/Service/StampService.swift b/SOPT-iOS/Projects/Modules/Networks/Sources/Service/StampService.swift index 3e0032385..37d1c16e6 100644 --- a/SOPT-iOS/Projects/Modules/Networks/Sources/Service/StampService.swift +++ b/SOPT-iOS/Projects/Modules/Networks/Sources/Service/StampService.swift @@ -22,6 +22,7 @@ public protocol StampService { func putStamp(requestModel: ListDetailRequestEntity) -> AnyPublisher func deleteStamp(stampId: Int) -> AnyPublisher func resetStamp() -> AnyPublisher + func getReportUrl() -> AnyPublisher } extension DefaultStampService: StampService { @@ -44,4 +45,8 @@ extension DefaultStampService: StampService { public func resetStamp() -> AnyPublisher { return requestObjectInCombineNoResult(StampAPI.resetStamp) } + + public func getReportUrl() -> AnyPublisher { + return requestObjectInCombine(StampAPI.getReportUrl) + } } diff --git a/SOPT-iOS/Projects/SOPT-iOS/Sources/Dependency/RegisterDependencies.swift b/SOPT-iOS/Projects/SOPT-iOS/Sources/Dependency/RegisterDependencies.swift index d70a5af9b..204c011e1 100644 --- a/SOPT-iOS/Projects/SOPT-iOS/Sources/Dependency/RegisterDependencies.swift +++ b/SOPT-iOS/Projects/SOPT-iOS/Sources/Dependency/RegisterDependencies.swift @@ -40,7 +40,8 @@ extension AppDelegate { userService: DefaultUserService(), configService: DefaultConfigService(), descriptionService: DefaultDescriptionService(), - pokeService: DefaultPokeService() + pokeService: DefaultPokeService(), + stampService: DefaultStampService() ) } )