diff --git a/Keychy/Keychy/CommonModels/KeyringBundle/Background.swift b/Keychy/Keychy/CommonModels/KeyringBundle/Background.swift index 8da019f7..5e1da7e8 100644 --- a/Keychy/Keychy/CommonModels/KeyringBundle/Background.swift +++ b/Keychy/Keychy/CommonModels/KeyringBundle/Background.swift @@ -29,6 +29,9 @@ struct Background: Identifiable, Codable, Equatable, Hashable { /// 배경 분류 태그 (ex. ["귀여움", "#키워드"]) let tags: [String] + /// 추천 조합 + let recommendedCombinations: String? + /// 구매 시 필요한 코인 (0이면 무료) let price: Int diff --git a/Keychy/Keychy/CommonModels/KeyringBundle/Carabiner.swift b/Keychy/Keychy/CommonModels/KeyringBundle/Carabiner.swift index 5801ea75..05cffa2c 100644 --- a/Keychy/Keychy/CommonModels/KeyringBundle/Carabiner.swift +++ b/Keychy/Keychy/CommonModels/KeyringBundle/Carabiner.swift @@ -43,6 +43,9 @@ struct Carabiner: Identifiable, Codable, Equatable, Hashable { /// 카라비너 분류 태그 (ex. ["귀여움", "#키워드"]) let tags: [String] + /// 추천 조합 + let recommendedCombinations: String? + /// 구매 시 필요한 코인 (0이면 무료) let price: Int diff --git a/Keychy/Keychy/Core/Components/View/Items/ItemDetailInfoSection.swift b/Keychy/Keychy/Core/Components/View/Items/ItemDetailInfoSection.swift index 4b57e34d..44a8aad6 100644 --- a/Keychy/Keychy/Core/Components/View/Items/ItemDetailInfoSection.swift +++ b/Keychy/Keychy/Core/Components/View/Items/ItemDetailInfoSection.swift @@ -20,7 +20,7 @@ struct ItemDetailInfoSection: View { Image(.myCoinMini) .resizable() .scaledToFit() - .frame(width: 21) + .frame(width: 27) } /// 이펙트 타입 표시 (사운드/파티클) @@ -36,10 +36,17 @@ struct ItemDetailInfoSection: View { /// item 이름 itemName - .padding(.bottom, 12) + .padding(.bottom, 8) /// item 설명 itemDescription + .padding(.bottom, hasRecommendedCombinations ? 8 : 10) + + /// 추천 조합 (있을 경우에만 표시) + if hasRecommendedCombinations { + recommendedCombinations + .padding(.bottom, 10) + } } } @@ -48,6 +55,16 @@ struct ItemDetailInfoSection: View { // MARK: - Components extension ItemDetailInfoSection { + /// 추천 조합 존재 여부 + private var hasRecommendedCombinations: Bool { + if let background = item as? Background { + return background.recommendedCombinations != nil && !(background.recommendedCombinations?.isEmpty ?? true) + } else if let carabiner = item as? Carabiner { + return carabiner.recommendedCombinations != nil && !(carabiner.recommendedCombinations?.isEmpty ?? true) + } + return false + } + /// 이펙트 타입 태그 (사운드/파티클) private var effectTypeTag: EffectFilterType? { if item is Sound { @@ -80,10 +97,17 @@ extension ItemDetailInfoSection { } private var itemName: some View { - Text(item.name) - .typography(.suit24B) - .lineLimit(nil) - .fixedSize(horizontal: false, vertical: true) + HStack(spacing: 7) { + if item.isLottie { + Image(.lottieIcon) + } + + Text(item.name) + .typography(.suit24B) + .lineLimit(nil) + .fixedSize(horizontal: false, vertical: true) + } + } private var itemDescription: some View { @@ -93,6 +117,34 @@ extension ItemDetailInfoSection { .lineLimit(nil) .fixedSize(horizontal: false, vertical: true) } + + private var recommendedCombinations: some View { + HStack(spacing: 5) { + Text("추천 조합") + .typography(.suit12M) + .foregroundStyle(.main500) + .padding(.horizontal, 4) + .padding(.vertical, 1) + .background(.mainOpacity15) + .fixedSize() + + if let background = item as? Background, + let combinations = background.recommendedCombinations { + Text(combinations) + .typography(.suit12M) + .foregroundStyle(.black30) + .lineLimit(nil) + .fixedSize(horizontal: false, vertical: true) + } else if let carabiner = item as? Carabiner, + let combinations = carabiner.recommendedCombinations { + Text(combinations) + .typography(.suit12M) + .foregroundStyle(.black30) + .lineLimit(nil) + .fixedSize(horizontal: false, vertical: true) + } + } + } } #Preview(traits: .sizeThatFitsLayout) { diff --git a/Keychy/Keychy/Core/Components/View/Popup/InvenExpandPopup.swift b/Keychy/Keychy/Core/Components/View/Popup/InvenExpandPopup.swift index d14a81cd..136a65df 100644 --- a/Keychy/Keychy/Core/Components/View/Popup/InvenExpandPopup.swift +++ b/Keychy/Keychy/Core/Components/View/Popup/InvenExpandPopup.swift @@ -64,6 +64,8 @@ struct InvenExpandPopup: View { Button(action: onConfirm) { HStack(spacing: 4) { Image(.myCoinMini) + .resizable() + .frame(width: 22, height: 22) Text("\(price)") .typography(.nanum18EB) diff --git a/Keychy/Keychy/Core/Components/View/Popup/PurchasePopup.swift b/Keychy/Keychy/Core/Components/View/Popup/PurchasePopup.swift index ea73ac73..26950117 100644 --- a/Keychy/Keychy/Core/Components/View/Popup/PurchasePopup.swift +++ b/Keychy/Keychy/Core/Components/View/Popup/PurchasePopup.swift @@ -43,6 +43,8 @@ struct PurchasePopup: View { Button(action: onConfirm) { HStack(spacing: 4) { Image(.myCoinMini) + .resizable() + .frame(width: 22, height: 22) Text("\(price)") .typography(.nanum18EB) diff --git a/Keychy/Keychy/Presentation/Workshop/Coin/CoinChargeView.swift b/Keychy/Keychy/Presentation/Workshop/Coin/CoinChargeView.swift index 3ceb0dab..74f64a6d 100644 --- a/Keychy/Keychy/Presentation/Workshop/Coin/CoinChargeView.swift +++ b/Keychy/Keychy/Presentation/Workshop/Coin/CoinChargeView.swift @@ -329,6 +329,8 @@ extension CoinChargeView { } label: { HStack(spacing: 5) { Image(.myCoinMini) + .resizable() + .frame(width: 22, height: 22) Text("\(selectedItem?.price ?? 0)") .typography(.nanum18EB12) diff --git a/Keychy/Keychy/Presentation/Workshop/ViewModels/WorkshopViewModel.swift b/Keychy/Keychy/Presentation/Workshop/ViewModels/WorkshopViewModel.swift index ee1b9ceb..e7e2a570 100644 --- a/Keychy/Keychy/Presentation/Workshop/ViewModels/WorkshopViewModel.swift +++ b/Keychy/Keychy/Presentation/Workshop/ViewModels/WorkshopViewModel.swift @@ -60,9 +60,14 @@ protocol WorkshopItem: Identifiable, Decodable { var downloadCount: Int { get } var useCount: Int { get } var createdAt: Date { get } + var isLottie: Bool { get } // 로티 여부 } // MARK: - Extensions +// 모든 아이템 기본적으로 isLottie false +extension WorkshopItem { + var isLottie: Bool { false } +} extension KeyringTemplate: WorkshopItem { var name: String { templateName } diff --git a/Keychy/Keychy/Presentation/Workshop/Views/Components/WorkshopItemActionButton.swift b/Keychy/Keychy/Presentation/Workshop/Views/Components/WorkshopItemActionButton.swift index 286c3518..b087865b 100644 --- a/Keychy/Keychy/Presentation/Workshop/Views/Components/WorkshopItemActionButton.swift +++ b/Keychy/Keychy/Presentation/Workshop/Views/Components/WorkshopItemActionButton.swift @@ -82,6 +82,8 @@ struct WorkshopItemActionButton: View { } label: { HStack(spacing: 5) { Image(.myCoinMini) + .resizable() + .frame(width: 22, height: 22) Text("\(item.workshopPrice)") .typography(.nanum18EB) diff --git a/Keychy/Keychy/Presentation/Workshop/Views/Components/WorkshopItemCard.swift b/Keychy/Keychy/Presentation/Workshop/Views/Components/WorkshopItemCard.swift index 5120659f..f13932ed 100644 --- a/Keychy/Keychy/Presentation/Workshop/Views/Components/WorkshopItemCard.swift +++ b/Keychy/Keychy/Presentation/Workshop/Views/Components/WorkshopItemCard.swift @@ -30,9 +30,17 @@ struct WorkshopItemCard: View { // 썸네일 이미지 thumbnailImage - // 아이템 이름 - Text(item.name) - .typography(.suit14SB18) + HStack(spacing: 4) { + if item.isLottie { + Image(.lottieIcon) + .resizable() + .frame(width: 15, height: 15) + } + + // 아이템 이름 + Text(item.name) + .typography(.notosans14M) + } } } .buttonStyle(.plain) @@ -166,7 +174,14 @@ struct WorkshopPriceOverlay: View { // 유료: 오른쪽 상단에 가격 또는 보유 표시 VStack { HStack { + if price != 0 { + Image(.myCoinMini) + .resizable() + .frame(width: 24, height: 24) + } + Spacer() + if isOwned { // 보유 Text("보유") @@ -184,9 +199,7 @@ struct WorkshopPriceOverlay: View { .typography(.nanum16EB) .foregroundStyle(.white100) .padding(.vertical, 4) - .padding(.horizontal, 8) - .padding(.top, 3) - .padding(.leading, -1) + .padding(.horizontal, 10) .background( RoundedRectangle(cornerRadius: 20) .fill(.mainOpacity80) diff --git a/Keychy/Keychy/Resources/Assets.xcassets/02. WorkShop/lottieIcon.imageset/Contents.json b/Keychy/Keychy/Resources/Assets.xcassets/02. WorkShop/lottieIcon.imageset/Contents.json new file mode 100644 index 00000000..f98dd73f --- /dev/null +++ b/Keychy/Keychy/Resources/Assets.xcassets/02. WorkShop/lottieIcon.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "lottieIcon.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Keychy/Keychy/Resources/Assets.xcassets/02. WorkShop/lottieIcon.imageset/lottieIcon.pdf b/Keychy/Keychy/Resources/Assets.xcassets/02. WorkShop/lottieIcon.imageset/lottieIcon.pdf new file mode 100644 index 00000000..372961b5 Binary files /dev/null and b/Keychy/Keychy/Resources/Assets.xcassets/02. WorkShop/lottieIcon.imageset/lottieIcon.pdf differ