@plusscommunities/pluss-feature-builder-app-d 1.0.1-beta.3

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 (118) hide show
  1. package/dist/module/actions/featureBuilderActions.js +106 -0
  2. package/dist/module/actions/featureBuilderActions.js.map +1 -0
  3. package/dist/module/actions/featureBuilderStringsActions.js +106 -0
  4. package/dist/module/actions/featureBuilderStringsActions.js.map +1 -0
  5. package/dist/module/actions/index.js +12 -0
  6. package/dist/module/actions/index.js.map +1 -0
  7. package/dist/module/actions/types.js +7 -0
  8. package/dist/module/actions/types.js.map +1 -0
  9. package/dist/module/components/FeatureDetailScreen.js +725 -0
  10. package/dist/module/components/FeatureDetailScreen.js.map +1 -0
  11. package/dist/module/components/FeatureListItem.js +174 -0
  12. package/dist/module/components/FeatureListItem.js.map +1 -0
  13. package/dist/module/components/FeatureListScreen.js +159 -0
  14. package/dist/module/components/FeatureListScreen.js.map +1 -0
  15. package/dist/module/components/FieldRenderer.js +218 -0
  16. package/dist/module/components/FieldRenderer.js.map +1 -0
  17. package/dist/module/components/FileDownload.js +74 -0
  18. package/dist/module/components/FileDownload.js.map +1 -0
  19. package/dist/module/components/WidgetGrid.js +158 -0
  20. package/dist/module/components/WidgetGrid.js.map +1 -0
  21. package/dist/module/components/WidgetLarge.js +274 -0
  22. package/dist/module/components/WidgetLarge.js.map +1 -0
  23. package/dist/module/components/WidgetSmall.js +315 -0
  24. package/dist/module/components/WidgetSmall.js.map +1 -0
  25. package/dist/module/components/common/index.js +25 -0
  26. package/dist/module/components/common/index.js.map +1 -0
  27. package/dist/module/components/layouts/CondensedList.js +195 -0
  28. package/dist/module/components/layouts/CondensedList.js.map +1 -0
  29. package/dist/module/components/layouts/FeatureImageList.js +172 -0
  30. package/dist/module/components/layouts/FeatureImageList.js.map +1 -0
  31. package/dist/module/components/layouts/RoundImageList.js +198 -0
  32. package/dist/module/components/layouts/RoundImageList.js.map +1 -0
  33. package/dist/module/components/layouts/SquareImageList.js +185 -0
  34. package/dist/module/components/layouts/SquareImageList.js.map +1 -0
  35. package/dist/module/config/index.js +10 -0
  36. package/dist/module/config/index.js.map +1 -0
  37. package/dist/module/core.config.js +17 -0
  38. package/dist/module/core.config.js.map +1 -0
  39. package/dist/module/feature.config.js +113 -0
  40. package/dist/module/feature.config.js.map +1 -0
  41. package/dist/module/index.js +24 -0
  42. package/dist/module/index.js.map +1 -0
  43. package/dist/module/js/Colors.js +25 -0
  44. package/dist/module/js/Colors.js.map +1 -0
  45. package/dist/module/js/FieldTypes.js +123 -0
  46. package/dist/module/js/FieldTypes.js.map +1 -0
  47. package/dist/module/js/NavigationService.js +10 -0
  48. package/dist/module/js/NavigationService.js.map +1 -0
  49. package/dist/module/js/Styles.js +3 -0
  50. package/dist/module/js/Styles.js.map +1 -0
  51. package/dist/module/js/helpers.js +29 -0
  52. package/dist/module/js/helpers.js.map +1 -0
  53. package/dist/module/js/index.js +24 -0
  54. package/dist/module/js/index.js.map +1 -0
  55. package/dist/module/js/spacing.js +29 -0
  56. package/dist/module/js/spacing.js.map +1 -0
  57. package/dist/module/js/types.js +254 -0
  58. package/dist/module/js/types.js.map +1 -0
  59. package/dist/module/reducers/featureBuilderReducer.js +75 -0
  60. package/dist/module/reducers/featureBuilderReducer.js.map +1 -0
  61. package/dist/module/utils/featureSelectors.js +9 -0
  62. package/dist/module/utils/featureSelectors.js.map +1 -0
  63. package/dist/module/values.config.a.js +96 -0
  64. package/dist/module/values.config.a.js.map +1 -0
  65. package/dist/module/values.config.b.js +96 -0
  66. package/dist/module/values.config.b.js.map +1 -0
  67. package/dist/module/values.config.c.js +96 -0
  68. package/dist/module/values.config.c.js.map +1 -0
  69. package/dist/module/values.config.d.js +96 -0
  70. package/dist/module/values.config.d.js.map +1 -0
  71. package/dist/module/values.config.js +96 -0
  72. package/dist/module/values.config.js.map +1 -0
  73. package/dist/module/webapi/featureBuilderAPI.js +59 -0
  74. package/dist/module/webapi/featureBuilderAPI.js.map +1 -0
  75. package/dist/module/webapi/helper.js +4 -0
  76. package/dist/module/webapi/helper.js.map +1 -0
  77. package/dist/module/webapi/index.js +8 -0
  78. package/dist/module/webapi/index.js.map +1 -0
  79. package/package.json +62 -0
  80. package/src/actions/featureBuilderActions.js +112 -0
  81. package/src/actions/featureBuilderStringsActions.js +114 -0
  82. package/src/actions/index.js +12 -0
  83. package/src/actions/types.js +7 -0
  84. package/src/components/FeatureDetailScreen.js +817 -0
  85. package/src/components/FeatureListItem.js +198 -0
  86. package/src/components/FeatureListScreen.js +160 -0
  87. package/src/components/FieldRenderer.js +272 -0
  88. package/src/components/FileDownload.js +79 -0
  89. package/src/components/WidgetGrid.js +181 -0
  90. package/src/components/WidgetLarge.js +305 -0
  91. package/src/components/WidgetSmall.js +344 -0
  92. package/src/components/common/index.js +25 -0
  93. package/src/components/layouts/CondensedList.js +230 -0
  94. package/src/components/layouts/FeatureImageList.js +193 -0
  95. package/src/components/layouts/RoundImageList.js +219 -0
  96. package/src/components/layouts/SquareImageList.js +205 -0
  97. package/src/config/index.js +10 -0
  98. package/src/core.config.js +29 -0
  99. package/src/feature.config.js +127 -0
  100. package/src/index.js +27 -0
  101. package/src/js/Colors.js +30 -0
  102. package/src/js/FieldTypes.js +131 -0
  103. package/src/js/NavigationService.js +12 -0
  104. package/src/js/Styles.js +3 -0
  105. package/src/js/helpers.js +30 -0
  106. package/src/js/index.js +24 -0
  107. package/src/js/spacing.js +30 -0
  108. package/src/js/types.js +253 -0
  109. package/src/reducers/featureBuilderReducer.js +64 -0
  110. package/src/utils/featureSelectors.js +8 -0
  111. package/src/values.config.a.js +104 -0
  112. package/src/values.config.b.js +104 -0
  113. package/src/values.config.c.js +104 -0
  114. package/src/values.config.d.js +104 -0
  115. package/src/values.config.js +104 -0
  116. package/src/webapi/featureBuilderAPI.js +65 -0
  117. package/src/webapi/helper.js +4 -0
  118. package/src/webapi/index.js +8 -0
