Skip to content

Commit 7af1b78

Browse files
committed
v2.0.0 - Refactor to use hook & support new Evenbrite widgets
1 parent 3184285 commit 7af1b78

File tree

11 files changed

+1945
-3625
lines changed

11 files changed

+1945
-3625
lines changed

.npmignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
.idea
22
src
3+
images
34
webpack.config.js

.nvmrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
16.17

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2019 Vancouver Startup Society
3+
Copyright (c) 2022 Enceladus Consulting Inc.
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

README.md

Lines changed: 63 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
1-
# React Eventbrite Popup Checkout
2-
A React component that bootstraps Eventbrite's popup checkout widget.
3-
4-
**Note:** Popup will only trigger if your app is served with **HTTPS**. Otherwise a new window is opened that links to your Eventbrite event page.
1+
# React Eventbrite Checkout
2+
A React component that loads Eventbrite's checkout widgets.
53

64
## Install
75
If using NPM:
@@ -15,43 +13,71 @@ $ yarn add react-eventbrite-popup-checkout
1513
```
1614

1715
## Usage
16+
**Note:** In-app checkout will only trigger when your app is served with **HTTPS**. Otherwise, the component directs the user to Eventbrite's website to complete the purchase.
17+
18+
### Modal Example
19+
![plot](./images/modal.gif)
20+
21+
Create a button that triggers a checkout modal.
1822

19-
### Example
20-
```js
23+
```jsx
2124
import React from 'react';
22-
import EventbriteButton from 'react-eventbrite-popup-checkout';
23-
24-
class MyApp extends React.Component {
25-
render() {
26-
return (
27-
<div>
28-
<EventbriteButton ebEventId='12555555'>Checkout</EventbriteButton>
29-
</div>
30-
);
31-
}
32-
}
33-
```
34-
### Required Props
35-
```
36-
ebEventId: <string>
37-
```
25+
import useEventbrite from 'react-eventbrite-popup-checkout';
3826

39-
### Optional Props
40-
```
41-
className: <string>
42-
ebScriptPath: <string>
43-
isModal: <boolean>
44-
onOrderComplete: <function>
45-
onClick: <function>
46-
component: <node>
47-
componentProps: <shape>
27+
const App = () => {
28+
const handleOrderCompleted = React.useCallback(() => {
29+
console.log('Order was completed successfully');
30+
}, []);
31+
const modalButtonCheckout = useEventbrite({
32+
eventId: 'YOUR-EB-EVENT-ID',
33+
modal: true,
34+
onOrderComplete: handleOrderCompleted,
35+
});
36+
37+
return (
38+
<div id="my-app">
39+
{/* guard for null - resolves when Eventbrite loads */}
40+
{modalButtonCheckout && (
41+
<button id={modalButtonCheckout.id} type="button">
42+
Modal Checkout
43+
</button>
44+
)}
45+
</div>
46+
)
47+
};
4848
```
4949

50-
#### `onClick`
51-
Pass an optional `onClick` function to process the click event before the Eventbrite widget gets fired (e.g., for analytics).
50+
### Embedded iFrame Example
51+
![plot](./images/iframe.gif)
52+
53+
Embed an iFrame checkout.
5254

53-
#### `component`
54-
Specify what component to use (e.g., a custom `<Button />`). Defaults to plain HTML button. Note: if using a custom component, it must accept an `id` prop.
55+
```jsx
56+
import React from 'react';
57+
import useEventbrite from 'react-eventbrite-popup-checkout';
58+
59+
const App = () => {
60+
const handleOrderCompleted = React.useCallback(() => {
61+
console.log('Order was completed successfully');
62+
}, []);
63+
const iframeCheckout = useEventbrite({
64+
eventId: 'YOUR-EB-EVENT-ID',
65+
modal: false,
66+
onOrderComplete: handleOrderCompleted,
67+
iFrameHeight: 500, // optional
68+
iFrameAutoAdapt: 100, // optional - The widget's viewport percentage (between 75-100)
69+
});
70+
71+
return (
72+
<div id="my-app">
73+
{/* guard for null - resolves when Eventbrite loads */}
74+
{iframeCheckout && (
75+
<div id={iframeCheckout.id} />
76+
)}
77+
</div>
78+
)
79+
};
80+
```
5581

56-
#### `componentProps`
57-
Props to pass to your custom component.
82+
### Auto Apply Promo Code
83+
You can pass `promoCode` to the `useEventbrite` hook to automatically apply a promo code during checkout.

images/iframe.gif

593 KB
Loading

images/modal.gif

785 KB
Loading

