@shopify/shop-minis-cli 0.0.35

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (152) hide show
  1. package/README.md +8 -0
  2. package/build/commands/create-mini/index.d.ts +2 -0
  3. package/build/commands/create-mini/index.js +116 -0
  4. package/build/commands/create-mini/index.js.map +1 -0
  5. package/build/commands/create-mini/utils/template-app.d.ts +1 -0
  6. package/build/commands/create-mini/utils/template-app.js +44 -0
  7. package/build/commands/create-mini/utils/template-app.js.map +1 -0
  8. package/build/commands/dev/index.d.ts +6 -0
  9. package/build/commands/dev/index.js +31 -0
  10. package/build/commands/dev/index.js.map +1 -0
  11. package/build/commands/dev/utils/android.d.ts +16 -0
  12. package/build/commands/dev/utils/android.js +165 -0
  13. package/build/commands/dev/utils/android.js.map +1 -0
  14. package/build/commands/dev/utils/binaries.d.ts +83 -0
  15. package/build/commands/dev/utils/binaries.js +173 -0
  16. package/build/commands/dev/utils/binaries.js.map +1 -0
  17. package/build/commands/dev/utils/binaries.test.d.ts +1 -0
  18. package/build/commands/dev/utils/binaries.test.js +275 -0
  19. package/build/commands/dev/utils/binaries.test.js.map +1 -0
  20. package/build/commands/dev/utils/deeplink.d.ts +3 -0
  21. package/build/commands/dev/utils/deeplink.js +30 -0
  22. package/build/commands/dev/utils/deeplink.js.map +1 -0
  23. package/build/commands/dev/utils/interactive-terminal.d.ts +23 -0
  24. package/build/commands/dev/utils/interactive-terminal.js +252 -0
  25. package/build/commands/dev/utils/interactive-terminal.js.map +1 -0
  26. package/build/commands/dev/utils/metro/metro-config.d.ts +2 -0
  27. package/build/commands/dev/utils/metro/metro-config.js +31 -0
  28. package/build/commands/dev/utils/metro/metro-config.js.map +1 -0
  29. package/build/commands/dev/utils/metro/metro-reporter.d.ts +14 -0
  30. package/build/commands/dev/utils/metro/metro-reporter.js +34 -0
  31. package/build/commands/dev/utils/metro/metro-reporter.js.map +1 -0
  32. package/build/commands/dev/utils/metro/metro-server-middleware.d.ts +6 -0
  33. package/build/commands/dev/utils/metro/metro-server-middleware.js +45 -0
  34. package/build/commands/dev/utils/metro/metro-server-middleware.js.map +1 -0
  35. package/build/commands/dev/utils/metro/metro-server.d.ts +2 -0
  36. package/build/commands/dev/utils/metro/metro-server.js +24 -0
  37. package/build/commands/dev/utils/metro/metro-server.js.map +1 -0
  38. package/build/commands/dev/utils/minis-manifest.d.ts +1 -0
  39. package/build/commands/dev/utils/minis-manifest.js +24 -0
  40. package/build/commands/dev/utils/minis-manifest.js.map +1 -0
  41. package/build/commands/dev/utils/qr-code.d.ts +1 -0
  42. package/build/commands/dev/utils/qr-code.js +12 -0
  43. package/build/commands/dev/utils/qr-code.js.map +1 -0
  44. package/build/commands/dev/utils/simulator.d.ts +19 -0
  45. package/build/commands/dev/utils/simulator.js +89 -0
  46. package/build/commands/dev/utils/simulator.js.map +1 -0
  47. package/build/commands/dev/utils/with-retries.d.ts +4 -0
  48. package/build/commands/dev/utils/with-retries.js +28 -0
  49. package/build/commands/dev/utils/with-retries.js.map +1 -0
  50. package/build/commands/generate-graphql-types/index.d.ts +5 -0
  51. package/build/commands/generate-graphql-types/index.js +90 -0
  52. package/build/commands/generate-graphql-types/index.js.map +1 -0
  53. package/build/commands/utils/exec-async-child-process.d.ts +18 -0
  54. package/build/commands/utils/exec-async-child-process.js +48 -0
  55. package/build/commands/utils/exec-async-child-process.js.map +1 -0
  56. package/build/commands/utils/wrap-with-loading-indicator.d.ts +9 -0
  57. package/build/commands/utils/wrap-with-loading-indicator.js +23 -0
  58. package/build/commands/utils/wrap-with-loading-indicator.js.map +1 -0
  59. package/build/dev-panel/images/bottomsheet.png +0 -0
  60. package/build/dev-panel/images/checkmark.svg +3 -0
  61. package/build/dev-panel/images/chevron.svg +3 -0
  62. package/build/dev-panel/images/copy.svg +4 -0
  63. package/build/dev-panel/images/get-started.svg +3 -0
  64. package/build/dev-panel/images/how-to.svg +3 -0
  65. package/build/dev-panel/images/navigation.png +0 -0
  66. package/build/dev-panel/images/references.svg +3 -0
  67. package/build/dev-panel/images/shop-minis-logo-inverse.svg +5 -0
  68. package/build/dev-panel/images/shop-minis-logo.svg +5 -0
  69. package/build/dev-panel/images/stories.png +0 -0
  70. package/build/dev-panel/images/topics.svg +3 -0
  71. package/build/dev-panel/index.html +302 -0
  72. package/build/dev-panel/middleware.d.ts +4 -0
  73. package/build/dev-panel/middleware.js +11 -0
  74. package/build/dev-panel/middleware.js.map +1 -0
  75. package/build/dev-panel/middleware.ts +6 -0
  76. package/build/dev-panel/styles.css +507 -0
  77. package/build/index.d.ts +2 -0
  78. package/build/index.js +26 -0
  79. package/build/index.js.map +1 -0
  80. package/package.json +83 -0
  81. package/templates/__template_blank/src/custom.d.ts +4 -0
  82. package/templates/__template_blank/src/index.tsx +9 -0
  83. package/templates/__template_blank/src/screens/HomeScreen.tsx +12 -0
  84. package/templates/__template_blank/src/types.ts +5 -0
  85. package/templates/__template_common/.eslintignore +1 -0
  86. package/templates/__template_common/.eslintrc.json +132 -0
  87. package/templates/__template_common/.prettierrc.json +8 -0
  88. package/templates/__template_common/babel.config.js +19 -0
  89. package/templates/__template_common/gitignore +3 -0
  90. package/templates/__template_common/index.tsx +43 -0
  91. package/templates/__template_common/metro.config.js +31 -0
  92. package/templates/__template_common/package.json +68 -0
  93. package/templates/__template_common/patches/react-native+0.68.5.patch +173 -0
  94. package/templates/__template_common/src/manifest.json +29 -0
  95. package/templates/__template_common/tsconfig.json +36 -0
  96. package/templates/__template_hello_world/src/assets/Modal-component-thumbnail.png +0 -0
  97. package/templates/__template_hello_world/src/assets/ProductCard-component-thumbnail.png +0 -0
  98. package/templates/__template_hello_world/src/assets/ProductLink-component-thumbnail.png +0 -0
  99. package/templates/__template_hello_world/src/assets/assets.d.ts +4 -0
  100. package/templates/__template_hello_world/src/assets/figma-logo.svg +14 -0
  101. package/templates/__template_hello_world/src/assets/shop-minis-logo.svg +7 -0
  102. package/templates/__template_hello_world/src/components/ButtonCTA.tsx +31 -0
  103. package/templates/__template_hello_world/src/components/ComponentLink.ts +70 -0
  104. package/templates/__template_hello_world/src/components/ComponentListItem.tsx +38 -0
  105. package/templates/__template_hello_world/src/components/FeaturedComponents.tsx +108 -0
  106. package/templates/__template_hello_world/src/components/Header.tsx +40 -0
  107. package/templates/__template_hello_world/src/data/Test.graphql +33 -0
  108. package/templates/__template_hello_world/src/data/Test.graphql.d.ts +114 -0
  109. package/templates/__template_hello_world/src/data/TestProducts.graphql +34 -0
  110. package/templates/__template_hello_world/src/data/TestProducts.graphql.d.ts +119 -0
  111. package/templates/__template_hello_world/src/index.tsx +9 -0
  112. package/templates/__template_hello_world/src/routes.tsx +107 -0
  113. package/templates/__template_hello_world/src/screens/AvatarScreen.tsx +95 -0
  114. package/templates/__template_hello_world/src/screens/BottomSheetScreen.tsx +711 -0
  115. package/templates/__template_hello_world/src/screens/ButtonsScreen.tsx +90 -0
  116. package/templates/__template_hello_world/src/screens/GridScreen.tsx +74 -0
  117. package/templates/__template_hello_world/src/screens/HomeScreen.tsx +70 -0
  118. package/templates/__template_hello_world/src/screens/IconsScreen.tsx +181 -0
  119. package/templates/__template_hello_world/src/screens/MediaScreen.tsx +130 -0
  120. package/templates/__template_hello_world/src/screens/ModalScreen.tsx +379 -0
  121. package/templates/__template_hello_world/src/screens/ProductCardGridScreen.tsx +68 -0
  122. package/templates/__template_hello_world/src/screens/ProductCardScreen.tsx +62 -0
  123. package/templates/__template_hello_world/src/screens/ProductLinkScreen.tsx +215 -0
  124. package/templates/__template_hello_world/src/screens/ProgressIndicatorScreen.tsx +77 -0
  125. package/templates/__template_hello_world/src/screens/QuantityPickerScreen.tsx +76 -0
  126. package/templates/__template_hello_world/src/screens/SpinnerScreen.tsx +63 -0
  127. package/templates/__template_hello_world/src/screens/TypographyScreen.tsx +274 -0
  128. package/templates/__template_hello_world/src/screens/WebViewScreen.tsx +42 -0
  129. package/templates/__template_hello_world/src/types.ts +25 -0
  130. package/templates/__template_snowboardz/src/assets/assets.d.ts +4 -0
  131. package/templates/__template_snowboardz/src/assets/circle-blue.svg +9 -0
  132. package/templates/__template_snowboardz/src/assets/circle-green.svg +9 -0
  133. package/templates/__template_snowboardz/src/assets/circle-purple.svg +9 -0
  134. package/templates/__template_snowboardz/src/assets/circle-rainbow.svg +34 -0
  135. package/templates/__template_snowboardz/src/assets/circle-red.svg +9 -0
  136. package/templates/__template_snowboardz/src/assets/circle-yellow.svg +9 -0
  137. package/templates/__template_snowboardz/src/assets/skill-level-icon-advanced.svg +3 -0
  138. package/templates/__template_snowboardz/src/assets/skill-level-icon-beginner.svg +3 -0
  139. package/templates/__template_snowboardz/src/assets/skill-level-icon-intermediate.svg +3 -0
  140. package/templates/__template_snowboardz/src/components/ColorButton.tsx +79 -0
  141. package/templates/__template_snowboardz/src/components/ColorPicker.tsx +40 -0
  142. package/templates/__template_snowboardz/src/components/EmptyResult.tsx +52 -0
  143. package/templates/__template_snowboardz/src/components/SkillLevelIcon.tsx +44 -0
  144. package/templates/__template_snowboardz/src/components/SkillLevelPicker.tsx +86 -0
  145. package/templates/__template_snowboardz/src/data/TestProducts.graphql +34 -0
  146. package/templates/__template_snowboardz/src/data/TestProducts.graphql.d.ts +108 -0
  147. package/templates/__template_snowboardz/src/hooks/useSnowboardData.tsx +37 -0
  148. package/templates/__template_snowboardz/src/index.tsx +9 -0
  149. package/templates/__template_snowboardz/src/routes.tsx +17 -0
  150. package/templates/__template_snowboardz/src/screens/HomeScreen.tsx +126 -0
  151. package/templates/__template_snowboardz/src/types.ts +12 -0
  152. package/templates/__template_snowboardz/src/utils.ts +17 -0