@@ -0,0 +1,274 @@
1
+ function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
2
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
3
+ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
4
+ import React, { Component } from "react";
5
+ import { Text, View, ScrollView, StyleSheet, TouchableOpacity, Image } from "react-native";
6
+ import { connect } from "react-redux";
7
+ import _ from "lodash";
8
+ import { Icon } from "react-native-elements";
9
+ import { Services } from "../feature.config";
10
+ import { Components, Colours } from "../core.config";
11
+ import { values } from "../values.config";
12
+ import { selectListings, selectFeatureDefinition } from "../reducers/featureBuilderReducer";
13
+ import { SPACING } from "../js/spacing";
14
+ import { getMainBrandingColourFromState } from "../js";
15
+ import { getSummaryFieldValue } from "../js/helpers";
16
+ class WidgetLarge extends Component {
17
+ constructor(props) {
18
+ super(props);
19
+ _defineProperty(this, "getTitle", () => {
20
+ const {
21
+ options,
22
+ featureDefinition
23
+ } = this.props;
24
+ if (options && !_.isEmpty(options.Title)) return options.Title;
25
+ // Use feature definition title
26
+ if (featureDefinition !== null && featureDefinition !== void 0 && featureDefinition.title || featureDefinition !== null && featureDefinition !== void 0 && featureDefinition.displayName) {
27
+ return featureDefinition.title || featureDefinition.displayName;
28
+ }
29
+ return values.featureName || "Custom Features";
30
+ });
31
+ _defineProperty(this, "getEmptyStateText", () => {
32
+ const {
33
+ options
34
+ } = this.props;
35
+ if (options && !_.isEmpty(options.EmptyText)) return options.EmptyText;
36
+ return "No custom features available";
37
+ });
38
+ _defineProperty(this, "refresh", () => {
39
+ this.onLoadingChanged(true, async () => {
40
+ try {
41
+ const {
42
+ initializeFeatureBuilder
43
+ } = await import("../actions/featureBuilderActions");
44
+ await initializeFeatureBuilder()(this.props.dispatch, () => this.props.getState);
45
+ } finally {
46
+ this.onLoadingChanged(false);
47
+ }
48
+ });
49
+ });
50
+ _defineProperty(this, "onLoadingChanged", (loading, callback) => {
51
+ this.setState({
52
+ loading
53
+ }, () => {
54
+ if (this.props.onLoadingChanged) this.props.onLoadingChanged(this.state.loading);
55
+ if (callback) callback();
56
+ });
57
+ });
58
+ _defineProperty(this, "getImageSource", imageField => {
59
+ if (!imageField) return null;
60
+ if (typeof imageField === "string") {
61
+ return {
62
+ uri: imageField
63
+ };
64
+ }
65
+ if (typeof imageField === "object" && imageField.uri) {
66
+ return imageField;
67
+ }
68
+ if (typeof imageField === "object" && imageField.url) {
69
+ return {
70
+ uri: imageField.url
71
+ };
72
+ }
73
+ return null;
74
+ });
75
+ _defineProperty(this, "onListingPress", listing => {
76
+ const {
77
+ featureDefinition
78
+ } = this.props;
79
+ const title = this.getTitle();
80
+ Services.navigation.navigate(values.screens.featureDetail, {
81
+ listing: listing,
82
+ featureDefinition: featureDefinition,
83
+ featureTitle: title
84
+ });
85
+ });
86
+ _defineProperty(this, "renderListingCard", listing => {
87
+ var _listing$fields, _listing$fields2;
88
+ const {
89
+ colourBrandingMain,
90
+ featureDefinition
91
+ } = this.props;
92
+ const title = ((_listing$fields = listing.fields) === null || _listing$fields === void 0 ? void 0 : _listing$fields[values.mandatoryFields.title]) || "Untitled";
93
+ const summary = getSummaryFieldValue(listing, featureDefinition);
94
+ const imageField = (_listing$fields2 = listing.fields) === null || _listing$fields2 === void 0 ? void 0 : _listing$fields2[values.mandatoryFields.featureImage];
95
+ const imageSource = this.getImageSource(imageField);
96
+ return /*#__PURE__*/React.createElement(TouchableOpacity, {
97
+ key: listing.id,
98
+ style: styles.listItem,
99
+ onPress: () => this.onListingPress(listing)
100
+ }, /*#__PURE__*/React.createElement(View, {
101
+ style: styles.avatarContainer
102
+ }, imageSource ? /*#__PURE__*/React.createElement(Image, {
103
+ source: imageSource,
104
+ style: styles.avatar,
105
+ resizeMode: "cover"
106
+ }) : /*#__PURE__*/React.createElement(View, {
107
+ style: [styles.avatar, styles.placeholderAvatar]
108
+ }, /*#__PURE__*/React.createElement(Icon, {
109
+ name: "image",
110
+ type: "font-awesome",
111
+ size: 16,
112
+ color: Colours.TEXT_LIGHT
113
+ }))), /*#__PURE__*/React.createElement(View, {
114
+ style: styles.textContainer
115
+ }, /*#__PURE__*/React.createElement(Text, {
116
+ style: styles.titleText,
117
+ numberOfLines: 1
118
+ }, title), summary && /*#__PURE__*/React.createElement(Text, {
119
+ style: styles.descriptionText,
120
+ numberOfLines: 1
121
+ }, summary)), /*#__PURE__*/React.createElement(View, {
122
+ style: styles.chevronContainer
123
+ }, /*#__PURE__*/React.createElement(Icon, {
124
+ name: "chevron-right",
125
+ type: "font-awesome",
126
+ size: 14,
127
+ color: Colours.TEXT_LIGHT
128
+ })));
129
+ });
130
+ this.state = {
131
+ loading: false
132
+ };
133
+ }
134
+ componentDidMount() {
135
+ this.refresh();
136
+ }
137
+ componentDidUpdate(prevProps) {
138
+ if (!prevProps.dataUpdated && this.props.dataUpdated) {
139
+ this.refresh();
140
+ }
141
+ }
142
+ renderContent() {
143
+ const {
144
+ listings
145
+ } = this.props;
146
+
147
+ // Don't render widget if no listings are available (and not loading)
148
+ if (_.isEmpty(listings) && !this.state.loading) {
149
+ return null;
150
+ }
151
+ if (_.isEmpty(listings)) {
152
+ if (this.state.loading) {
153
+ return /*#__PURE__*/React.createElement(View, {
154
+ style: styles.loadingPadding
155
+ }, /*#__PURE__*/React.createElement(Components.LoadingStateWidget, {
156
+ height: 300
157
+ }));
158
+ }
159
+ return null;
160
+ }
161
+ return /*#__PURE__*/React.createElement(ScrollView, {
162
+ contentContainerStyle: styles.featuresContainer,
163
+ showsVerticalScrollIndicator: false
164
+ }, listings.map(listing => this.renderListingCard(listing)));
165
+ }
166
+ render() {
167
+ const {
168
+ colourBrandingMain
169
+ } = this.props;
170
+ const content = this.renderContent();
171
+ // Don't render widget section if content is null (no features available)
172
+ if (content === null) {
173
+ return null;
174
+ }
175
+ return /*#__PURE__*/React.createElement(View, {
176
+ style: styles.sectionContainer
177
+ }, /*#__PURE__*/React.createElement(View, {
178
+ style: styles.sectionPadding
179
+ }, /*#__PURE__*/React.createElement(View, {
180
+ style: styles.sectionHeading
181
+ }, /*#__PURE__*/React.createElement(Text, {
182
+ style: styles.sectionTitle
183
+ }, this.getTitle()))), content);
184
+ }
185
+ }
186
+ const styles = StyleSheet.create({
187
+ sectionContainer: {
188
+ backgroundColor: "#fff",
189
+ flex: 1
190
+ },
191
+ sectionPadding: {
192
+ paddingHorizontal: SPACING.MD,
193
+ paddingBottom: SPACING.XS + 2,
194
+ paddingTop: SPACING.MD
195
+ },
196
+ loadingPadding: {
197
+ paddingHorizontal: SPACING.MD
198
+ },
199
+ sectionHeading: {
200
+ marginBottom: SPACING.MD
201
+ },
202
+ sectionTitle: {
203
+ fontFamily: "sf-bold",
204
+ fontSize: 24,
205
+ color: "#000"
206
+ },
207
+ featuresContainer: {
208
+ paddingHorizontal: SPACING.MD,
209
+ paddingBottom: SPACING.MD
210
+ },
211
+ // Listing item styles (similar to CondensedListItem)
212
+ listItem: {
213
+ flexDirection: "row",
214
+ alignItems: "center",
215
+ paddingHorizontal: 16,
216
+ paddingVertical: 8,
217
+ backgroundColor: "#fff"
218
+ },
219
+ avatarContainer: {
220
+ width: 40,
221
+ height: 40,
222
+ borderRadius: 20,
223
+ marginRight: 12
224
+ },
225
+ avatar: {
226
+ width: 40,
227
+ height: 40,
228
+ borderRadius: 20,
229
+ backgroundColor: Colours.BACKGROUND_LIGHT || "#f0f0f0"
230
+ },
231
+ placeholderAvatar: {
232
+ backgroundColor: Colours.BACKGROUND_LIGHT || "#f0f0f0",
233
+ justifyContent: "center",
234
+ alignItems: "center"
235
+ },
236
+ textContainer: {
237
+ flex: 1,
238
+ justifyContent: "center"
239
+ },
240
+ titleText: {
241
+ fontFamily: "sf-semibold",
242
+ fontSize: 16,
243
+ color: Colours.TEXT_DARK || "#333",
244
+ marginBottom: 2
245
+ },
246
+ descriptionText: {
247
+ fontFamily: "sf-regular",
248
+ fontSize: 14,
249
+ color: Colours.TEXT_LIGHT || "#666",
250
+ lineHeight: 18
251
+ },
252
+ chevronContainer: {
253
+ paddingLeft: 8
254
+ }
255
+ });
256
+ const mapStateToProps = state => {
257
+ var _state$strings;
258
+ const {
259
+ user,
260
+ notifications
261
+ } = state;
262
+ return {
263
+ colourBrandingMain: getMainBrandingColourFromState(state),
264
+ listings: selectListings(state),
265
+ featureDefinition: selectFeatureDefinition(state),
266
+ site: user.site,
267
+ dataUpdated: notifications.dataUpdated[values.notificationKey],
268
+ strings: ((_state$strings = state.strings) === null || _state$strings === void 0 ? void 0 : _state$strings.config) || {}
269
+ };
270
+ };
271
+ export default connect(mapStateToProps, null, null, {
272
+ forwardRef: true
273
+ })(WidgetLarge);
274
+ //# sourceMappingURL=WidgetLarge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["React","Component","Text","View","ScrollView","StyleSheet","TouchableOpacity","Image","connect","_","Icon","Services","Components","Colours","values","selectListings","selectFeatureDefinition","SPACING","getMainBrandingColourFromState","getSummaryFieldValue","WidgetLarge","constructor","props","_defineProperty","options","featureDefinition","isEmpty","Title","title","displayName","featureName","EmptyText","onLoadingChanged","initializeFeatureBuilder","dispatch","getState","loading","callback","setState","state","imageField","uri","url","listing","getTitle","navigation","navigate","screens","featureDetail","featureTitle","_listing$fields","_listing$fields2","colourBrandingMain","fields","mandatoryFields","summary","featureImage","imageSource","getImageSource","createElement","key","id","style","styles","listItem","onPress","onListingPress","avatarContainer","source","avatar","resizeMode","placeholderAvatar","name","type","size","color","TEXT_LIGHT","textContainer","titleText","numberOfLines","descriptionText","chevronContainer","componentDidMount","refresh","componentDidUpdate","prevProps","dataUpdated","renderContent","listings","loadingPadding","LoadingStateWidget","height","contentContainerStyle","featuresContainer","showsVerticalScrollIndicator","map","renderListingCard","render","content","sectionContainer","sectionPadding","sectionHeading","sectionTitle","create","backgroundColor","flex","paddingHorizontal","MD","paddingBottom","XS","paddingTop","marginBottom","fontFamily","fontSize","flexDirection","alignItems","paddingVertical","width","borderRadius","marginRight","BACKGROUND_LIGHT","justifyContent","TEXT_DARK","lineHeight","paddingLeft","mapStateToProps","_state$strings","user","notifications","site","notificationKey","strings","config","forwardRef"],"sources":["WidgetLarge.js"],"sourcesContent":["import React, { Component } from \"react\";\nimport {\n\tText,\n\tView,\n\tScrollView,\n\tStyleSheet,\n\tTouchableOpacity,\n\tImage,\n} from \"react-native\";\nimport { connect } from \"react-redux\";\nimport _ from \"lodash\";\nimport { Icon } from \"react-native-elements\";\nimport { Services } from \"../feature.config\";\nimport { Components, Colours } from \"../core.config\";\nimport { values } from \"../values.config\";\nimport { selectListings, selectFeatureDefinition } from \"../reducers/featureBuilderReducer\";\nimport { SPACING } from \"../js/spacing\";\nimport { getMainBrandingColourFromState } from \"../js\";\nimport { getSummaryFieldValue } from \"../js/helpers\";\n\nclass WidgetLarge extends Component {\n\tconstructor(props) {\n\t\tsuper(props);\n\t\tthis.state = { loading: false };\n\t}\n\n\tcomponentDidMount() {\n\t\tthis.refresh();\n\t}\n\n\tcomponentDidUpdate(prevProps) {\n\t\tif (!prevProps.dataUpdated && this.props.dataUpdated) {\n\t\t\tthis.refresh();\n\t\t}\n\t}\n\n\tgetTitle = () => {\n\t\tconst { options, featureDefinition } = this.props;\n\t\tif (options && !_.isEmpty(options.Title)) return options.Title;\n\t\t// Use feature definition title\n\t\tif (\n\t\t\tfeatureDefinition?.title ||\n\t\t\tfeatureDefinition?.displayName\n\t\t) {\n\t\t\treturn (\n\t\t\t\tfeatureDefinition.title || featureDefinition.displayName\n\t\t\t);\n\t\t}\n\t\treturn values.featureName || \"Custom Features\";\n\t};\n\n\tgetEmptyStateText = () => {\n\t\tconst { options } = this.props;\n\t\tif (options && !_.isEmpty(options.EmptyText)) return options.EmptyText;\n\t\treturn \"No custom features available\";\n\t};\n\n\trefresh = () => {\n\t\tthis.onLoadingChanged(true, async () => {\n\t\t\ttry {\n\t\t\t\tconst { initializeFeatureBuilder } = await import(\n\t\t\t\t\t\"../actions/featureBuilderActions\"\n\t\t\t\t);\n\t\t\t\tawait initializeFeatureBuilder()(\n\t\t\t\t\tthis.props.dispatch,\n\t\t\t\t\t() => this.props.getState,\n\t\t\t\t);\n\t\t\t} finally {\n\t\t\t\tthis.onLoadingChanged(false);\n\t\t\t}\n\t\t});\n\t};\n\n\tonLoadingChanged = (loading, callback) => {\n\t\tthis.setState({ loading }, () => {\n\t\t\tif (this.props.onLoadingChanged)\n\t\t\t\tthis.props.onLoadingChanged(this.state.loading);\n\t\t\tif (callback) callback();\n\t\t});\n\t};\n\n\tgetImageSource = (imageField) => {\n\t\tif (!imageField) return null;\n\n\t\tif (typeof imageField === \"string\") {\n\t\t\treturn { uri: imageField };\n\t\t}\n\n\t\tif (typeof imageField === \"object\" && imageField.uri) {\n\t\t\treturn imageField;\n\t\t}\n\n\t\tif (typeof imageField === \"object\" && imageField.url) {\n\t\t\treturn { uri: imageField.url };\n\t\t}\n\n\t\treturn null;\n\t};\n\n\tonListingPress = (listing) => {\n\t\tconst { featureDefinition } = this.props;\n\t\tconst title = this.getTitle();\n\t\tServices.navigation.navigate(values.screens.featureDetail, {\n\t\t\tlisting: listing,\n\t\t\tfeatureDefinition: featureDefinition,\n\t\t\tfeatureTitle: title,\n\t\t});\n\t};\n\n\trenderListingCard = (listing) => {\n\t\tconst { colourBrandingMain, featureDefinition } = this.props;\n\t\tconst title = listing.fields?.[values.mandatoryFields.title] || \"Untitled\";\n\t\tconst summary = getSummaryFieldValue(listing, featureDefinition);\n\t\tconst imageField = listing.fields?.[values.mandatoryFields.featureImage];\n\t\tconst imageSource = this.getImageSource(imageField);\n\n\t\treturn (\n\t\t\t<TouchableOpacity\n\t\t\t\tkey={listing.id}\n\t\t\t\tstyle={styles.listItem}\n\t\t\t\tonPress={() => this.onListingPress(listing)}\n\t\t\t>\n\t\t\t\t{/* Small circular avatar image */}\n\t\t\t\t<View style={styles.avatarContainer}>\n\t\t\t\t\t{imageSource ? (\n\t\t\t\t\t\t<Image\n\t\t\t\t\t\t\tsource={imageSource}\n\t\t\t\t\t\t\tstyle={styles.avatar}\n\t\t\t\t\t\t\tresizeMode=\"cover\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<View style={[styles.avatar, styles.placeholderAvatar]}>\n\t\t\t\t\t\t\t<Icon\n\t\t\t\t\t\t\t\tname=\"image\"\n\t\t\t\t\t\t\t\ttype=\"font-awesome\"\n\t\t\t\t\t\t\t\tsize={16}\n\t\t\t\t\t\t\t\tcolor={Colours.TEXT_LIGHT}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</View>\n\t\t\t\t\t)}\n\t\t\t\t</View>\n\n\t\t\t\t{/* Text content */}\n\t\t\t\t<View style={styles.textContainer}>\n\t\t\t\t\t<Text style={styles.titleText} numberOfLines={1}>\n\t\t\t\t\t\t{title}\n\t\t\t\t\t</Text>\n\t\t\t\t\t{summary && (\n\t\t\t\t\t\t<Text style={styles.descriptionText} numberOfLines={1}>\n\t\t\t\t\t\t\t{summary}\n\t\t\t\t\t\t</Text>\n\t\t\t\t\t)}\n\t\t\t\t</View>\n\n\t\t\t\t{/* Chevron icon */}\n\t\t\t\t<View style={styles.chevronContainer}>\n\t\t\t\t\t<Icon\n\t\t\t\t\t\tname=\"chevron-right\"\n\t\t\t\t\t\ttype=\"font-awesome\"\n\t\t\t\t\t\tsize={14}\n\t\t\t\t\t\tcolor={Colours.TEXT_LIGHT}\n\t\t\t\t\t/>\n\t\t\t\t</View>\n\t\t\t</TouchableOpacity>\n\t\t);\n\t};\n\n\trenderContent() {\n\t\tconst { listings } = this.props;\n\n\t\t// Don't render widget if no listings are available (and not loading)\n\t\tif (_.isEmpty(listings) && !this.state.loading) {\n\t\t\treturn null;\n\t\t}\n\n\t\tif (_.isEmpty(listings)) {\n\t\t\tif (this.state.loading) {\n\t\t\t\treturn (\n\t\t\t\t\t<View style={styles.loadingPadding}>\n\t\t\t\t\t\t<Components.LoadingStateWidget height={300} />\n\t\t\t\t\t</View>\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\n\t\treturn (\n\t\t\t<ScrollView\n\t\t\t\tcontentContainerStyle={styles.featuresContainer}\n\t\t\t\tshowsVerticalScrollIndicator={false}\n\t\t\t>\n\t\t\t\t{listings.map((listing) => this.renderListingCard(listing))}\n\t\t\t</ScrollView>\n\t\t);\n\t}\n\n\trender() {\n\t\tconst { colourBrandingMain } = this.props;\n\n\t\tconst content = this.renderContent();\n\t\t// Don't render widget section if content is null (no features available)\n\t\tif (content === null) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn (\n\t\t\t<View style={styles.sectionContainer}>\n\t\t\t\t<View style={styles.sectionPadding}>\n\t\t\t\t\t<View style={styles.sectionHeading}>\n\t\t\t\t\t\t<Text style={styles.sectionTitle}>{this.getTitle()}</Text>\n\t\t\t\t\t</View>\n\t\t\t\t</View>\n\t\t\t\t{content}\n\t\t\t</View>\n\t\t);\n\t}\n}\n\nconst styles = StyleSheet.create({\n\tsectionContainer: {\n\t\tbackgroundColor: \"#fff\",\n\t\tflex: 1,\n\t},\n\tsectionPadding: {\n\t\tpaddingHorizontal: SPACING.MD,\n\t\tpaddingBottom: SPACING.XS + 2,\n\t\tpaddingTop: SPACING.MD,\n\t},\n\tloadingPadding: {\n\t\tpaddingHorizontal: SPACING.MD,\n\t},\n\tsectionHeading: {\n\t\tmarginBottom: SPACING.MD,\n\t},\n\tsectionTitle: {\n\t\tfontFamily: \"sf-bold\",\n\t\tfontSize: 24,\n\t\tcolor: \"#000\",\n\t},\n\tfeaturesContainer: {\n\t\tpaddingHorizontal: SPACING.MD,\n\t\tpaddingBottom: SPACING.MD,\n\t},\n\t// Listing item styles (similar to CondensedListItem)\n\tlistItem: {\n\t\tflexDirection: \"row\",\n\t\talignItems: \"center\",\n\t\tpaddingHorizontal: 16,\n\t\tpaddingVertical: 8,\n\t\tbackgroundColor: \"#fff\",\n\t},\n\tavatarContainer: {\n\t\twidth: 40,\n\t\theight: 40,\n\t\tborderRadius: 20,\n\t\tmarginRight: 12,\n\t},\n\tavatar: {\n\t\twidth: 40,\n\t\theight: 40,\n\t\tborderRadius: 20,\n\t\tbackgroundColor: Colours.BACKGROUND_LIGHT || \"#f0f0f0\",\n\t},\n\tplaceholderAvatar: {\n\t\tbackgroundColor: Colours.BACKGROUND_LIGHT || \"#f0f0f0\",\n\t\tjustifyContent: \"center\",\n\t\talignItems: \"center\",\n\t},\n\ttextContainer: {\n\t\tflex: 1,\n\t\tjustifyContent: \"center\",\n\t},\n\ttitleText: {\n\t\tfontFamily: \"sf-semibold\",\n\t\tfontSize: 16,\n\t\tcolor: Colours.TEXT_DARK || \"#333\",\n\t\tmarginBottom: 2,\n\t},\n\tdescriptionText: {\n\t\tfontFamily: \"sf-regular\",\n\t\tfontSize: 14,\n\t\tcolor: Colours.TEXT_LIGHT || \"#666\",\n\t\tlineHeight: 18,\n\t},\n\tchevronContainer: {\n\t\tpaddingLeft: 8,\n\t},\n});\n\nconst mapStateToProps = (state) => {\n\tconst { user, notifications } = state;\n\n\treturn {\n\t\tcolourBrandingMain: getMainBrandingColourFromState(state),\n\t\tlistings: selectListings(state),\n\t\tfeatureDefinition: selectFeatureDefinition(state),\n\t\tsite: user.site,\n\t\tdataUpdated: notifications.dataUpdated[values.notificationKey],\n\t\tstrings: state.strings?.config || {},\n\t};\n};\n\nexport default connect(mapStateToProps, null, null, { forwardRef: true })(\n\tWidgetLarge,\n);\n"],"mappings":";;;AAAA,OAAOA,KAAK,IAAIC,SAAS,QAAQ,OAAO;AACxC,SACCC,IAAI,EACJC,IAAI,EACJC,UAAU,EACVC,UAAU,EACVC,gBAAgB,EAChBC,KAAK,QACC,cAAc;AACrB,SAASC,OAAO,QAAQ,aAAa;AACrC,OAAOC,CAAC,MAAM,QAAQ;AACtB,SAASC,IAAI,QAAQ,uBAAuB;AAC5C,SAASC,QAAQ,QAAQ,mBAAmB;AAC5C,SAASC,UAAU,EAAEC,OAAO,QAAQ,gBAAgB;AACpD,SAASC,MAAM,QAAQ,kBAAkB;AACzC,SAASC,cAAc,EAAEC,uBAAuB,QAAQ,mCAAmC;AAC3F,SAASC,OAAO,QAAQ,eAAe;AACvC,SAASC,8BAA8B,QAAQ,OAAO;AACtD,SAASC,oBAAoB,QAAQ,eAAe;AAEpD,MAAMC,WAAW,SAASnB,SAAS,CAAC;EACnCoB,WAAWA,CAACC,KAAK,EAAE;IAClB,KAAK,CAACA,KAAK,CAAC;IAACC,eAAA,mBAcH,MAAM;MAChB,MAAM;QAAEC,OAAO;QAAEC;MAAkB,CAAC,GAAG,IAAI,CAACH,KAAK;MACjD,IAAIE,OAAO,IAAI,CAACf,CAAC,CAACiB,OAAO,CAACF,OAAO,CAACG,KAAK,CAAC,EAAE,OAAOH,OAAO,CAACG,KAAK;MAC9D;MACA,IACCF,iBAAiB,aAAjBA,iBAAiB,eAAjBA,iBAAiB,CAAEG,KAAK,IACxBH,iBAAiB,aAAjBA,iBAAiB,eAAjBA,iBAAiB,CAAEI,WAAW,EAC7B;QACD,OACCJ,iBAAiB,CAACG,KAAK,IAAIH,iBAAiB,CAACI,WAAW;MAE1D;MACA,OAAOf,MAAM,CAACgB,WAAW,IAAI,iBAAiB;IAC/C,CAAC;IAAAP,eAAA,4BAEmB,MAAM;MACzB,MAAM;QAAEC;MAAQ,CAAC,GAAG,IAAI,CAACF,KAAK;MAC9B,IAAIE,OAAO,IAAI,CAACf,CAAC,CAACiB,OAAO,CAACF,OAAO,CAACO,SAAS,CAAC,EAAE,OAAOP,OAAO,CAACO,SAAS;MACtE,OAAO,8BAA8B;IACtC,CAAC;IAAAR,eAAA,kBAES,MAAM;MACf,IAAI,CAACS,gBAAgB,CAAC,IAAI,EAAE,YAAY;QACvC,IAAI;UACH,MAAM;YAAEC;UAAyB,CAAC,GAAG,MAAM,MAAM,CAChD,kCACD,CAAC;UACD,MAAMA,wBAAwB,CAAC,CAAC,CAC/B,IAAI,CAACX,KAAK,CAACY,QAAQ,EACnB,MAAM,IAAI,CAACZ,KAAK,CAACa,QAClB,CAAC;QACF,CAAC,SAAS;UACT,IAAI,CAACH,gBAAgB,CAAC,KAAK,CAAC;QAC7B;MACD,CAAC,CAAC;IACH,CAAC;IAAAT,eAAA,2BAEkB,CAACa,OAAO,EAAEC,QAAQ,KAAK;MACzC,IAAI,CAACC,QAAQ,CAAC;QAAEF;MAAQ,CAAC,EAAE,MAAM;QAChC,IAAI,IAAI,CAACd,KAAK,CAACU,gBAAgB,EAC9B,IAAI,CAACV,KAAK,CAACU,gBAAgB,CAAC,IAAI,CAACO,KAAK,CAACH,OAAO,CAAC;QAChD,IAAIC,QAAQ,EAAEA,QAAQ,CAAC,CAAC;MACzB,CAAC,CAAC;IACH,CAAC;IAAAd,eAAA,yBAEiBiB,UAAU,IAAK;MAChC,IAAI,CAACA,UAAU,EAAE,OAAO,IAAI;MAE5B,IAAI,OAAOA,UAAU,KAAK,QAAQ,EAAE;QACnC,OAAO;UAAEC,GAAG,EAAED;QAAW,CAAC;MAC3B;MAEA,IAAI,OAAOA,UAAU,KAAK,QAAQ,IAAIA,UAAU,CAACC,GAAG,EAAE;QACrD,OAAOD,UAAU;MAClB;MAEA,IAAI,OAAOA,UAAU,KAAK,QAAQ,IAAIA,UAAU,CAACE,GAAG,EAAE;QACrD,OAAO;UAAED,GAAG,EAAED,UAAU,CAACE;QAAI,CAAC;MAC/B;MAEA,OAAO,IAAI;IACZ,CAAC;IAAAnB,eAAA,yBAEiBoB,OAAO,IAAK;MAC7B,MAAM;QAAElB;MAAkB,CAAC,GAAG,IAAI,CAACH,KAAK;MACxC,MAAMM,KAAK,GAAG,IAAI,CAACgB,QAAQ,CAAC,CAAC;MAC7BjC,QAAQ,CAACkC,UAAU,CAACC,QAAQ,CAAChC,MAAM,CAACiC,OAAO,CAACC,aAAa,EAAE;QAC1DL,OAAO,EAAEA,OAAO;QAChBlB,iBAAiB,EAAEA,iBAAiB;QACpCwB,YAAY,EAAErB;MACf,CAAC,CAAC;IACH,CAAC;IAAAL,eAAA,4BAEoBoB,OAAO,IAAK;MAAA,IAAAO,eAAA,EAAAC,gBAAA;MAChC,MAAM;QAAEC,kBAAkB;QAAE3B;MAAkB,CAAC,GAAG,IAAI,CAACH,KAAK;MAC5D,MAAMM,KAAK,GAAG,EAAAsB,eAAA,GAAAP,OAAO,CAACU,MAAM,cAAAH,eAAA,uBAAdA,eAAA,CAAiBpC,MAAM,CAACwC,eAAe,CAAC1B,KAAK,CAAC,KAAI,UAAU;MAC1E,MAAM2B,OAAO,GAAGpC,oBAAoB,CAACwB,OAAO,EAAElB,iBAAiB,CAAC;MAChE,MAAMe,UAAU,IAAAW,gBAAA,GAAGR,OAAO,CAACU,MAAM,cAAAF,gBAAA,uBAAdA,gBAAA,CAAiBrC,MAAM,CAACwC,eAAe,CAACE,YAAY,CAAC;MACxE,MAAMC,WAAW,GAAG,IAAI,CAACC,cAAc,CAAClB,UAAU,CAAC;MAEnD,oBACCxC,KAAA,CAAA2D,aAAA,CAACrD,gBAAgB;QAChBsD,GAAG,EAAEjB,OAAO,CAACkB,EAAG;QAChBC,KAAK,EAAEC,MAAM,CAACC,QAAS;QACvBC,OAAO,EAAEA,CAAA,KAAM,IAAI,CAACC,cAAc,CAACvB,OAAO;MAAE,gBAG5C3C,KAAA,CAAA2D,aAAA,CAACxD,IAAI;QAAC2D,KAAK,EAAEC,MAAM,CAACI;MAAgB,GAClCV,WAAW,gBACXzD,KAAA,CAAA2D,aAAA,CAACpD,KAAK;QACL6D,MAAM,EAAEX,WAAY;QACpBK,KAAK,EAAEC,MAAM,CAACM,MAAO;QACrBC,UAAU,EAAC;MAAO,CAClB,CAAC,gBAEFtE,KAAA,CAAA2D,aAAA,CAACxD,IAAI;QAAC2D,KAAK,EAAE,CAACC,MAAM,CAACM,MAAM,EAAEN,MAAM,CAACQ,iBAAiB;MAAE,gBACtDvE,KAAA,CAAA2D,aAAA,CAACjD,IAAI;QACJ8D,IAAI,EAAC,OAAO;QACZC,IAAI,EAAC,cAAc;QACnBC,IAAI,EAAE,EAAG;QACTC,KAAK,EAAE9D,OAAO,CAAC+D;MAAW,CAC1B,CACI,CAEF,CAAC,eAGP5E,KAAA,CAAA2D,aAAA,CAACxD,IAAI;QAAC2D,KAAK,EAAEC,MAAM,CAACc;MAAc,gBACjC7E,KAAA,CAAA2D,aAAA,CAACzD,IAAI;QAAC4D,KAAK,EAAEC,MAAM,CAACe,SAAU;QAACC,aAAa,EAAE;MAAE,GAC9CnD,KACI,CAAC,EACN2B,OAAO,iBACPvD,KAAA,CAAA2D,aAAA,CAACzD,IAAI;QAAC4D,KAAK,EAAEC,MAAM,CAACiB,eAAgB;QAACD,aAAa,EAAE;MAAE,GACpDxB,OACI,CAEF,CAAC,eAGPvD,KAAA,CAAA2D,aAAA,CAACxD,IAAI;QAAC2D,KAAK,EAAEC,MAAM,CAACkB;MAAiB,gBACpCjF,KAAA,CAAA2D,aAAA,CAACjD,IAAI;QACJ8D,IAAI,EAAC,eAAe;QACpBC,IAAI,EAAC,cAAc;QACnBC,IAAI,EAAE,EAAG;QACTC,KAAK,EAAE9D,OAAO,CAAC+D;MAAW,CAC1B,CACI,CACW,CAAC;IAErB,CAAC;IA9IA,IAAI,CAACrC,KAAK,GAAG;MAAEH,OAAO,EAAE;IAAM,CAAC;EAChC;EAEA8C,iBAAiBA,CAAA,EAAG;IACnB,IAAI,CAACC,OAAO,CAAC,CAAC;EACf;EAEAC,kBAAkBA,CAACC,SAAS,EAAE;IAC7B,IAAI,CAACA,SAAS,CAACC,WAAW,IAAI,IAAI,CAAChE,KAAK,CAACgE,WAAW,EAAE;MACrD,IAAI,CAACH,OAAO,CAAC,CAAC;IACf;EACD;EAqIAI,aAAaA,CAAA,EAAG;IACf,MAAM;MAAEC;IAAS,CAAC,GAAG,IAAI,CAAClE,KAAK;;IAE/B;IACA,IAAIb,CAAC,CAACiB,OAAO,CAAC8D,QAAQ,CAAC,IAAI,CAAC,IAAI,CAACjD,KAAK,CAACH,OAAO,EAAE;MAC/C,OAAO,IAAI;IACZ;IAEA,IAAI3B,CAAC,CAACiB,OAAO,CAAC8D,QAAQ,CAAC,EAAE;MACxB,IAAI,IAAI,CAACjD,KAAK,CAACH,OAAO,EAAE;QACvB,oBACCpC,KAAA,CAAA2D,aAAA,CAACxD,IAAI;UAAC2D,KAAK,EAAEC,MAAM,CAAC0B;QAAe,gBAClCzF,KAAA,CAAA2D,aAAA,CAAC/C,UAAU,CAAC8E,kBAAkB;UAACC,MAAM,EAAE;QAAI,CAAE,CACxC,CAAC;MAET;MACA,OAAO,IAAI;IACZ;IAEA,oBACC3F,KAAA,CAAA2D,aAAA,CAACvD,UAAU;MACVwF,qBAAqB,EAAE7B,MAAM,CAAC8B,iBAAkB;MAChDC,4BAA4B,EAAE;IAAM,GAEnCN,QAAQ,CAACO,GAAG,CAAEpD,OAAO,IAAK,IAAI,CAACqD,iBAAiB,CAACrD,OAAO,CAAC,CAC/C,CAAC;EAEf;EAEAsD,MAAMA,CAAA,EAAG;IACR,MAAM;MAAE7C;IAAmB,CAAC,GAAG,IAAI,CAAC9B,KAAK;IAEzC,MAAM4E,OAAO,GAAG,IAAI,CAACX,aAAa,CAAC,CAAC;IACpC;IACA,IAAIW,OAAO,KAAK,IAAI,EAAE;MACrB,OAAO,IAAI;IACZ;IAEA,oBACClG,KAAA,CAAA2D,aAAA,CAACxD,IAAI;MAAC2D,KAAK,EAAEC,MAAM,CAACoC;IAAiB,gBACpCnG,KAAA,CAAA2D,aAAA,CAACxD,IAAI;MAAC2D,KAAK,EAAEC,MAAM,CAACqC;IAAe,gBAClCpG,KAAA,CAAA2D,aAAA,CAACxD,IAAI;MAAC2D,KAAK,EAAEC,MAAM,CAACsC;IAAe,gBAClCrG,KAAA,CAAA2D,aAAA,CAACzD,IAAI;MAAC4D,KAAK,EAAEC,MAAM,CAACuC;IAAa,GAAE,IAAI,CAAC1D,QAAQ,CAAC,CAAQ,CACpD,CACD,CAAC,EACNsD,OACI,CAAC;EAET;AACD;AAEA,MAAMnC,MAAM,GAAG1D,UAAU,CAACkG,MAAM,CAAC;EAChCJ,gBAAgB,EAAE;IACjBK,eAAe,EAAE,MAAM;IACvBC,IAAI,EAAE;EACP,CAAC;EACDL,cAAc,EAAE;IACfM,iBAAiB,EAAEzF,OAAO,CAAC0F,EAAE;IAC7BC,aAAa,EAAE3F,OAAO,CAAC4F,EAAE,GAAG,CAAC;IAC7BC,UAAU,EAAE7F,OAAO,CAAC0F;EACrB,CAAC;EACDlB,cAAc,EAAE;IACfiB,iBAAiB,EAAEzF,OAAO,CAAC0F;EAC5B,CAAC;EACDN,cAAc,EAAE;IACfU,YAAY,EAAE9F,OAAO,CAAC0F;EACvB,CAAC;EACDL,YAAY,EAAE;IACbU,UAAU,EAAE,SAAS;IACrBC,QAAQ,EAAE,EAAE;IACZtC,KAAK,EAAE;EACR,CAAC;EACDkB,iBAAiB,EAAE;IAClBa,iBAAiB,EAAEzF,OAAO,CAAC0F,EAAE;IAC7BC,aAAa,EAAE3F,OAAO,CAAC0F;EACxB,CAAC;EACD;EACA3C,QAAQ,EAAE;IACTkD,aAAa,EAAE,KAAK;IACpBC,UAAU,EAAE,QAAQ;IACpBT,iBAAiB,EAAE,EAAE;IACrBU,eAAe,EAAE,CAAC;IAClBZ,eAAe,EAAE;EAClB,CAAC;EACDrC,eAAe,EAAE;IAChBkD,KAAK,EAAE,EAAE;IACT1B,MAAM,EAAE,EAAE;IACV2B,YAAY,EAAE,EAAE;IAChBC,WAAW,EAAE;EACd,CAAC;EACDlD,MAAM,EAAE;IACPgD,KAAK,EAAE,EAAE;IACT1B,MAAM,EAAE,EAAE;IACV2B,YAAY,EAAE,EAAE;IAChBd,eAAe,EAAE3F,OAAO,CAAC2G,gBAAgB,IAAI;EAC9C,CAAC;EACDjD,iBAAiB,EAAE;IAClBiC,eAAe,EAAE3F,OAAO,CAAC2G,gBAAgB,IAAI,SAAS;IACtDC,cAAc,EAAE,QAAQ;IACxBN,UAAU,EAAE;EACb,CAAC;EACDtC,aAAa,EAAE;IACd4B,IAAI,EAAE,CAAC;IACPgB,cAAc,EAAE;EACjB,CAAC;EACD3C,SAAS,EAAE;IACVkC,UAAU,EAAE,aAAa;IACzBC,QAAQ,EAAE,EAAE;IACZtC,KAAK,EAAE9D,OAAO,CAAC6G,SAAS,IAAI,MAAM;IAClCX,YAAY,EAAE;EACf,CAAC;EACD/B,eAAe,EAAE;IAChBgC,UAAU,EAAE,YAAY;IACxBC,QAAQ,EAAE,EAAE;IACZtC,KAAK,EAAE9D,OAAO,CAAC+D,UAAU,IAAI,MAAM;IACnC+C,UAAU,EAAE;EACb,CAAC;EACD1C,gBAAgB,EAAE;IACjB2C,WAAW,EAAE;EACd;AACD,CAAC,CAAC;AAEF,MAAMC,eAAe,GAAItF,KAAK,IAAK;EAAA,IAAAuF,cAAA;EAClC,MAAM;IAAEC,IAAI;IAAEC;EAAc,CAAC,GAAGzF,KAAK;EAErC,OAAO;IACNa,kBAAkB,EAAElC,8BAA8B,CAACqB,KAAK,CAAC;IACzDiD,QAAQ,EAAEzE,cAAc,CAACwB,KAAK,CAAC;IAC/Bd,iBAAiB,EAAET,uBAAuB,CAACuB,KAAK,CAAC;IACjD0F,IAAI,EAAEF,IAAI,CAACE,IAAI;IACf3C,WAAW,EAAE0C,aAAa,CAAC1C,WAAW,CAACxE,MAAM,CAACoH,eAAe,CAAC;IAC9DC,OAAO,EAAE,EAAAL,cAAA,GAAAvF,KAAK,CAAC4F,OAAO,cAAAL,cAAA,uBAAbA,cAAA,CAAeM,MAAM,KAAI,CAAC;EACpC,CAAC;AACF,CAAC;AAED,eAAe5H,OAAO,CAACqH,eAAe,EAAE,IAAI,EAAE,IAAI,EAAE;EAAEQ,UAAU,EAAE;AAAK,CAAC,CAAC,CACxEjH,WACD,CAAC","ignoreList":[]}
@@ -0,0 +1,315 @@
1
+ function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
2
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
3
+ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
4
+ import React, { Component } from "react";
5
+ import { Text, View, ScrollView, StyleSheet, TouchableOpacity, Image } from "react-native";
6
+ import { connect } from "react-redux";
7
+ import _ from "lodash";
8
+ import { Icon } from "react-native-elements";
9
+ import { Services } from "../feature.config";
10
+ import { Components, Colours } from "../core.config";
11
+ import { values } from "../values.config";
12
+ import { selectListings, selectFeatureDefinition } from "../reducers/featureBuilderReducer";
13
+ import { SPACING } from "../js/spacing";
14
+ import { getMainBrandingColourFromState } from "../js";
15
+ import { getSummaryFieldValue } from "../js/helpers";
16
+ class WidgetSmall extends Component {
17
+ constructor(props) {
18
+ super(props);
19
+ _defineProperty(this, "getTitle", () => {
20
+ const {
21
+ options,
22
+ featureDefinition
23
+ } = this.props;
24
+ if (options && !_.isEmpty(options.Title)) return options.Title;
25
+ // Use feature definition title
26
+ if (featureDefinition !== null && featureDefinition !== void 0 && featureDefinition.title || featureDefinition !== null && featureDefinition !== void 0 && featureDefinition.displayName) {
27
+ return featureDefinition.title || featureDefinition.displayName;
28
+ }
29
+ return values.featureName || "Features";
30
+ });
31
+ _defineProperty(this, "getEmptyStateText", () => {
32
+ const {
33
+ options
34
+ } = this.props;
35
+ if (options && !_.isEmpty(options.EmptyText)) return options.EmptyText;
36
+ return values.labels.emptyState;
37
+ });
38
+ _defineProperty(this, "refresh", () => {
39
+ this.onLoadingChanged(true, async () => {
40
+ try {
41
+ // Import actions dynamically to avoid circular dependencies
42
+ const {
43
+ initializeFeatureBuilder
44
+ } = await import("../actions/featureBuilderActions");
45
+ await initializeFeatureBuilder()(this.props.dispatch, () => this.props.getState);
46
+ } finally {
47
+ this.onLoadingChanged(false);
48
+ }
49
+ });
50
+ });
51
+ _defineProperty(this, "onLoadingChanged", (loading, callback) => {
52
+ this.setState({
53
+ loading
54
+ }, () => {
55
+ if (this.props.onLoadingChanged) this.props.onLoadingChanged(this.state.loading);
56
+ if (callback) callback();
57
+ });
58
+ });
59
+ _defineProperty(this, "onPressAll", () => {
60
+ Services.navigation.navigate(values.screens.featureList, {
61
+ options: this.props.options
62
+ });
63
+ });
64
+ _defineProperty(this, "getImageSource", imageField => {
65
+ if (!imageField) return null;
66
+ if (typeof imageField === "string") {
67
+ return {
68
+ uri: imageField
69
+ };
70
+ }
71
+ if (typeof imageField === "object" && imageField.uri) {
72
+ return imageField;
73
+ }
74
+ if (typeof imageField === "object" && imageField.url) {
75
+ return {
76
+ uri: imageField.url
77
+ };
78
+ }
79
+ return null;
80
+ });
81
+ _defineProperty(this, "onListingPress", listing => {
82
+ const {
83
+ featureDefinition
84
+ } = this.props;
85
+ const title = this.getTitle();
86
+ Services.navigation.navigate(values.screens.featureDetail, {
87
+ listing: listing,
88
+ featureDefinition: featureDefinition,
89
+ featureTitle: title
90
+ });
91
+ });
92
+ _defineProperty(this, "renderListingCard", listing => {
93
+ var _listing$fields, _listing$fields2;
94
+ const {
95
+ colourBrandingMain,
96
+ featureDefinition
97
+ } = this.props;
98
+ const title = ((_listing$fields = listing.fields) === null || _listing$fields === void 0 ? void 0 : _listing$fields[values.mandatoryFields.title]) || "Untitled";
99
+ const summary = getSummaryFieldValue(listing, featureDefinition);
100
+ const imageField = (_listing$fields2 = listing.fields) === null || _listing$fields2 === void 0 ? void 0 : _listing$fields2[values.mandatoryFields.featureImage];
101
+ const imageSource = this.getImageSource(imageField);
102
+ return /*#__PURE__*/React.createElement(TouchableOpacity, {
103
+ key: listing.id,
104
+ style: styles.cardContainer,
105
+ onPress: () => this.onListingPress(listing)
106
+ }, /*#__PURE__*/React.createElement(View, {
107
+ style: styles.borderContainer
108
+ }, imageSource ? /*#__PURE__*/React.createElement(Image, {
109
+ source: imageSource,
110
+ style: styles.cardImage,
111
+ resizeMode: "cover"
112
+ }) : /*#__PURE__*/React.createElement(View, {
113
+ style: [styles.cardImage, styles.placeholderImage]
114
+ }, /*#__PURE__*/React.createElement(Icon, {
115
+ name: "image",
116
+ type: "font-awesome",
117
+ size: 24,
118
+ color: Colours.TEXT_LIGHT
119
+ })), /*#__PURE__*/React.createElement(Text, {
120
+ style: styles.cardTitle,
121
+ numberOfLines: 1
122
+ }, title), summary && /*#__PURE__*/React.createElement(Text, {
123
+ style: styles.cardSummary,
124
+ numberOfLines: 1
125
+ }, summary)));
126
+ });
127
+ this.state = {
128
+ loading: false
129
+ };
130
+ }
131
+ componentDidMount() {
132
+ this.refresh();
133
+ }
134
+ componentDidUpdate(prevProps) {
135
+ if (!prevProps.dataUpdated && this.props.dataUpdated) {
136
+ this.refresh();
137
+ }
138
+ }
139
+ renderContent() {
140
+ const {
141
+ listings
142
+ } = this.props;
143
+
144
+ // Don't render widget if no listings are available (and not loading)
145
+ if (_.isEmpty(listings) && !this.state.loading) {
146
+ return null;
147
+ }
148
+ if (_.isEmpty(listings)) {
149
+ if (this.state.loading) {
150
+ return /*#__PURE__*/React.createElement(View, {
151
+ style: styles.loadingPadding
152
+ }, /*#__PURE__*/React.createElement(Components.LoadingStateWidget, {
153
+ height: 180
154
+ }));
155
+ }
156
+ return null;
157
+ }
158
+
159
+ // Show first 3 listings with peeking indicator
160
+ const listingsToShow = listings.slice(0, values.widget.maxItems);
161
+ return /*#__PURE__*/React.createElement(ScrollView, {
162
+ horizontal: true,
163
+ contentContainerStyle: {
164
+ paddingLeft: SPACING.XS + 2,
165
+ paddingRight: SPACING.SM
166
+ },
167
+ showsHorizontalScrollIndicator: false
168
+ }, listingsToShow.map(listing => this.renderListingCard(listing)), listings.length > values.widget.maxItems && /*#__PURE__*/React.createElement(TouchableOpacity, {
169
+ style: [styles.cardContainer, styles.viewMoreCard],
170
+ onPress: this.onPressAll
171
+ }, /*#__PURE__*/React.createElement(View, {
172
+ style: [styles.borderContainer, styles.viewMoreContainer]
173
+ }, /*#__PURE__*/React.createElement(Text, {
174
+ style: styles.viewMoreText
175
+ }, "View all"), /*#__PURE__*/React.createElement(Text, {
176
+ style: styles.viewMoreCount
177
+ }, listings.length, " items"))));
178
+ }
179
+ render() {
180
+ const {
181
+ colourBrandingMain
182
+ } = this.props;
183
+ const content = this.renderContent();
184
+ // Don't render widget section if content is null (no features available)
185
+ if (content === null) {
186
+ return null;
187
+ }
188
+ return /*#__PURE__*/React.createElement(View, {
189
+ style: styles.sectionContainer
190
+ }, /*#__PURE__*/React.createElement(View, {
191
+ style: styles.sectionPadding
192
+ }, /*#__PURE__*/React.createElement(View, {
193
+ style: styles.sectionHeading
194
+ }, /*#__PURE__*/React.createElement(Text, {
195
+ style: styles.sectionTitle
196
+ }, this.getTitle()), /*#__PURE__*/React.createElement(Components.InlineButton, {
197
+ onPress: this.onPressAll,
198
+ color: colourBrandingMain,
199
+ touchableStyle: {
200
+ paddingTop: SPACING.XS + 2
201
+ },
202
+ textStyle: {
203
+ color: "#fff"
204
+ }
205
+ }, values.labels.viewAll))), content);
206
+ }
207
+ }
208
+ const styles = StyleSheet.create({
209
+ sectionContainer: {
210
+ backgroundColor: "#fff",
211
+ paddingTop: SPACING.MD
212
+ },
213
+ sectionPadding: {
214
+ paddingHorizontal: SPACING.MD,
215
+ paddingBottom: SPACING.XS + 2
216
+ },
217
+ loadingPadding: {
218
+ paddingHorizontal: SPACING.MD
219
+ },
220
+ sectionHeading: {
221
+ marginBottom: SPACING.XS,
222
+ flexDirection: "row",
223
+ alignContent: "flex-start",
224
+ justifyContent: "space-between"
225
+ },
226
+ sectionTitle: {
227
+ fontFamily: "sf-bold",
228
+ fontSize: 24,
229
+ color: "#000"
230
+ },
231
+ // Listing card styles
232
+ cardContainer: {
233
+ marginRight: SPACING.SM + 4,
234
+ width: values.widget.itemMaxWidth
235
+ },
236
+ borderContainer: {
237
+ borderRadius: SPACING.SM,
238
+ backgroundColor: "#fff",
239
+ shadowColor: "#000",
240
+ shadowOffset: {
241
+ width: 0,
242
+ height: 2
243
+ },
244
+ shadowOpacity: 0.1,
245
+ shadowRadius: 3.84,
246
+ elevation: 4,
247
+ padding: SPACING.SM,
248
+ minHeight: values.widget.itemMinWidth
249
+ },
250
+ cardImage: {
251
+ width: 88,
252
+ height: 88,
253
+ borderRadius: 44,
254
+ backgroundColor: "#f0f0f0",
255
+ alignSelf: "center",
256
+ marginBottom: SPACING.XS
257
+ },
258
+ placeholderImage: {
259
+ justifyContent: "center",
260
+ alignItems: "center",
261
+ backgroundColor: "#f0f0f0"
262
+ },
263
+ cardTitle: {
264
+ fontFamily: "sf-semibold",
265
+ fontSize: 14,
266
+ color: "#000",
267
+ textAlign: "center",
268
+ marginBottom: 4
269
+ },
270
+ cardSummary: {
271
+ fontFamily: "sf-regular",
272
+ fontSize: 12,
273
+ color: "#666",
274
+ textAlign: "center"
275
+ },
276
+ // View more card
277
+ viewMoreCard: {
278
+ justifyContent: "center"
279
+ },
280
+ viewMoreContainer: {
281
+ justifyContent: "center",
282
+ alignItems: "center",
283
+ minHeight: values.widget.itemMinWidth
284
+ },
285
+ viewMoreText: {
286
+ fontFamily: "sf-semibold",
287
+ fontSize: 14,
288
+ color: Colours.TEXT_DARK || "#000"
289
+ },
290
+ viewMoreCount: {
291
+ fontFamily: "sf-regular",
292
+ fontSize: 12,
293
+ color: "#666",
294
+ marginTop: 2
295
+ }
296
+ });
297
+ const mapStateToProps = state => {
298
+ var _state$strings;
299
+ const {
300
+ user,
301
+ notifications
302
+ } = state;
303
+ return {
304
+ colourBrandingMain: getMainBrandingColourFromState(state),
305
+ listings: selectListings(state),
306
+ featureDefinition: selectFeatureDefinition(state),
307
+ site: user.site,
308
+ dataUpdated: notifications.dataUpdated[values.notificationKey],
309
+ strings: ((_state$strings = state.strings) === null || _state$strings === void 0 ? void 0 : _state$strings.config) || {}
310
+ };
311
+ };
312
+ export default connect(mapStateToProps, null, null, {
313
+ forwardRef: true
314
+ })(WidgetSmall);
315
+ //# sourceMappingURL=WidgetSmall.js.map