@woosmap/ui 4.186.0 → 4.187.1

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.
@@ -1,633 +0,0 @@
1
- import React, { Component } from 'react';
2
- import GoogleMapReact from 'google-map-react';
3
- import PropTypes from 'prop-types';
4
- import { motion, AnimatePresence } from 'framer-motion';
5
- import Demo from './SkeletonDemo';
6
- import Marker from '../Map/Marker';
7
- import Button from '../Button/Button';
8
- import { viewport, boundsFromViewport } from '../Map/drawOnMap';
9
- import Constants from '../../Constants';
10
- import { tr } from '../utils/locale';
11
- import IphoneTime from '../../images/iphone-time.png';
12
- import IphoneIcons from '../../images/iphone-right-icons.png';
13
- import IphoneBack from '../../images/iphone-back-button.png';
14
- import IphoneAvatar from '../../images/iphone-avatar.png';
15
- import McDo from '../../images/mcdo.png';
16
- import Carrefour from '../../images/carrefour.png';
17
- import Apple from '../../images/apple.png';
18
- import Zara from '../../images/zara.png';
19
- import Apollo from '../../images/apollo.png';
20
- import PizzaHut from '../../images/pizza-hut.png';
21
- import Restaurant from '../../images/restaurant_poi_icon.png';
22
- import TransactionChevron from '../../images/transaction-chevron.png';
23
-
24
- const transition = { ease: 'easeInOut', duration: 0.3 };
25
- const variants = (isPush, isPop) => ({
26
- enter() {
27
- return {
28
- x: 0,
29
- transition,
30
- transitionEnd: {
31
- // after animation has finished, reset the position to static
32
- position: 'static',
33
- },
34
- // keep top "layer" of animation as a fixed position
35
- ...(isPush
36
- ? {
37
- position: 'absolute',
38
- top: 0,
39
- right: 0,
40
- left: 0,
41
- bottom: 0,
42
- }
43
- : {}),
44
- };
45
- },
46
- initial() {
47
- return {
48
- x: isPush ? '100%' : '-25%',
49
- transition,
50
- // keep top "layer" of animation as a fixed position
51
- position: 'absolute',
52
- top: 0,
53
- right: 0,
54
- left: 0,
55
- bottom: 0,
56
- };
57
- },
58
-
59
- // an updated history.action is provided in AnimatedSwitch via "custom" prop for AnimatePresence
60
- exit() {
61
- return {
62
- x: isPop ? '100%' : '-10%',
63
- zIndex: isPop ? 1 : -1,
64
- transitionStart: {
65
- // after animation has finished, reset the position to static
66
- zIndex: -1,
67
- },
68
- transition,
69
-
70
- // keep top "layer" of animation as a fixed position
71
- // this will, however, reset the scroll position of the page being dismissed
72
- ...(isPop
73
- ? {
74
- position: 'absolute',
75
- top: 0,
76
- right: 0,
77
- left: 0,
78
- bottom: 0,
79
- }
80
- : {}),
81
- };
82
- },
83
- });
84
- const request = {
85
- merchants: [
86
- {
87
- dirty_name: 'MCDO UK 2231 EP',
88
- country: 'GB',
89
- merchant_id: '234482729011',
90
- },
91
- {
92
- dirty_name: 'Zara Fashion Retail, S.A.',
93
- country: 'IT',
94
- merchant_id: '*44532UY2T33219',
95
- },
96
- {
97
- dirty_name: 'APOLLO PHARMACY BANGALORE IN',
98
- country: 'IN',
99
- },
100
- {
101
- dirty_name: 'PIZZA HUT - SHOP 157',
102
- },
103
- {
104
- dirty_name: 'CARREFOUR CITY 3112846',
105
- country: 'FR',
106
- merchant_id: '9651781125',
107
- },
108
- {
109
- dirty_name: 'ITUNES.COM/BILL',
110
- country: 'IE',
111
- merchant_id: '2070070200925',
112
- },
113
- {
114
- dirty_name: 'Pepa SL Gracia',
115
- country: 'ES',
116
- merchant_id: '34J21189',
117
- },
118
- ],
119
- };
120
- const response = {
121
- merchants: [
122
- {
123
- dirty_name: 'MCDO UK 2231 EP',
124
- clean_name: "McDonald's",
125
- date: '12:42',
126
- price: '£10',
127
- status: 'OK',
128
- logo: '956bcb3591a8976ff94871a59b09eecc',
129
- logo_url: 'https://api.woosmap.com/merchants/logos/956bcb3591a8976ff94871a59b09eecc.png',
130
- internal_logo: McDo,
131
- country: 'GB',
132
- merchant_id: '234482729011',
133
- place_id: 'ChIJGS7Sga0cdkgR46nd-S661TM',
134
- },
135
- {
136
- dirty_name: 'Zara Fashion Retail, S.A.',
137
- clean_name: 'Zara',
138
- date: '11:24',
139
- price: '98€',
140
- status: 'OK',
141
- internal_logo: Zara,
142
- logo: '72fc39033e0d9e923a0236cb874c9309',
143
- logo_url: 'https://api.woosmap.com/merchants/logos/72fc39033e0d9e923a0236cb874c9309.png',
144
- country: 'IT',
145
- merchant_id: '*44532UY2T33219',
146
- place_id: 'ChIJF2vQecLGhkcR83Zbpwpej3I',
147
- },
148
- {
149
- dirty_name: 'APOLLO PHARMACY BANGALORE IN',
150
- clean_name: 'Apollo Pharmacy',
151
- date: '11:07',
152
- price: '₹48',
153
- status: 'OK',
154
- internal_logo: Apollo,
155
- logo: 'c776d3336e0d8c2b9e893e9e92b2caf7',
156
- logo_url: 'https://api.woosmap.com/merchants/logos/c776d3336e0d8c2b9e893e9e92b2caf7.png',
157
- country: 'IN',
158
- },
159
- {
160
- dirty_name: 'PIZZA HUT - SHOP 157',
161
- clean_name: 'Pizza Hut',
162
- date: '10:36',
163
- price: '$12',
164
- status: 'OK',
165
- internal_logo: PizzaHut,
166
- logo: 'd5463410f32a5f497459ac79552d3ce3',
167
- logo_url: 'https://api.woosmap.com/merchants/logos/d5463410f32a5f497459ac79552d3ce3.png',
168
- country: '',
169
- },
170
- {
171
- dirty_name: 'CARREFOUR CITY 3112846',
172
- clean_name: 'Carrefour City',
173
- date: '10:07',
174
- price: '77€',
175
- status: 'OK',
176
- internal_logo: Carrefour,
177
- logo: '08ee8a3cecbcd3b7d9103bcf0e04db7e',
178
- logo_url: 'https://api.woosmap.com/merchants/logos/08ee8a3cecbcd3b7d9103bcf0e04db7e.png',
179
- country: 'FR',
180
- merchant_id: '9651781125',
181
- place_id: 'ChIJJ7ZEZDUnVQ0Ru5gudUqdvKM',
182
- },
183
- {
184
- dirty_name: 'ITUNES.COM/BILL',
185
- clean_name: 'Apple',
186
- status: 'OK',
187
- date: '09:14',
188
- price: '2€99',
189
- internal_logo: Apple,
190
- logo: '5eb75a5239b76287f44021f8e6e1bd41',
191
- logo_url: 'https://api.woosmap.com/merchants/logos/5eb75a5239b76287f44021f8e6e1bd41.png',
192
- country: 'IE',
193
- merchant_id: '2070070200925',
194
- place_id: '',
195
- },
196
- {
197
- status: 'OK',
198
- clean_name: '',
199
- logo: '',
200
- logo_url: '',
201
- price: '60€',
202
- country: 'ES',
203
- internal_logo: Restaurant,
204
- dirty_name: 'Pepa SL Gracia',
205
- merchant_id: '34J21189',
206
- place_id: 'ChIJZ9fQvb2ipBIRyaZy8wUqRGQ',
207
- },
208
- ],
209
- };
210
-
211
- export default class MerchantDemo extends Component {
212
- constructor(props) {
213
- super(props);
214
- this.state = {
215
- transaction: null,
216
- place: {},
217
- };
218
- this.map = null;
219
- this.marker = null;
220
- this.viewport = null;
221
- }
222
-
223
- getRequestUrl = () => {
224
- const { transaction } = this.state;
225
- if (transaction) {
226
- return 'https://api.woosmap.com/merchants/place';
227
- }
228
- return 'https://api.woosmap.com/merchants/brand';
229
- };
230
-
231
- getRequestBody = () => {
232
- const { transaction } = this.state;
233
- if (!transaction) {
234
- return JSON.stringify(
235
- {
236
- merchants: request.merchants.map((item) => ({
237
- dirty_name: item.dirty_name,
238
- country: item.country,
239
- })),
240
- },
241
- null,
242
- 2,
243
- );
244
- }
245
- return JSON.stringify(
246
- {
247
- merchants: [request.merchants.find((item) => item.dirty_name === transaction.dirty_name)],
248
- },
249
- null,
250
- 2,
251
- );
252
- };
253
-
254
- selectTransaction = (transaction) => {
255
- this.setState({ transaction, place: {} });
256
- };
257
-
258
- // eslint-disable-next-line class-methods-use-this
259
- getRequestparams = () => ({
260
- private_key: '{your private key}',
261
- });
262
-
263
- getResponse = () => {
264
- const { transaction } = this.state;
265
- if (!transaction) {
266
- return {
267
- merchants: response.merchants.map((merchant) => ({
268
- dirty_name: merchant.dirty_name,
269
- clean_name: merchant.clean_name,
270
- status: 'OK',
271
- logo: merchant.logo,
272
- logo_url: merchant.logo_url,
273
- country: merchant.country,
274
- merchant_id: merchant.merchant_id,
275
- })),
276
- };
277
- }
278
- const merchant = {
279
- ...response.merchants.find((item) => item.dirty_name === transaction.dirty_name),
280
- };
281
- delete merchant.internal_logo;
282
- delete merchant.date;
283
- delete merchant.price;
284
- return {
285
- merchants: [merchant],
286
- };
287
- };
288
-
289
- getDetailsOfTransaction = () => {
290
- const { transaction } = this.state;
291
- if (!google.maps.places) {
292
- return;
293
- }
294
- const placesProvider = new google.maps.places.PlacesService(document.createElement('div'));
295
- placesProvider.getDetails(
296
- {
297
- placeId: transaction.place_id,
298
- fields: [
299
- 'address_component',
300
- 'adr_address',
301
- 'formatted_address',
302
- 'geometry',
303
- 'icon',
304
- 'name',
305
- 'place_id',
306
- 'type',
307
- 'url',
308
- 'vicinity',
309
- ],
310
- },
311
- (item) => {
312
- this.setState({ place: item });
313
- },
314
- );
315
- };
316
-
317
- displayOnMap = () => {
318
- const { geolocation } = this.state;
319
- if (this.viewport) {
320
- this.viewport.setMap(null);
321
- }
322
- if (this.map && geolocation) {
323
- this.map.fitBounds(boundsFromViewport(geolocation.viewport), 20);
324
- this.viewport = viewport(this.map, geolocation.viewport);
325
- }
326
- };
327
-
328
- renderDirtyList = () => (
329
- <motion.article
330
- className="merchant__mobile merchant__mobile--dirty"
331
- key="dirtylist"
332
- initial="initial"
333
- animate="enter"
334
- exit="exit"
335
- style={{ zIndex: '-1' }}
336
- variants={variants(false, false)}
337
- >
338
- <header className="merchant__mobile__header">
339
- <div className="merchant__mobile__header__icons">
340
- <span>
341
- <img src={IphoneTime} alt="mobile time" />
342
- </span>
343
- <span>
344
- <img src={IphoneIcons} alt="mobile icons" />
345
- </span>
346
- </div>
347
- <div className="merchant__mobile__header__nav">
348
- <span>
349
- <img src={IphoneBack} className="merchant__mobile__header__nav__back" alt="Back button" />
350
- </span>
351
- <span>My account</span>
352
- <span>
353
- <img src={IphoneAvatar} className="merchant__mobile__header__nav__avatar" alt="User avatar" />
354
- </span>
355
- </div>
356
- </header>
357
- <section className="merchant__mobile__section">
358
- <div className="merchant__mobile__section__date">20 April</div>
359
- <ul>
360
- {response.merchants.map((item) => (
361
- <li key={item.dirty_name}>
362
- <button
363
- className="merchant__mobile__section__transaction"
364
- type="button"
365
- onClick={() => this.selectTransaction(item)}
366
- >
367
- <div className="merchant__mobile__section__transaction__info">
368
- <div className="merchant__mobile__section__transaction__info__name">
369
- {item.dirty_name}
370
- </div>
371
- <div className="merchant__mobile__section__transaction__info__date">
372
- {item.date}
373
- </div>
374
- </div>
375
- <div className="merchant__mobile__section__transaction__price">{item.price}</div>
376
- <div className="merchant__mobile__section__transaction__link">
377
- <img src={TransactionChevron} alt="See transaction" />
378
- </div>
379
- </button>
380
- </li>
381
- ))}
382
- </ul>
383
- </section>
384
- </motion.article>
385
- );
386
-
387
- renderDirtyTransaction = () => {
388
- const { transaction } = this.state;
389
- return (
390
- <motion.article
391
- key="dirtytransaction"
392
- className="merchant__mobile merchant__mobile--details--dirty"
393
- initial="initial"
394
- animate="enter"
395
- exit="exit"
396
- style={{ zIndex: '1' }}
397
- variants={variants(true, true)}
398
- >
399
- <header className="merchant__mobile__header">
400
- <div className="merchant__mobile__header__icons">
401
- <span>
402
- <img src={IphoneTime} alt="mobile time" />
403
- </span>
404
- <span>
405
- <img src={IphoneIcons} alt="mobile icons" />
406
- </span>
407
- </div>
408
- <div className="merchant__mobile__header__nav">
409
- <Button
410
- className="merchant__mobile__header__nav__button"
411
- onClick={() => this.setState({ transaction: null })}
412
- >
413
- <img src={IphoneBack} className="merchant__mobile__header__nav__back" alt="Back button" />
414
- </Button>
415
- <span className="merchant__mobile__header__nav__title">&nbsp;</span>
416
- </div>
417
- </header>
418
- <section className="merchant__mobile__section">
419
- <div className="merchant__mobile__section__date">20 April - {transaction.date}</div>
420
- <div className="merchant__mobile__section__transaction__info__name">{transaction.dirty_name}</div>
421
- <div className="merchant__mobile__section__transaction__price">{transaction.price}</div>
422
- </section>
423
- </motion.article>
424
- );
425
- };
426
-
427
- renderCleanList = () => (
428
- <motion.article
429
- className="merchant__mobile merchant__mobile--clean"
430
- key="cleanlist"
431
- initial="initial"
432
- animate="enter"
433
- exit="exit"
434
- style={{ zIndex: '-1' }}
435
- variants={variants(false, false)}
436
- >
437
- <header className="merchant__mobile__header">
438
- <div className="merchant__mobile__header__icons">
439
- <span>
440
- <img src={IphoneTime} alt="mobile time" />
441
- </span>
442
- <span>
443
- <img src={IphoneIcons} alt="mobile icons" />
444
- </span>
445
- </div>
446
- <div className="merchant__mobile__header__nav">
447
- <span>
448
- <img src={IphoneBack} className="merchant__mobile__header__nav__back" alt="Back button" />
449
- </span>
450
- <span>My account</span>
451
- <span>
452
- <img src={IphoneAvatar} className="merchant__mobile__header__nav__avatar" alt="User avatar" />
453
- </span>
454
- </div>
455
- </header>
456
- <section className="merchant__mobile__section">
457
- <div className="merchant__mobile__section__date">20 April</div>
458
- <ul>
459
- {response.merchants.map((item) => (
460
- <li key={item.dirty_name}>
461
- <button
462
- className="merchant__mobile__section__transaction"
463
- type="button"
464
- onClick={() => this.selectTransaction(item)}
465
- >
466
- <div className="merchant__mobile__section__transaction__info">
467
- <div className="merchant__mobile__section__transaction__info__logo">
468
- <img src={item.internal_logo} alt={item.clean_name || item.dirty_name} />
469
- </div>
470
- <div className="fullw">
471
- <div className="merchant__mobile__section__transaction__info__name">
472
- {item.clean_name || item.dirty_name}
473
- </div>
474
- <div className="merchant__mobile__section__transaction__info__date">
475
- {item.date}
476
- </div>
477
- </div>
478
- </div>
479
- <div className="merchant__mobile__section__transaction__price">{item.price}</div>
480
- <div className="merchant__mobile__section__transaction__link">
481
- <img src={TransactionChevron} alt="See transaction" />
482
- </div>
483
- </button>
484
- </li>
485
- ))}
486
- </ul>
487
- </section>
488
- </motion.article>
489
- );
490
-
491
- renderCleanTransaction = () => {
492
- const { transaction, place } = this.state;
493
- return (
494
- <motion.article
495
- key="cleantransaction"
496
- className="merchant__mobile merchant__mobile--details"
497
- initial="initial"
498
- animate="enter"
499
- exit="exit"
500
- style={{ zIndex: '1' }}
501
- variants={variants(true, true)}
502
- >
503
- <header className="merchant__mobile__header">
504
- <div className="merchant__mobile__header__icons">
505
- <span>
506
- <img src={IphoneTime} alt="mobile time" />
507
- </span>
508
- <span>
509
- <img src={IphoneIcons} alt="mobile icons" />
510
- </span>
511
- </div>
512
- <div className="merchant__mobile__header__nav">
513
- <Button
514
- className="merchant__mobile__header__nav__button"
515
- onClick={() => this.setState({ transaction: null })}
516
- >
517
- <img src={IphoneBack} className="merchant__mobile__header__nav__back" alt="Back button" />
518
- </Button>
519
- <span className="merchant__mobile__header__nav__title">
520
- {transaction.clean_name || transaction.dirty_name}
521
- </span>
522
- </div>
523
- </header>
524
- <section className="merchant__mobile__section">
525
- {transaction.place_id ? this.renderMap() : <div className="merchant__mobile__section__no-map" />}
526
- <div className="merchant__mobile__section__transaction__info">
527
- <div className="merchant__mobile__section__transaction__info__logo">
528
- <img
529
- src={transaction.internal_logo}
530
- alt={transaction.clean_name || transaction.dirty_name}
531
- />
532
- </div>
533
- <div className="merchant__mobile__section__transaction__info__name">
534
- {transaction.clean_name || transaction.dirty_name}
535
- </div>
536
- <div className="merchant__mobile__section__date">20 April - {transaction.date}</div>
537
- <div className="merchant__mobile__section__transaction__price">{transaction.price}</div>
538
- <div className="merchant__mobile__section__transaction__info__address">
539
- {place.formatted_address}
540
- </div>
541
- </div>
542
- </section>
543
- </motion.article>
544
- );
545
- };
546
-
547
- renderMap = () => {
548
- const { place } = this.state;
549
- const marker = place.geometry ? (
550
- <Marker lat={place.geometry.location.lat()} lng={place.geometry.location.lng()} />
551
- ) : null;
552
- return (
553
- <div className="merchant__mobile__section__map">
554
- <GoogleMapReact
555
- defaultZoom={10}
556
- options={{ disableDefaultUI: true }}
557
- center={
558
- place.geometry?.location
559
- ? [place.geometry.location.lat(), place.geometry.location.lng()]
560
- : [0, 0]
561
- }
562
- bootstrapURLKeys={{
563
- key: Constants.gmapKey,
564
- libraries: ['geometry', 'places'],
565
- }}
566
- yesIWantToUseGoogleMapApiInternals
567
- onGoogleApiLoaded={({ map }) => {
568
- this.map = map;
569
- this.getDetailsOfTransaction();
570
- }}
571
- >
572
- {marker}
573
- </GoogleMapReact>
574
- </div>
575
- );
576
- };
577
-
578
- renderResult = () => {
579
- const { transaction } = this.state;
580
- return (
581
- <div className="merchant__wrapper">
582
- <div className="merchant__mobilewrapper">
583
- <div className="merchant__mobilecontainer__title">Transactions</div>
584
- <div className="merchant__mobilecontainer" style={{ zIndex: 2 }}>
585
- <AnimatePresence exitBeforeEnter={false} initial={false}>
586
- {transaction ? this.renderDirtyTransaction() : this.renderDirtyList()}
587
- </AnimatePresence>
588
- </div>
589
- </div>
590
- <div className="merchant__mobilewrapper">
591
- <div className="merchant__mobilecontainer__title">Cleaned transactions</div>
592
- <div className="merchant__mobilecontainer" style={{ zIndex: 2 }}>
593
- <AnimatePresence exitBeforeEnter={false} initial={false}>
594
- {transaction ? this.renderCleanTransaction() : this.renderCleanList()}
595
- </AnimatePresence>
596
- </div>
597
- </div>
598
- </div>
599
- );
600
- };
601
-
602
- render() {
603
- const { noheader } = this.props;
604
- const headerLabels = {
605
- title: tr('Merchant API'),
606
- desc: tr(
607
- 'An API that helps your customers better understand their payments and where they took place. Send unclear merchant names to the API to convert them into clean names to improve the UX of your transactions list and add enriched data for Europe, North America and Asia: easy-to-recognize merchant names, brand logos, Google Place id of the location.',
608
- ),
609
- };
610
- return (
611
- <Demo
612
- noheader={noheader}
613
- className="demo--merchant"
614
- id="merchant-demo"
615
- docLink="https://developers.woosmap.com/products/merchant-api/get-started/"
616
- header={headerLabels}
617
- request={this.getRequestUrl()}
618
- params={this.getRequestparams()}
619
- body={this.getRequestBody()}
620
- method="POST"
621
- response={this.getResponse()}
622
- mainContent={this.renderResult()}
623
- />
624
- );
625
- }
626
- }
627
-
628
- MerchantDemo.defaultProps = {
629
- noheader: false,
630
- };
631
- MerchantDemo.propTypes = {
632
- noheader: PropTypes.bool,
633
- };
@@ -1,26 +0,0 @@
1
- import React from 'react';
2
- import MerchantDemo from './MerchantDemo';
3
- import { changeLanguage } from '../utils/locale';
4
-
5
- const Story = {
6
- title: 'demo/Merchant',
7
- component: MerchantDemo,
8
- };
9
-
10
- export default Story;
11
-
12
- function Template() {
13
- return <MerchantDemo />;
14
- }
15
- export const Merchant = Template.bind({});
16
-
17
- function TemplateNoHeader() {
18
- return <MerchantDemo noheader />;
19
- }
20
- export const MerchantNoHeader = TemplateNoHeader.bind({});
21
-
22
- function TemplateNoHeaderFr() {
23
- changeLanguage('fr');
24
- return <MerchantDemo noheader />;
25
- }
26
- export const MerchantNoHeaderFr = TemplateNoHeaderFr.bind({});