From 9b7d9880978c536dba98c663fc03ee4cab83d02e Mon Sep 17 00:00:00 2001 From: leedoyeon849 Date: Sun, 18 Aug 2024 12:03:11 +0900 Subject: [PATCH] feat(AnnouncementDomain): Add AnnouncementSummaryEntity --- .../Sources/AnnouncementSummaryEntity.swift | 57 +++++++++++++++++ .../Sources/AppleLoginUsecase.swift | 1 - .../GetAnnouncementsByGroupUsecase.swift} | 63 +++++++++++++++++-- .../OrganizationDetailConverter.swift | 9 ++- .../Reactor/OrganizationDetailReactor.swift | 17 ++--- .../OrganizationDetailViewController.swift | 11 ++-- .../Reactor/OrganizationTabReactor.swift | 2 - 7 files changed, 135 insertions(+), 25 deletions(-) create mode 100644 Projects/Domain/AnnouncementDomainModule/AnnouncementEntity/Sources/AnnouncementSummaryEntity.swift rename Projects/Domain/{AnnouncementDomainModule/AnnouncementUsecase/Sources/GetAnnouncementsByGroup.swift => OrganizationDomainModule/OrganizationUsecase/Sources/GetAnnouncementsByGroupUsecase.swift} (78%) diff --git a/Projects/Domain/AnnouncementDomainModule/AnnouncementEntity/Sources/AnnouncementSummaryEntity.swift b/Projects/Domain/AnnouncementDomainModule/AnnouncementEntity/Sources/AnnouncementSummaryEntity.swift new file mode 100644 index 00000000..29bf39e6 --- /dev/null +++ b/Projects/Domain/AnnouncementDomainModule/AnnouncementEntity/Sources/AnnouncementSummaryEntity.swift @@ -0,0 +1,57 @@ +// +// AnnouncementSummaryEntity.swift +// AnnouncementEntity +// +// Created by DOYEON LEE on 8/18/24. +// + +import Foundation + +/** + Represents a announcement in group(organization). + */ +public struct AnnouncementSummaryEntity: Identifiable, Equatable { + /// Unique identifier for the announcement item + public let id: Int + + /// ID of organization that will generate announcement + public let organizationId: Int + + /// Announcement creation date + public let createdAt: Date? + + /// Image URL for the announcement illustration. (optional) + public let imageUrl: String? + + /// Title of the announcement + public let title: String + + /// Body text of the announcement + public let body: String + + /// Place of the announcement (optional) + public let placeName: String? + + /// Count of todo items (optional) + public let todoCount: Int? + + public init( + id: Int, + organizationId: Int, + imageUrl: String? = nil, + createdAt: Date? = nil, + title: String, + body: String, + placeName: String? = nil, + todoCount: Int? = nil + ) { + self.id = id + self.organizationId = organizationId + self.createdAt = createdAt + self.imageUrl = imageUrl + self.title = title + self.body = body + self.placeName = placeName + self.todoCount = todoCount + } +} diff --git a/Projects/Domain/MemberDomainModule/MemberUsecase/Sources/AppleLoginUsecase.swift b/Projects/Domain/MemberDomainModule/MemberUsecase/Sources/AppleLoginUsecase.swift index 062f5624..1f50f95b 100644 --- a/Projects/Domain/MemberDomainModule/MemberUsecase/Sources/AppleLoginUsecase.swift +++ b/Projects/Domain/MemberDomainModule/MemberUsecase/Sources/AppleLoginUsecase.swift @@ -141,7 +141,6 @@ extension AppleLoginUsecase: ASAuthorizationControllerDelegate, return Observable.error(Error.invalidToken) } } - .debug() .subscribe(onNext: { [weak self] output in self?.authorizationResultSubject.onNext(output) }, onError: { [weak self] error in diff --git a/Projects/Domain/AnnouncementDomainModule/AnnouncementUsecase/Sources/GetAnnouncementsByGroup.swift b/Projects/Domain/OrganizationDomainModule/OrganizationUsecase/Sources/GetAnnouncementsByGroupUsecase.swift similarity index 78% rename from Projects/Domain/AnnouncementDomainModule/AnnouncementUsecase/Sources/GetAnnouncementsByGroup.swift rename to Projects/Domain/OrganizationDomainModule/OrganizationUsecase/Sources/GetAnnouncementsByGroupUsecase.swift index 228edabd..2be49a44 100644 --- a/Projects/Domain/AnnouncementDomainModule/AnnouncementUsecase/Sources/GetAnnouncementsByGroup.swift +++ b/Projects/Domain/OrganizationDomainModule/OrganizationUsecase/Sources/GetAnnouncementsByGroupUsecase.swift @@ -1,5 +1,5 @@ // -// GetAnnouncementsByGroup.swift +// GetAnnouncementsByGroupUsecase.swift // AnnouncementUsecase // // Created by DOYEON LEE on 8/1/24. @@ -7,16 +7,71 @@ import Foundation +import Container +import OrganizationEntity import AnnouncementEntity +import OrganizationDataInterface +import Swinject import RxSwift -public struct GetAnnouncementsByGroup { +import RxSwift + +public struct GetAnnouncementsByGroupUsecase { + // MARK: DTO + public struct Input { + public let organizationId: Int + + public init(organizationId: Int) { + self.organizationId = organizationId + } + } + + public struct Output { + public let announcements: [AnnouncementSummaryEntity] + } + + // MARK: Error + public enum Error: LocalizedError { + case contentFieldNotFound + } + + // MARK: Dependency + private let organizationRepository = Container.shared.resolve(OrganizationRepositoryInterface.self)! + // MARK: Initializer public init() { } - public func execute(groupId: Int) -> Observable<[AnnouncementEntity]> { - return .just(Mock.AnnouncementEntities) + // MARK: Execute method + public func execute(_ input: Input) -> Observable { + + + let outputObservable = organizationRepository.getPublishedAnnouncements( + .init( + organizationId: Int64(input.organizationId), + pageable: .init() // TODO: + ) + ).flatMap { result -> Observable in + if let content = result.content { + let announcements = content.map { + AnnouncementSummaryEntity( + id: Int($0.announcementId ?? -1), + organizationId: input.organizationId, + imageUrl: $0.profileImageUrl, + createdAt: $0.createdAt, + title: $0.title ?? "", + body: $0.content ?? "", + placeName: $0.placeLinkName, + todoCount: 0 // todo 조회 API 사용? 같이 담아줄 수 있는지 요청 필요 + ) + } + return Observable.just(Output(announcements: announcements)) + } else { + return Observable.error(Error.contentFieldNotFound) + } + } + + return outputObservable } } diff --git a/Projects/Present/OrganizationPresentModule/OrganizationPresent/Sources/OrganizationDetail/Compositional/Converter/OrganizationDetailConverter.swift b/Projects/Present/OrganizationPresentModule/OrganizationPresent/Sources/OrganizationDetail/Compositional/Converter/OrganizationDetailConverter.swift index 5f4f0a80..721024c0 100644 --- a/Projects/Present/OrganizationPresentModule/OrganizationPresent/Sources/OrganizationDetail/Compositional/Converter/OrganizationDetailConverter.swift +++ b/Projects/Present/OrganizationPresentModule/OrganizationPresent/Sources/OrganizationDetail/Compositional/Converter/OrganizationDetailConverter.swift @@ -10,8 +10,8 @@ import AnnouncementEntity struct OrganizationDetailConverter { static func convert( - from announcements: [AnnouncementEntity], - onTapAnnouncementItem: @escaping (AnnouncementEntity) -> Void + from announcements: [AnnouncementSummaryEntity], + onTapAnnouncementItem: @escaping (AnnouncementSummaryEntity) -> Void ) -> [any CompositionalSection] { return [ AnnouncementSection( @@ -19,9 +19,8 @@ struct OrganizationDetailConverter { AnnouncementItem( id: announcement.id, title: announcement.title, - endDate: announcement.endAt, - place: announcement.place?.name, - todoCount: announcement.todos?.count, + place: announcement.placeName, + todoCount: announcement.todoCount, body: announcement.body, createdDate: announcement.createdAt ?? .now, onTap: { diff --git a/Projects/Present/OrganizationPresentModule/OrganizationPresent/Sources/OrganizationDetail/Reactor/OrganizationDetailReactor.swift b/Projects/Present/OrganizationPresentModule/OrganizationPresent/Sources/OrganizationDetail/Reactor/OrganizationDetailReactor.swift index 0f11dca1..561b15f0 100644 --- a/Projects/Present/OrganizationPresentModule/OrganizationPresent/Sources/OrganizationDetail/Reactor/OrganizationDetailReactor.swift +++ b/Projects/Present/OrganizationPresentModule/OrganizationPresent/Sources/OrganizationDetail/Reactor/OrganizationDetailReactor.swift @@ -20,13 +20,13 @@ class OrganizationDetailReactor: Reactor { enum Mutation { case setOrganization(OrganizationEntity) - case setAnnouncements([AnnouncementEntity]) + case setAnnouncements([AnnouncementSummaryEntity]) } // MARK: State struct State { var organization: OrganizationEntity? - var announcements: [AnnouncementEntity] = [] + var announcements: [AnnouncementSummaryEntity] = [] } let initialState: State = State() @@ -36,7 +36,7 @@ class OrganizationDetailReactor: Reactor { // MARK: Dependency private let getOrganizationDetailUsecase = GetOrganizationDetailUsecase() - private let getAnnouncementsByGroupUseCase = GetAnnouncementsByGroup() + private let getAnnouncementsByGroupUseCase = GetAnnouncementsByGroupUsecase() // MARK: DisposeBag private let disposeBag = DisposeBag() @@ -50,12 +50,15 @@ class OrganizationDetailReactor: Reactor { case let .viewDidLoad(organization): let setOrganization = getOrganizationDetailUsecase .execute(.init(organizationId: organization.id)) - .map { Mutation.setOrganization($0.organization) } + .map { output in + Mutation.setOrganization(output.organization) + } let setAnnouncements = getAnnouncementsByGroupUseCase - .execute(groupId: organization.id) - .delay(.seconds(2), scheduler: MainScheduler.instance) - .map { Mutation.setAnnouncements($0) } + .execute(.init(organizationId: organization.id)) + .map { output in + Mutation.setAnnouncements(output.announcements) + } return .merge( setOrganization, diff --git a/Projects/Present/OrganizationPresentModule/OrganizationPresent/Sources/OrganizationDetail/View/OrganizationDetailViewController.swift b/Projects/Present/OrganizationPresentModule/OrganizationPresent/Sources/OrganizationDetail/View/OrganizationDetailViewController.swift index 8dcf5eee..91ef1509 100644 --- a/Projects/Present/OrganizationPresentModule/OrganizationPresent/Sources/OrganizationDetail/View/OrganizationDetailViewController.swift +++ b/Projects/Present/OrganizationPresentModule/OrganizationPresent/Sources/OrganizationDetail/View/OrganizationDetailViewController.swift @@ -59,7 +59,6 @@ class OrganizationDetailViewController: BaseViewController