Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@ -52,5 +52,9 @@ public struct DataSourceDependencyAssembler: DependencyAssemblerProtocol {
DIContainer.shared.register(type: FileRepositoryProtocol.self) { _ in
return FileRepository()
}

DIContainer.shared.register(type: ActivityHistoryRepositoryProtocol.self) { _ in
return ActivityHistoryRepository()
}
}
}
23 changes: 23 additions & 0 deletions Projects/DataSource/Sources/DTO/EmotionMarbleHistoryDTO.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//
// EmotionMarbleHistoryDTO.swift
// DataSource
//
// Created by 최정인 on 7/21/26.
//

import Domain

struct EmotionMarbleHistoryDTO: Decodable {
let date: String
let emotionMarbleType: String
let emotionMarbleName: String
let imageUrl: String

func toEmotionHistoryEntity() -> EmotionHistoryEntity {
return EmotionHistoryEntity(
date: date,
emotionMarbleType: emotionMarbleType,
emotionMarbleName: emotionMarbleName,
imageUrl: imageUrl)
}
}
27 changes: 27 additions & 0 deletions Projects/DataSource/Sources/DTO/MonthlyBadgesDTO.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//
// MonthlyBadgesDTO.swift
// DataSource
//
// Created by 최정인 on 7/21/26.
//

import Domain

struct MonthlyBadgesDTO: Decodable {
let badgeTitle: String
let badgeDescription: String
let badges: [BadgeDTO]

func toBadgeEntity() -> BadgeEntity {
return BadgeEntity(
title: badgeTitle,
description: badgeDescription,
imageUrls: badges.map({ $0.imageUrl }))
}
}

struct BadgeDTO: Decodable {
let badgeType: String
let imageUrl: String
let acquiredAt: String?
}
64 changes: 64 additions & 0 deletions Projects/DataSource/Sources/Endpoint/ActivityHistoryEndpoint.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
//
// ActivityHistoryEndpoint.swift
// DataSource
//
// Created by 최정인 on 7/15/26.
//

import Domain

enum ActivityHistoryEndpoint {
case fetchMonthlyBadges(year: String, month: String)
case fetchEmotionHistory(startDate: String, endDate: String)
}

extension ActivityHistoryEndpoint: Endpoint {
var baseURL: String {
return AppProperties.baseURL + "/api/v1/activity-logs"
}

var path: String {
switch self {
case .fetchMonthlyBadges:
return baseURL + "/badges"
case .fetchEmotionHistory:
return baseURL + "/emotion-marbles"
}
}

var method: HTTPMethod {
switch self {
case .fetchMonthlyBadges: .get
case .fetchEmotionHistory: .get
}
}

var headers: [String : String] {
let headers: [String: String] = [
"Content-Type": "application/json",
"accept": "*/*"
]
return headers
}

var queryParameters: [String : String] {
switch self {
case .fetchMonthlyBadges(let year, let month):
return [
"year": year,
"month": month]
case .fetchEmotionHistory(let startDate, let endDate):
return [
"startDate": startDate,
"endDate": endDate]
}
}

var bodyParameters: [String : Any] {
return [:]
}

var isAuthorized: Bool {
return true
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
//
// ActivityHistoryRepository.swift
// DataSource
//
// Created by 최정인 on 7/21/26.
//

import Domain

final class ActivityHistoryRepository: ActivityHistoryRepositoryProtocol {
private let networkService = NetworkService.shared

func fetchMonthlyBadges(year: Int, month: Int) async throws -> BadgeEntity {
let endpoint = ActivityHistoryEndpoint.fetchMonthlyBadges(year: "\(year)", month: "\(month)")
do {
guard let monthlyBadgesDTO = try await networkService.request(endpoint: endpoint, type: MonthlyBadgesDTO.self)
else { throw NetworkError.decodingError }
return monthlyBadgesDTO.toBadgeEntity()
} catch let error as NetworkError {
switch error {
case .needRetry, .invalidURL, .emptyData:
throw DomainError.requireRetry
default:
throw DomainError.business(error.description)
}
} catch {
throw DomainError.unknown
}
}

func fetchEmotionMarbles(startDate: String, endDate: String) async throws -> [EmotionHistoryEntity] {
let endpoint = ActivityHistoryEndpoint.fetchEmotionHistory(startDate: startDate, endDate: endDate)

do {
guard let emotionMarbleDTOs = try await networkService.request(endpoint: endpoint, type: [EmotionMarbleHistoryDTO].self)
else { throw NetworkError.decodingError }
return emotionMarbleDTOs.map { $0.toEmotionHistoryEntity() }
} catch let error as NetworkError {
switch error {
case .needRetry, .invalidURL, .emptyData:
throw DomainError.requireRetry
default:
throw DomainError.business(error.description)
}
} catch {
throw DomainError.unknown
}
}
}
22 changes: 22 additions & 0 deletions Projects/Domain/Sources/Entity/BadgeEntity.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//
// BadgeEntity.swift
// Domain
//
// Created by 최정인 on 7/21/26.
//

public struct BadgeEntity {
public let title: String
public let description: String
public let imageUrls: [String]

public init(
title: String,
description: String,
imageUrls: [String]
) {
self.title = title
self.description = description
self.imageUrls = imageUrls
}
}
25 changes: 25 additions & 0 deletions Projects/Domain/Sources/Entity/EmotionHistoryEntity.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//
// EmotionHistoryEntity.swift
// Domain
//
// Created by 최정인 on 7/21/26.
//

public struct EmotionHistoryEntity {
public let date: String
public let emotionMarbleType: String
public let emotionMarbleName: String
public let imageUrl: String

public init(
date: String,
emotionMarbleType: String,
emotionMarbleName: String,
imageUrl: String
) {
self.date = date
self.emotionMarbleType = emotionMarbleType
self.emotionMarbleName = emotionMarbleName
self.imageUrl = imageUrl
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//
// ActivityHistoryRepositoryProtocol.swift
// Domain
//
// Created by 최정인 on 7/21/26.
//

/// 활동 기록 관련 로직(월 별 뱃지 조회, 감정 구슬 기록 조회 등)을 수행하는 Repository
public protocol ActivityHistoryRepositoryProtocol {
/// 월 별 뱃지를 조회합니다.
/// - Parameters:
/// - year: 조회하려고 하는 연도
/// - month: 조회하려고 하는 월
func fetchMonthlyBadges(year: Int, month: Int) async throws -> BadgeEntity

/// 기간 내 감정 구슬 기록을 조회합니다.
/// - Parameters:
/// - startDate: 조회 시작 날짜 (yyyy-MM-dd)
/// - endDate: 조회 종료 날짜 (yyyy-MM-dd)
func fetchEmotionMarbles(startDate: String, endDate: String) async throws -> [EmotionHistoryEntity]
}

This file was deleted.

Binary file not shown.
Binary file not shown.
Binary file not shown.

This file was deleted.

Binary file not shown.
Binary file not shown.
Binary file not shown.

This file was deleted.

Binary file not shown.
Binary file not shown.
Binary file not shown.

This file was deleted.

Binary file not shown.
Binary file not shown.
Binary file not shown.

This file was deleted.

Binary file not shown.
Binary file not shown.
Binary file not shown.

This file was deleted.

Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading
Loading