diff --git a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/Contents.json b/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/Contents.json index cf51597..50c4762 100644 --- a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,41 +1,35 @@ { "images" : [ - { "filename" : "icon_iphone_20pt@2x.png", "idiom" : "iphone", "scale" : "2x", "size" : "20x20" }, - { "appearances" : [ { "appearance" : "luminosity", "value" : "dark" } ], "filename" : "icon_iphone_20pt@2x_dark.png", "idiom" : "iphone", "scale" : "2x", "size" : "20x20" }, - { "filename" : "icon_iphone_20pt@3x.png", "idiom" : "iphone", "scale" : "3x", "size" : "20x20" }, - { "appearances" : [ { "appearance" : "luminosity", "value" : "dark" } ], "filename" : "icon_iphone_20pt@3x_dark.png", "idiom" : "iphone", "scale" : "3x", "size" : "20x20" }, - { "filename" : "icon_iphone_29pt@2x.png", "idiom" : "iphone", "scale" : "2x", "size" : "29x29" }, - { "appearances" : [ { "appearance" : "luminosity", "value" : "dark" } ], "filename" : "icon_iphone_29pt@2x_dark.png", "idiom" : "iphone", "scale" : "2x", "size" : "29x29" }, - { "filename" : "icon_iphone_29pt@3x.png", "idiom" : "iphone", "scale" : "3x", "size" : "29x29" }, - { "appearances" : [ { "appearance" : "luminosity", "value" : "dark" } ], "filename" : "icon_iphone_29pt@3x_dark.png", "idiom" : "iphone", "scale" : "3x", "size" : "29x29" }, - { "filename" : "icon_iphone_40pt@2x.png", "idiom" : "iphone", "scale" : "2x", "size" : "40x40" }, - { "appearances" : [ { "appearance" : "luminosity", "value" : "dark" } ], "filename" : "icon_iphone_40pt@2x_dark.png", "idiom" : "iphone", "scale" : "2x", "size" : "40x40" }, - { "filename" : "icon_iphone_40pt@3x.png", "idiom" : "iphone", "scale" : "3x", "size" : "40x40" }, - { "appearances" : [ { "appearance" : "luminosity", "value" : "dark" } ], "filename" : "icon_iphone_40pt@3x_dark.png", "idiom" : "iphone", "scale" : "3x", "size" : "40x40" }, - { "filename" : "icon_iphone_60pt@2x.png", "idiom" : "iphone", "scale" : "2x", "size" : "60x60" }, - { "appearances" : [ { "appearance" : "luminosity", "value" : "dark" } ], "filename" : "icon_iphone_60pt@2x_dark.png", "idiom" : "iphone", "scale" : "2x", "size" : "60x60" }, - { "filename" : "icon_iphone_60pt@3x.png", "idiom" : "iphone", "scale" : "3x", "size" : "60x60" }, - { "appearances" : [ { "appearance" : "luminosity", "value" : "dark" } ], "filename" : "icon_iphone_60pt@3x_dark.png", "idiom" : "iphone", "scale" : "3x", "size" : "60x60" }, - { "filename" : "icon_ipad_20pt@1x.png", "idiom" : "ipad", "scale" : "1x", "size" : "20x20" }, - { "appearances" : [ { "appearance" : "luminosity", "value" : "dark" } ], "filename" : "icon_ipad_20pt@1x_dark.png", "idiom" : "ipad", "scale" : "1x", "size" : "20x20" }, - { "filename" : "icon_ipad_20pt@2x.png", "idiom" : "ipad", "scale" : "2x", "size" : "20x20" }, - { "appearances" : [ { "appearance" : "luminosity", "value" : "dark" } ], "filename" : "icon_ipad_20pt@2x_dark.png", "idiom" : "ipad", "scale" : "2x", "size" : "20x20" }, - { "filename" : "icon_ipad_29pt@1x.png", "idiom" : "ipad", "scale" : "1x", "size" : "29x29" }, - { "appearances" : [ { "appearance" : "luminosity", "value" : "dark" } ], "filename" : "icon_ipad_29pt@1x_dark.png", "idiom" : "ipad", "scale" : "1x", "size" : "29x29" }, - { "filename" : "icon_ipad_29pt@2x.png", "idiom" : "ipad", "scale" : "2x", "size" : "29x29" }, - { "appearances" : [ { "appearance" : "luminosity", "value" : "dark" } ], "filename" : "icon_ipad_29pt@2x_dark.png", "idiom" : "ipad", "scale" : "2x", "size" : "29x29" }, - { "filename" : "icon_ipad_40pt@1x.png", "idiom" : "ipad", "scale" : "1x", "size" : "40x40" }, - { "appearances" : [ { "appearance" : "luminosity", "value" : "dark" } ], "filename" : "icon_ipad_40pt@1x_dark.png", "idiom" : "ipad", "scale" : "1x", "size" : "40x40" }, - { "filename" : "icon_ipad_40pt@2x.png", "idiom" : "ipad", "scale" : "2x", "size" : "40x40" }, - { "appearances" : [ { "appearance" : "luminosity", "value" : "dark" } ], "filename" : "icon_ipad_40pt@2x_dark.png", "idiom" : "ipad", "scale" : "2x", "size" : "40x40" }, - { "filename" : "icon_ipad_76pt@1x.png", "idiom" : "ipad", "scale" : "1x", "size" : "76x76" }, - { "appearances" : [ { "appearance" : "luminosity", "value" : "dark" } ], "filename" : "icon_ipad_76pt@1x_dark.png", "idiom" : "ipad", "scale" : "1x", "size" : "76x76" }, - { "filename" : "icon_ipad_76pt@2x.png", "idiom" : "ipad", "scale" : "2x", "size" : "76x76" }, - { "appearances" : [ { "appearance" : "luminosity", "value" : "dark" } ], "filename" : "icon_ipad_76pt@2x_dark.png", "idiom" : "ipad", "scale" : "2x", "size" : "76x76" }, - { "filename" : "icon_ipad_83.5pt@2x.png", "idiom" : "ipad", "scale" : "2x", "size" : "83.5x83.5" }, - { "appearances" : [ { "appearance" : "luminosity", "value" : "dark" } ], "filename" : "icon_ipad_83.5pt@2x_dark.png", "idiom" : "ipad", "scale" : "2x", "size" : "83.5x83.5" }, - { "filename" : "icon_ios-marketing_1024pt@1x.png", "idiom" : "ios-marketing", "scale" : "1x", "size" : "1024x1024" }, - { "appearances" : [ { "appearance" : "luminosity", "value" : "dark" } ], "filename" : "icon_ios-marketing_1024pt@1x_dark.png", "idiom" : "ios-marketing", "scale" : "1x", "size" : "1024x1024" } + { + "filename" : "icon_pattern_1024x1024.png", + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "filename" : "icon_pattern_dark_1024x1024.png", + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "tinted" + } + ], + "filename" : "icon_pattern_1024x1024 1.png", + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + } ], "info" : { "author" : "xcode", diff --git a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_ios-marketing_1024pt@1x.png b/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_ios-marketing_1024pt@1x.png deleted file mode 100644 index 360784b..0000000 Binary files a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_ios-marketing_1024pt@1x.png and /dev/null differ diff --git a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_ios-marketing_1024pt@1x_dark.png b/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_ios-marketing_1024pt@1x_dark.png deleted file mode 100644 index a2fcdf0..0000000 Binary files a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_ios-marketing_1024pt@1x_dark.png and /dev/null differ diff --git a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_ipad_20pt@1x.png b/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_ipad_20pt@1x.png deleted file mode 100644 index 305dea2..0000000 Binary files a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_ipad_20pt@1x.png and /dev/null differ diff --git a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_ipad_20pt@1x_dark.png b/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_ipad_20pt@1x_dark.png deleted file mode 100644 index 06cb6c6..0000000 Binary files a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_ipad_20pt@1x_dark.png and /dev/null differ diff --git a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_ipad_20pt@2x.png b/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_ipad_20pt@2x.png deleted file mode 100644 index 0d43501..0000000 Binary files a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_ipad_20pt@2x.png and /dev/null differ diff --git a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_ipad_20pt@2x_dark.png b/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_ipad_20pt@2x_dark.png deleted file mode 100644 index 45feda1..0000000 Binary files a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_ipad_20pt@2x_dark.png and /dev/null differ diff --git a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_ipad_29pt@1x.png b/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_ipad_29pt@1x.png deleted file mode 100644 index 48f75b1..0000000 Binary files a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_ipad_29pt@1x.png and /dev/null differ diff --git a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_ipad_29pt@1x_dark.png b/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_ipad_29pt@1x_dark.png deleted file mode 100644 index 0766d17..0000000 Binary files a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_ipad_29pt@1x_dark.png and /dev/null differ diff --git a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_ipad_29pt@2x.png b/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_ipad_29pt@2x.png deleted file mode 100644 index c5e4078..0000000 Binary files a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_ipad_29pt@2x.png and /dev/null differ diff --git a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_ipad_29pt@2x_dark.png b/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_ipad_29pt@2x_dark.png deleted file mode 100644 index f595ca3..0000000 Binary files a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_ipad_29pt@2x_dark.png and /dev/null differ diff --git a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_ipad_40pt@1x.png b/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_ipad_40pt@1x.png deleted file mode 100644 index 0d43501..0000000 Binary files a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_ipad_40pt@1x.png and /dev/null differ diff --git a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_ipad_40pt@1x_dark.png b/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_ipad_40pt@1x_dark.png deleted file mode 100644 index 45feda1..0000000 Binary files a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_ipad_40pt@1x_dark.png and /dev/null differ diff --git a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_ipad_40pt@2x.png b/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_ipad_40pt@2x.png deleted file mode 100644 index 2bb2f5d..0000000 Binary files a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_ipad_40pt@2x.png and /dev/null differ diff --git a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_ipad_40pt@2x_dark.png b/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_ipad_40pt@2x_dark.png deleted file mode 100644 index 3a581ac..0000000 Binary files a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_ipad_40pt@2x_dark.png and /dev/null differ diff --git a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_ipad_76pt@1x.png b/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_ipad_76pt@1x.png deleted file mode 100644 index 8506bb1..0000000 Binary files a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_ipad_76pt@1x.png and /dev/null differ diff --git a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_ipad_76pt@1x_dark.png b/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_ipad_76pt@1x_dark.png deleted file mode 100644 index 514468c..0000000 Binary files a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_ipad_76pt@1x_dark.png and /dev/null differ diff --git a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_ipad_76pt@2x.png b/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_ipad_76pt@2x.png deleted file mode 100644 index 5181b5a..0000000 Binary files a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_ipad_76pt@2x.png and /dev/null differ diff --git a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_ipad_76pt@2x_dark.png b/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_ipad_76pt@2x_dark.png deleted file mode 100644 index 2f94225..0000000 Binary files a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_ipad_76pt@2x_dark.png and /dev/null differ diff --git a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_ipad_83.5pt@2x.png b/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_ipad_83.5pt@2x.png deleted file mode 100644 index 0e99578..0000000 Binary files a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_ipad_83.5pt@2x.png and /dev/null differ diff --git a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_ipad_83.5pt@2x_dark.png b/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_ipad_83.5pt@2x_dark.png deleted file mode 100644 index ab824af..0000000 Binary files a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_ipad_83.5pt@2x_dark.png and /dev/null differ diff --git a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_iphone_20pt@2x.png b/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_iphone_20pt@2x.png deleted file mode 100644 index 0d43501..0000000 Binary files a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_iphone_20pt@2x.png and /dev/null differ diff --git a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_iphone_20pt@2x_dark.png b/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_iphone_20pt@2x_dark.png deleted file mode 100644 index 45feda1..0000000 Binary files a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_iphone_20pt@2x_dark.png and /dev/null differ diff --git a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_iphone_20pt@3x.png b/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_iphone_20pt@3x.png deleted file mode 100644 index 85145c9..0000000 Binary files a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_iphone_20pt@3x.png and /dev/null differ diff --git a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_iphone_20pt@3x_dark.png b/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_iphone_20pt@3x_dark.png deleted file mode 100644 index 8cc1f26..0000000 Binary files a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_iphone_20pt@3x_dark.png and /dev/null differ diff --git a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_iphone_29pt@2x.png b/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_iphone_29pt@2x.png deleted file mode 100644 index c5e4078..0000000 Binary files a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_iphone_29pt@2x.png and /dev/null differ diff --git a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_iphone_29pt@2x_dark.png b/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_iphone_29pt@2x_dark.png deleted file mode 100644 index f595ca3..0000000 Binary files a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_iphone_29pt@2x_dark.png and /dev/null differ diff --git a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_iphone_29pt@3x.png b/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_iphone_29pt@3x.png deleted file mode 100644 index d39b326..0000000 Binary files a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_iphone_29pt@3x.png and /dev/null differ diff --git a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_iphone_29pt@3x_dark.png b/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_iphone_29pt@3x_dark.png deleted file mode 100644 index 415c3b7..0000000 Binary files a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_iphone_29pt@3x_dark.png and /dev/null differ diff --git a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_iphone_40pt@2x.png b/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_iphone_40pt@2x.png deleted file mode 100644 index 2bb2f5d..0000000 Binary files a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_iphone_40pt@2x.png and /dev/null differ diff --git a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_iphone_40pt@2x_dark.png b/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_iphone_40pt@2x_dark.png deleted file mode 100644 index 3a581ac..0000000 Binary files a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_iphone_40pt@2x_dark.png and /dev/null differ diff --git a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_iphone_40pt@3x.png b/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_iphone_40pt@3x.png deleted file mode 100644 index eae7619..0000000 Binary files a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_iphone_40pt@3x.png and /dev/null differ diff --git a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_iphone_40pt@3x_dark.png b/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_iphone_40pt@3x_dark.png deleted file mode 100644 index b6e2f71..0000000 Binary files a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_iphone_40pt@3x_dark.png and /dev/null differ diff --git a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_iphone_60pt@2x.png b/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_iphone_60pt@2x.png deleted file mode 100644 index eae7619..0000000 Binary files a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_iphone_60pt@2x.png and /dev/null differ diff --git a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_iphone_60pt@2x_dark.png b/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_iphone_60pt@2x_dark.png deleted file mode 100644 index b6e2f71..0000000 Binary files a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_iphone_60pt@2x_dark.png and /dev/null differ diff --git a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_iphone_60pt@3x.png b/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_iphone_60pt@3x.png deleted file mode 100644 index 84e5633..0000000 Binary files a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_iphone_60pt@3x.png and /dev/null differ diff --git a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_iphone_60pt@3x_dark.png b/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_iphone_60pt@3x_dark.png deleted file mode 100644 index fd74bda..0000000 Binary files a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_iphone_60pt@3x_dark.png and /dev/null differ diff --git a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_pattern_1024x1024 1.png b/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_pattern_1024x1024 1.png new file mode 100644 index 0000000..55cea2c Binary files /dev/null and b/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_pattern_1024x1024 1.png differ diff --git a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_pattern_1024x1024.png b/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_pattern_1024x1024.png new file mode 100644 index 0000000..55cea2c Binary files /dev/null and b/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_pattern_1024x1024.png differ diff --git a/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_pattern_dark_1024x1024.png b/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_pattern_dark_1024x1024.png new file mode 100644 index 0000000..00271b7 Binary files /dev/null and b/pedi-foods/Darwin/Assets.xcassets/AppIcon.appiconset/icon_pattern_dark_1024x1024.png differ diff --git a/pedi-foods/Sources/PediFoods/Views/Main/StoreDetailSupport.swift b/pedi-foods/Sources/PediFoods/Views/Main/StoreDetailSupport.swift index 1ba5e28..0920c50 100644 --- a/pedi-foods/Sources/PediFoods/Views/Main/StoreDetailSupport.swift +++ b/pedi-foods/Sources/PediFoods/Views/Main/StoreDetailSupport.swift @@ -61,3 +61,31 @@ struct AsyncStoreImage: View { .scaledToFill() } } + +struct SafeAreaTopPreferenceKey: PreferenceKey { + static let defaultValue: CGFloat = 0 + static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) { + let next = nextValue() + if next > 0 { + value = next + } + } +} + +struct SafeAreaTopReader: View { + @Binding var safeAreaTop: CGFloat + + var body: some View { + GeometryReader { geometry in + Color.clear + .preference(key: SafeAreaTopPreferenceKey.self, value: geometry.safeAreaInsets.top) + } + .frame(height: 0) + .onPreferenceChange(SafeAreaTopPreferenceKey.self) { value in + if value > 0 && safeAreaTop != value { + safeAreaTop = value + } + } + } +} + diff --git a/pedi-foods/Sources/PediFoods/Views/Main/StoreDetailView+Components.swift b/pedi-foods/Sources/PediFoods/Views/Main/StoreDetailView+Components.swift new file mode 100644 index 0000000..e426626 --- /dev/null +++ b/pedi-foods/Sources/PediFoods/Views/Main/StoreDetailView+Components.swift @@ -0,0 +1,348 @@ +import SwiftUI + +extension StoreDetailView { + + var topSection: some View { + ZStack(alignment: .top) { + heroSection + .frame(height: topSectionHeight) + + // Hard cut: cover cannot appear below this line. + Rectangle() + .fill(AppColors.backgroundLight) + .frame(height: max(0, topSectionHeight - coverVisibleUntilY)) + .offset(y: coverVisibleUntilY) + + summaryCard + .padding(.horizontal, 16) + .padding(.top, cardTopInset) + + storeLogoBadge + .padding(.top, cardTopInset - (storeLogoSize / 2)) + } + .frame(height: topSectionHeight) + } + + var heroSection: some View { + ZStack(alignment: .top) { + AsyncStoreImage(imageURL: resolvedURL(storeCoverURL)) + .frame(height: topSectionHeight) + .overlay( + LinearGradient( + colors: [Color.black.opacity(0.32), Color.black.opacity(0.05)], + startPoint: .top, + endPoint: .bottom + ) + ) + .ignoresSafeArea(.container, edges: .top) + + VStack(spacing: 0) { + HStack { + heroIconButton(icon: "chevron.left") { + dismiss() + } + Spacer() + heroIconButton(icon: "magnifyingglass") {} + heroIconButton( + icon: isFavoriteStore ? "heart.fill" : "heart", + foregroundStyle: isFavoriteStore ? Color.red : Color.white + ) { + Task { + await toggleFavoriteStore() + } + } + } + .padding(.horizontal, 14) + .padding(.top, UIDevice.topNotch) + + Spacer() + + Text("RESTAURANT") + .font(AppTypography.overline) + .tracking(1.8) + .foregroundStyle(Color.white.opacity(0.92)) + .padding(.bottom, 14) + } + } + } + + var storeLogoBadge: some View { + ZStack { + Circle() + .fill(AppColors.surface) + .frame(width: storeLogoSize, height: storeLogoSize) + .overlay( + Circle() + .stroke(Color.white, lineWidth: 0.1) + ) + + AsyncStoreImage(imageURL: resolvedURL(storeLogoURL)) + .frame(width: storeLogoSize - 10, height: storeLogoSize - 10) + .clipShape(Circle()) + } + .shadow(color: Color.black.opacity(0.10), radius: 8, y: 3) + } + + var summaryCard: some View { + VStack(spacing: 0) { + VStack(alignment: .leading, spacing: 14) { + HStack(alignment: .top) { + VStack(alignment: .leading, spacing: 6) { + Text(storeName) + .font(AppTypography.heading2) + .foregroundStyle(AppColors.textPrimary) + .lineLimit(2) + .padding(.top, 30) + + Text(storeSubtitle) + .font(.caption) + .foregroundStyle(AppColors.textMuted) + .lineLimit(1) + } + + Spacer() + + ratingChip + } + + HStack(spacing: 0) { + statItem(title: "DISTÂNCIA", value: distanceValueLabel) + Divider().frame(height: 34) + if let deliveryTime = info?.deliveryTime { + statItem(title: "TEMPO MIN.", value: deliveryTime+" min.") + } else { + statItem(title: "TEMPO", value: "--") + } + Divider().frame(height: 34) + statItem(title: "PED. MIN.", value: deliveryValueLabel) + } + .padding(.vertical, 4) + } + .padding(16) + + if isStoreOpen == false { + Text(closedStoreBannerText) + .font(AppTypography.heading3) + .foregroundStyle(Color.white) + .frame(maxWidth: .infinity, minHeight: closedBannerHeight) + .background(AppColors.brandDark) + } + } + .frame(height: summaryCardHeight) + .background(AppColors.surface) + .clipShape(RoundedRectangle(cornerRadius: AppLayout.radiusXL, style: .continuous)) + .shadow(color: AppShadow.soft.color, radius: AppShadow.soft.radius, y: AppShadow.soft.y) + } + + @ViewBuilder + var sectionedProducts: some View { + if isLoading { + VStack(spacing: 10) { + ProgressView() + Text("Carregando cardápio...") + .font(AppTypography.body) + .foregroundStyle(AppColors.textMuted) + } + .frame(maxWidth: .infinity, minHeight: 280, alignment: .center) + } else if let errorMessage { + VStack(alignment: .leading, spacing: 10) { + Text(errorMessage) + .font(AppTypography.body) + .foregroundStyle(AppColors.textMuted) + Button("Tentar novamente") { + Task { await loadStoreData() } + } + .font(AppTypography.heading3) + .foregroundStyle(AppColors.primary) + } + .padding(.top, 16) + } else if categories.isEmpty { + Text("Cardápio indisponível no momento.") + .font(AppTypography.body) + .foregroundStyle(AppColors.textMuted) + .padding(.top, 16) + .padding(.horizontal, 16) + .padding(.bottom, 120) + } else { + ForEach(categories, id: \.id) { category in + Text(category.name) + .font(AppTypography.heading2) + .foregroundStyle(AppColors.textPrimary) + .id(sectionAnchorId(for: category.id)) + .frame(maxWidth: .infinity, alignment: .leading) + .padding(.horizontal, 16) + .padding(.top, 8) + .padding(.bottom, 8) + .background(AppColors.backgroundLight) + .background( + GeometryReader { geometry in + Color.clear.preference( + key: CategoryHeaderOffsetPreferenceKey.self, + value: [category.id: geometry.frame(in: .global).minY] + ) + } + ) + + VStack(spacing: 12) { + ForEach(listItems(for: category)) { item in + productCard(item, in: category) + } + } + .padding(.horizontal, 16) + .padding(.bottom, 8) + } + Color.clear.frame(height: 140) + } + } + + func categoryTabs(proxy: ScrollViewProxy, topExtension: CGFloat = 0, stickyProgress: CGFloat = 0) -> some View { + let chipPaddingH: CGFloat = 10 + 6 * stickyProgress + let chipPaddingV: CGFloat = 4 + 5 * stickyProgress + let containerPaddingV: CGFloat = 2 + 8 * stickyProgress + + return ScrollView(.horizontal, showsIndicators: false) { + HStack(spacing: 10) { + ForEach(categories, id: \.id) { category in + let active = selectedCategoryId == category.id + Button { + selectedCategoryId = category.id + isProgrammaticCategoryScroll = true + withAnimation(.easeInOut(duration: 0.25)) { + proxy.scrollTo(sectionAnchorId(for: category.id), anchor: .top) + } + DispatchQueue.main.asyncAfter(deadline: .now() + 0.35) { + isProgrammaticCategoryScroll = false + } + } label: { + Text(category.name) + .font(AppTypography.heading3) + .foregroundStyle(active ? AppColors.textInverse : AppColors.textMuted) + .padding(.horizontal, chipPaddingH) + .padding(.vertical, chipPaddingV) + .background(active ? AppColors.primary : AppColors.surface) + .clipShape(Capsule()) + } + .buttonStyle(.plain) + } + } + .padding(.horizontal, 16) + .padding(.vertical, containerPaddingV) + } + .background(AppColors.backgroundLight) + .overlay(alignment: .top) { + AppColors.backgroundLight + .frame(height: topExtension) + .frame(maxWidth: .infinity) + .offset(y: -topExtension) + .allowsHitTesting(false) + } + } + + func productCard(_ item: StoreCatalogListItem, in category: StoreCatalogCategory) -> some View { + let product = item.product + let hasSelectableAddons = product.addonGroups.contains { $0.items.isEmpty == false } + + return HStack(spacing: 12) { + VStack(alignment: .leading, spacing: 8) { + Text(item.title) + .font(AppTypography.heading3) + .foregroundStyle(AppColors.textPrimary) + .lineLimit(2) + .multilineTextAlignment(.leading) + + if let description = item.description, description.isEmpty == false { + Text(description) + .font(.caption) + .foregroundStyle(AppColors.textMuted) + .lineLimit(2) + .multilineTextAlignment(.leading) + } + + Text(listPriceLabel(for: product, in: category)) + .font(AppTypography.heading3) + .foregroundStyle(AppColors.textPrimary) + } + + Spacer() + + ZStack(alignment: .bottomTrailing) { + AsyncStoreImage(imageURL: resolvedURL(item.imageURL)) + .frame(width: 92, height: 92) + .clipShape(RoundedRectangle(cornerRadius: AppLayout.radiusLG, style: .continuous)) + + Button { + guard isStoreOpen else { + SnackbarCenter.shared.show(title: "Loja fechada no momento.", style: .warning, icon: "moon.zzz.fill", duration: 2.0) + return + } + if item.isPizzaSummary, let pizzaCategoryId = item.pizzaCategoryId { + requestOpenPizzaSheet(categoryId: pizzaCategoryId) + return + } + if hasSelectableAddons == false { + let basePrice = product.price ?? 0 + let item = CartItemState( + id: "\(storeId)::\(product.id)::base", + productId: product.id, + storeId: storeId, + name: product.name, + imageURL: resolvedURL(product.image), + quantity: 1, + unitPrice: basePrice + ) + requestAddToCart(item) + } else { + requestOpenProductSheet(product) + } + } label: { + ZStack(alignment: .leading) { + Image(systemName: "plus") + .font(.system(size: 16, weight: .bold)) + .foregroundStyle(AppColors.textPrimary) + .frame(width: 30, height: 30) + .background(AppColors.tertiary) + .clipShape(Circle()) + + let qty = quantityInCart(for: item) + if qty > 0 { + Text("\(qty)") + .font(.system(size: 10, weight: .bold)) + .foregroundStyle(Color.white) + .padding(.horizontal, 5) + .padding(.vertical, 2) + .background(Color.red) + .clipShape(Capsule()) + .offset(x: -6, y: -10) + .zIndex(1) + } + } + .offset(x: 3, y: -3) + .frame(width: 30, height: 30) + .appContentShape(Circle()) + } + .buttonStyle(.plain) + .frame(width: 30, height: 30) + .disabled(isStoreOpen == false) + .opacity(isStoreOpen ? 1 : 0.65) + .offset(x: 7, y: 7) + } + } + .padding(12) + .background(AppColors.surface) + .clipShape(RoundedRectangle(cornerRadius: AppLayout.radiusLG, style: .continuous)) + .appContentShape(RoundedRectangle(cornerRadius: AppLayout.radiusLG, style: .continuous)) + .onTapGesture { + guard isStoreOpen else { + SnackbarCenter.shared.show(title: "Loja fechada no momento.", style: .warning, icon: "moon.zzz.fill", duration: 2.0) + return + } + if item.isPizzaSummary, let pizzaCategoryId = item.pizzaCategoryId { + requestOpenPizzaSheet(categoryId: pizzaCategoryId) + return + } + guard hasSelectableAddons else { return } + requestOpenProductSheet(product) + } + } + +} diff --git a/pedi-foods/Sources/PediFoods/Views/Main/StoreDetailView.swift b/pedi-foods/Sources/PediFoods/Views/Main/StoreDetailView.swift index 1e56099..335d0de 100644 --- a/pedi-foods/Sources/PediFoods/Views/Main/StoreDetailView.swift +++ b/pedi-foods/Sources/PediFoods/Views/Main/StoreDetailView.swift @@ -14,6 +14,7 @@ struct StoreDetailView: View { let storeCategory: String? let storeRating: Double? let storeDistance: String? + let storeDeliveryFee: Double? @Binding var appState: AppState @Environment(\.dismiss) var dismiss @@ -33,60 +34,50 @@ struct StoreDetailView: View { @State var didLoad = false @State var categoryHeaderOffsets: [String: CGFloat] = [:] @State var isProgrammaticCategoryScroll = false - @State var scrollOffsetY: CGFloat = 0 + @State var scrollOffset: CGFloat = 0 + @State var safeAreaTop: CGFloat = 0 @State var isFavoriteRequestInFlight = false - let cardTopInset: CGFloat = 168 - let summaryCardBaseHeight: CGFloat = 170 + let cardTopInset: CGFloat = 180 + let summaryCardBaseHeight: CGFloat = 212 let closedBannerHeight: CGFloat = 44 let coverVisibleUntilY: CGFloat = 253 let storeLogoSize: CGFloat = 84 var body: some View { - GeometryReader { geometry in - let safeTop = geometry.safeAreaInsets.top - ScrollViewReader { proxy in - - ZStack(alignment: .top) { - AppColors.backgroundLight.ignoresSafeArea() + ScrollViewReader { proxy in + let stickyProgress = categoryTabsStickyProgress(safeTop: safeAreaTop) - ScrollView(showsIndicators: false) { -#if os(Android) - LazyVStack(spacing: 0) { - ScrollOffsetReader(offsetY: $scrollOffsetY) - topSection + ZStack(alignment: .top) { + SafeAreaTopReader(safeAreaTop: $safeAreaTop) - categoryTabs(proxy: proxy, safeTop: safeTop, isSticky: false) + AppColors.backgroundLight.ignoresSafeArea() + ScrollView(showsIndicators: false) { + LazyVStack(spacing: 0, pinnedViews: [.sectionHeaders]) { + ScrollOffsetReader(offsetY: $scrollOffset) + topSection + Section { sectionedProducts + } header: { + categoryTabs(proxy: proxy, topExtension: 0, stickyProgress: 1) + .opacity(Double(1 - stickyProgress)) } -#else - LazyVStack(spacing: 0, pinnedViews: [.sectionHeaders]) { - ScrollOffsetReader(offsetY: $scrollOffsetY) - topSection - - categoryTabs(proxy: proxy, safeTop: safeTop, isSticky: false) - - sectionedProducts - } -#endif } - .refreshable { - await loadStoreData(forceRefresh: true) - } - .appNamedCoordinateSpace(StoreDetailScrollCoordinateSpace.name) - .ignoresSafeArea(edges: .top) + } + .coordinateSpace(name: StoreDetailScrollCoordinateSpace.name) + .refreshable { + await loadStoreData(forceRefresh: true) } .ignoresSafeArea(edges: .top) - .overlay(alignment: .top) { - if isCategoryTabsPinned(safeTop: safeTop) { - categoryTabs(proxy: proxy, safeTop: safeTop, isSticky: true) - .transition(.opacity) - .zIndex(20) - } - } - .saturation(isStoreOpen ? 1 : 0) + + categoryTabs(proxy: proxy, topExtension: stickyProgress * safeAreaTop, stickyProgress: 1) + .opacity(Double(stickyProgress)) + .allowsHitTesting(stickyProgress > 0.1) + .offset(y: safeAreaTop) } + .ignoresSafeArea(edges: .top) + .saturation(isStoreOpen ? 1 : 0) } .navigationBarBackButtonHidden(true) .appHiddenNavigationBar() @@ -180,343 +171,4 @@ struct StoreDetailView: View { syncCategoryWithScroll() } } - - private var topSection: some View { - ZStack(alignment: .top) { - heroSection - .frame(height: topSectionHeight) - - // Hard cut: cover cannot appear below this line. - Rectangle() - .fill(AppColors.backgroundLight) - .frame(height: max(0, topSectionHeight - coverVisibleUntilY)) - .offset(y: coverVisibleUntilY) - - summaryCard - .padding(.horizontal, 16) - .padding(.top, cardTopInset) - - storeLogoBadge - .padding(.top, cardTopInset - (storeLogoSize / 2)) - } - .frame(height: topSectionHeight) - } - - private var heroSection: some View { - ZStack(alignment: .top) { - AsyncStoreImage(imageURL: resolvedURL(storeCoverURL)) - .frame(height: topSectionHeight) - .overlay( - LinearGradient( - colors: [Color.black.opacity(0.32), Color.black.opacity(0.05)], - startPoint: .top, - endPoint: .bottom - ) - ) - - VStack(spacing: 0) { - HStack { - heroIconButton(icon: "chevron.left") { - dismiss() - } - Spacer() - heroIconButton(icon: "magnifyingglass") {} - heroIconButton( - icon: isFavoriteStore ? "heart.fill" : "heart", - foregroundStyle: isFavoriteStore ? Color.red : Color.white - ) { - Task { - await toggleFavoriteStore() - } - } - } - .padding(.horizontal, 14) - .padding(.top, UIDevice.topNotch) - - Spacer() - - Text("RESTAURANT") - .font(AppTypography.overline) - .tracking(1.8) - .foregroundStyle(Color.white.opacity(0.92)) - .padding(.bottom, 14) - } - } - } - - private var storeLogoBadge: some View { - ZStack { - Circle() - .fill(AppColors.surface) - .frame(width: storeLogoSize, height: storeLogoSize) - .overlay( - Circle() - .stroke(Color.white, lineWidth: 0.1) - ) - - AsyncStoreImage(imageURL: resolvedURL(storeLogoURL)) - .frame(width: storeLogoSize - 10, height: storeLogoSize - 10) - .clipShape(Circle()) - } - .shadow(color: Color.black.opacity(0.10), radius: 8, y: 3) - } - - private var summaryCard: some View { - VStack(spacing: 0) { - VStack(alignment: .leading, spacing: 14) { - HStack(alignment: .top) { - VStack(alignment: .leading, spacing: 6) { - Text(storeName) - .font(AppTypography.heading2) - .foregroundStyle(AppColors.textPrimary) - .lineLimit(2) - .padding(.top, 30) - - Text(storeSubtitle) - .font(.caption) - .foregroundStyle(AppColors.textMuted) - .lineLimit(1) - } - - Spacer() - - ratingChip - } - - HStack(spacing: 0) { - statItem(title: "DISTÂNCIA", value: distanceValueLabel) - Divider().frame(height: 34) - statItem(title: "TEMPO", value: info?.deliveryTime ?? "--") - Divider().frame(height: 34) - statItem(title: "ENTREGA", value: deliveryValueLabel) - } - .padding(.vertical, 4) - } - .padding(16) - - if isStoreOpen == false { - Text(closedStoreBannerText) - .font(AppTypography.heading3) - .foregroundStyle(Color.white) - .frame(maxWidth: .infinity, minHeight: closedBannerHeight) - .background(AppColors.brandDark) - } - } - .frame(height: summaryCardHeight) - .background(AppColors.surface) - .clipShape(RoundedRectangle(cornerRadius: AppLayout.radiusXL, style: .continuous)) - .shadow(color: AppShadow.soft.color, radius: AppShadow.soft.radius, y: AppShadow.soft.y) - } - - @ViewBuilder - private var sectionedProducts: some View { - if isLoading { - ProgressView() - .frame(maxWidth: .infinity, alignment: .center) - .padding(.top, 26) - } else if let errorMessage { - VStack(alignment: .leading, spacing: 10) { - Text(errorMessage) - .font(AppTypography.body) - .foregroundStyle(AppColors.textMuted) - Button("Tentar novamente") { - Task { await loadStoreData() } - } - .font(AppTypography.heading3) - .foregroundStyle(AppColors.primary) - } - .padding(.top, 16) - } else if categories.isEmpty { - Text("Cardápio indisponível no momento.") - .font(AppTypography.body) - .foregroundStyle(AppColors.textMuted) - .padding(.top, 16) - .padding(.horizontal, 16) - .padding(.bottom, 120) - } else { - ForEach(categories, id: \.id) { category in - Section { - VStack(spacing: 12) { - ForEach(listItems(for: category)) { item in - productCard(item, in: category) - } - } - .padding(.horizontal, 16) - .padding(.bottom, 8) - } header: { - Text(category.name) - .font(AppTypography.heading2) - .foregroundStyle(AppColors.textPrimary) - .id(sectionAnchorId(for: category.id)) - .frame(maxWidth: .infinity, alignment: .leading) - .padding(.horizontal, 16) - .padding(.top, 8) - .padding(.bottom, 8) - .background(AppColors.backgroundLight) - .background( - GeometryReader { geometry in - Color.clear.preference( - key: CategoryHeaderOffsetPreferenceKey.self, - value: [category.id: geometry.frame(in: .global).minY] - ) - } - ) - } - } - Color.clear.frame(height: 120) - } - } - - private func categoryTabs(proxy: ScrollViewProxy, safeTop: CGFloat, isSticky: Bool) -> some View { - ScrollView(.horizontal, showsIndicators: false) { - HStack(spacing: 10) { - ForEach(categories, id: \.id) { category in - let active = selectedCategoryId == category.id - Button { - selectedCategoryId = category.id - isProgrammaticCategoryScroll = true - withAnimation(.easeInOut(duration: 0.25)) { - proxy.scrollTo(sectionAnchorId(for: category.id), anchor: .top) - } - DispatchQueue.main.asyncAfter(deadline: .now() + 0.35) { - isProgrammaticCategoryScroll = false - } - } label: { - Text(category.name) - .font(AppTypography.heading3) - .foregroundStyle(active ? AppColors.textInverse : AppColors.textMuted) - .padding(.horizontal, 16) - .padding(.vertical, 9) - .background(active ? AppColors.primary : AppColors.surface) - .clipShape(Capsule()) - } - .buttonStyle(.plain) - } - } - .padding(.horizontal, 16) - .padding(.bottom, 10) - .padding(.top, isSticky ? categoryTabsPinnedInset(safeTop: safeTop) : 10) - } - .background(AppColors.backgroundLight) - } - - private func isCategoryTabsPinned(safeTop: CGFloat) -> Bool { - scrollOffsetY >= categoryTabsPinThreshold(safeTop: safeTop) - } - - private func categoryTabsPinThreshold(safeTop: CGFloat) -> CGFloat { - max(0, topSectionHeight + 10 - safeTop) - } - - private func categoryTabsPinnedInset(safeTop: CGFloat) -> CGFloat { - max(8, safeTop - 44) - } - - private func productCard(_ item: StoreCatalogListItem, in category: StoreCatalogCategory) -> some View { - let product = item.product - let hasSelectableAddons = product.addonGroups.contains { $0.items.isEmpty == false } - - return HStack(spacing: 12) { - VStack(alignment: .leading, spacing: 8) { - Text(item.title) - .font(AppTypography.heading3) - .foregroundStyle(AppColors.textPrimary) - .lineLimit(2) - .multilineTextAlignment(.leading) - - if let description = item.description, description.isEmpty == false { - Text(description) - .font(.caption) - .foregroundStyle(AppColors.textMuted) - .lineLimit(2) - .multilineTextAlignment(.leading) - } - - Text(listPriceLabel(for: product, in: category)) - .font(AppTypography.heading3) - .foregroundStyle(AppColors.textPrimary) - } - - Spacer() - - ZStack(alignment: .bottomTrailing) { - AsyncStoreImage(imageURL: resolvedURL(item.imageURL)) - .frame(width: 92, height: 92) - .clipShape(RoundedRectangle(cornerRadius: AppLayout.radiusLG, style: .continuous)) - - Button { - guard isStoreOpen else { - SnackbarCenter.shared.show(title: "Loja fechada no momento.", style: .warning, icon: "moon.zzz.fill", duration: 2.0) - return - } - if item.isPizzaSummary, let pizzaCategoryId = item.pizzaCategoryId { - requestOpenPizzaSheet(categoryId: pizzaCategoryId) - return - } - if hasSelectableAddons == false { - let basePrice = product.price ?? 0 - let item = CartItemState( - id: "\(storeId)::\(product.id)::base", - productId: product.id, - storeId: storeId, - name: product.name, - imageURL: resolvedURL(product.image), - quantity: 1, - unitPrice: basePrice - ) - requestAddToCart(item) - } else { - requestOpenProductSheet(product) - } - } label: { - ZStack(alignment: .leading) { - Image(systemName: "plus") - .font(.system(size: 16, weight: .bold)) - .foregroundStyle(AppColors.textPrimary) - .frame(width: 30, height: 30) - .background(AppColors.tertiary) - .clipShape(Circle()) - - let qty = quantityInCart(for: item) - if qty > 0 { - Text("\(qty)") - .font(.system(size: 10, weight: .bold)) - .foregroundStyle(Color.white) - .padding(.horizontal, 5) - .padding(.vertical, 2) - .background(Color.red) - .clipShape(Capsule()) - .offset(x: -6, y: -10) - .zIndex(1) - } - } - .offset(x: 3, y: -3) - .frame(width: 30, height: 30) - .appContentShape(Circle()) - } - .buttonStyle(.plain) - .frame(width: 30, height: 30) - .disabled(isStoreOpen == false) - .opacity(isStoreOpen ? 1 : 0.65) - .offset(x: 7, y: 7) - } - } - .padding(12) - .background(AppColors.surface) - .clipShape(RoundedRectangle(cornerRadius: AppLayout.radiusLG, style: .continuous)) - .appContentShape(RoundedRectangle(cornerRadius: AppLayout.radiusLG, style: .continuous)) - .onTapGesture { - guard isStoreOpen else { - SnackbarCenter.shared.show(title: "Loja fechada no momento.", style: .warning, icon: "moon.zzz.fill", duration: 2.0) - return - } - if item.isPizzaSummary, let pizzaCategoryId = item.pizzaCategoryId { - requestOpenPizzaSheet(categoryId: pizzaCategoryId) - return - } - guard hasSelectableAddons else { return } - requestOpenProductSheet(product) - } - } - }