muba-posting 5.0.13 → 5.0.15

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.
package/Posting.js CHANGED
@@ -20,6 +20,7 @@ import Publish6 from './Publish6';
20
20
  import Preview from './Preview';
21
21
  import PublishProgressBar from './PublishProgressBar.js';
22
22
  import EditHead from './EditHead.js';
23
+ import PictureSelector from 'muba-picture';
23
24
  import PopupPermissions from 'muba-popup-permissions';
24
25
  import PaymentOnlinePopup from 'muba-payment-online';
25
26
  import { createIconSetFromFontello } from 'react-native-vector-icons';
@@ -58,6 +59,7 @@ export default class Posting extends React.Component {
58
59
  currentScreen: 1,
59
60
  fontLoaded: false,
60
61
  isLoading: false,
62
+ showImageBrowser: false,
61
63
  headerHeight: 0,
62
64
  progressBarHeight: 0,
63
65
  adId: this.props.adId,
@@ -90,7 +92,6 @@ export default class Posting extends React.Component {
90
92
  pax: null,
91
93
  minNights: null,
92
94
  images: [],
93
- deletedFiles: [],
94
95
  age: null,
95
96
  floorType: null,
96
97
  floorNumber: null,
@@ -430,6 +431,20 @@ export default class Posting extends React.Component {
430
431
  return new Promise(resolve => setTimeout(resolve, ms));
431
432
  }
432
433
 
434
+ _openPictureSelector() {
435
+ this.setState({ showImageBrowser: true })
436
+ }
437
+
438
+ imageBrowserCallback = async (photos) => {
439
+ this.setState({
440
+ showImageBrowser: false
441
+ }, () => {
442
+ for (let photo of photos) {
443
+ this.publish4?.loadUri(photo)
444
+ }
445
+ });
446
+ }
447
+
433
448
  getAd = async (id) => {
434
449
  const responseJson = await this.props.request(this, AD, {
435
450
  adId: id
@@ -438,6 +453,12 @@ export default class Posting extends React.Component {
438
453
  return responseJson;
439
454
  }
440
455
 
456
+ _savePicture = async (picture) => {
457
+ this.setState({
458
+ showImageBrowser: false
459
+ }, () => this.publish4?.loadUri(picture));
460
+ }
461
+
441
462
  render() {
442
463
  return (
443
464
  <View style={[commonStyles.flex1, commonStyles.containerBg]}>
@@ -447,6 +468,10 @@ export default class Posting extends React.Component {
447
468
  <View onLayout={(event) => this.setState({ headerHeight: event.nativeEvent.layout.height })}>
448
469
  {!this.state.showImageBrowser && this.state.view !== Views.PAYMENT_ONLINE ? this.props.topBar : null}
449
470
  </View>
471
+ {this.state.showImageBrowser ?
472
+ <PictureSelector max={this.state.maxPictures - this.state.postingAd.images.length} callback={this.imageBrowserCallback} savePicture={this._savePicture} goBack={() => this.goBack(true)} />
473
+ :
474
+ null}
450
475
 
451
476
  <PopupPermissions ref={(element) => this.popupPermissions = element} camera={true} mediaLibrary={true} message={strings('setup.permissionsMessage')} onClose={this.loadData} />
452
477
 
@@ -468,6 +493,7 @@ export default class Posting extends React.Component {
468
493
 
469
494
  {this.state.view === Views.PUBLISH_1 ?
470
495
  <Publish1 postingAd={this.state.postingAd}
496
+ baseUrl={this.props.baseUrl}
471
497
  request={this.props.request}
472
498
  context={this.props.context}
473
499
  showLoading={() => this._showLoading()}
@@ -548,6 +574,7 @@ export default class Posting extends React.Component {
548
574
  fullPosting={this.state.fullPosting}
549
575
  progressBarHeight={this.state.progressBarHeight}
550
576
  headerHeight={this.state.headerHeight}
577
+ openPictureSelector={() => this._openPictureSelector()}
551
578
  maxPictures={this.state.maxPictures} />
552
579
  :
553
580
  null
package/Publish1.js CHANGED
@@ -3,12 +3,9 @@ import { Text, View, TouchableHighlight, Dimensions } from 'react-native';
3
3
  import { strings } from 'muba-i18n';
4
4
  import commonStyles from './commonStyles';
5
5
  import RadioButtonGroup from 'muba-radio-button-group';
6
- import InputSelect from 'muba-input-select';
7
6
  import { Views } from './utils/Views';
8
7
  const window = Dimensions.get('window');
9
8
 
10
- const GET_PROMOTIONS = { method: 'GET', url: '/controller/posting/promotions' };
11
- const PROMOTION_LOCATION = { method: 'GET', url: '/controller/promotions/{promotionId}/location' };
12
9
  const GET_TRANSACTIONS = { method: 'GET', url: '/controller/transactions' };
13
10
 
14
11
  export default class Publish1 extends React.Component {
@@ -21,10 +18,6 @@ export default class Publish1 extends React.Component {
21
18
  this.state = {
22
19
  isLoading: false,
23
20
  showTypeBienError: false,
24
- promotionOptions: {
25
- elements: [{ section: true, value: null, label: strings('setup.selectPromotion') }],
26
- selectedItem: this.props.postingAd.promotionId
27
- },
28
21
  transactionOptions: { elements: [], selectedItem: this.props.postingAd.transaction },
29
22
  typeBienOptions: { elements: [], selectedItem: this.props.postingAd.adType }
30
23
  };
@@ -54,24 +47,6 @@ export default class Publish1 extends React.Component {
54
47
  if (this.state.minHeight != minHeight) {
55
48
  this.setState({ minHeight: minHeight })
56
49
  }
57
-
58
- this.loadPromotions();
59
- }
60
-
61
- async loadPromotions() {
62
- const responseJson = await this.props.request(this.props.context, GET_PROMOTIONS);
63
- if (responseJson.httpStatus === 200) {
64
- const promotionOptions = {
65
- elements: [this.state.promotionOptions.elements[0]],
66
- selectedItem: this.props.postingAd.promotionId
67
- };
68
-
69
- responseJson.list.map((item) => {
70
- promotionOptions.elements.push(item);
71
- });
72
-
73
- this.setState({ promotionOptions: promotionOptions });
74
- }
75
50
  }
76
51
 
77
52
  getAdTypes(transaction) {
@@ -113,23 +88,6 @@ export default class Publish1 extends React.Component {
113
88
  this.props.postingAd.adType = value;
114
89
  }
115
90
 
116
- async changePromotion(value) {
117
- const responseJson = await this.props.request(this.props.context, PROMOTION_LOCATION, {
118
- promotionId: value
119
- });
120
- if (responseJson.httpStatus === 200) {
121
- this.props.postingAd.latitude = responseJson.latitude;
122
- this.props.postingAd.longitude = responseJson.longitude;
123
- this.props.postingAd.region = responseJson.regionId;
124
- this.props.postingAd.province = responseJson.provinceId;
125
- this.props.postingAd.city = responseJson.cityId;
126
- this.props.postingAd.district = responseJson.districtId;
127
- this.props.postingAd.town = responseJson.townId;
128
- this.props.postingAd.exactlyLocated = true;
129
- }
130
- this.props.postingAd.promotionId = value;
131
- }
132
-
133
91
  async nextStep() {
134
92
  if (this.validateForm()) {
135
93
  for (var i = 0; i < this.state.typeBienOptions.elements.length; i++) {
@@ -156,11 +114,7 @@ export default class Publish1 extends React.Component {
156
114
  }
157
115
 
158
116
  validateForm() {
159
- let validPromotions = this.state.promotionOptions.elements.length <= 1;
160
- if (!validPromotions) {
161
- validPromotions = this.inputSelectPromotions.onSubmitValidate();
162
- }
163
- return validPromotions && this.radioButtonAdType.onSubmitValidate();
117
+ return this.radioButtonAdType.onSubmitValidate();
164
118
  }
165
119
 
166
120
  render() {
@@ -170,18 +124,6 @@ export default class Publish1 extends React.Component {
170
124
  <View style={commonStyles.progressbarInputArea}>
171
125
  <Text style={commonStyles.progressbarInputAreaH3}>{strings('setup.typeTransaction')}</Text>
172
126
 
173
- <InputSelect
174
- label={strings('setup.selectPromotion')}
175
- placeholder={strings('setup.select')}
176
- labelStyle={commonStyles.progressbarField}
177
- ref={(element) => this.inputSelectPromotions = element}
178
- visible={this.state.promotionOptions.elements.length > 1}
179
- required={true}
180
- scroll={(ref) => this.props.scroll(ref)}
181
- options={this.state.promotionOptions}
182
- onChange={(value) => this.changePromotion(value)}
183
- selectStyle={commonStyles.inputSelect} />
184
-
185
127
  <RadioButtonGroup
186
128
  style={commonStyles.progressbarFieldContainer}
187
129
  required={true}
package/Publish2.js CHANGED
@@ -29,7 +29,7 @@ export default class Publish2 extends React.Component {
29
29
  if (await this.validateLocation()) {
30
30
  const responseCheckZone = await this.props.request(this.props.context, GET_CHECK_ZONE, {
31
31
  businessId: this.props.postingAd.businessId,
32
- townId: this.props.postingAd.city
32
+ cityId: this.props.postingAd.city
33
33
  });
34
34
 
35
35
  if (responseCheckZone.value === 'true') {
package/Publish2b.js CHANGED
@@ -220,7 +220,7 @@ export default class Publish2b extends React.Component {
220
220
  if (this.validateForm()) {
221
221
  const responseCheckZone = await this.props.request(this.props.context, GET_CHECK_ZONE, {
222
222
  businessId: this.props.postingAd.businessId,
223
- townId: this.props.postingAd.city
223
+ cityId: this.props.postingAd.city
224
224
  });
225
225
 
226
226
  if (responseCheckZone.value === 'true') {
package/Publish4.js CHANGED
@@ -1,7 +1,6 @@
1
1
  import React from 'react';
2
2
  import { Text, View, TouchableHighlight, TouchableOpacity, ImageBackground, Dimensions, Image } from 'react-native';
3
3
  import PopupAdvice from 'muba-popup-advice';
4
- import PictureSelector from 'muba-picture';
5
4
  import { strings } from 'muba-i18n';
6
5
  import commonStyles from './commonStyles';
7
6
  import { Views } from './utils/Views';
@@ -15,11 +14,24 @@ export default class Publish4 extends React.Component {
15
14
  super(props);
16
15
 
17
16
  this.state = {
18
- minHeight: 0
17
+ images: [],
18
+ popupSelectPhotoVisible: false,
19
+ showErrorNoSelectedImages: false,
20
+ allPhotosSelected: false,
21
+ updateMainPhoto: false,
22
+ isLoading: false,
23
+ imageBrowserOpen: false,
24
+ imageSize: [],
25
+ containerWidth: 0,
26
+ containerHeight: 0
19
27
  }
20
28
  }
21
29
 
22
30
  componentDidMount() {
31
+ for (let photo of this.props.postingAd.images) {
32
+ this.loadImage(photo);
33
+ }
34
+
23
35
  const componentsHeight = this.props.headerHeight + this.props.progressBarHeight;
24
36
  const minHeight = window.height - componentsHeight;
25
37
  if (this.state.minHeight != minHeight) {
@@ -27,19 +39,227 @@ export default class Publish4 extends React.Component {
27
39
  }
28
40
  }
29
41
 
42
+ componentDidUpdate = async (prevProps) => {
43
+ if (!this.isSameList(prevProps.postingAd.images, this.props.postingAd.images)) {
44
+ this.setState({ images: [] }, () => {
45
+ for (let photo of this.props.postingAd.images) {
46
+ this.loadImage(photo);
47
+ }
48
+ });
49
+ }
50
+ }
51
+
52
+ isSameList = (firstList, secondList) => {
53
+ if (firstList.length != secondList.length) {
54
+ return false;
55
+ }
56
+ for (let index = 0; index < firstList.length; ++index) {
57
+ if (firstList[index].id != secondList[index].id || firstList[index].uri != secondList[index].uri) {
58
+ return false;
59
+ }
60
+ }
61
+ return true;
62
+ }
63
+
64
+ async loadUri(photo) {
65
+ if (photo) {
66
+ const photoStr = photo.uri.lastIndexOf('.') > 0 && photo.uri.lastIndexOf('.') > photo.uri.length - 5 ? photo.uri : photo.filename;
67
+ const fileType = photoStr.substring(photoStr.lastIndexOf('.') + 1).toLowerCase();
68
+
69
+ const image = {
70
+ uri: photo.uri,
71
+ name: 'photo_' + this.state.images.length + '.' + fileType,
72
+ type: 'image/' + fileType,
73
+ mainPicture: this.state.images.length === 0,
74
+ referenceType: 'AD',
75
+ referenceId: this.props.postingAd.id,
76
+ extraInfo: this.state.images.length,
77
+ width: photo.width,
78
+ height: photo.height
79
+ }
80
+
81
+ this.loadImage(image);
82
+ }
83
+ }
84
+
85
+ loadImage(image) {
86
+ let imagesArray = this.state.images;
87
+ imagesArray.push(image);
88
+
89
+ this.calculateImageSize(image, imagesArray.length - 1)
90
+
91
+ this.setState({
92
+ showErrorNoSelectedImages: false,
93
+ images: imagesArray
94
+ }, () => {
95
+ if (this.state.images.length == this.props.maxPictures) {
96
+ this.setState({ allPhotosSelected: true });
97
+ } else if (this.state.images.length == 1) {
98
+ this.selectMainPhoto(this.state.images[0]);
99
+ }
100
+ });
101
+ }
102
+
103
+ async imageExists(imageUrl) {
104
+ return fetch(imageUrl).then(response => response.status === 200);
105
+ }
106
+
107
+ async deleteImage(itemId, index) {
108
+ if (itemId) {
109
+ if (!this.props.postingAd.deletedFiles) {
110
+ this.props.postingAd.deletedFiles = [];
111
+ }
112
+ this.props.postingAd.deletedFiles.push(itemId);
113
+ }
114
+
115
+ let imagesArray = [...this.state.images];
116
+ let imageSize = [...this.state.imageSize];
117
+ imagesArray.splice(index, 1)
118
+ imageSize.splice(index, 1)
119
+
120
+ await this.setState({
121
+ allPhotosSelected: false,
122
+ images: imagesArray,
123
+ imageSize: imageSize
124
+ });
125
+
126
+ if (this.state.images.length >= 1) {
127
+ this.selectMainPhoto(this.state.images[0]);
128
+ }
129
+ }
130
+
131
+ selectMainPhoto(itemSelected) {
132
+ let imagesArray = this.state.images.slice();
133
+ let imageSize = this.state.imageSize.slice();
134
+
135
+ for (let imageObject of imagesArray) {
136
+ imageObject.mainPicture = false;
137
+
138
+ if (imageObject.uri === itemSelected.uri) {
139
+ imageObject.mainPicture = true;
140
+ const imageIndex = imagesArray.indexOf(imageObject);
141
+ imagesArray.splice(imageIndex, 1);
142
+ imagesArray.splice(0, 0, imageObject);
143
+
144
+ const size = imageSize.splice(imageIndex, 1);
145
+ imageSize.splice(0, 0, ...size);
146
+ }
147
+ }
148
+ let index = 0;
149
+ for (let imageObject of imagesArray) {
150
+ imageObject.name = 'photo_' + index + (imageObject.id ? '_' + imageObject.id : '') + imageObject.name.substring(imageObject.name.indexOf('.'));
151
+ imageObject.extraInfo = index;
152
+ ++index;
153
+ }
154
+
155
+ this.setState({
156
+ updateMainPhoto: true,
157
+ images: imagesArray,
158
+ imageSize: imageSize
159
+ });
160
+ }
161
+
30
162
  nextStep() {
31
- this.setState({ showErrorNoSelectedImages: false });
32
- if (this.props.postingAd.id == null || this.props.fullPosting) {
33
- if (this.props.postingAd.adTypeDetails.filter(function (detail) {
34
- return detail.value !== 'surface' && detail.value !== 'baths' && detail.value !== 'pax' && detail.value !== 'minNights' &&
35
- detail.value !== 'rooms' && detail.value !== 'pieces' && detail.value !== 'pricePeriod'
36
- }).length > 0) {
37
- this.props.goToPage(Views.PUBLISH_5);
163
+ if (this.state.images.length == 0) {
164
+ this.setState({ showErrorNoSelectedImages: true });
165
+ } else {
166
+ this.props.postingAd.images = this.state.images;
167
+ this.setState({ showErrorNoSelectedImages: false });
168
+ if (this.props.postingAd.id == null || this.props.fullPosting) {
169
+ if (this.props.postingAd.adTypeDetails.filter(function (detail) {
170
+ return detail.value !== 'surface' && detail.value !== 'baths' && detail.value !== 'pax' && detail.value !== 'minNights' &&
171
+ detail.value !== 'rooms' && detail.value !== 'pieces' && detail.value !== 'pricePeriod'
172
+ }).length > 0) {
173
+ this.props.goToPage(Views.PUBLISH_5);
174
+ } else {
175
+ this.props.goToPage(Views.PUBLISH_6);
176
+ }
38
177
  } else {
39
- this.props.goToPage(Views.PUBLISH_6);
178
+ this.props.saveEditAd();
40
179
  }
180
+ }
181
+ }
182
+
183
+ rerenderImage(index) {
184
+ const images = this.state.images;
185
+ if (images[index].uri.indexOf('?t=') < 0) {
186
+ images[index].uri = images[index].uri + '?t=' + Date.now();
41
187
  } else {
42
- this.props.saveEditAd();
188
+ images[index].uri = images[index].uri.substring(0, images[index].uri.indexOf('?t=')) + '?t=' + Date.now();
189
+ }
190
+
191
+ setTimeout(() => {
192
+ this.setState({
193
+ images: images
194
+ });
195
+ }, 500);
196
+ }
197
+
198
+ calculateImageSize = async (image) => {
199
+ if (image.width && image.height) {
200
+ this.setImageSize(image.width, image.height);
201
+ } else if (!image.uri.startsWith('https://') || await this.imageExists(image.uri)) {
202
+ Image.getSize(image.uri, (width, height) => {
203
+ this.setImageSize(width, height);
204
+ });
205
+ } else {
206
+ setTimeout(() => this.calculateImageSize(image), 500);
207
+ }
208
+ }
209
+
210
+ setImageSize(width, height) {
211
+ let imageSize = this.state.imageSize;
212
+ if (this.state.containerWidth !== 0 && this.state.containerHeight !== 0) {
213
+ const containerRatio = this.state.containerWidth / this.state.containerHeight;
214
+ const imageRatio = width / height;
215
+
216
+ let finalWidth;
217
+ let finalHeight;
218
+ if (imageRatio > containerRatio) {
219
+ if (width > this.state.containerWidth) {
220
+ finalWidth = this.state.containerWidth;
221
+ } else {
222
+ finalWidth = width;
223
+ }
224
+ finalHeight = height * (finalWidth / width);
225
+ } else if (imageRatio < containerRatio) {
226
+ if (height > this.state.containerHeight) {
227
+ finalHeight = this.state.containerHeight;
228
+ } else {
229
+ finalHeight = height;
230
+ }
231
+ finalWidth = width * (finalHeight / height);
232
+ } else {
233
+ if (width > this.state.containerWidth) {
234
+ finalWidth = this.state.containerWidth;
235
+ finalHeight = this.state.containerHeight;
236
+ } else {
237
+ finalWidth = width;
238
+ finalHeight = height;
239
+ }
240
+ }
241
+ imageSize.push({
242
+ width: finalWidth,
243
+ height: finalHeight,
244
+ marginVertical: (this.state.containerHeight - finalHeight) / 2,
245
+ marginHorizontal: (this.state.containerWidth - finalWidth) / 2
246
+ });
247
+ } else {
248
+ imageSize.push({
249
+ width: '100%',
250
+ height: '100%',
251
+ marginVertical: 0,
252
+ marginHorizontal: 0
253
+ })
254
+ }
255
+ this.setState({
256
+ imageSize: imageSize
257
+ });
258
+ }
259
+
260
+ setContainerWidth = (event) => {
261
+ if (this.state.containerWidth === 0) {
262
+ this.setState({ containerWidth: event.nativeEvent.layout.width, containerHeight: event.nativeEvent.layout.height })
43
263
  }
44
264
  }
45
265
 
@@ -47,24 +267,64 @@ export default class Publish4 extends React.Component {
47
267
  return (
48
268
  <View style={{ minHeight: this.state.minHeight }}>
49
269
  <View style={commonStyles.formFieldset}>
50
- <PictureSelector
51
- context={this.props.context}
52
- request={this.props.request}
53
- title={strings('setup.publishPhotos')}
54
- referenceId={this.props.postingAd.id}
55
- referenceType='AD'
56
- maxPictures={this.props.maxPictures}
57
- images={this.props.postingAd.images}
58
- video={this.props.postingAd.video}
59
- updateImages={images => this.props.postingAd.images = images}
60
- updateVideo={video => this.props.postingAd.video = video}
61
- deletedFiles={this.props.postingAd.deletedFiles}
62
- showVideo={this.props.businessId} />
63
- <View style={commonStyles.conseilBox}>
64
- <TouchableOpacity style={commonStyles.alignCenter} activeOpacity={1} onPress={() => this.popupShowAdvice.show()}>
65
- <FontAwesomeIcon style={commonStyles.conseilIcon} name="help-circled" />
66
- <Text style={commonStyles.conseilText}>{strings('setup.advice')}</Text>
67
- </TouchableOpacity>
270
+ <View style={commonStyles.progressbarInputArea}>
271
+ <Text style={commonStyles.progressbarInputAreaH3}>{strings('setup.publishPhotos')}</Text>
272
+ {this.state.allPhotosSelected ?
273
+ <View style={commonStyles.confirmNote}>
274
+ <View style={commonStyles.row}>
275
+ <FontAwesomeIcon style={commonStyles.confirmIcon} name="check" />
276
+ <Text style={commonStyles.confirmNoteText}>{strings('setup.allPicturesSelected')}</Text>
277
+ </View>
278
+ </View>
279
+ :
280
+ <View>
281
+ <Text style={this.state.showErrorNoSelectedImages ? [commonStyles.subNote, commonStyles.red] : commonStyles.subNote}>{strings('setup.publishPhotosSubNote1', { maxPictures: this.props.maxPictures })}</Text>
282
+ <Text style={commonStyles.subNote}>{strings('setup.publishPhotosSubNote2')}</Text>
283
+ </View>
284
+ }
285
+
286
+ <View style={commonStyles.progressbarFieldContainer}>
287
+ <View style={{ flexDirection: 'row', flex: 1, flexWrap: 'wrap', alignItems: 'flex-start' }}>
288
+ {this.state.allPhotosSelected ?
289
+ null
290
+ :
291
+ <TouchableOpacity onLayout={this.setContainerWidth} style={[commonStyles.photoBox, this.state.showErrorNoSelectedImages ? commonStyles.fieldError : null]} onPress={() => this.props.openPictureSelector()}>
292
+ <TouchableOpacity style={[commonStyles.photoBoxAddIcon]} onPress={() => this.props.openPictureSelector()}>
293
+ <TouchableHighlight underlayColor="#104a7a" onPress={() => this.props.openPictureSelector()}>
294
+ <FontAwesomeIcon style={commonStyles.photoAddIcon} name="plus-circled" />
295
+ </TouchableHighlight>
296
+ <TouchableOpacity activeOpacity={0.5} onPress={() => this.props.openPictureSelector()}>
297
+ <Text style={commonStyles.photoAddText}>{strings('setup.addPhotos')}</Text>
298
+ </TouchableOpacity>
299
+ </TouchableOpacity>
300
+ </TouchableOpacity>
301
+ }
302
+ {this.state.images.map((item, index) => {
303
+ return (
304
+ <View style={[commonStyles.photoBox]} onLayout={this.setContainerWidth} key={index}>
305
+ <Image style={{ width: this.state.imageSize[index]?.width, height: this.state.imageSize[index]?.height, marginVertical: this.state.imageSize[index]?.marginVertical, marginHorizontal: this.state.imageSize[index]?.marginHorizontal }}
306
+ resizeMode='cover' source={{ uri: item.uri }} borderRadius={10} onError={() => this.rerenderImage(index)} />
307
+ <ImageBackground style={[commonStyles.photoControls, commonStyles.row]} source={require('./assets/images/bg-shadow.png')} resizeMode='stretch' borderRadius={1.5}>
308
+
309
+ <TouchableHighlight style={commonStyles.leftIcon} onPress={() => this.deleteImage(item.id, index)}>
310
+ <FontAwesomeIcon style={commonStyles.whiteIcon} name="cancel-circled" />
311
+ </TouchableHighlight>
312
+ <TouchableHighlight style={commonStyles.rightIcon} onPress={() => this.selectMainPhoto(item)}>
313
+ <FontAwesomeIcon style={[commonStyles.heartIcon, item.mainPicture ? '' : commonStyles.whiteIcon]} name={item.mainPicture ? 'heart' : 'heart-empty'} />
314
+ </TouchableHighlight>
315
+
316
+ </ImageBackground>
317
+ </View>
318
+ )
319
+ })}
320
+ </View>
321
+ <View style={commonStyles.conseilBox}>
322
+ <TouchableOpacity style={commonStyles.alignCenter} activeOpacity={1} onPress={() => this.popupShowAdvice.show()}>
323
+ <FontAwesomeIcon style={commonStyles.conseilIcon} name="help-circled" />
324
+ <Text style={commonStyles.conseilText}>{strings('setup.advice')}</Text>
325
+ </TouchableOpacity>
326
+ </View>
327
+ </View>
68
328
  </View>
69
329
  </View>
70
330
  <View style={commonStyles.buttomButton}>
@@ -79,7 +339,7 @@ export default class Publish4 extends React.Component {
79
339
  <Text />
80
340
  <Text style={commonStyles.popupText}>{strings('setup.adviceText2')}</Text>
81
341
  </PopupAdvice>
82
- </View >
342
+ </View>
83
343
  );
84
344
  }
85
345
  }
package/locales/ar.json CHANGED
@@ -30,7 +30,12 @@
30
30
  "propertyCharacteristics": "خصائص العقار",
31
31
  "price": "السعر",
32
32
  "currency": "العملة",
33
+ "selectPicture": "حدد الصورة",
34
+ "galleryOrCamera": "هل تريد استخدام الرواق أو الكاميرا؟",
35
+ "addPhotos": "إضافة",
33
36
  "publishPhotos": "انشروا صوركم",
37
+ "publishPhotosSubNote1": "الحد الأدنى صورة واحدة. الحد الأقصى {{maxPictures}} صورة.",
38
+ "publishPhotosSubNote2": "انقروا على القلب للقيام بصورة الغلاف",
34
39
  "advice": "نصائح",
35
40
  "adviceText1": " الحد الأقصى لحجم الصورة 5 ميغابايت ويجب ألا يتجاوز 3456 × 3456 بكسل. يجب تنزيل الصور بحجم .jpg أو .gif أو .png.",
36
41
  "adviceText2": "المنشورات التي تتضمن صورة تتلقى ما يصل إلى 3 مرات أكثر من الزيارات. اختر كصورة غلاف تلك التي تمثل أفضل ميزات العقار.",
@@ -104,14 +109,16 @@
104
109
  "posting_tip_description_9": "من الأفضل ذكر جميع الخصائص المميزة لهذا العقار ",
105
110
  "posting_tip_description_10": "ملاحظة: لا تضع رقم الهاتف أو البريد الإلكتروني في المكان المخصص للوصف، سيتم ربطكم مباشرة مع الزبون ",
106
111
  "contactOwner": "اتصل بالناشر",
112
+ "allPicturesSelected": "لقد قمت بتحديد جميع الصور",
113
+ "selected": "المختار(ة)",
114
+ "max": "(كحد أقصى)",
107
115
  "orientation": "اتجاه",
108
116
  "north": "شمال",
109
117
  "south": "جنوب",
110
118
  "west": "الغرب",
111
119
  "est": "شرق",
112
120
  "highlight": "رفع قيمة",
113
- "ad_cant_post_zone": "لا يمكنك النشر في هذه المدينة",
114
- "selectPromotion": "إلى أي ترويج وتخفيض تنتمي الممتلكات الخاصة بك؟*"
121
+ "ad_cant_post_zone":"لا يمكنك النشر في هذه المدينة"
115
122
  },
116
123
  "product": {
117
124
  "LISTING": "قوائم",
package/locales/en.json CHANGED
@@ -30,7 +30,12 @@
30
30
  "propertyCharacteristics": "Characteristics of the property",
31
31
  "price": "Price",
32
32
  "currency": "Currency",
33
+ "selectPicture": "Select image",
34
+ "galleryOrCamera": "Do you want to use the gallery or the camera?",
35
+ "addPhotos": "Add",
33
36
  "publishPhotos": "Publish your photos",
37
+ "publishPhotosSubNote1": "Minimum 1 photo. Maximum {{maxPictures}} photos.",
38
+ "publishPhotosSubNote2": "Click on the heart to make the cover photo.",
34
39
  "advice": "Advices",
35
40
  "adviceText1": "The size of the image has a maximum of 5 MB and must not exceed 3456 x 3456 pixels. Images must be downloaded in .jpg, .gif or .png format.",
36
41
  "adviceText2": "Publications including a photo receive up to 3 times more visits. Choose as a cover photo which best represents the most important features of the property",
@@ -104,14 +109,16 @@
104
109
  "posting_tip_description_9": "Highlight the qualities which make this property stand out.",
105
110
  "posting_tip_description_10": "Note: Don't include your telephone number or email address in these observations they'll be shown to anyone interested when they send a request for more information.",
106
111
  "contactOwner": "Price on request",
112
+ "allPicturesSelected": "You have already selected all the photos",
113
+ "selected": "Selected",
114
+ "max": "(max)",
107
115
  "orientation": "Orientation",
108
116
  "north": "North",
109
117
  "south": "South",
110
118
  "west": "West",
111
119
  "est": "Est",
112
120
  "highlight": "Highlight",
113
- "ad_cant_post_zone": "You can't post in this city",
114
- "selectPromotion": "What promotion does your property belong to? *"
121
+ "ad_cant_post_zone":"You can't post in this city"
115
122
  },
116
123
  "product": {
117
124
  "LISTING": "Listing",
package/locales/es.json CHANGED
@@ -30,7 +30,12 @@
30
30
  "propertyCharacteristics": "Características de la propiedad",
31
31
  "price": "Precio",
32
32
  "currency": "Moneda",
33
+ "selectPicture": "Seleccionar foto",
34
+ "galleryOrCamera": "¿Quieres usar la galería o la cámara?",
35
+ "addPhotos": "Añadir",
33
36
  "publishPhotos": "Subir fotos",
37
+ "publishPhotosSubNote1": "Mínimo 1 foto. Máximo {{maxPictures}} fotos.",
38
+ "publishPhotosSubNote2": "Haz click en el corazón para marcar la foto de portada",
34
39
  "advice": "Consejos",
35
40
  "adviceText1": "El tamaño de la imagen tiene un máximo de 20 MB y no debe exceder los 3456 x 3456 píxeles. Las imágenes deben descargarse en formato .jpg, .gif o .png.",
36
41
  "adviceText2": "Las anuncios que incluyan fotos reciben hasta 3 veces más de visitas. Elija como foto de portada la que mejor represente las características más importantes de la propiedad.",
@@ -104,14 +109,16 @@
104
109
  "posting_tip_description_9": "Comenta las cualidades que hacen que esta propiedad destaque.",
105
110
  "posting_tip_description_10": "Nota: No incluyas tu número de teléfono o dirección de correo electrónico en estas observaciones. Se mostrarán a cualquier persona interesada cuando envíen una solicitud para obtener más información.",
106
111
  "contactOwner": "Precio a consultar",
112
+ "allPicturesSelected": "Ya has seleccionado todas las fotos",
113
+ "selected": "Seleccionado",
114
+ "max": "(max)",
107
115
  "orientation": "Orientación",
108
116
  "north": "Norte",
109
117
  "south": "Sur",
110
118
  "west": "Oeste",
111
119
  "est": "Este",
112
120
  "highlight": "Destacar",
113
- "ad_cant_post_zone": "No puedes publicar en esta ciudad",
114
- "selectPromotion": "¿A qué promoción pertenece tu bien? *"
121
+ "ad_cant_post_zone":"No puedes publicar en esta ciudad"
115
122
  },
116
123
  "product": {
117
124
  "LISTING": "Listing",
package/locales/fr.json CHANGED
@@ -30,7 +30,12 @@
30
30
  "propertyCharacteristics": "Caractéristiques du bien",
31
31
  "price": "Prix",
32
32
  "currency": "Devise",
33
+ "selectPicture": "Sélectionnez l'image",
34
+ "galleryOrCamera": "Voulez-vous utiliser la galerie ou la caméra?",
35
+ "addPhotos": "Ajouter",
33
36
  "publishPhotos": "Publiez vos photos",
37
+ "publishPhotosSubNote1": "Minimum 1 photo. Maximum {{maxPictures}} photos.",
38
+ "publishPhotosSubNote2": "Cliquez sur Favoris pour sélectionner la photo de couverture.",
34
39
  "advice": "Conseils",
35
40
  "adviceText1": "La taille de l'image a un maximum de 5 Mo et ne doit pas dépasser 3456 x 3456 pixels. Les images doivent être téléchargées au format .jpg, .gif ou .png.",
36
41
  "adviceText2": "Les publications incluant une photo reçoivent jusqu'à 3 fois plus de visites. Choisissez comme photo de couverture celle qui représente le mieux les caractéristiques les plus importantes du bien",
@@ -104,14 +109,16 @@
104
109
  "posting_tip_description_9": "Renforcez les caractéristiques uniques de ce bien.",
105
110
  "posting_tip_description_10": "Remarque: Ne mettez pas votre numéro de téléphone ou votre adresse email dans les commentaires, notre équipe se chargera de vous envoyer automatiquement toutes les demandes d'informations.",
106
111
  "contactOwner": "Prix à consulter",
112
+ "allPicturesSelected": "Vous avez déjà sélectionné toutes les photos",
113
+ "selected": "Sélectionné(s)",
114
+ "max": "(max)",
107
115
  "orientation": "Orientation",
108
116
  "north": "Nord",
109
117
  "south": "South",
110
118
  "west": "Ouest",
111
119
  "est": "Est",
112
120
  "highlight": "Mettre en valeur",
113
- "ad_cant_post_zone": "Vous ne pouvez pas poster dans cette ville",
114
- "selectPromotion": "A quelle promotion appartient votre bien? *"
121
+ "ad_cant_post_zone":"Vous ne pouvez pas poster dans cette ville"
115
122
  },
116
123
  "product": {
117
124
  "LISTING": "Liste",
package/locales/it.json CHANGED
@@ -30,7 +30,12 @@
30
30
  "propertyCharacteristics": "Caratteristiche principali dell’immobile",
31
31
  "price": "Prezzo",
32
32
  "currency": "Valuta",
33
+ "selectPicture": "Seleziona immagine",
34
+ "galleryOrCamera": "Vuoi usare la galleria o la fotocamera?",
35
+ "addPhotos": "Aggiungi",
33
36
  "publishPhotos": "Pubblica le tue foto",
37
+ "publishPhotosSubNote1": "Minimo 1 foto. Massimo {{maxPictures}} foto.",
38
+ "publishPhotosSubNote2": "Clicca sul cuore per creare l’immagine di copertina.",
34
39
  "advice": "Consigli",
35
40
  "adviceText1": "La dimensione massima dell’immagine è di 20 MB e non può superare i 3456 x 3456 pixel. Le immagini devono essere scaricate in .jpg, .gif o .png.",
36
41
  "adviceText2": "Le pubblicazioni con foto ricevono fino a 3 volte più visualizzazioni. Scegli l’immagine di copertina che meglio rappresenta la caratteristica principale dell’immobile",
@@ -104,14 +109,16 @@
104
109
  "posting_tip_description_9": "Risalta le qualità principali dell’immobile.",
105
110
  "posting_tip_description_10": "Nota: Non includere il tuo numero di telefono o indirizzo e-mail in queste osservazioni. Verranno mostrate agli interessati quando invieranno la richiesta.",
106
111
  "contactOwner": "Prezzo su richiesta",
112
+ "allPicturesSelected": "Hai già selezionato tutte le foto",
113
+ "selected": "Selezionato",
114
+ "max": "(max)",
107
115
  "orientation": "Orientamento",
108
116
  "north": "Nord",
109
117
  "south": "Sud",
110
118
  "west": "Ovest",
111
119
  "est": "Est",
112
120
  "highlight": "Evidenziare",
113
- "ad_cant_post_zone": "Non puoi postare in questa città",
114
- "selectPromotion": "A quale promozione appartiene il tuo immobile? *"
121
+ "ad_cant_post_zone":"Non puoi postare in questa città"
115
122
  },
116
123
  "product": {
117
124
  "LISTING": "Inserzioni",
package/locales/nl.json CHANGED
@@ -30,7 +30,12 @@
30
30
  "propertyCharacteristics": "De belangrijkste kenmerken van het pand",
31
31
  "price": "Prijs",
32
32
  "currency": "Valuta",
33
+ "selectPicture": "Afbeelding selecteren",
34
+ "galleryOrCamera": "Wilt u de galerij of de camera gebruiken?",
35
+ "addPhotos": "Toevoegen",
33
36
  "publishPhotos": "Publiceer uw foto's",
37
+ "publishPhotosSubNote1": "Minimaa 1 foto. Maximaal {{maxPictures}} foto's.",
38
+ "publishPhotosSubNote2": "Klik op het hartje om hier uw omslagfoto van te maken.",
34
39
  "advice": "Adviezen",
35
40
  "adviceText1": "De afbeelding mag maximaal 20 MG zijn en mag niet meer dan 3456 x 3456 pixels zijn. Afbeeldingen moeten worden gedownload als .jpg, .gif of .png.",
36
41
  "adviceText2": "Publicaties met een foto worden drie keer zo vaak bezocht. Kies een omslagfoto die de belangrijkste kenmerken van het pand het beste benadrukken",
@@ -104,14 +109,16 @@
104
109
  "posting_tip_description_9": "Benadruk de kenmerken waardoor dit pand opvalt.",
105
110
  "posting_tip_description_10": "Opmerking: vermeld hier niet uw telefoonnummer of e-mailadres. Die worden getoond aan mensen die interesse hebben wanneer ze om meer informatie vragen.",
106
111
  "contactOwner": "Prijs op aanvraag",
112
+ "allPicturesSelected": "U hebt alle foto's al geselecteerd",
113
+ "selected": "Geselecteerd",
114
+ "max": "(max)",
107
115
  "orientation": "Oriëntatie",
108
116
  "north": "North",
109
117
  "south": "Zuid",
110
118
  "west": "Oost",
111
119
  "est": "North",
112
120
  "highlight": "Highlighting",
113
- "ad_cant_post_zone": "In deze stad mag je niet posten",
114
- "selectPromotion": "Bij welke promotie hoort uw accommodatie? *"
121
+ "ad_cant_post_zone":"In deze stad mag je niet posten"
115
122
  },
116
123
  "product": {
117
124
  "LISTING": "Advertenties",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "muba-posting",
3
- "version": "5.0.13",
3
+ "version": "5.0.15",
4
4
  "description": "Posting",
5
5
  "main": "Posting.js",
6
6
  "scripts": {