diff --git a/PyeonHaeng-iOS.xcodeproj/project.pbxproj b/PyeonHaeng-iOS.xcodeproj/project.pbxproj index c024ed3..f998e77 100644 --- a/PyeonHaeng-iOS.xcodeproj/project.pbxproj +++ b/PyeonHaeng-iOS.xcodeproj/project.pbxproj @@ -32,6 +32,9 @@ BAA4D9B12B5A1796005999F8 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = BAA4D9B02B5A1796005999F8 /* Assets.xcassets */; }; BAA4D9B42B5A1796005999F8 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = BAA4D9B32B5A1796005999F8 /* Preview Assets.xcassets */; }; BAB569612B639F3000D1E0F9 /* DesignSystem in Frameworks */ = {isa = PBXBuildFile; productRef = BAB569602B639F3000D1E0F9 /* DesignSystem */; }; + BAE159D82B65FA6F002DCF94 /* HomeProductDetailSelectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BAE159D72B65FA6F002DCF94 /* HomeProductDetailSelectionView.swift */; }; + BAE159DA2B65FC35002DCF94 /* HomeProductListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BAE159D92B65FC35002DCF94 /* HomeProductListView.swift */; }; + BAE159DE2B663A9A002DCF94 /* HomeProductSorterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BAE159DD2B663A9A002DCF94 /* HomeProductSorterView.swift */; }; BAF2BEB32B61236100931AF0 /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = BAF2BEB22B61236100931AF0 /* Localizable.xcstrings */; }; E5462C662B65677B00E9FDF2 /* PromotionTag.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5462C652B65677B00E9FDF2 /* PromotionTag.swift */; }; E5F2EC402B637D4A00EE0838 /* ProductInfoHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5F2EC3F2B637D4A00EE0838 /* ProductInfoHeader.swift */; }; @@ -77,6 +80,9 @@ BAA4D9B02B5A1796005999F8 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; BAA4D9B32B5A1796005999F8 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; BABFEA6F2B6399C30084C0EC /* Shared */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = Shared; sourceTree = ""; }; + BAE159D72B65FA6F002DCF94 /* HomeProductDetailSelectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeProductDetailSelectionView.swift; sourceTree = ""; }; + BAE159D92B65FC35002DCF94 /* HomeProductListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeProductListView.swift; sourceTree = ""; }; + BAE159DD2B663A9A002DCF94 /* HomeProductSorterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeProductSorterView.swift; sourceTree = ""; }; BAF2BEB22B61236100931AF0 /* Localizable.xcstrings */ = {isa = PBXFileReference; lastKnownFileType = text.json.xcstrings; path = Localizable.xcstrings; sourceTree = ""; }; E5462C652B65677B00E9FDF2 /* PromotionTag.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PromotionTag.swift; sourceTree = ""; }; E5F2EC3F2B637D4A00EE0838 /* ProductInfoHeader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProductInfoHeader.swift; sourceTree = ""; }; @@ -186,6 +192,9 @@ isa = PBXGroup; children = ( BA28F1872B6155910052855E /* HomeView.swift */, + BAE159D72B65FA6F002DCF94 /* HomeProductDetailSelectionView.swift */, + BAE159DD2B663A9A002DCF94 /* HomeProductSorterView.swift */, + BAE159D92B65FC35002DCF94 /* HomeProductListView.swift */, ); path = HomeScene; sourceTree = ""; @@ -460,6 +469,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + BAE159DA2B65FC35002DCF94 /* HomeProductListView.swift in Sources */, E5F2EC402B637D4A00EE0838 /* ProductInfoHeader.swift in Sources */, BA28F1852B6155810052855E /* OnboardingView.swift in Sources */, BA28F1882B6155910052855E /* HomeView.swift in Sources */, @@ -469,6 +479,8 @@ E5462C662B65677B00E9FDF2 /* PromotionTag.swift in Sources */, BA28F1912B61566E0052855E /* ProductSearchView.swift in Sources */, BA28F18E2B6156420052855E /* SettingsView.swift in Sources */, + BAE159DE2B663A9A002DCF94 /* HomeProductSorterView.swift in Sources */, + BAE159D82B65FA6F002DCF94 /* HomeProductDetailSelectionView.swift in Sources */, BAA4D9AF2B5A1795005999F8 /* SplashView.swift in Sources */, BAA4D9AD2B5A1795005999F8 /* PyeonHaengApp.swift in Sources */, ); diff --git a/PyeonHaeng-iOS/Resources/Localizable.xcstrings b/PyeonHaeng-iOS/Resources/Localizable.xcstrings index 25105c4..89b3f21 100644 --- a/PyeonHaeng-iOS/Resources/Localizable.xcstrings +++ b/PyeonHaeng-iOS/Resources/Localizable.xcstrings @@ -3,6 +3,53 @@ "strings" : { "" : { + }, + "총 %lld개의 상품이 있어요!" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "variations" : { + "plural" : { + "one" : { + "stringUnit" : { + "state" : "translated", + "value" : "There is a total of %lld product!" + } + }, + "other" : { + "stringUnit" : { + "state" : "translated", + "value" : "There are a total of %lld product!" + } + } + } + } + }, + "ja" : { + "variations" : { + "plural" : { + "other" : { + "stringUnit" : { + "state" : "translated", + "value" : "合計%lld個の商品があります!" + } + } + } + } + }, + "ko" : { + "variations" : { + "plural" : { + "other" : { + "stringUnit" : { + "state" : "translated", + "value" : "총 %lld개의 상품이 있어요!" + } + } + } + } + } + } }, "개당" : { "extractionState" : "manual", diff --git a/PyeonHaeng-iOS/Sources/Scenes/HomeScene/HomeProductDetailSelectionView.swift b/PyeonHaeng-iOS/Sources/Scenes/HomeScene/HomeProductDetailSelectionView.swift new file mode 100644 index 0000000..f55e0fc --- /dev/null +++ b/PyeonHaeng-iOS/Sources/Scenes/HomeScene/HomeProductDetailSelectionView.swift @@ -0,0 +1,78 @@ +// +// HomeProductDetailSelectionView.swift +// PyeonHaeng-iOS +// +// Created by 홍승현 on 1/28/24. +// + +import SwiftUI + +// MARK: - HomeProductDetailSelectionView + +struct HomeProductDetailSelectionView: View { + var body: some View { + HStack { + Button {} label: { + HStack { + Image.gs25 + .resizable() + .scaledToFit() + Image(systemName: "chevron.down") + .resizable() + .scaledToFit() + .frame(width: Metrics.iconWidth, height: Metrics.iconHeight) + .foregroundStyle(Color.gray300) + .bold() + } + } + + Spacer() + + Button {} label: { + HStack { + Text(verbatim: "All") + .font(.title2) + .frame(height: Metrics.textHeight) + Image(systemName: "arrowtriangle.down.fill") + .resizable() + .scaledToFill() + .frame(width: Metrics.iconWidth, height: Metrics.iconHeight) + } + .foregroundStyle(Color.gray400) + .padding( + .init( + top: Metrics.promotionButtonPaddingTop, + leading: Metrics.promotionButtonPaddingLeading, + bottom: Metrics.promotionButtonPaddingBottom, + trailing: Metrics.promotionButtonPaddingTrailing + ) + ) + } + .overlay { + RoundedRectangle(cornerRadius: Metrics.promotionButtonCornerRadius) + .stroke() + .foregroundStyle(Color.gray400) + } + } + .frame(height: Metrics.height) + } +} + +// MARK: HomeProductDetailSelectionView.Metrics + +private extension HomeProductDetailSelectionView { + enum Metrics { + static let textHeight: CGFloat = 24 + static let horizontal: CGFloat = 20 + static let iconWidth: CGFloat = 8 + static let iconHeight: CGFloat = 4 + + static let promotionButtonPaddingTop: CGFloat = 4 + static let promotionButtonPaddingLeading: CGFloat = 16 + static let promotionButtonPaddingBottom: CGFloat = 4 + static let promotionButtonPaddingTrailing: CGFloat = 16 + static let promotionButtonCornerRadius: CGFloat = 16 + + static let height: CGFloat = 56 + } +} diff --git a/PyeonHaeng-iOS/Sources/Scenes/HomeScene/HomeProductListView.swift b/PyeonHaeng-iOS/Sources/Scenes/HomeScene/HomeProductListView.swift new file mode 100644 index 0000000..d35444c --- /dev/null +++ b/PyeonHaeng-iOS/Sources/Scenes/HomeScene/HomeProductListView.swift @@ -0,0 +1,98 @@ +// +// HomeProductListView.swift +// PyeonHaeng-iOS +// +// Created by 홍승현 on 1/28/24. +// + +import SwiftUI + +// MARK: - HomeProductListView + +struct HomeProductListView: View { + private let items = Array(repeating: "펩시 제로 라임 250ml", count: 10) + + var body: some View { + List(items, id: \.self) { item in + ProductRow(product: item) + } + .listStyle(.plain) + .scrollIndicators(.hidden) + } +} + +// MARK: - ProductRow + +struct ProductRow: View { + let product: String + + var body: some View { + HStack(spacing: 16) { + ProductImageView() + ProductDetailsView(product: product) + } + .padding(.vertical, 16) + .alignmentGuide(.listRowSeparatorLeading) { _ in + 0 + } + } +} + +// MARK: - ProductImageView + +private struct ProductImageView: View { + var body: some View { + Image(systemName: "photo") // 이미지를 추가합니다. + .resizable() + .scaledToFit() + .frame(width: 70, height: 70) + .padding(.all, 12) + } +} + +// MARK: - ProductDetailsView + +private struct ProductDetailsView: View { + let product: String + + var body: some View { + VStack(alignment: .leading, spacing: 16) { + VStack(alignment: .leading, spacing: 8) { + Text(verbatim: "1+1") + .font(.b3) + .padding(.horizontal, 8) + .background(Color.pyeonHaengRed.opacity(0.1)) + .foregroundColor(Color.pyeonHaengRed) + .cornerRadius(5) + Text(product) + .font(.title1) + } + PriceView() + } + } +} + +// MARK: - PriceView + +private struct PriceView: View { + var body: some View { + HStack(spacing: 10) { + Spacer() + Text(verbatim: "1800원") + .font(.x2) + .strikethrough() + .foregroundColor(Color.gray200) + HStack(spacing: 4) { + Text(verbatim: "개당") + .font(.c3) + Text(verbatim: "900원") + .font(.h4) + } + .foregroundStyle(Color.gray900) + } + } +} + +#Preview { + HomeProductListView() +} diff --git a/PyeonHaeng-iOS/Sources/Scenes/HomeScene/HomeProductSorterView.swift b/PyeonHaeng-iOS/Sources/Scenes/HomeScene/HomeProductSorterView.swift new file mode 100644 index 0000000..fc1d575 --- /dev/null +++ b/PyeonHaeng-iOS/Sources/Scenes/HomeScene/HomeProductSorterView.swift @@ -0,0 +1,42 @@ +// +// HomeProductSorterView.swift +// PyeonHaeng-iOS +// +// Created by 홍승현 on 1/28/24. +// + +import SwiftUI + +struct HomeProductSorterView: View { + private let count: Int + + init(count: Int) { + self.count = count + } + + var body: some View { + HStack { + Text(productCountString) + .font(.title2) + Spacer() + Button {} label: { + Image(systemName: "arrow.up.arrow.down") + } + } + .padding(.all, 8) + } + + var productCountString: AttributedString { + var string = AttributedString(localized: "총 \(count)개의 상품이 있어요!") + + if let range = string.range(of: "\(count)") { + string[range].foregroundColor = .green500 + } + + return string + } +} + +#Preview { + HomeProductSorterView(count: 50) +} diff --git a/PyeonHaeng-iOS/Sources/Scenes/HomeScene/HomeView.swift b/PyeonHaeng-iOS/Sources/Scenes/HomeScene/HomeView.swift index 5ea20ba..d5040b4 100644 --- a/PyeonHaeng-iOS/Sources/Scenes/HomeScene/HomeView.swift +++ b/PyeonHaeng-iOS/Sources/Scenes/HomeScene/HomeView.swift @@ -5,11 +5,55 @@ // Created by 홍승현 on 1/24/24. // +import DesignSystem import SwiftUI +// MARK: - HomeView + struct HomeView: View { var body: some View { - Text("") + NavigationStack { + VStack { + HomeProductDetailSelectionView() + HomeProductSorterView(count: 12) + HomeProductListView() + } + .padding(.horizontal, Metrics.horizontal) + .navigationBarTitleDisplayMode(.inline) + .toolbar { + ToolbarItem(placement: .topBarLeading) { + HStack { + Image(systemName: "storefront") + .foregroundStyle(Color.gray900) + } + } + + ToolbarItemGroup(placement: .topBarTrailing) { + NavigationLink { + ProductInfoView() + .toolbarRole(.editor) + } label: { + Image(systemName: "magnifyingglass") + .foregroundStyle(Color.gray900) + } + NavigationLink { + SettingsView() + .toolbarRole(.editor) + } label: { + Image(systemName: "gear") + .foregroundStyle(Color.gray900) + } + } + } + } + } +} + +// MARK: HomeView.Metrics + +private extension HomeView { + enum Metrics { + static let horizontal: CGFloat = 20 } }