Skip to content

Commit

Permalink
feat(ImageData): Create Image repository
Browse files Browse the repository at this point in the history
  • Loading branch information
dodo849 committed Aug 25, 2024
1 parent 8de03ff commit fcfb9f6
Show file tree
Hide file tree
Showing 23 changed files with 239 additions and 41 deletions.
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
TUIST = tuist
SWIFTLINT = swiftlint
FASTLANE = fastlane

all: lint generate

generate:
$(TUIST) install
TUIST_ROOT_DIR=${PWD} $(TUIST) generate
$(SWIFTLINT) autocorrect --fix
$(FASTLANE) match

lint:
$(SWIFTLINT)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// This file is used to generate the TuistBundle file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//
// ImageError.swift
// ImageData
//
// Created by DOYEON LEE on 8/25/24.
//

import Foundation

/// An error type that announcement related errors.
public enum ImageError: LocalizedError {
/// The response from the server is not match client scheme.
case invalidResponse

/// Wraps another error that caused this error.
case underlying(_ error: Error)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
//
// ImageRepository.swift
// ImageData
//
// Created by DOYEON LEE on 8/25/24.
//

import OpenapiGenerated
import ImageDataInterface
import CommonData

import OpenAPIURLSession
import RxSwift

public struct ImageRepository: ImageRepositoryInterface {
private let client: APIProtocol

public init() {
self.client = Client(
serverURL: UrlConfig.baseUrl.url,
configuration: .init(dateTranscoder: .custom),
transport: URLSessionTransport(),
middlewares: [AuthenticationMiddleware()]
)
}

func getImageUploadPath(
_ request: GetImageUploadPathRequest
) -> Observable<GetImageUploadPathResponse> {
return Observable.create { observer in
Task {
do {
let response = try await client.getContentImage(
.init(query: request)
)

let data = try response.ok.body.json

observer.onNext(data)
observer.onCompleted()
} catch {
observer.onError(ImageError.underlying(error))
}
}

return Disposables.create()
}
}

func notifyImageUploadComplete(
_ request: NotifyImageUploadCompleteRequest
) -> Observable<NotifyImageUploadCompleteResponse> {
return Observable.create { observer in
Task {
do {
let response = try await client.notifyContentImageSaveSuccess(
body: request
)

let data = try response.ok

observer.onNext(())
observer.onCompleted()
} catch {
observer.onError(ImageError.underlying(error))
}
}

return Disposables.create()
}
}
}
9 changes: 9 additions & 0 deletions Projects/Data/ImageDataModule/Project.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import ProjectDescription
import ProjectDescriptionHelpers

let project = Project.makeDataModule(
.image,
dependencies: [
.dataInterface(.image)
]
)
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// This file is used to generate the TuistBundle file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//
// ImageRepositoryInterface.swift
// ImageDataInterface
//
// Created by DOYEON LEE on 8/25/24.
//

import RxSwift

public protocol ImageRepositoryInterface {
func getImageUploadPath(
_ request: GetImageUploadPathRequest
) -> Observable<GetImageUploadPathResponse>

func notifyImageUploadComplete(
_ request: NotifyImageUploadCompleteRequest
) -> Observable<NotifyImageUploadCompleteResponse>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//
// GetImageUploadPathRequest&Response.swift
// ImageDataInterface
//
// Created by DOYEON LEE on 8/25/24.
//

import OpenapiGenerated

// MARK: Request
public typealias GetImageUploadPathRequest = Operations.getContentImage.Input.Query

// MARK: Response
public typealias GetImageUploadPathResponse = Components.Schemas.ContentImagePresignedUrlVO
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//
// NotifyImageUploadCompleteRequest&Response.swift
// ImageDataInterface
//
// Created by DOYEON LEE on 8/25/24.
//

import OpenapiGenerated

// MARK: Request
public typealias NotifyImageUploadCompleteRequest = Operations.notifyContentImageSaveSuccess.Input.Body

// MARK: Response
public typealias NotifyImageUploadCompleteResponse = Void
4 changes: 4 additions & 0 deletions Projects/DataInterface/ImageDataInterfaceModule/Project.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import ProjectDescription
import ProjectDescriptionHelpers

let project = Project.makeDataInterfaceModule(.image)
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,46 @@ public struct CreateAnnouncementUsecase {

// MARK: Execute method
public func execute(_ input: Input) -> Observable<Output> {
guard let member = memberUserDefaultsManager.get() else {
fatalError("해당 유즈케이스는 로그인 상태에서 실행되어야합니다.")
}

let newAnnouncement = input.newAnnouncement

let autoGeneratedEndAt = generateAutoEndDate()

// endAt이 nil이면 한 달 뒤의 날짜로 설정
let autoGeneratedEndAt = Calendar.current
.date(byAdding: .month, value: 1, to: Date())!
let (noticeBefore, noticeDate) = parseNotificationDates(
from: newAnnouncement.notifications
)

return announcementRepository
.createAnnouncement(
.init(
organizationId: newAnnouncement.organizationId,
memberId: member.id,
title: newAnnouncement.title,
content: newAnnouncement.body,
tasks: (newAnnouncement.todos ?? [])
.map { .init(content: $0) },
endAt: newAnnouncement.endAt ?? autoGeneratedEndAt,
noticeBefore: noticeBefore,
noticeDate: noticeDate
)
)
.map { result in
Output(announcementId: Int(result.announcementId ?? 0))
}
}

let (noticeBefore, noticeDate) = (newAnnouncement.notifications ?? [])
// MARK: Private method
private func generateAutoEndDate() -> Date {
Calendar.current.date(byAdding: .month, value: 1, to: Date())!
}

private func parseNotificationDates(
from notifications: [AnnouncementRemindNotification]?
) -> ([Date], [Date]) {
return (notifications ?? [])
.reduce(into: ([Date](), [Date]())) { result, notification in
switch notification {
case let .before(timeInterval):
Expand All @@ -59,30 +92,5 @@ public struct CreateAnnouncementUsecase {
result.1.append(date)
}
}

if let member = memberUserDefaultsManager.get() {
return announcementRepository
.createAnnouncement(
.init(
organizationId: newAnnouncement.organizationId,
memberId: member.id,
title: newAnnouncement.title,
content: newAnnouncement.body,
tasks: (newAnnouncement.todos ?? []).map {
.init(content: $0)
},
endAt: newAnnouncement.endAt ?? autoGeneratedEndAt,
noticeBefore: noticeBefore,
noticeDate: noticeDate
)
)
.map { result in
let announcementId = Int(result.announcementId ?? 0)
return Output(announcementId: announcementId)
}

} else {
fatalError("해당 유즈케이스는 로그인 상태에서 실행되어야합니다.")
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//
// UploadImageUsecase.swift
// CommonUsecase
//
// Created by DOYEON LEE on 8/25/24.
//

import RxSwift

public struct UploadImageUsecase {
// MARK: DTO
public struct Input {
public init() { }
}

public struct Output { }

// MARK: Dependency

// MARK: Initializer
public init() { }

// MARK: Execute method
public func execute(_ input: Input) -> Observable<Output> {
let outputObservable = Observable.just(Output())
return outputObservable
}
}
1 change: 1 addition & 0 deletions Projects/Domain/CommonDomainModule/Project.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ import ProjectDescriptionHelpers
let project = Project.makeDomainModule(
.common,
dependencies: [
.dataInterface(.image)
]
)
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import Foundation
*/
public struct OrganizationSummaryEntity: Identifiable, Equatable {
/// Unique identifier for the organization.
public let id: Int
public let id: Int64

/// Name of the organization.
public let name: String
Expand All @@ -21,7 +21,7 @@ public struct OrganizationSummaryEntity: Identifiable, Equatable {
public let profileImageUrl: URL?

public init(
id: Int,
id: Int64,
name: String,
profileImageUrl: URL? = nil
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public class GetMyOrganizationsUsecase {

let organizations: [OrganizationSummaryEntity] = result.content?.map {
OrganizationSummaryEntity(
id: Int($0.organizationId),
id: $0.organizationId,
name: $0.organizationName,
profileImageUrl: URL(string: $0.profileImage)
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ class AnnouncementPageViewController: BaseViewController<AnnouncementPageView> {
Router.shared.push(
.organizationDetail(
.init(
id: organization.id,
id: Int64(organization.id),
name: organization.name,
profileImageUrl: organization.profileImageUrl
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ class NewAnnouncementFunnelReactor: Reactor {
todos: editTodoReactor.currentState.todos.map {
$0.content
},
notification: Array(editNotificationReactor.currentState.selectedTimeOptions)
notifications: Array(editNotificationReactor.currentState.selectedTimeOptions)
)

return self.createAnnouncementUsecase
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import Foundation
enum NewOrganizationFunnelPage: CaseIterable {
case name
case category
// case image
// case endDate
case image
case endDate
case promotion
case complete
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,10 @@ extension NewOrganizationFunnelPage: Paginable {
return NewOrganizationNamePageViewController()
case .category:
return NewOrganizationCategoryPageViewController()
// case .image:
// return NewOrganizationImagePageViewController()
// case .endDate:
// return NewOrganizationDatePageViewController()
case .image:
return NewOrganizationImagePageViewController()
case .endDate:
return NewOrganizationDatePageViewController()
case .promotion:
return NewOrganizationPromotionPageViewController()
case .complete:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ class OrganizationDetailReactor: Reactor {
switch action {
case let .viewDidLoad(organization):
let setOrganization = getOrganizationDetailUsecase
.execute(.init(organizationId: organization.id))
.execute(.init(organizationId: Int(organization.id)))
.map { output in
Mutation.setOrganization(output.organization)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ struct OrganizationTabConverter {
OrganizationSection(
items: entities.map { organization in
OrganizationItem(
id: organization.id,
name: organization.name,
profileImageUrl: organization.profileImageUrl
) {
Expand Down
Loading

0 comments on commit fcfb9f6

Please sign in to comment.