@articles-media/articles-dev-box 1.0.0 → 1.0.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.
- package/README.md +18 -2
- package/index.js +3 -1
- package/package.json +7 -1
- package/src/GameScoreboard.jsx +234 -17
- package/src/components/Ad.jsx +629 -0
- package/src/hooks/Ads/useAd.js +55 -0
- package/src/hooks/Ads/useAds.js +54 -0
- package/src/hooks/useGameScoreboard.js +59 -0
- package/styles/components/Ad.scss +223 -0
- package/styles/components/GameScoreboard.scss +35 -1
- package/styles/global.scss +98 -0
- package/styles/variables.scss +3 -0
- /package/src/{ArticlesAd.jsx → components/ArticlesAd.jsx} +0 -0
|
@@ -0,0 +1,629 @@
|
|
|
1
|
+
import { useState, useEffect, memo } from 'react';
|
|
2
|
+
|
|
3
|
+
// import { useSelector, useDispatch } from 'react-redux'
|
|
4
|
+
|
|
5
|
+
// import Link from 'next/link'
|
|
6
|
+
// import dynamic from 'next/dynamic'
|
|
7
|
+
|
|
8
|
+
import axios from 'axios'
|
|
9
|
+
|
|
10
|
+
// import Popover from 'react-bootstrap/Popover';
|
|
11
|
+
// import OverlayTrigger from 'react-bootstrap/OverlayTrigger';
|
|
12
|
+
|
|
13
|
+
import { useInView } from 'react-intersection-observer';
|
|
14
|
+
|
|
15
|
+
// import ROUTES from 'components/constants/routes';
|
|
16
|
+
import useAd from '../hooks/Ads/useAd';
|
|
17
|
+
import useAds from '../hooks/Ads/useAds';
|
|
18
|
+
|
|
19
|
+
// import SavePromoModal from 'components/Ads/SavePromoModal';
|
|
20
|
+
// const SavePromoModal = dynamic(
|
|
21
|
+
// () => import('@/components/Ads/SavePromoModal'),
|
|
22
|
+
// { ssr: false }
|
|
23
|
+
// )
|
|
24
|
+
|
|
25
|
+
// const AdDetailsModal = dynamic(
|
|
26
|
+
// () => import('@/components/Ads/AdDetailsModal'),
|
|
27
|
+
// { ssr: false }
|
|
28
|
+
// )
|
|
29
|
+
|
|
30
|
+
// import generateRandomInteger from 'util/generateRandomInteger'
|
|
31
|
+
// import { setViewedAds } from '@/redux/actions/adsActions';
|
|
32
|
+
import { differenceInMinutes, parse, parseISO } from 'date-fns';
|
|
33
|
+
import ArticlesButton from '../Button';
|
|
34
|
+
// import useAds from 'hooks/Ads/useAds';
|
|
35
|
+
|
|
36
|
+
// import "../../styles/components/Ads/Ad.scss";
|
|
37
|
+
import "../../styles/components/Ad.scss";
|
|
38
|
+
|
|
39
|
+
function generateRandomInteger(min, max) {
|
|
40
|
+
return Math.floor(Math.random() * (max - min + 1)) + min;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function Ad(props) {
|
|
44
|
+
|
|
45
|
+
// const dispatch = useDispatch()
|
|
46
|
+
|
|
47
|
+
const userReduxState = false
|
|
48
|
+
const viewedAds = []
|
|
49
|
+
|
|
50
|
+
// const userReduxState = useSelector((state) => state.auth.user_details)
|
|
51
|
+
// const viewedAds = useSelector((state) => state.ads.viewed_ads)
|
|
52
|
+
|
|
53
|
+
// const reduxAds = useSelector((state) => state.ads.ads)
|
|
54
|
+
// const dev_force_ad = useSelector((state) => state.site.dev_force_ad)
|
|
55
|
+
|
|
56
|
+
// const ads = []
|
|
57
|
+
|
|
58
|
+
const {
|
|
59
|
+
data: ads,
|
|
60
|
+
isLoading: adsIsLoading,
|
|
61
|
+
mutate: adsMutate
|
|
62
|
+
} = useAds()
|
|
63
|
+
|
|
64
|
+
// props.setLocation(props.tabLocation);
|
|
65
|
+
|
|
66
|
+
let { previewMode } = props;
|
|
67
|
+
let previewData = props.previewData || {}
|
|
68
|
+
|
|
69
|
+
const [adId, setAdId] = useState(null)
|
|
70
|
+
|
|
71
|
+
const [randomAdId, setRandomAdId] = useState(null);
|
|
72
|
+
const [promoId, setPromoId] = useState(null);
|
|
73
|
+
|
|
74
|
+
// const [ad, setAd] = useState({});
|
|
75
|
+
|
|
76
|
+
const [promo, setPromo] = useState(null);
|
|
77
|
+
const [promoIndex, setPromoIndex] = useState(0);
|
|
78
|
+
|
|
79
|
+
const [modalShow, setModalShow] = useState(false);
|
|
80
|
+
// const [modalLoading, setModalLoading] = useState(false);
|
|
81
|
+
|
|
82
|
+
const [adDetailsExpanded, setAdDetailsExpanded] = useState(false);
|
|
83
|
+
|
|
84
|
+
const [selectedDate, handleDateChange] = useState(new Date());
|
|
85
|
+
|
|
86
|
+
const [loggedEvents, setLoggedEvents] = useState([]);
|
|
87
|
+
|
|
88
|
+
const { data: ad, isLoading: adIsLoading } = useAd(adId)
|
|
89
|
+
|
|
90
|
+
useEffect(() => {
|
|
91
|
+
|
|
92
|
+
if (!ads) return
|
|
93
|
+
|
|
94
|
+
if (ads?.length > 0 && !adId) {
|
|
95
|
+
console.log("Ad Mounted or reduxAds changed")
|
|
96
|
+
setAdId(props.ad_id || ads[generateRandomInteger(0, ads?.length - 1)]?._id)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return
|
|
100
|
+
|
|
101
|
+
let randomId = props.ad_id || reduxAds[generateRandomInteger(0, reduxAds.length - 1)]?._id
|
|
102
|
+
|
|
103
|
+
setRandomAdId(randomId)
|
|
104
|
+
|
|
105
|
+
getAdData()
|
|
106
|
+
|
|
107
|
+
}, [ads]);
|
|
108
|
+
|
|
109
|
+
// useEffect(() => {
|
|
110
|
+
|
|
111
|
+
// if (randomAdId) {
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
// }
|
|
116
|
+
|
|
117
|
+
// }, [randomAdId]);
|
|
118
|
+
|
|
119
|
+
useEffect(() => {
|
|
120
|
+
|
|
121
|
+
// if (randomAdId) {
|
|
122
|
+
|
|
123
|
+
// axios.get(`/api/ads/${randomAdId}`, {
|
|
124
|
+
// params: {
|
|
125
|
+
// ad_id: props.ad_id,
|
|
126
|
+
// ...(dev_force_ad && { force_ad: dev_force_ad })
|
|
127
|
+
// }
|
|
128
|
+
// })
|
|
129
|
+
// .then(function (response) {
|
|
130
|
+
// setAd(response.data.result)
|
|
131
|
+
// })
|
|
132
|
+
// .catch(function (error) {
|
|
133
|
+
// console.log(error);
|
|
134
|
+
// });
|
|
135
|
+
|
|
136
|
+
// }
|
|
137
|
+
|
|
138
|
+
}, [ad]);
|
|
139
|
+
|
|
140
|
+
useEffect(() => {
|
|
141
|
+
|
|
142
|
+
if (ad?.populated_promos && promoIndex >= 0) {
|
|
143
|
+
setPromo(ad?.populated_promos[promoIndex])
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
}, [promoIndex, ad]);
|
|
147
|
+
|
|
148
|
+
// const popover = (
|
|
149
|
+
// <Popover className="hours-popover " id="popover-basic">
|
|
150
|
+
// <Popover.Header as="h3">Store Hours</Popover.Header>
|
|
151
|
+
// <Popover.Body>
|
|
152
|
+
// <div className="day-wrap">
|
|
153
|
+
// <div className="day">Sunday:</div>
|
|
154
|
+
// <div className="hours">6:30AM–8PM</div>
|
|
155
|
+
// </div>
|
|
156
|
+
// <div className="day-wrap active">
|
|
157
|
+
// <div className="day"><b>Monday:</b></div>
|
|
158
|
+
// <div className="hours">6:30AM–8PM</div>
|
|
159
|
+
// </div>
|
|
160
|
+
// <div className="day-wrap">
|
|
161
|
+
// <div className="day">Tuesday:</div>
|
|
162
|
+
// <div className="hours">6:30AM–8PM</div>
|
|
163
|
+
// </div>
|
|
164
|
+
// <div className="day-wrap">
|
|
165
|
+
// <div className="day">Wednesday:</div>
|
|
166
|
+
// <div className="hours">6:30AM–8PM</div>
|
|
167
|
+
// </div>
|
|
168
|
+
// <div className="day-wrap">
|
|
169
|
+
// <div className="day">Thursday:</div>
|
|
170
|
+
// <div className="hours">6:30AM–8PM</div>
|
|
171
|
+
// </div>
|
|
172
|
+
// <div className="day-wrap">
|
|
173
|
+
// <div className="day">Friday:</div>
|
|
174
|
+
// <div className="hours">6:30AM–8PM</div>ad?.
|
|
175
|
+
// </div>
|
|
176
|
+
// <div className="day-wrap">
|
|
177
|
+
// <div className="day">Saturday:</div>
|
|
178
|
+
// <div className="hours">6:30AM–8PM</div>
|
|
179
|
+
// </div>
|
|
180
|
+
// </Popover.Body>
|
|
181
|
+
// </Popover>
|
|
182
|
+
// );
|
|
183
|
+
|
|
184
|
+
function adDetailsExpandedToggle() {
|
|
185
|
+
setAdDetailsExpanded(!adDetailsExpanded);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
const { ref, inView, entry } = useInView({
|
|
189
|
+
/* Optional options */
|
|
190
|
+
threshold: 0,
|
|
191
|
+
triggerOnce: true
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
function logEvent(event) {
|
|
195
|
+
|
|
196
|
+
if (previewMode) {
|
|
197
|
+
console.log("Preventing this event from being logged as this ad is being shown in preview mode.")
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
if (loggedEvents.find(obj => obj == event)) {
|
|
201
|
+
console.log("Already logged this event");
|
|
202
|
+
return
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
axios.get(`/api/ads/event`, {
|
|
206
|
+
params: {
|
|
207
|
+
ad_id: ad?._id,
|
|
208
|
+
event: event
|
|
209
|
+
}
|
|
210
|
+
})
|
|
211
|
+
.then(function (response) {
|
|
212
|
+
setLoggedEvents([...loggedEvents, event])
|
|
213
|
+
console.log(response.data);
|
|
214
|
+
// setAd(response.data.result)
|
|
215
|
+
})
|
|
216
|
+
.catch(function (error) {
|
|
217
|
+
console.log(error);
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
useEffect(() => {
|
|
223
|
+
|
|
224
|
+
if (!previewMode) {
|
|
225
|
+
|
|
226
|
+
console.log("inView", inView)
|
|
227
|
+
|
|
228
|
+
if (inView && adId) {
|
|
229
|
+
|
|
230
|
+
// Records previously viewed ads from the last 5 minutes
|
|
231
|
+
|
|
232
|
+
// Attempts to prevent duplicate viewed ads for more then 5 minutes
|
|
233
|
+
|
|
234
|
+
let unexpiredRecentViews = [
|
|
235
|
+
|
|
236
|
+
{
|
|
237
|
+
ad_id: adId,
|
|
238
|
+
date: new Date().toString()
|
|
239
|
+
},
|
|
240
|
+
|
|
241
|
+
...viewedAds.filter(obj => {
|
|
242
|
+
|
|
243
|
+
console.log(
|
|
244
|
+
differenceInMinutes(new Date(), new Date(obj.date))
|
|
245
|
+
)
|
|
246
|
+
|
|
247
|
+
if (
|
|
248
|
+
differenceInMinutes(new Date(), new Date(obj.date)) > 5
|
|
249
|
+
) {
|
|
250
|
+
console.log("adsViewed - Remove Old Ad View Object")
|
|
251
|
+
return
|
|
252
|
+
} else {
|
|
253
|
+
console.log("adsViewed - Keep Ad View Object")
|
|
254
|
+
return (obj)
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
})
|
|
258
|
+
|
|
259
|
+
]
|
|
260
|
+
|
|
261
|
+
console.log("unexpiredRecentViews", unexpiredRecentViews)
|
|
262
|
+
|
|
263
|
+
// TODO - Record viewed ad locally to prevent repeat
|
|
264
|
+
// dispatch(
|
|
265
|
+
// setViewedAds(
|
|
266
|
+
// unexpiredRecentViews
|
|
267
|
+
// // []
|
|
268
|
+
// // [
|
|
269
|
+
// // {
|
|
270
|
+
// // ad_id: adId,
|
|
271
|
+
// // date: new Date().toString()
|
|
272
|
+
// // },
|
|
273
|
+
// // unexpiredRecentViews,
|
|
274
|
+
// // ]
|
|
275
|
+
// )
|
|
276
|
+
// )
|
|
277
|
+
|
|
278
|
+
// axios.post(`/api/ads/viewed`, {
|
|
279
|
+
// ad_id: adId,
|
|
280
|
+
// section: props.section,
|
|
281
|
+
// section_id: props.section_id
|
|
282
|
+
// })
|
|
283
|
+
// .then(function (response) {
|
|
284
|
+
// // console.log(response);
|
|
285
|
+
// // setAd(response.data.result)
|
|
286
|
+
// })
|
|
287
|
+
// .catch(function (error) {
|
|
288
|
+
// console.log(error);
|
|
289
|
+
// });
|
|
290
|
+
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
}, [inView, adId]);
|
|
296
|
+
|
|
297
|
+
// TODO - Log when a ad free member would have viewed an ad to later show them how many ads they avoided
|
|
298
|
+
// TODO - Make component to show to user in membership settings page how many ads they avoided
|
|
299
|
+
|
|
300
|
+
return (
|
|
301
|
+
<div
|
|
302
|
+
ref={ref}
|
|
303
|
+
className="ad-wrap"
|
|
304
|
+
style={
|
|
305
|
+
{
|
|
306
|
+
"--articles-ad-background-color": previewData.background_color || ad?.background_color,
|
|
307
|
+
"--articles-ad-font-color": previewData.font_color || ad?.font_color,
|
|
308
|
+
"--articles-ad-border-color": previewData.border_color || ad?.border_color,
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
>
|
|
312
|
+
|
|
313
|
+
{/* TODO */}
|
|
314
|
+
{/* {modalShow &&
|
|
315
|
+
<SavePromoModal
|
|
316
|
+
setModalShow={setModalShow}
|
|
317
|
+
promo={promo}
|
|
318
|
+
ad={ad}
|
|
319
|
+
/>
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
{adDetailsExpanded &&
|
|
323
|
+
<AdDetailsModal
|
|
324
|
+
setModalShow={setAdDetailsExpanded}
|
|
325
|
+
ad={ad}
|
|
326
|
+
previewData={previewData}
|
|
327
|
+
/>
|
|
328
|
+
} */}
|
|
329
|
+
|
|
330
|
+
<div
|
|
331
|
+
className='ad'
|
|
332
|
+
>
|
|
333
|
+
|
|
334
|
+
<div
|
|
335
|
+
className="main-panel"
|
|
336
|
+
>
|
|
337
|
+
|
|
338
|
+
<div className="ad-warning flex-header">
|
|
339
|
+
|
|
340
|
+
<div className=''>{ad?.city && 'Local'} Advertisement</div>
|
|
341
|
+
|
|
342
|
+
{/* TODO - Quick link to manage for devs */}
|
|
343
|
+
{/* {userReduxState?.roles?.isDev &&
|
|
344
|
+
<div className=''>
|
|
345
|
+
<Link
|
|
346
|
+
href={`${ROUTES.ADVERTISING}/${ad?._id}`}
|
|
347
|
+
>
|
|
348
|
+
<i
|
|
349
|
+
className="fad fa-code action me-0"
|
|
350
|
+
style={{
|
|
351
|
+
fontSize: '0.7rem',
|
|
352
|
+
width: '20px',
|
|
353
|
+
height: '20px'
|
|
354
|
+
}}
|
|
355
|
+
>
|
|
356
|
+
|
|
357
|
+
</i>
|
|
358
|
+
</Link>
|
|
359
|
+
</div>
|
|
360
|
+
} */}
|
|
361
|
+
|
|
362
|
+
</div>
|
|
363
|
+
|
|
364
|
+
<div className="content-wrap">
|
|
365
|
+
<div className="photo-banner">
|
|
366
|
+
|
|
367
|
+
<div className="logo">
|
|
368
|
+
{(previewData.logo?.location || ad?.logo?.location) &&
|
|
369
|
+
<img
|
|
370
|
+
src={previewData?.logo?.key ?
|
|
371
|
+
`${process.env.NEXT_PUBLIC_CDN}${previewData?.logo?.key}`
|
|
372
|
+
:
|
|
373
|
+
`${process.env.NEXT_PUBLIC_CDN}${ad?.logo?.key}`
|
|
374
|
+
}
|
|
375
|
+
alt=""
|
|
376
|
+
/>
|
|
377
|
+
}
|
|
378
|
+
</div>
|
|
379
|
+
|
|
380
|
+
<div className="icon d-none">
|
|
381
|
+
<i className="fas fa-mug-hot"></i>
|
|
382
|
+
</div>
|
|
383
|
+
|
|
384
|
+
<img
|
|
385
|
+
className="photo" src={
|
|
386
|
+
previewData?.background?.key ?
|
|
387
|
+
`${process.env.NEXT_PUBLIC_CDN}${previewData.background?.key}`
|
|
388
|
+
:
|
|
389
|
+
`${process.env.NEXT_PUBLIC_CDN}${ad?.background?.key}`
|
|
390
|
+
}
|
|
391
|
+
alt=""
|
|
392
|
+
/>
|
|
393
|
+
|
|
394
|
+
</div>
|
|
395
|
+
|
|
396
|
+
<div className="details-wrap">
|
|
397
|
+
|
|
398
|
+
<div className="detail-title">
|
|
399
|
+
|
|
400
|
+
<div className="detail">
|
|
401
|
+
{/* <span className="icon"><i className="fas fa-store-alt"></i></span> */}
|
|
402
|
+
<span className='h4'>{previewData?.business || ad?.business}</span>
|
|
403
|
+
</div>
|
|
404
|
+
|
|
405
|
+
<div className='flex flex-column d-none'>
|
|
406
|
+
<div className="detail">
|
|
407
|
+
<span className="icon"><i className="fas fa-search-location"></i></span>
|
|
408
|
+
<span>{ad?.city}, {ad?.state}</span>
|
|
409
|
+
</div>
|
|
410
|
+
|
|
411
|
+
<div className="detail">
|
|
412
|
+
|
|
413
|
+
<span className="icon"><i className="fas fa-clock me-2"></i></span>
|
|
414
|
+
|
|
415
|
+
<span>
|
|
416
|
+
6:30AM–8PM
|
|
417
|
+
{/* <i className="fas fa-caret-square-down me-0 ms-1"></i> */}
|
|
418
|
+
{/* <OverlayTrigger rootClose trigger="click" placement="bottom" overlay={popover}>
|
|
419
|
+
<i style={{ cursor: 'pointer' }} className="fas fa-caret-square-down me-0 ms-1"></i>
|
|
420
|
+
</OverlayTrigger> */}
|
|
421
|
+
</span>
|
|
422
|
+
|
|
423
|
+
</div>
|
|
424
|
+
</div>
|
|
425
|
+
|
|
426
|
+
</div>
|
|
427
|
+
|
|
428
|
+
{ad?.city && <div className="details mb-3 d-none">
|
|
429
|
+
{/*
|
|
430
|
+
<div className="detail">
|
|
431
|
+
<span className="icon"><i className="fas fa-search-location"></i></span>
|
|
432
|
+
<span>{ad?.city}, {ad?.state}</span>
|
|
433
|
+
</div> */}
|
|
434
|
+
|
|
435
|
+
{/* <div className="detail">
|
|
436
|
+
<span className="icon"><i className="fas fa-user-friends"></i></span>
|
|
437
|
+
<span>5-10 Employees</span>
|
|
438
|
+
</div> */}
|
|
439
|
+
|
|
440
|
+
{/* <div className="detail">
|
|
441
|
+
<span className="icon"><i className="fas fa-user-friends"></i></span>
|
|
442
|
+
<span>Outdoor Seating</span>
|
|
443
|
+
</div> */}
|
|
444
|
+
|
|
445
|
+
</div>}
|
|
446
|
+
|
|
447
|
+
<div className="short-description">{previewData?.description || ad?.description}</div>
|
|
448
|
+
|
|
449
|
+
{/* <p>{JSON.stringify(previewData)}</p> */}
|
|
450
|
+
|
|
451
|
+
</div>
|
|
452
|
+
</div>
|
|
453
|
+
|
|
454
|
+
{/* Make dynamic */}
|
|
455
|
+
{(userReduxState?.roles?.isDev && ad?.populated_promos?.length > 0) &&
|
|
456
|
+
<div>
|
|
457
|
+
|
|
458
|
+
{/* {ad?.populated_promos && <pre>
|
|
459
|
+
{
|
|
460
|
+
JSON.stringify(ad?.populated_promos[Math.floor(Math.random() * ad?.populated_promos?.length)])
|
|
461
|
+
}
|
|
462
|
+
</pre>} */}
|
|
463
|
+
|
|
464
|
+
{/* Active Promo */}
|
|
465
|
+
{promo && <div className="promos-wrap">
|
|
466
|
+
{
|
|
467
|
+
promo &&
|
|
468
|
+
<div
|
|
469
|
+
key={promo._id}
|
|
470
|
+
className="promo-wrap d-flex justify-content-between align-items-center mx-2 p-1 px-2 border border-2 border-light mb-0"
|
|
471
|
+
>
|
|
472
|
+
|
|
473
|
+
<div className=''>
|
|
474
|
+
<div>
|
|
475
|
+
{promo.title}
|
|
476
|
+
</div>
|
|
477
|
+
<div className="small">
|
|
478
|
+
<div className="small">
|
|
479
|
+
{promo.details}
|
|
480
|
+
</div>
|
|
481
|
+
</div>
|
|
482
|
+
</div>
|
|
483
|
+
|
|
484
|
+
<ArticlesButton
|
|
485
|
+
className="px-3"
|
|
486
|
+
small
|
|
487
|
+
onClick={() => {
|
|
488
|
+
console.log("Load Save Modal")
|
|
489
|
+
setModalShow(true)
|
|
490
|
+
}}
|
|
491
|
+
>
|
|
492
|
+
Save
|
|
493
|
+
</ArticlesButton>
|
|
494
|
+
|
|
495
|
+
</div>
|
|
496
|
+
|
|
497
|
+
}
|
|
498
|
+
</div>}
|
|
499
|
+
|
|
500
|
+
{/* Controls */}
|
|
501
|
+
<div className='d-flex justify-content-between'>
|
|
502
|
+
<div className='px-2'>{ad?.populated_promos?.length} Promos Active</div>
|
|
503
|
+
<div className='controls'>
|
|
504
|
+
<i
|
|
505
|
+
className="fad fa-arrow-circle-left"
|
|
506
|
+
type="button"
|
|
507
|
+
onClick={() => {
|
|
508
|
+
|
|
509
|
+
if (promoIndex == 0) {
|
|
510
|
+
setPromoIndex(ad?.populated_promos?.length - 1)
|
|
511
|
+
} else {
|
|
512
|
+
setPromoIndex(prev => prev - 1)
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
}}
|
|
516
|
+
></i>
|
|
517
|
+
{ad?.populated_promos?.map((obj, obj_i) =>
|
|
518
|
+
<i
|
|
519
|
+
key={obj._id}
|
|
520
|
+
className={`fa-square ${obj_i == promoIndex ? 'fad' : 'fas'}`}
|
|
521
|
+
>
|
|
522
|
+
|
|
523
|
+
</i>
|
|
524
|
+
)}
|
|
525
|
+
<i
|
|
526
|
+
className="fad fa-arrow-circle-right"
|
|
527
|
+
type="button"
|
|
528
|
+
onClick={() => {
|
|
529
|
+
|
|
530
|
+
if (promoIndex == ad?.populated_promos?.length - 1) {
|
|
531
|
+
setPromoIndex(0)
|
|
532
|
+
} else {
|
|
533
|
+
setPromoIndex(prev => prev + 1)
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
}}
|
|
537
|
+
></i>
|
|
538
|
+
</div>
|
|
539
|
+
</div>
|
|
540
|
+
|
|
541
|
+
</div>
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
<hr style={{ borderColor: 'white' }} className="mt-auto mb-0" />
|
|
545
|
+
|
|
546
|
+
<div className="action-wrap d-flex justify-content-lg-between px-3 py-2">
|
|
547
|
+
|
|
548
|
+
<div
|
|
549
|
+
onClick={() => {
|
|
550
|
+
adDetailsExpandedToggle()
|
|
551
|
+
logEvent('Details')
|
|
552
|
+
}}
|
|
553
|
+
className="action flex-grow-1 flex-shrink-0"
|
|
554
|
+
>
|
|
555
|
+
Details
|
|
556
|
+
</div>
|
|
557
|
+
|
|
558
|
+
{/* <a style={
|
|
559
|
+
{
|
|
560
|
+
color: ad?.font_color,
|
|
561
|
+
borderColor: `${ad?.border_color}!important`
|
|
562
|
+
}
|
|
563
|
+
} className="action flex-grow-1 flex-shrink-0" href={ad?.website} target="_blank" rel="noreferrer">
|
|
564
|
+
<div>
|
|
565
|
+
Hours
|
|
566
|
+
</div>
|
|
567
|
+
</a> */}
|
|
568
|
+
|
|
569
|
+
<span className='px-4'></span>
|
|
570
|
+
|
|
571
|
+
<a
|
|
572
|
+
className="action flex-grow-1 flex-shrink-0"
|
|
573
|
+
href={ad?.website}
|
|
574
|
+
target="_blank"
|
|
575
|
+
rel="noreferrer"
|
|
576
|
+
onClick={() => logEvent('Website')}
|
|
577
|
+
>
|
|
578
|
+
<div>
|
|
579
|
+
Website
|
|
580
|
+
</div>
|
|
581
|
+
</a>
|
|
582
|
+
|
|
583
|
+
</div>
|
|
584
|
+
</div>
|
|
585
|
+
|
|
586
|
+
</div>
|
|
587
|
+
|
|
588
|
+
{/* {previewMode &&
|
|
589
|
+
<div className='small'>
|
|
590
|
+
<pre>
|
|
591
|
+
{JSON.stringify(previewData, null, 2)}
|
|
592
|
+
</pre>
|
|
593
|
+
</div>
|
|
594
|
+
} */}
|
|
595
|
+
|
|
596
|
+
{!previewMode &&
|
|
597
|
+
<div
|
|
598
|
+
className='advertise-with-us p-1'
|
|
599
|
+
style={
|
|
600
|
+
{
|
|
601
|
+
// ...(props.previewData ? props.previewData.background_color : ad?.background_color),
|
|
602
|
+
backgroundColor: previewData.background_color || ad?.background_color,
|
|
603
|
+
color: previewData.font_color || ad?.font_color,
|
|
604
|
+
borderColor: previewData.border_color || ad?.border_color
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
>
|
|
608
|
+
{/* <Link
|
|
609
|
+
className='small d-block w-100 text-center'
|
|
610
|
+
href={ROUTES.ADVERTISING}
|
|
611
|
+
>
|
|
612
|
+
<i className="fas fa-share me-1"></i>
|
|
613
|
+
Advertise with Articles Media!
|
|
614
|
+
</Link> */}
|
|
615
|
+
<div
|
|
616
|
+
className='small d-block w-100 text-center'
|
|
617
|
+
// href={ROUTES.ADVERTISING}
|
|
618
|
+
>
|
|
619
|
+
<i className="fas fa-share me-1"></i>
|
|
620
|
+
Advertise with Articles Media!
|
|
621
|
+
</div>
|
|
622
|
+
</div>
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
</div>
|
|
626
|
+
);
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
export default memo(Ad)
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import useSWR from "swr";
|
|
2
|
+
|
|
3
|
+
import axios from "axios";
|
|
4
|
+
|
|
5
|
+
const fetcher = async (data) => {
|
|
6
|
+
if (process.env.NODE_ENV === 'development') {
|
|
7
|
+
try {
|
|
8
|
+
const res = await axios.get(`http://localhost:3001/api/ads/${data.ad_id}`, {
|
|
9
|
+
params: {
|
|
10
|
+
ad_id: data.ad_id
|
|
11
|
+
}
|
|
12
|
+
});
|
|
13
|
+
return res.data.result;
|
|
14
|
+
} catch (err) {
|
|
15
|
+
// Failed to fetch from localhost, fallback to default URL
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return axios.get(data.url, {
|
|
20
|
+
params: {
|
|
21
|
+
ad_id: data.ad_id
|
|
22
|
+
}
|
|
23
|
+
}).then((res) => res.data.result);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const minutes = 60;
|
|
27
|
+
const options = {
|
|
28
|
+
dedupingInterval: ((1000 * 60) * minutes),
|
|
29
|
+
// keepPreviousData: true,
|
|
30
|
+
// fallbackData: []
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const useAd = (ad_id) => {
|
|
34
|
+
|
|
35
|
+
const { data, error, isLoading, mutate } = useSWR(
|
|
36
|
+
ad_id ?
|
|
37
|
+
{
|
|
38
|
+
url: `https://articles.media/api/ads/${ad_id}`,
|
|
39
|
+
ad_id
|
|
40
|
+
}
|
|
41
|
+
:
|
|
42
|
+
null,
|
|
43
|
+
fetcher,
|
|
44
|
+
options
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
return {
|
|
48
|
+
data,
|
|
49
|
+
error,
|
|
50
|
+
isLoading,
|
|
51
|
+
mutate,
|
|
52
|
+
};
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export default useAd;
|