Skip to content

Commit

Permalink
[Feat] #95 - 유저의 프로필뷰에서 작성한 글 보여주는 API 연결
Browse files Browse the repository at this point in the history
  • Loading branch information
Genesis2010 committed Aug 7, 2024
2 parents 1d1c2bf + 1dd42dc commit e768ec1
Show file tree
Hide file tree
Showing 21 changed files with 373 additions and 229 deletions.
29 changes: 29 additions & 0 deletions Treehouse/Treehouse/Application/TreehouseApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ struct TreehouseApp: App {
@State var viewRouter = ViewRouter()
@AppStorage(Config.loginKey) private var isLogin = false

init() {
configureNavigationBar()
}

var body: some Scene {
WindowGroup {
Group {
Expand All @@ -27,4 +31,29 @@ struct TreehouseApp: App {
}
}
}

private func configureNavigationBar() {
let appearance = UINavigationBarAppearance()

// 배경색 및 title 색상 폰트 설정
appearance.backgroundColor = UIColor.grayscaleWhite
appearance.backButtonAppearance.normal.titlePositionAdjustment = UIOffset(horizontal: +0, vertical: 0)
appearance.titleTextAttributes = [
.foregroundColor: UIColor.treeBlack,
.font: Font.uiFontGuide(.body2)
]

let backButtonAppearance = UIBarButtonItemAppearance(style: .plain)
backButtonAppearance.normal.titleTextAttributes = [.foregroundColor: UIColor.clear] // 뒤로가기 버튼의 텍스트 제거
appearance.backButtonAppearance = backButtonAppearance
appearance.shadowColor = .clear // 하단 선 제거

// 뒤로가기 버튼 이미지 설정
let backImage = UIImage.icBack.withTintColor(.treeBlack, renderingMode: .alwaysOriginal)
appearance.setBackIndicatorImage(backImage, transitionMaskImage: backImage)

UINavigationBar.appearance().standardAppearance = appearance
UINavigationBar.appearance().compactAppearance = appearance
UINavigationBar.appearance().scrollEdgeAppearance = appearance
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,18 @@

import Foundation

struct ReadMemberFeedResponseEntity: Decodable {
struct ReadMemberFeedResponseEntity: Decodable, Identifiable {
var id = UUID()
let memberProfile: MemberProfileEntity
let postList: [PostListResponseEntity]
}

struct PostListResponseEntity: Decodable {
struct PostListResponseEntity: Decodable, Identifiable {
var id = UUID()
let postId: Int
let context: String
let pictureUrlList: [String]
let commentCount: Int
let reactionList: [ReactionListEntity]
let reactionList: ReactionListDataEntity
let postedAt: String
}
21 changes: 12 additions & 9 deletions Treehouse/Treehouse/Global/Components/TabView/TreeTabView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,26 +21,29 @@ struct TreeTabView: View {
@Bindable var viewRouter = viewRouter

NavigationStack(path: $viewRouter.path) {
TabView {
TabView(selection: $viewRouter.selectedTab) {
FeedHomeView()
.background(.grayscaleWhite)
.tabItem {
Label("", image: "ic_home")
.fontWithLineHeight(fontLevel: .caption2)
}
.environment(userInfoViewModel)
.tag(TabType.home)

TreeTab()
.tabItem {
Label("트리", image: "ic_tree")
.fontWithLineHeight(fontLevel: .caption2)
}
.tag(TabType.tree)

NotificationView()
.tabItem {
Label("알림", image: "ic_noti")
.fontWithLineHeight(fontLevel: .caption2)
}
.tag(TabType.notice)

MyProfileView()
.background(.grayscaleWhite)
Expand All @@ -49,18 +52,11 @@ struct TreeTabView: View {
.fontWithLineHeight(fontLevel: .caption2)
}
.environment(userInfoViewModel)
.tag(TabType.setting)
}
.tint(.treeGreen)
.environment(viewRouter)
.environment(currentTreehouseInfoViewModel)
.navigationDestination(for: ProfileRouter.self) { router in
switch router {
case .editProfileView:
viewRouter.buildScene(inputRouter: router, viewModel: userInfoViewModel)
case .memberProfileView:
viewRouter.buildScene(inputRouter: router)
}
}
.onAppear {
if let currentTreehouseId = currentTreehouseInfoViewModel.currentTreehouseId {
Task {
Expand Down Expand Up @@ -97,3 +93,10 @@ struct TreeTabView: View {
TreeTabView()
.environment(ViewRouter())
}

enum TabType {
case home
case tree
case notice
case setting
}
2 changes: 1 addition & 1 deletion Treehouse/Treehouse/Global/Extension/UIImage+.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ extension UIImage {
kCGImageSourceCreateThumbnailFromImageAlways: true,
kCGImageSourceShouldCacheImmediately: true,
kCGImageSourceCreateThumbnailWithTransform: true,
kCGImageSourceThumbnailMaxPixelSize: maxDimensionInPixels
kCGImageSourceThumbnailMaxPixelSize: maxDimensionInPixels * 3
] as CFDictionary

guard let downsampledImage = CGImageSourceCreateThumbnailAtIndex(imageSource, 0, downsampleOptions) else {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"images" : [
{
"filename" : "ic_back.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "[email protected]",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "[email protected]",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
64 changes: 60 additions & 4 deletions Treehouse/Treehouse/Global/ViewModel/MemberProfileViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,25 +15,81 @@ final class MemberProfileViewModel: BaseViewModel {
// MARK: - UseCase Property

@ObservationIgnored
private let readMemberInfoUseCase: GetReadMemberInfoUseCaseProtocol
private let readMemberInfoUseCase: GetReadMemberInfoUseCaseProtocol

@ObservationIgnored
private let readMemberFeedUseCase: GetReadMemberFeedUseCaseProtocol

var memberProfileData: ReadMemberInfoResponseEntity?
var errorMessage: String = ""

@ObservationIgnored
private var treehouseId: Int

@ObservationIgnored
private var memberId: Int

var memberFeedData: ReadMemberFeedResponseEntity?
var title = ""
var isLoading = true

// MARK: - init

init(readMemberInfoUseCase: GetReadMemberInfoUseCaseProtocol) {
init(readMemberInfoUseCase: GetReadMemberInfoUseCaseProtocol,
readMemberFeedUseCase: GetReadMemberFeedUseCaseProtocol,
treehouseId: Int,
memberId: Int
) {
self.readMemberInfoUseCase = readMemberInfoUseCase
self.readMemberFeedUseCase = readMemberFeedUseCase
self.treehouseId = treehouseId
self.memberId = memberId
}

func performAsyncTasks() async {
async let memberInfo = readMemberInfo(treehouseId: treehouseId, memberId: memberId)
async let memberFeed = readMemberFeed(treehouseId: treehouseId, memberId: memberId)

let (memberInfoResult, memberFeedResult) = await (memberInfo, memberFeed)

if memberInfoResult && memberFeedResult {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
self.isLoading = false
}
}
}
}

extension MemberProfileViewModel {
private extension MemberProfileViewModel {
func readMemberInfo(treehouseId: Int, memberId: Int) async -> Bool {
let result = await readMemberInfoUseCase.execute(treehouseId: treehouseId, memberId: memberId)

switch result {
case .success(let response):
memberProfileData = response
await MainActor.run {
memberProfileData = response
title = response.memberName
}
return true
case .failure(let error):
await MainActor.run {
self.errorMessage = error.localizedDescription
print(errorMessage)
}
return false
}
}

func readMemberFeed(treehouseId: Int, memberId: Int) async -> Bool {
let result = await readMemberFeedUseCase.execute(treehouseId: treehouseId, memberId: memberId)

switch result {
case .success(let response):

await MainActor.run {
memberFeedData = response
}

return true
case .failure(let error):
await MainActor.run {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,38 +27,41 @@ struct GetReadMemberFeedResponseDTO: Decodable {
var result = [PostListResponseEntity]()

data.forEach {
result.append(PostListResponseEntity(postId: $0.postId,
context: $0.context,
pictureUrlList: $0.pictureUrlList,
commentCount: $0.commentCount,
reactionList: convertReactionListEntity($0.reactionList),
postedAt: $0.postedAt)
result.append(
PostListResponseEntity(
postId: $0.postId,
context: $0.context,
pictureUrlList: $0.pictureUrlList,
commentCount: $0.commentCount,
reactionList: convertReactionListDataEntity($0.reactionList),
postedAt: $0.postedAt
)
)
}

return result
}

private func convertReactionListDataEntity(_ data: ReactionListData) -> ReactionListDataEntity {
return ReactionListDataEntity(reactionList: convertReactionListEntity(data.reactionList))
}

private func convertReactionListEntity(_ data: [ReactionListResponseData]) -> [ReactionListEntity] {
var result = [ReactionListEntity]()

data.forEach {
result.append(ReactionListEntity(reactionName: $0.reactionName,
reactionCount: $0.reactionCount,
isPushed: $0.isPushed)
)
result.append(ReactionListEntity(reactionName: $0.reactionName, reactionCount: $0.reactionCount, isPushed: $0.isPushed))
}

return result
}

}

struct PostListResponseDTO: Decodable {
let postId: Int
let context: String
let pictureUrlList: [String]
let commentCount: Int
let reactionList: [ReactionListResponseData]
let reactionList: ReactionListData//[ReactionListResponseData]
let postedAt: String
}
26 changes: 3 additions & 23 deletions Treehouse/Treehouse/Network/Notification/NotificationService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,36 +9,16 @@ import Foundation

final class NotificationService {

private let networkServiceManager = NetworkServiceManager()

/// 알림 조회 요청 서비스
func getNotifications() async throws -> GetCheckNotificationsResponseDTO {
print("1️⃣ 🔑 GetCheckNotifications API 호출 ========================================")
let request = NetworkRequest(requestType: NotificationAPI.getCheckNotifications)

guard let urlRequest = request.request() else {
throw NetworkError.clientError(message: "Request 생성불가")
}

let (data, response) = try await URLSession.shared.data(for: urlRequest)

// 응답 데이터와 상태 코드 출력
if let httpResponse = response as? HTTPURLResponse {
print("2️⃣ Status Code: \(httpResponse.statusCode)")
print("\(httpResponse.statusCode)")
}

if let jsonString = String(data: data, encoding: .utf8) {
print("3️⃣ Response JSON")
}

// JSON 디코딩
do {
let model = try JSONDecoder().decode(BaseResponse<GetCheckNotificationsResponseDTO>.self, from: data)
print(model.data.notifications)
print("4️⃣ GetCheckNotification API 종료 ========================================")
return model.data
} catch {
print("4️⃣ GetCheckNotifiication API Error: \(String(describing: NetworkError.jsonDecodingError.errorDescription))========================================")
throw NetworkError.jsonDecodingError
}
return try await networkServiceManager.performRequest(with: urlRequest, decodingType: GetCheckNotificationsResponseDTO.self)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,8 @@ final class PostViewModel: BaseViewModel {

func changeEmojiData(postId: Int, selectEmoji: String) async {
if let postIndex = feedListData.firstIndex(where: { $0.postId == postId }) {
// if let index = feedEmojiData?.reactionList.firstIndex(where: { $0.reactionName == selectEmoji }) {
if let index = feedListData[postIndex].reactionList.reactionList.firstIndex(where: { $0.reactionName == selectEmoji }) {
// if feedListData[postIndex].feedEmojiData?.reactionList[index].isPushed == false {
if feedListData[postIndex].reactionList.reactionList[index].isPushed == false {
print("여기로 가야돼")
feedListData[postIndex].reactionList.reactionList[index].isPushed = true
feedListData[postIndex].reactionList.reactionList[index].reactionCount += 1
} else {
Expand All @@ -67,30 +64,6 @@ final class PostViewModel: BaseViewModel {
feedListData[postIndex].reactionList.reactionList.append(ReactionListEntity(reactionName: selectEmoji, reactionCount: 1, isPushed: true))
}
}

// if let index = feedEmojiData?.reactionList.firstIndex(where: { $0.reactionName == selectEmoji }) {
// if feedEmojiData?.reactionList[index].isPushed == false {
// print("증가")
// feedEmojiData?.reactionList[index].isPushed = true
// feedEmojiData?.reactionList[index].reactionCount += 1
//
// if let index = feedListData.firstIndex(where: {$0.postId == postId}) {
// feedListData[index].reactionList = feedEmojiData ?? ""
// }
// } else {
// print("감소")
// feedEmojiData?.reactionList[index].isPushed = false
// feedEmojiData?.reactionList[index].reactionCount -= 1
//
// if feedEmojiData?.reactionList[index].reactionCount == 0 {
// await MainActor.run {
// feedEmojiData?.reactionList.remove(at: index)
// }
// }
// }
// } else {
// feedEmojiData?.reactionList.append(ReactionListEntity(reactionName: selectEmoji, reactionCount: 1, isPushed: true))
// }
}

func changePostContent(postId: Int, content: String) -> Bool {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,14 @@ struct FeedHomeView: View {
.navigationDestination(for: FeedRouter.self) { router in
viewRouter.buildScene(inputRouter: router, viewModel: feedViewModel)
}
.navigationDestination(for: ProfileRouter.self) { router in
switch router {
case .editProfileView:
viewRouter.buildScene(inputRouter: router, viewModel: userInfoViewModel)
case .memberProfileView:
viewRouter.buildScene(inputRouter: router, viewModel: feedViewModel)
}
}
.onAppear {
feedViewModel.currentTreehouseId = currentTreehouseInfoViewModel.currentTreehouseId
feedViewModel.userId = currentTreehouseInfoViewModel.userId
Expand Down
Loading

0 comments on commit e768ec1

Please sign in to comment.