Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/#172 검색로직 수정 #177

Merged
merged 14 commits into from
Feb 7, 2025
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ struct ResturantpickListResponse: Codable {
let zzimCardResponses: [PickListCardResponse]
}

struct PickListCardResponse: Codable {
struct PickListCardResponse: Codable, Equatable {
let placeId: Int
let placeName: String
let placeAddress: String
Expand All @@ -20,9 +20,21 @@ struct PickListCardResponse: Codable {
let latitude: Double
let longitude: Double
let categoryColorResponse: BottomSheetCategoryColorResponse

static func == (lhs: PickListCardResponse, rhs: PickListCardResponse) -> Bool {
return lhs.placeId == rhs.placeId &&
lhs.placeName == rhs.placeName &&
lhs.placeAddress == rhs.placeAddress &&
lhs.postTitle == rhs.postTitle &&
lhs.photoUrl == rhs.photoUrl &&
lhs.latitude == rhs.latitude &&
lhs.longitude == rhs.longitude &&
lhs.categoryColorResponse == rhs.categoryColorResponse
Comment on lines +25 to +32
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

placeId가 고유한 값이 아닌가요?
고유한 값이라면 나머지 값들도 비교하는 이유가 있을까요??

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

지금은 수정이 되었는데 해당 코드 작성시에 해당 placeID 와 식당 정보들이 매핑이 이상하게 내려오고 있었습니다.
현재는 수정되어있으니 placeID가 유일한 코드가 맞아요!

}
}

struct BottomSheetCategoryColorResponse: Codable {
struct BottomSheetCategoryColorResponse: Codable, Equatable {
let categoryId: Int
let categoryName: String
let iconUrl: String
let iconTextColor: String
Expand Down
45 changes: 45 additions & 0 deletions Spoony-iOS/Spoony-iOS/Network/Model/SearchLocationResponse.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
//
// SearchLocationResponse.swift
// Spoony-iOS
//
// Created by 이지훈 on 1/30/25.
//

import Foundation

struct SearchLocationResponse: Codable {
let success: Bool
let data: SearchLocationData?
let error: String?
}

struct SearchLocationData: Codable {
let zzimCardResponses: [SearchLocationResult]
}

struct SearchLocationResult: Codable, Identifiable {
var id = UUID()
let locationId: Int
let placeId: Int?
let title: String
let address: String
let postTitle: String?
let photoUrl: String?
let latitude: Double?
let longitude: Double?
let categoryColorResponse: SearchCategoryColorResponse?
}

struct SearchCategoryColorResponse: Codable {
let categoryId: Int
let categoryName: String
let iconUrl: String
let iconTextColor: String
let iconBackgroundColor: String
}

extension SearchLocationResponse {
func toEntity() -> [SearchLocationResult] {
return data?.zzimCardResponses ?? []
}
}
71 changes: 71 additions & 0 deletions Spoony-iOS/Spoony-iOS/Network/Model/SearchResult.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
//
// SearchResult.swift
// Spoony-iOS
//
// Created by 이지훈 on 1/16/25.
//

import Foundation

struct SearchResult: Identifiable, Equatable {
let id = UUID()
let title: String
let locationId: Int
let address: String
}

extension PickListCardResponse {
func toSearchLocationResult() -> SearchLocationResult {
return SearchLocationResult(
locationId: self.placeId,
placeId: self.placeId,
title: self.placeName,
address: self.placeAddress,
postTitle: self.postTitle,
photoUrl: self.photoUrl,
latitude: self.latitude,
longitude: self.longitude,
categoryColorResponse: self.categoryColorResponse.toSearchCategoryColorResponse()
)
}
}

extension BottomSheetCategoryColorResponse {
func toSearchCategoryColorResponse() -> SearchCategoryColorResponse {
return SearchCategoryColorResponse(
categoryId: self.categoryId,
categoryName: self.categoryName,
iconUrl: self.iconUrl,
iconTextColor: self.iconTextColor,
iconBackgroundColor: self.iconBackgroundColor
)
}
}

extension SearchLocationResult {
func toPickListCardResponse() -> PickListCardResponse {
return PickListCardResponse(
placeId: self.placeId ?? 0,
placeName: self.title,
placeAddress: self.address,
postTitle: self.postTitle ?? "",
photoUrl: self.photoUrl ?? "",
latitude: self.latitude ?? 0.0,
longitude: self.longitude ?? 0.0,
categoryColorResponse: self.categoryColorResponse?.toBottomSheetCategoryColorResponse() ??
BottomSheetCategoryColorResponse(categoryId: 0, categoryName: "", iconUrl: "", iconTextColor: "", iconBackgroundColor: "")
)
}
}

extension SearchCategoryColorResponse {
func toBottomSheetCategoryColorResponse() -> BottomSheetCategoryColorResponse {
return BottomSheetCategoryColorResponse(
categoryId: self.categoryId,
categoryName: self.categoryName,
iconUrl: self.iconUrl,
iconTextColor: self.iconTextColor,
iconBackgroundColor: self.iconBackgroundColor
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ protocol HomeServiceType {
func fetchPickList(userId: Int) async throws -> ResturantpickListResponse
func fetchSpoonCount(userId: Int) async throws -> Int
func fetchFocusedPlace(userId: Int, placeId: Int) async throws -> MapFocusResponse
func fetchLocationList(userId: Int, locationId: Int) async throws -> ResturantpickListResponse
}

final class DefaultHomeService: HomeServiceType {
Expand Down Expand Up @@ -83,4 +84,25 @@ final class DefaultHomeService: HomeServiceType {
}
}
}

func fetchLocationList(userId: Int, locationId: Int) async throws -> ResturantpickListResponse {
return try await withCheckedThrowingContinuation { continuation in
provider.request(.getLocationList(userId: userId, locationId: locationId)) { result in
switch result {
case .success(let response):
do {
let responseDto = try response.map(BaseResponse<ResturantpickListResponse>.self)
guard let data = responseDto.data else {
throw NSError(domain: "HomeService", code: -1, userInfo: [NSLocalizedDescriptionKey: "No data available"])
Copy link
Member

@thingineeer thingineeer Feb 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이건 무슨 에러 인가요??

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fetchLocation 에 대한 기본 에러타입 지정을 안해서 기본 NSError로 전부 빼놓았습니다 (fatalerror같은종류,,)
해당 코드 에러케이스 추가해서 넣어두겟습니다

}
continuation.resume(returning: data)
} catch {
continuation.resume(throwing: error)
}
case .failure(let error):
continuation.resume(throwing: error)
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ enum HomeTargetType {
case getMapFocus(userId: Int, placeId: Int)
case getSearchResultList(query: String)
case getSearchResultLocation(userId: Int, locationId: Int)
case getLocationList(userId: Int, locationId: Int)
}

extension HomeTargetType: TargetType {
Expand All @@ -36,7 +37,9 @@ extension HomeTargetType: TargetType {
case .getSearchResultList:
return "/location/search"
case .getSearchResultLocation(let userId, let locationId):
return "/post/zzin/\(userId)/\(locationId)"
return "/post/zzim/\(userId)/\(locationId)"
case .getLocationList(let userId, let locationId):
return "/post/zzim/location/\(userId)/\(locationId)"
}
}

Expand All @@ -46,6 +49,7 @@ extension HomeTargetType: TargetType {
.getMapList,
.getMapFocus,
.getSearchResultList,
.getLocationList,
.getSearchResultLocation:
return .get
}
Expand All @@ -56,6 +60,7 @@ extension HomeTargetType: TargetType {
case .getSpoonCount,
.getMapList,
.getMapFocus,
.getLocationList,
.getSearchResultLocation:
return .requestPlain

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
//
// BottomSheetItem.swift
// Spoony-iOS
//
// Created by 이지훈 on 1/30/25.
//

import SwiftUI

struct BottomSheetListItem: View {
let pickCard: PickListCardResponse

var body: some View {
HStack(spacing: 12) {
VStack(alignment: .leading, spacing: 8) {
HStack(spacing: 8) {
Text(pickCard.placeName)
.customFont(.body1b)
.lineLimit(1)
.truncationMode(.tail)

// 카테고리 칩
HStack(spacing: 4) {
// 카테고리 아이콘
AsyncImage(url: URL(string: pickCard.categoryColorResponse.iconUrl)) { phase in
switch phase {
case .success(let image):
image
.resizable()
.scaledToFit()
.frame(width: 16.adjusted, height: 16.adjustedH)
default:
Color.clear
.frame(width: 16.adjusted, height: 16.adjustedH)
}
}

Text(pickCard.categoryColorResponse.categoryName)
.customFont(.caption1m)
.lineLimit(1)
}
.padding(.horizontal, 8)
.padding(.vertical, 4)
.background(Color(hex: pickCard.categoryColorResponse.iconBackgroundColor))
.foregroundColor(Color(hex: pickCard.categoryColorResponse.iconTextColor))
.cornerRadius(12)
}

Text(pickCard.placeAddress)
.customFont(.caption1m)
.foregroundColor(.gray600)
.lineLimit(1)
.truncationMode(.tail)

Text(pickCard.postTitle)
.customFont(.caption1m)
.foregroundColor(.spoonBlack)
.lineLimit(1)
.truncationMode(.tail)
.frame(maxWidth: .infinity, alignment: .leading)
.padding(12)
.background(.white)
.cornerRadius(8)
.overlay(
RoundedRectangle(cornerRadius: 8)
.stroke(Color(.gray0), lineWidth: 1)
)
.shadow(
color: Color(.gray0),
radius: 16,
x: 0,
y: 2
)
}
// 이미지
AsyncImage(url: URL(string: pickCard.photoUrl)) { phase in
switch phase {
case .success(let image):
image
.resizable()
.scaledToFill()
case .failure:
defaultPlaceholder
case .empty:
defaultPlaceholder
default:
defaultPlaceholder
}
}
.frame(width: 98.adjusted, height: 98.adjusted)
.clipShape(RoundedRectangle(cornerRadius: 8))
.layoutPriority(0)
}
.padding(.horizontal, 16)
.frame(height: 120.adjusted)
}

private var defaultPlaceholder: some View {
RoundedRectangle(cornerRadius: 8)
.fill(Color.gray.opacity(0.1))
}
}
Loading