package.json

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "react-eventbrite-popup-checkout",
3-
"version": "1.0.5",
4-
"description": "A React component for the Eventbrite checkout widget",
3+
"version": "2.0.0",
4+
"description": "A React component for the Eventbrite checkout widgets",
55
"main": "dist/main.js",
66
"repository": {
77
"type": "git",
@@ -22,20 +22,21 @@
2222
"prepublish": "npx webpack --config webpack.config.js"
2323
},
2424
"peerDependencies": {
25-
"react": "^16.0.0"
25+
"react": ">= 16.8.0",
26+
"react-dom": ">= 16.8.0"
2627
},
2728
"devDependencies": {
28-
"@babel/core": "^7.4.5",
29-
"@babel/preset-env": "^7.4.5",
30-
"@babel/preset-react": "^7.0.0",
31-
"babel-loader": "^8.0.6",
32-
"babel-plugin-transform-class-properties": "^6.24.1",
33-
"react": "^16.8.6",
34-
"webpack": "^4.33.0",
35-
"webpack-cli": "^3.3.4"
29+
"@babel/core": "^7.19.0",
30+
"@babel/preset-env": "^7.19.0",
31+
"@babel/preset-react": "^7.18.6",
32+
"babel-loader": "^8.2.5",
33+
"react": "^18.2.0",
34+
"react-dom": "^18.2.0",
35+
"webpack": "^5.74.0",
36+
"webpack-cli": "^4.10.0"
3637
},
3738
"dependencies": {
38-
"prop-types": "^15.7.2",
39-
"uuid": "^3.4.0"
39+
"prop-types": "^15.8.1",
40+
"uuid": "^9.0.0"
4041
}
4142
}

src/index.jsx

Lines changed: 0 additions & 118 deletions
This file was deleted.

src/useEventbrite.js

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import React from 'react';
2+
import { v4 as uuid } from 'uuid';
3+
4+
const TAG_ID = `EB_SCRIPT_${uuid()}`;
5+
const SCRIPT_URL = 'https://www.eventbrite.com/static/widgets/eb_widgets.js';
6+
7+
const useEventbrite = ({
8+
eventId,
9+
modal,
10+
onOrderComplete,
11+
iFrameHeight,
12+
iFrameAutoAdapt,
13+
promoCode,
14+
}) => {
15+
const id = `EB_${uuid()}`;
16+
const [isLoaded, setLoaded] = React.useState(false);
17+
const onLoad = React.useCallback(() => setLoaded(true), [setLoaded]);
18+
const onErr = React.useCallback(e => {
19+
console.error(`Failed to load Eventbrite script from ${scriptUrl}`);
20+
console.error(e);
21+
22+
setLoaded(false);
23+
}, [setLoaded]);
24+
25+
React.useEffect(() => {
26+
if (window?.EBWidgets) {
27+
setLoaded(true);
28+
return;
29+
}
30+
31+
const existing = document.getElementById(TAG_ID);
32+
33+
if (existing) {
34+
existing.remove();
35+
}
36+
37+
const script = document.createElement('script');
38+
script.id = TAG_ID;
39+
script.async = true;
40+
script.src = SCRIPT_URL;
41+
script.addEventListener('load', onLoad);
42+
script.addEventListener('error', onErr);
43+
script.addEventListener('abort', onErr);
44+
document.head.appendChild(script);
45+
46+
return () => {
47+
script.removeEventListener('load', onLoad);
48+
script.removeEventListener('error', onErr);
49+
script.removeEventListener('abort', onErr);
50+
script.remove();
51+
setLoaded(false);
52+
};
53+
}, [
54+
setLoaded,
55+
onLoad,
56+
onErr,
57+
]);
58+
59+
React.useEffect(() => {
60+
if (!isLoaded) {
61+
return;
62+
}
63+
64+
const config = {
65+
widgetType: 'checkout',
66+
eventId,
67+
onOrderComplete,
68+
modal,
69+
};
70+
71+
if (modal) {
72+
config.modalTriggerElementId = id;
73+
} else {
74+
config.iFrameContainerId = id;
75+
config.iFrameContainerHeight = iFrameHeight || 425;
76+
config.iFrameAutoAdapt = iFrameAutoAdapt || 100;
77+
}
78+
79+
if (promoCode) {
80+
config.promoCode = promoCode;
81+
}
82+
83+
window.EBWidgets.createWidget(config);
84+
}, [isLoaded]);
85+
86+
return isLoaded ? { id } : null;
87+
};
88+
89+
export default useEventbrite;

0 commit comments

Comments
 (0)