@plusscommunities/pluss-feature-builder-app-c 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,725 @@
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 { SPACING } from "../js/spacing";
6
+ import { Platform, View, ScrollView, Animated, Dimensions, StatusBar, Text, TouchableOpacity, Linking, StyleSheet, KeyboardAvoidingView, Image } from "react-native";
7
+ import { Icon } from "react-native-elements";
8
+ import { connect } from "react-redux";
9
+ import _ from "lodash";
10
+ import { LinearGradient } from "expo-linear-gradient";
11
+ import { Services } from "../feature.config";
12
+ import { Components, Colours, COLOUR_TRANSPARENT, TEXT_DARK } from "../core.config";
13
+ import { TEXT_MID, LINEGREY } from "../js/Colors";
14
+ import FileDownload from "./FileDownload";
15
+ import { values } from "../values.config";
16
+ import { selectFeatureDefinition } from "../reducers/featureBuilderReducer";
17
+ import Constants from "expo-constants";
18
+ import { InlineButton } from "./common";
19
+ import { FIELD_TYPES } from "../js/FieldTypes";
20
+ const SCREEN_HEIGHT = Dimensions.get("window").height;
21
+ const CARD_IMAGE_HEIGHT = SCREEN_HEIGHT * 0.3;
22
+ const SCREEN_WIDTH = Dimensions.get("window").width;
23
+
24
+ // StatusBarHeight function copied to avoid import from outside extension
25
+ const StatusBarHeight = size => {
26
+ return getStatusBarHeight() + size;
27
+ };
28
+ const getStatusBarHeight = () => {
29
+ return Platform.OS === "ios" ? Constants.statusBarHeight : StatusBar.currentHeight;
30
+ };
31
+ class FeatureDetailScreen extends Component {
32
+ constructor(props) {
33
+ super(props);
34
+ _defineProperty(this, "onPressBack", () => {
35
+ Services.navigation.goBack();
36
+ });
37
+ /**
38
+ * Collect all images from listing fields
39
+ */
40
+ _defineProperty(this, "collectAllImages", () => {
41
+ const {
42
+ listing,
43
+ featureDefinition
44
+ } = this.props;
45
+ if (!listing || !listing.fields || !featureDefinition) {
46
+ return [];
47
+ }
48
+ const allImages = [];
49
+ const fieldDefinitions = featureDefinition.fields || [];
50
+
51
+ // Add primary feature image first
52
+ const primaryImage = listing.fields[values.mandatoryFields.featureImage];
53
+ if (primaryImage) {
54
+ const imageObj = this.normalizeImageField(primaryImage);
55
+ if (imageObj) {
56
+ allImages.push({
57
+ ...imageObj,
58
+ fieldId: values.mandatoryFields.featureImage,
59
+ fieldLabel: values.labels.featureImage
60
+ });
61
+ }
62
+ }
63
+
64
+ // Add additional image fields
65
+ fieldDefinitions.forEach(fieldDef => {
66
+ if ((fieldDef.type === FIELD_TYPES.IMAGE || fieldDef.type === FIELD_TYPES.GALLERY) && fieldDef.id !== values.mandatoryFields.featureImage) {
67
+ const fieldValue = listing.fields[fieldDef.id];
68
+ if (fieldValue) {
69
+ if (fieldDef.type === FIELD_TYPES.GALLERY) {
70
+ // Handle Gallery (Array of images)
71
+ if (Array.isArray(fieldValue)) {
72
+ fieldValue.forEach(item => {
73
+ const imageObj = this.normalizeImageField(item);
74
+ if (imageObj) {
75
+ allImages.push({
76
+ ...imageObj,
77
+ fieldId: fieldDef.id,
78
+ fieldLabel: fieldDef.label || fieldDef.id
79
+ });
80
+ }
81
+ });
82
+ }
83
+ } else {
84
+ // Handle Single Image
85
+ const imageObj = this.normalizeImageField(fieldValue);
86
+ if (imageObj) {
87
+ allImages.push({
88
+ ...imageObj,
89
+ fieldId: fieldDef.id,
90
+ fieldLabel: fieldDef.label || fieldDef.id
91
+ });
92
+ }
93
+ }
94
+ }
95
+ }
96
+ });
97
+ return allImages;
98
+ });
99
+ /**
100
+ * Normalize image field to object format
101
+ */
102
+ _defineProperty(this, "normalizeImageField", imageField => {
103
+ if (!imageField) return null;
104
+ if (typeof imageField === "string") {
105
+ return {
106
+ uri: imageField,
107
+ url: imageField
108
+ };
109
+ }
110
+ if (typeof imageField === "object") {
111
+ if (imageField.uri) {
112
+ return {
113
+ uri: imageField.uri,
114
+ url: imageField.uri,
115
+ ...imageField
116
+ };
117
+ }
118
+ if (imageField.url) {
119
+ return {
120
+ uri: imageField.url,
121
+ url: imageField.url,
122
+ ...imageField
123
+ };
124
+ }
125
+ }
126
+ return null;
127
+ });
128
+ /**
129
+ * Open image popup with all images
130
+ */
131
+ _defineProperty(this, "openImagePopup", (imageIndex = 0) => {
132
+ const {
133
+ allImages
134
+ } = this.state;
135
+ if (allImages.length > 0) {
136
+ this.setState({
137
+ showImagePopup: true,
138
+ selectedImageIndex: imageIndex
139
+ });
140
+ }
141
+ });
142
+ /**
143
+ * Close image popup
144
+ */
145
+ _defineProperty(this, "closeImagePopup", () => {
146
+ this.setState({
147
+ showImagePopup: false,
148
+ selectedImageIndex: 0
149
+ });
150
+ });
151
+ /**
152
+ * Handle link opening for various field types
153
+ */
154
+ _defineProperty(this, "handleLinkPress", url => {
155
+ if (url) {
156
+ Linking.openURL(url).catch(err => {
157
+ // Silently handle URL open errors
158
+ });
159
+ }
160
+ });
161
+ _defineProperty(this, "handleFilePress", file => {
162
+ if (file !== null && file !== void 0 && file.url) {
163
+ Linking.openURL(file.url).catch(err => {
164
+ // Silently handle URL open errors
165
+ });
166
+ }
167
+ });
168
+ this.state = {
169
+ isHomeTab: false,
170
+ showImagePopup: false,
171
+ selectedImageIndex: 0,
172
+ allImages: []
173
+ };
174
+ }
175
+ componentDidMount() {
176
+ this.setState({
177
+ isHomeTab: !Services.navigation.getParentRoute(),
178
+ allImages: this.collectAllImages()
179
+ });
180
+ }
181
+ componentDidUpdate(prevProps) {
182
+ // Recalculate allImages when listing or featureDefinition changes
183
+ if (prevProps.listing !== this.props.listing || prevProps.featureDefinition !== this.props.featureDefinition) {
184
+ this.setState({
185
+ allImages: this.collectAllImages()
186
+ });
187
+ }
188
+ }
189
+ componentWillUnmount() {
190
+ if (Platform.OS === "ios") StatusBar.setBarStyle("dark-content");
191
+ }
192
+ /**
193
+ * Process fields: filter out mandatory fields and sort by order
194
+ */
195
+ processFields() {
196
+ const {
197
+ listing,
198
+ featureDefinition
199
+ } = this.props;
200
+ if (!listing || !listing.fields || !featureDefinition) {
201
+ return [];
202
+ }
203
+ const fieldDefinitions = featureDefinition.fields || [];
204
+ const excludedFieldIds = new Set([values.mandatoryFields.title, values.mandatoryFields.featureImage]);
205
+
206
+ // Filter and map fields with their definitions
207
+ const filteredFields = Object.keys(listing.fields).filter(fieldId => {
208
+ if (!fieldId || excludedFieldIds.has(fieldId)) return false;
209
+ if (listing.fields[fieldId] == null) return false;
210
+
211
+ // Only include fields that have definitions
212
+ const hasDefinition = fieldDefinitions.some(f => f.id === fieldId);
213
+ if (!hasDefinition) {
214
+ return false;
215
+ }
216
+ return true;
217
+ }).map(fieldId => {
218
+ const fieldDefinition = fieldDefinitions.find(fieldDef => fieldDef.id === fieldId);
219
+ return {
220
+ fieldId,
221
+ fieldValue: listing.fields[fieldId],
222
+ fieldDefinition,
223
+ fieldType: (fieldDefinition === null || fieldDefinition === void 0 ? void 0 : fieldDefinition.type) || FIELD_TYPES.TEXT
224
+ };
225
+ });
226
+
227
+ // Sort by order property if available
228
+ return _.sortBy(filteredFields, field => {
229
+ var _field$fieldDefinitio;
230
+ return ((_field$fieldDefinitio = field.fieldDefinition) === null || _field$fieldDefinitio === void 0 ? void 0 : _field$fieldDefinitio.order) || 999;
231
+ });
232
+ }
233
+ /**
234
+ * Render individual field based on its type
235
+ */
236
+ renderField(fieldDef, fieldValue) {
237
+ const {
238
+ colourBrandingMain
239
+ } = this.props;
240
+
241
+ // Defensive: ensure fieldDef is always an object
242
+ const safeFieldDef = fieldDef || {};
243
+ const type = safeFieldDef.type || FIELD_TYPES.TEXT;
244
+ const label = safeFieldDef.label || safeFieldDef.id || "Unknown Field";
245
+ switch (type) {
246
+ case FIELD_TYPES.CTA:
247
+ {
248
+ const btnLabel = (fieldValue === null || fieldValue === void 0 ? void 0 : fieldValue.label) || label;
249
+ const btnUrl = fieldValue === null || fieldValue === void 0 ? void 0 : fieldValue.url;
250
+ return /*#__PURE__*/React.createElement(View, {
251
+ style: styles.ctaContainer
252
+ }, /*#__PURE__*/React.createElement(InlineButton, {
253
+ large: true,
254
+ color: colourBrandingMain,
255
+ onPress: () => this.handleLinkPress(btnUrl)
256
+ }, btnLabel));
257
+ }
258
+ case FIELD_TYPES.EMAIL:
259
+ return /*#__PURE__*/React.createElement(TouchableOpacity, {
260
+ style: styles.linkContainer,
261
+ onPress: () => this.handleLinkPress(`mailto:${fieldValue}`)
262
+ }, /*#__PURE__*/React.createElement(Icon, {
263
+ type: "font-awesome",
264
+ name: "envelope",
265
+ size: 16,
266
+ color: colourBrandingMain,
267
+ style: styles.fieldIcon
268
+ }), /*#__PURE__*/React.createElement(Text, {
269
+ style: [styles.linkText, {
270
+ color: colourBrandingMain
271
+ }]
272
+ }, fieldValue));
273
+ case FIELD_TYPES.DATE:
274
+ return /*#__PURE__*/React.createElement(View, {
275
+ style: styles.dateContainer
276
+ }, /*#__PURE__*/React.createElement(Icon, {
277
+ type: "font-awesome",
278
+ name: "calendar",
279
+ size: 16,
280
+ color: TEXT_DARK,
281
+ style: styles.fieldIcon
282
+ }), /*#__PURE__*/React.createElement(Text, {
283
+ style: styles.bodyText
284
+ }, fieldValue));
285
+ case FIELD_TYPES.FILE:
286
+ {
287
+ // Handle both single file and multiple files (array)
288
+ const files = Array.isArray(fieldValue) ? fieldValue : [fieldValue];
289
+ return /*#__PURE__*/React.createElement(View, {
290
+ style: styles.filesContainer
291
+ }, /*#__PURE__*/React.createElement(Text, {
292
+ style: styles.sectionTitle
293
+ }, values.labels.attachments), files.map((file, index) => {
294
+ // Skip null/undefined files
295
+ if (!file) return null;
296
+ return /*#__PURE__*/React.createElement(FileDownload, {
297
+ key: index,
298
+ file: file,
299
+ onPress: this.handleFilePress,
300
+ color: this.props.colourBrandingMain
301
+ });
302
+ }));
303
+ }
304
+ case FIELD_TYPES.DESCRIPTION:
305
+ return /*#__PURE__*/React.createElement(Text, {
306
+ style: styles.descriptionText
307
+ }, fieldValue);
308
+ case FIELD_TYPES.IMAGE:
309
+ {
310
+ // Render secondary images inline with click handler
311
+ const imgUri = (fieldValue === null || fieldValue === void 0 ? void 0 : fieldValue.url) || (fieldValue === null || fieldValue === void 0 ? void 0 : fieldValue.uri) || (typeof fieldValue === "string" ? fieldValue : null);
312
+ if (!imgUri) return null;
313
+
314
+ // Find this image's index for popup
315
+ const {
316
+ allImages
317
+ } = this.state;
318
+ const imageIndex = allImages.findIndex(img => img.uri === imgUri || img.url === imgUri);
319
+ const caption = fieldValue === null || fieldValue === void 0 ? void 0 : fieldValue.caption;
320
+ return /*#__PURE__*/React.createElement(TouchableOpacity, {
321
+ onPress: () => this.openImagePopup(imageIndex),
322
+ activeOpacity: 0.8
323
+ }, /*#__PURE__*/React.createElement(Image, {
324
+ source: {
325
+ uri: imgUri
326
+ },
327
+ style: styles.inlineImage,
328
+ resizeMode: "cover"
329
+ }), caption && /*#__PURE__*/React.createElement(Text, {
330
+ style: styles.imageCaption
331
+ }, caption));
332
+ }
333
+ case FIELD_TYPES.GALLERY:
334
+ {
335
+ // Handle Gallery Fields (arrays of images)
336
+ if (!Array.isArray(fieldValue)) return null;
337
+ return /*#__PURE__*/React.createElement(View, {
338
+ style: {
339
+ marginVertical: 16
340
+ }
341
+ }, /*#__PURE__*/React.createElement(View, {
342
+ style: {
343
+ flexDirection: "row",
344
+ flexWrap: "wrap",
345
+ marginHorizontal: -4
346
+ }
347
+ }, fieldValue.map((imgItem, index) => {
348
+ const imgUri = (imgItem === null || imgItem === void 0 ? void 0 : imgItem.url) || (imgItem === null || imgItem === void 0 ? void 0 : imgItem.uri) || (typeof imgItem === "string" ? imgItem : null);
349
+ if (!imgUri) return null;
350
+
351
+ // Find global index for the popup
352
+ const {
353
+ allImages
354
+ } = this.state;
355
+ const globalIndex = allImages.findIndex(img => img.uri === imgUri || img.url === imgUri);
356
+ return /*#__PURE__*/React.createElement(TouchableOpacity, {
357
+ key: index,
358
+ onPress: () => this.openImagePopup(globalIndex !== -1 ? globalIndex : 0),
359
+ activeOpacity: 0.8,
360
+ style: {
361
+ width: "50%",
362
+ padding: 4
363
+ } // 2 column grid
364
+ }, /*#__PURE__*/React.createElement(Image, {
365
+ source: {
366
+ uri: imgUri
367
+ },
368
+ style: [styles.inlineImage, {
369
+ height: 150,
370
+ marginVertical: 0
371
+ }],
372
+ resizeMode: "cover"
373
+ }));
374
+ })));
375
+ }
376
+ case FIELD_TYPES.TITLE:
377
+ return /*#__PURE__*/React.createElement(Text, {
378
+ style: styles.titleText
379
+ }, fieldValue);
380
+ case FIELD_TYPES.NUMBER:
381
+ return /*#__PURE__*/React.createElement(Text, {
382
+ style: styles.numberText
383
+ }, fieldValue);
384
+ default:
385
+ // Default text fallback
386
+ return /*#__PURE__*/React.createElement(Text, {
387
+ style: styles.bodyText
388
+ }, typeof fieldValue === "object" ? JSON.stringify(fieldValue) : fieldValue);
389
+ }
390
+ }
391
+
392
+ /**
393
+ * Render all fields with proper spacing and structure
394
+ */
395
+ renderFields() {
396
+ const processedFields = this.processFields();
397
+ return processedFields.map((field, _index) => {
398
+ var _field$fieldDefinitio2, _field$fieldDefinitio3;
399
+ return /*#__PURE__*/React.createElement(View, {
400
+ key: field.fieldId,
401
+ style: styles.fieldContainer
402
+ }, field.fieldType !== FIELD_TYPES.CTA && field.fieldType !== FIELD_TYPES.IMAGE && ((_field$fieldDefinitio2 = field.fieldDefinition) === null || _field$fieldDefinitio2 === void 0 ? void 0 : _field$fieldDefinitio2.label) && /*#__PURE__*/React.createElement(Text, {
403
+ style: styles.fieldLabel
404
+ }, (_field$fieldDefinitio3 = field.fieldDefinition) === null || _field$fieldDefinitio3 === void 0 ? void 0 : _field$fieldDefinitio3.label), this.renderField(field.fieldDefinition, field.fieldValue));
405
+ });
406
+ }
407
+ getImageSource() {
408
+ const {
409
+ listing
410
+ } = this.props;
411
+ if (!listing || !listing.fields) {
412
+ return null;
413
+ }
414
+ const imageField = listing.fields[values.mandatoryFields.featureImage];
415
+ if (!imageField) {
416
+ return null;
417
+ }
418
+
419
+ // Parse the image field value
420
+ if (typeof imageField === "string") {
421
+ return imageField;
422
+ }
423
+ return (imageField === null || imageField === void 0 ? void 0 : imageField.uri) || (imageField === null || imageField === void 0 ? void 0 : imageField.url) || null;
424
+ }
425
+ getTitle() {
426
+ const {
427
+ listing
428
+ } = this.props;
429
+ if (!listing || !listing.fields) {
430
+ return values.labels.defaultTitle;
431
+ }
432
+ return listing.fields[values.mandatoryFields.title] || values.labels.defaultTitle;
433
+ }
434
+ render() {
435
+ const {
436
+ listing
437
+ } = this.props;
438
+ const imageSource = this.getImageSource();
439
+ const title = this.getTitle();
440
+ if (!listing || !listing.fields) {
441
+ return /*#__PURE__*/React.createElement(View, {
442
+ style: styles.centerContainer
443
+ }, /*#__PURE__*/React.createElement(Text, {
444
+ style: styles.errorText
445
+ }, "Item not found"));
446
+ }
447
+ return /*#__PURE__*/React.createElement(KeyboardAvoidingView, {
448
+ behavior: Platform.OS === "ios" && "padding",
449
+ style: {
450
+ position: "relative",
451
+ flex: 1,
452
+ backgroundColor: Colours.BACKGROUND_WHITE || "#fff"
453
+ }
454
+ }, /*#__PURE__*/React.createElement(View, {
455
+ style: styles.backButton
456
+ }, /*#__PURE__*/React.createElement(View, {
457
+ style: styles.headerContent
458
+ }, /*#__PURE__*/React.createElement(Components.BackButton, {
459
+ onPress: this.onPressBack,
460
+ style: {
461
+ marginLeft: 16
462
+ }
463
+ }))), /*#__PURE__*/React.createElement(ScrollView, {
464
+ style: {
465
+ backgroundColor: Colours.BACKGROUND_WHITE || "#fff"
466
+ },
467
+ keyboardShouldPersistTaps: "always",
468
+ ref: ref => {
469
+ this.scrollView = ref;
470
+ }
471
+ }, /*#__PURE__*/React.createElement(View, {
472
+ style: [styles.mainHeader]
473
+ }, imageSource ? /*#__PURE__*/React.createElement(TouchableOpacity, {
474
+ onPress: () => this.openImagePopup(0),
475
+ activeOpacity: 0.9
476
+ }, /*#__PURE__*/React.createElement(Components.AutoOffsetImage, {
477
+ uri: imageSource,
478
+ height: CARD_IMAGE_HEIGHT,
479
+ width: SCREEN_WIDTH
480
+ })) : /*#__PURE__*/React.createElement(View, {
481
+ style: [styles.grayPlaceholder, {
482
+ height: CARD_IMAGE_HEIGHT,
483
+ width: SCREEN_WIDTH
484
+ }]
485
+ }), /*#__PURE__*/React.createElement(LinearGradient, {
486
+ style: styles.gradientOverlay,
487
+ colors: ["rgba(0,0,0,0.7)", COLOUR_TRANSPARENT],
488
+ start: {
489
+ x: 0,
490
+ y: 0
491
+ },
492
+ end: {
493
+ x: 0,
494
+ y: 1
495
+ },
496
+ locations: [0, 0.5]
497
+ })), /*#__PURE__*/React.createElement(View, {
498
+ style: {
499
+ paddingHorizontal: 16
500
+ }
501
+ }, /*#__PURE__*/React.createElement(View, {
502
+ style: styles.titleContainer
503
+ }, /*#__PURE__*/React.createElement(Text, {
504
+ style: styles.eventTitle
505
+ }, title))), /*#__PURE__*/React.createElement(View, {
506
+ style: {
507
+ minHeight: SCREEN_HEIGHT - CARD_IMAGE_HEIGHT - 56
508
+ }
509
+ }, this.renderFields())), this.state.showImagePopup && /*#__PURE__*/React.createElement(Components.ImagePopup, {
510
+ visible: this.state.showImagePopup,
511
+ images: this.state.allImages,
512
+ index: this.state.selectedImageIndex,
513
+ onClose: this.closeImagePopup
514
+ }));
515
+ }
516
+ }
517
+ const styles = StyleSheet.create({
518
+ backButton: {
519
+ position: "absolute",
520
+ left: 0,
521
+ top: 0,
522
+ zIndex: 10,
523
+ elevation: 10,
524
+ height: StatusBarHeight(70)
525
+ },
526
+ headerContent: {
527
+ alignSelf: "stretch",
528
+ flexDirection: "row",
529
+ flex: 1,
530
+ paddingTop: StatusBarHeight(12)
531
+ },
532
+ image: {
533
+ backgroundColor: Colours.BACKGROUND_WHITE || "#fff",
534
+ position: "relative",
535
+ width: undefined,
536
+ height: undefined,
537
+ flex: 1
538
+ },
539
+ mainHeader: {
540
+ position: "relative",
541
+ height: CARD_IMAGE_HEIGHT,
542
+ width: SCREEN_WIDTH
543
+ },
544
+ gradientOverlay: {
545
+ flex: 1
546
+ },
547
+ // Field container and spacing
548
+ fieldContainer: {
549
+ paddingHorizontal: 16,
550
+ marginVertical: 12
551
+ },
552
+ // Field labels/captions
553
+ fieldLabel: {
554
+ fontFamily: "sf-regular",
555
+ fontSize: 11,
556
+ color: TEXT_MID,
557
+ marginBottom: 6,
558
+ textTransform: "uppercase",
559
+ letterSpacing: 1.2,
560
+ alignSelf: "center",
561
+ textAlign: "center",
562
+ paddingHorizontal: 8,
563
+ paddingVertical: 4,
564
+ backgroundColor: "rgba(0,0,0,0.03)",
565
+ borderRadius: 12,
566
+ maxWidth: "80%"
567
+ },
568
+ // Field type styles
569
+ bodyText: {
570
+ fontFamily: "sf-regular",
571
+ fontSize: 16,
572
+ color: TEXT_DARK,
573
+ lineHeight: 22
574
+ },
575
+ titleText: {
576
+ fontFamily: "sf-semibold",
577
+ fontSize: 16,
578
+ fontWeight: "600",
579
+ color: TEXT_DARK
580
+ },
581
+ descriptionText: {
582
+ fontFamily: "sf-regular",
583
+ fontSize: 16,
584
+ color: TEXT_DARK,
585
+ lineHeight: 24
586
+ },
587
+ numberText: {
588
+ fontFamily: "sf-medium",
589
+ fontSize: 16,
590
+ fontWeight: "500",
591
+ color: TEXT_DARK
592
+ },
593
+ // Link styles
594
+ linkContainer: {
595
+ flexDirection: "row",
596
+ alignItems: "center",
597
+ paddingVertical: 4
598
+ },
599
+ linkText: {
600
+ fontFamily: "sf-medium",
601
+ fontSize: 16,
602
+ textDecorationLine: "underline"
603
+ },
604
+ // Date styles
605
+ dateContainer: {
606
+ flexDirection: "row",
607
+ alignItems: "center",
608
+ paddingVertical: 4
609
+ },
610
+ // Image styles
611
+ inlineImage: {
612
+ width: "100%",
613
+ height: 200,
614
+ borderRadius: 8,
615
+ marginVertical: 8
616
+ },
617
+ imageCaption: {
618
+ fontFamily: "sf-italic",
619
+ fontSize: 14,
620
+ fontStyle: "italic",
621
+ color: TEXT_MID,
622
+ marginTop: 4,
623
+ textAlign: "center"
624
+ },
625
+ // CTA styles
626
+ ctaContainer: {
627
+ alignItems: "center",
628
+ justifyContent: "center",
629
+ paddingVertical: 8
630
+ },
631
+ // Section title styles
632
+ sectionTitle: {
633
+ fontFamily: "sf-bold",
634
+ fontSize: 14,
635
+ fontWeight: "700",
636
+ color: TEXT_DARK,
637
+ marginBottom: SPACING.SM
638
+ },
639
+ // Icon styles
640
+ fieldIcon: {
641
+ marginRight: 8
642
+ },
643
+ // Legacy styles (kept for compatibility)
644
+ section: {
645
+ paddingVertical: 16
646
+ },
647
+ divider: {
648
+ height: 1,
649
+ backgroundColor: LINEGREY,
650
+ marginVertical: 8,
651
+ marginHorizontal: 16
652
+ },
653
+ facilityDetailTitle: {
654
+ fontFamily: "sf-bold",
655
+ color: TEXT_DARK,
656
+ fontSize: 14
657
+ },
658
+ facilityDetailContent: {
659
+ fontFamily: "sf-regular",
660
+ color: TEXT_DARK,
661
+ fontSize: 16,
662
+ lineHeight: 22
663
+ },
664
+ facilityDetailsContainer: {
665
+ flex: 1
666
+ },
667
+ facilityDetailsTextContainer: {
668
+ flex: 1,
669
+ justifyContent: "center"
670
+ },
671
+ facilityDetailContainer: {
672
+ marginTop: 16,
673
+ flexDirection: "row"
674
+ },
675
+ facilityDetailTitleContainer: {
676
+ width: 100,
677
+ marginRight: 10
678
+ },
679
+ titleContainer: {
680
+ paddingVertical: 16,
681
+ paddingTop: 20
682
+ },
683
+ eventTitle: {
684
+ fontFamily: "sf-bold",
685
+ fontSize: 24,
686
+ lineHeight: 32,
687
+ color: TEXT_DARK,
688
+ backgroundColor: "transparent",
689
+ flex: 1
690
+ },
691
+ textLink: {
692
+ fontFamily: "sf-medium",
693
+ fontSize: 16,
694
+ lineHeight: 22
695
+ },
696
+ grayPlaceholder: {
697
+ backgroundColor: LINEGREY
698
+ },
699
+ centerContainer: {
700
+ flex: 1,
701
+ justifyContent: "center",
702
+ alignItems: "center",
703
+ paddingHorizontal: 20
704
+ },
705
+ errorText: {
706
+ fontSize: 16,
707
+ color: TEXT_MID,
708
+ textAlign: "center"
709
+ },
710
+ filesContainer: {
711
+ marginVertical: 8
712
+ }
713
+ });
714
+ const mapStateToProps = (state, ownProps) => {
715
+ return {
716
+ colourBrandingMain: Colours.getMainBrandingColourFromState(state),
717
+ colourBrandingHeader: Colours.getMainBrandingColourFromState(state),
718
+ featureDefinition: selectFeatureDefinition(state),
719
+ user: state.user
720
+ };
721
+ };
722
+ export default connect(mapStateToProps, null, null, {
723
+ forwardRef: true
724
+ })(FeatureDetailScreen);
725
+ //# sourceMappingURL=FeatureDetailScreen.js.map