@@ -0,0 +1,86 @@
1
+ import {Box, Button, Text, useTheme} from '@shopify/shop-minis-platform-sdk'
2
+ import {ScrollView} from 'react-native-gesture-handler'
3
+
4
+ import {SkillLevel} from '../types'
5
+
6
+ import {SkillLevelIcon} from './SkillLevelIcon'
7
+
8
+ const skillLevels: SkillLevel[] = ['Beginner', 'Intermediate', 'Advanced']
9
+
10
+ interface SkillLevelButtonProps {
11
+ onPress: () => void
12
+ text: string
13
+ selected?: boolean
14
+ }
15
+ const SkillLevelButton = ({onPress, text, selected}: SkillLevelButtonProps) => {
16
+ const theme = useTheme()
17
+
18
+ const hasIcon = text !== 'All'
19
+
20
+ if (!hasIcon) {
21
+ return (
22
+ <Box>
23
+ <Button
24
+ size="m"
25
+ variant={selected ? 'primary' : 'tertiary'}
26
+ style={{
27
+ alignSelf: 'baseline',
28
+ marginRight: theme.spacing.xs,
29
+ paddingHorizontal: theme.spacing.s,
30
+ }}
31
+ text={text}
32
+ onPress={onPress}
33
+ />
34
+ </Box>
35
+ )
36
+ }
37
+ return (
38
+ <Box justifyContent="center">
39
+ <Button
40
+ size="m"
41
+ variant={selected ? 'primary' : 'tertiary'}
42
+ style={{
43
+ alignSelf: 'baseline',
44
+ marginRight: theme.spacing.xs,
45
+ paddingRight: theme.spacing.s,
46
+ paddingLeft: theme.spacing.xl,
47
+ }}
48
+ text={text}
49
+ onPress={onPress}
50
+ />
51
+ <SkillLevelIcon level={text as SkillLevel} />
52
+ </Box>
53
+ )
54
+ }
55
+
56
+ interface SkillLevelPickerProps {
57
+ handleSelectedSkillLevel: (
58
+ handleSelectedSkillLevel: SkillLevel | null
59
+ ) => void
60
+ selectedSkillLevel: SkillLevel | null
61
+ }
62
+ export const SkillLevelPicker = ({
63
+ handleSelectedSkillLevel,
64
+ selectedSkillLevel,
65
+ }: SkillLevelPickerProps) => {
66
+ return (
67
+ <>
68
+ <Text marginBottom="xs">Select skill level</Text>
69
+ <ScrollView horizontal showsHorizontalScrollIndicator={false}>
70
+ <SkillLevelButton
71
+ selected={!selectedSkillLevel}
72
+ text="All"
73
+ onPress={() => handleSelectedSkillLevel(null)}
74
+ />
75
+ {skillLevels.map(skillLevel => (
76
+ <SkillLevelButton
77
+ selected={selectedSkillLevel === skillLevel}
78
+ key={skillLevel}
79
+ text={skillLevel}
80
+ onPress={() => handleSelectedSkillLevel(skillLevel)}
81
+ />
82
+ ))}
83
+ </ScrollView>
84
+ </>
85
+ )
86
+ }
@@ -0,0 +1,34 @@
1
+ query __MINI_APP_HANDLE_PASCAL_CASE__TestProducts($shopId: ID!, $productIds: [ID!]!) {
2
+ shop(id: $shopId) {
3
+ id
4
+ name
5
+ productsByIds(ids: $productIds) {
6
+ id
7
+ title
8
+ tags
9
+ featuredImage {
10
+ id
11
+ altText
12
+ url
13
+ }
14
+ defaultVariant {
15
+ id
16
+ title
17
+ isFavorited
18
+ compareAtPrice {
19
+ amount
20
+ currencyCode
21
+ }
22
+ price {
23
+ amount
24
+ currencyCode
25
+ }
26
+ image {
27
+ id
28
+ altText
29
+ url
30
+ }
31
+ }
32
+ }
33
+ }
34
+ }
@@ -0,0 +1,108 @@
1
+ import { DocumentNode } from "graphql-typed";
2
+ import { URL, Decimal, CurrencyCode } from "../node_modules/@shopify/shop-minis-platform-sdk/src/api/types";
3
+ export namespace __MINI_APP_HANDLE_PASCAL_CASE__TestProductsQueryPartialData {
4
+ export interface ShopProductsByIdsFeaturedImage {
5
+ __typename?: "Image" | null;
6
+ id?: string | null;
7
+ altText?: string | null;
8
+ url?: URL | null;
9
+ }
10
+ export interface ShopProductsByIdsDefaultVariantCompareAtPrice {
11
+ __typename?: "Money" | null;
12
+ amount?: Decimal | null;
13
+ currencyCode?: CurrencyCode | null;
14
+ }
15
+ export interface ShopProductsByIdsDefaultVariantPrice {
16
+ __typename?: "Money" | null;
17
+ amount?: Decimal | null;
18
+ currencyCode?: CurrencyCode | null;
19
+ }
20
+ export interface ShopProductsByIdsDefaultVariantImage {
21
+ __typename?: "Image" | null;
22
+ id?: string | null;
23
+ altText?: string | null;
24
+ url?: URL | null;
25
+ }
26
+ export interface ShopProductsByIdsDefaultVariant {
27
+ __typename?: "ProductVariant" | null;
28
+ id?: string | null;
29
+ title?: string | null;
30
+ isFavorited?: boolean | null;
31
+ compareAtPrice?: __MINI_APP_HANDLE_PASCAL_CASE__TestProductsQueryPartialData.ShopProductsByIdsDefaultVariantCompareAtPrice | null;
32
+ price?: __MINI_APP_HANDLE_PASCAL_CASE__TestProductsQueryPartialData.ShopProductsByIdsDefaultVariantPrice | null;
33
+ image?: __MINI_APP_HANDLE_PASCAL_CASE__TestProductsQueryPartialData.ShopProductsByIdsDefaultVariantImage | null;
34
+ }
35
+ export interface ShopProductsByIds {
36
+ __typename?: "Product" | null;
37
+ id?: string | null;
38
+ title?: string | null;
39
+ tags?: (string | null)[] | null;
40
+ featuredImage?: __MINI_APP_HANDLE_PASCAL_CASE__TestProductsQueryPartialData.ShopProductsByIdsFeaturedImage | null;
41
+ defaultVariant?: __MINI_APP_HANDLE_PASCAL_CASE__TestProductsQueryPartialData.ShopProductsByIdsDefaultVariant | null;
42
+ }
43
+ export interface Shop {
44
+ __typename?: "Shop" | null;
45
+ id?: string | null;
46
+ name?: string | null;
47
+ productsByIds?: (__MINI_APP_HANDLE_PASCAL_CASE__TestProductsQueryPartialData.ShopProductsByIds | null)[] | null;
48
+ }
49
+ }
50
+ export interface __MINI_APP_HANDLE_PASCAL_CASE__TestProductsQueryPartialData {
51
+ shop?: __MINI_APP_HANDLE_PASCAL_CASE__TestProductsQueryPartialData.Shop | null;
52
+ }
53
+ export namespace __MINI_APP_HANDLE_PASCAL_CASE__TestProductsQueryData {
54
+ export interface Variables {
55
+ shopId: string;
56
+ productIds: string[];
57
+ }
58
+ export interface ShopProductsByIdsFeaturedImage {
59
+ __typename: "Image";
60
+ id?: string | null;
61
+ altText?: string | null;
62
+ url: URL;
63
+ }
64
+ export interface ShopProductsByIdsDefaultVariantCompareAtPrice {
65
+ __typename: "Money";
66
+ amount: Decimal;
67
+ currencyCode: CurrencyCode;
68
+ }
69
+ export interface ShopProductsByIdsDefaultVariantPrice {
70
+ __typename: "Money";
71
+ amount: Decimal;
72
+ currencyCode: CurrencyCode;
73
+ }
74
+ export interface ShopProductsByIdsDefaultVariantImage {
75
+ __typename: "Image";
76
+ id?: string | null;
77
+ altText?: string | null;
78
+ url: URL;
79
+ }
80
+ export interface ShopProductsByIdsDefaultVariant {
81
+ __typename: "ProductVariant";
82
+ id: string;
83
+ title: string;
84
+ isFavorited: boolean;
85
+ compareAtPrice?: __MINI_APP_HANDLE_PASCAL_CASE__TestProductsQueryData.ShopProductsByIdsDefaultVariantCompareAtPrice | null;
86
+ price: __MINI_APP_HANDLE_PASCAL_CASE__TestProductsQueryData.ShopProductsByIdsDefaultVariantPrice;
87
+ image?: __MINI_APP_HANDLE_PASCAL_CASE__TestProductsQueryData.ShopProductsByIdsDefaultVariantImage | null;
88
+ }
89
+ export interface ShopProductsByIds {
90
+ __typename: "Product";
91
+ id: string;
92
+ title: string;
93
+ tags: string[];
94
+ featuredImage?: __MINI_APP_HANDLE_PASCAL_CASE__TestProductsQueryData.ShopProductsByIdsFeaturedImage | null;
95
+ defaultVariant: __MINI_APP_HANDLE_PASCAL_CASE__TestProductsQueryData.ShopProductsByIdsDefaultVariant;
96
+ }
97
+ export interface Shop {
98
+ __typename: "Shop";
99
+ id: string;
100
+ name: string;
101
+ productsByIds: (__MINI_APP_HANDLE_PASCAL_CASE__TestProductsQueryData.ShopProductsByIds | null)[];
102
+ }
103
+ }
104
+ export interface __MINI_APP_HANDLE_PASCAL_CASE__TestProductsQueryData {
105
+ shop?: __MINI_APP_HANDLE_PASCAL_CASE__TestProductsQueryData.Shop | null;
106
+ }
107
+ declare const document: DocumentNode<__MINI_APP_HANDLE_PASCAL_CASE__TestProductsQueryData, __MINI_APP_HANDLE_PASCAL_CASE__TestProductsQueryData.Variables, __MINI_APP_HANDLE_PASCAL_CASE__TestProductsQueryPartialData>;
108
+ export default document;
@@ -0,0 +1,37 @@
1
+ import {useMinisQuery} from '@shopify/shop-minis-platform-sdk'
2
+
3
+ import TestProductsQuery from '../data/TestProducts.graphql'
4
+
5
+ const SHOP_GID = 'gid://shopify/Shop/68822335510'
6
+ const PRODUCT_GIDS = [
7
+ 'gid://shopify/Product/7982542651414',
8
+ 'gid://shopify/Product/7982528397334',
9
+ 'gid://shopify/Product/7982535704598',
10
+ 'gid://shopify/Product/7982577352726',
11
+ 'gid://shopify/Product/7982564245526',
12
+ 'gid://shopify/Product/7982547763222',
13
+ 'gid://shopify/Product/7982499495958',
14
+ 'gid://shopify/Product/7982540521494',
15
+ 'gid://shopify/Product/7982554710038',
16
+ 'gid://shopify/Product/7982557200406',
17
+ 'gid://shopify/Product/7982571257878',
18
+ 'gid://shopify/Product/7982372388886',
19
+ ]
20
+
21
+ export const useSnowboardData = () => {
22
+ const {loading, data, error} = useMinisQuery(TestProductsQuery, {
23
+ variables: {
24
+ shopId: SHOP_GID,
25
+ productIds: PRODUCT_GIDS,
26
+ },
27
+ fetchPolicy: 'cache-and-network',
28
+ })
29
+
30
+ const snowboards = data?.shop?.productsByIds ?? []
31
+
32
+ return {
33
+ snowboards,
34
+ loading,
35
+ error,
36
+ }
37
+ }
@@ -0,0 +1,9 @@
1
+ import {theme as defaultTheme, Theme} from '@shopify/shop-minis-platform-sdk'
2
+
3
+ import {__MINI_APP_HANDLE_PASCAL_CASE__Navigator} from './routes'
4
+
5
+ export const theme: Theme = {
6
+ ...defaultTheme,
7
+ }
8
+
9
+ export default __MINI_APP_HANDLE_PASCAL_CASE__Navigator
@@ -0,0 +1,17 @@
1
+ import {createNativeStackNavigator} from '@react-navigation/native-stack'
2
+
3
+ import {HomeScreen} from './screens/HomeScreen'
4
+
5
+ const Stack = createNativeStackNavigator()
6
+
7
+ export const __MINI_APP_HANDLE_PASCAL_CASE__Navigator = () => {
8
+ return (
9
+ <Stack.Navigator>
10
+ <Stack.Screen
11
+ name="__MINI_APP_HANDLE_PASCAL_CASE__.Home"
12
+ component={HomeScreen}
13
+ options={{title: 'Home', headerShown: false}}
14
+ />
15
+ </Stack.Navigator>
16
+ )
17
+ }
@@ -0,0 +1,126 @@
1
+ import {
2
+ Box,
3
+ ProductCard,
4
+ ProductCardGrid,
5
+ Spinner,
6
+ Text,
7
+ TouchableProduct,
8
+ useTheme,
9
+ } from '@shopify/shop-minis-platform-sdk'
10
+ import {useCallback, useState, useMemo} from 'react'
11
+ import {SafeAreaView} from 'react-native'
12
+
13
+ import {ColorPicker} from '../components/ColorPicker'
14
+ import {EmptyResult} from '../components/EmptyResult'
15
+ import {SkillLevelPicker} from '../components/SkillLevelPicker'
16
+ import {useSnowboardData} from '../hooks/useSnowboardData'
17
+ import {SkillLevel, SnowBoard} from '../types'
18
+ import {getSnowboardColors, getTagForColor, getTagForSkillLevel} from '../utils'
19
+
20
+ export const HomeScreen = () => {
21
+ const theme = useTheme()
22
+
23
+ const {snowboards, loading} = useSnowboardData()
24
+
25
+ const [selectedSkillLevel, setSelectedSkillLevel] =
26
+ useState<SkillLevel | null>(null)
27
+
28
+ const handleSelectedSkillLevel = useCallback(
29
+ (newSkillLevel: SkillLevel | null) => {
30
+ setSelectedSkillLevel(newSkillLevel)
31
+ },
32
+ []
33
+ )
34
+
35
+ const [selectedColor, setSelectedColor] = useState<string | null>(null)
36
+ const handleSelectedColor = useCallback((newColor: string | null) => {
37
+ setSelectedColor(newColor)
38
+ }, [])
39
+
40
+ const handleFilterReset = useCallback(() => {
41
+ setSelectedColor(null)
42
+ setSelectedSkillLevel(null)
43
+ }, [])
44
+
45
+ const snowBoardsToDisplay = useMemo(() => {
46
+ let filteredSnowboards = [...snowboards] as SnowBoard[]
47
+
48
+ if (selectedSkillLevel) {
49
+ filteredSnowboards = filteredSnowboards.filter(({tags}) =>
50
+ tags.includes(getTagForSkillLevel(selectedSkillLevel))
51
+ )
52
+ }
53
+
54
+ if (selectedColor) {
55
+ filteredSnowboards = filteredSnowboards.filter(({tags}) =>
56
+ tags.includes(getTagForColor(selectedColor))
57
+ )
58
+ }
59
+
60
+ return filteredSnowboards
61
+ }, [selectedColor, selectedSkillLevel, snowboards])
62
+
63
+ const listFooter = useMemo(() => {
64
+ if (loading) {
65
+ return (
66
+ <Box flex={1} justifyContent="center" alignItems="center">
67
+ <Spinner />
68
+ </Box>
69
+ )
70
+ }
71
+ if (snowBoardsToDisplay.length === 0) {
72
+ return (
73
+ <EmptyResult
74
+ selectedColor={selectedColor}
75
+ selectedSkillLevel={selectedSkillLevel}
76
+ handleFilterReset={handleFilterReset}
77
+ />
78
+ )
79
+ }
80
+ return null
81
+ }, [
82
+ handleFilterReset,
83
+ loading,
84
+ selectedColor,
85
+ selectedSkillLevel,
86
+ snowBoardsToDisplay.length,
87
+ ])
88
+
89
+ return (
90
+ <SafeAreaView style={{flex: 1}}>
91
+ <Box flex={1} backgroundColor="backgrounds-regular">
92
+ <ProductCardGrid
93
+ ListHeaderComponent={
94
+ <Box paddingBottom="m">
95
+ <Text variant="heroNormal" marginBottom="m">
96
+ Find your board
97
+ </Text>
98
+ <Box marginBottom="s">
99
+ <SkillLevelPicker
100
+ handleSelectedSkillLevel={handleSelectedSkillLevel}
101
+ selectedSkillLevel={selectedSkillLevel}
102
+ />
103
+ </Box>
104
+ <ColorPicker
105
+ handleSelectedColor={handleSelectedColor}
106
+ selectedColor={selectedColor}
107
+ snowboardColors={getSnowboardColors(snowboards as SnowBoard[])}
108
+ />
109
+ </Box>
110
+ }
111
+ products={snowBoardsToDisplay}
112
+ renderItem={({product}) => (
113
+ <TouchableProduct product={product} key={product.id}>
114
+ <ProductCard shopId="12" product={product} />
115
+ </TouchableProduct>
116
+ )}
117
+ contentContainerStyle={{
118
+ padding: theme.spacing.m,
119
+ marginBottom: theme.spacing.xxl,
120
+ }}
121
+ ListFooterComponent={listFooter}
122
+ />
123
+ </Box>
124
+ </SafeAreaView>
125
+ )
126
+ }
@@ -0,0 +1,12 @@
1
+ // @react-navigation/native-stack requires a `type` instead of an `interface`
2
+
3
+ import {__MINI_APP_HANDLE_PASCAL_CASE__TestProductsQueryData} from './data/TestProducts.graphql'
4
+
5
+ // eslint-disable-next-line @typescript-eslint/consistent-type-definitions
6
+ export type StackParamList = {
7
+ '__MINI_APP_HANDLE_PASCAL_CASE__.Home': undefined
8
+ }
9
+
10
+ export type SkillLevel = 'Beginner' | 'Intermediate' | 'Advanced'
11
+
12
+ export type SnowBoard = __MINI_APP_HANDLE_PASCAL_CASE__TestProductsQueryData.ShopProductsByIds
@@ -0,0 +1,17 @@
1
+ import {SkillLevel, SnowBoard} from './types'
2
+
3
+ export const getTagForSkillLevel = (skillLevel: SkillLevel) =>
4
+ `skill-level-${skillLevel.toLowerCase()}`
5
+
6
+ export const getTagForColor = (color: string) => `color-${color}`
7
+
8
+ const colorTagPrefix = 'color-'
9
+ export const getSnowboardColors = (snowboards: SnowBoard[]) => {
10
+ const allTags = snowboards.map(({tags}) => tags).flat()
11
+ const allColorsTags = allTags.filter(tag => tag.startsWith(colorTagPrefix))
12
+ const uniqueColorTags = [...new Set(allColorsTags)]
13
+
14
+ return uniqueColorTags.map(colorTag =>
15
+ colorTag.substring(colorTagPrefix.length)
16
+ )
17
+ }