payload-subscribers-plugin 0.0.7 → 0.0.9
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 +83 -6
- package/dist/components/app/RequestMagicLink.d.ts +12 -1
- package/dist/components/app/RequestMagicLink.js +59 -31
- package/dist/components/app/RequestMagicLink.js.map +1 -1
- package/dist/components/app/RequestOrSubscribe.d.ts +21 -6
- package/dist/components/app/RequestOrSubscribe.js +13 -1
- package/dist/components/app/RequestOrSubscribe.js.map +1 -1
- package/dist/components/app/SelectOptInChannels.d.ts +9 -0
- package/dist/components/app/SelectOptInChannels.js +7 -1
- package/dist/components/app/SelectOptInChannels.js.map +1 -1
- package/dist/components/app/Subscribe.d.ts +11 -1
- package/dist/components/app/Subscribe.js +42 -9
- package/dist/components/app/Subscribe.js.map +1 -1
- package/dist/components/app/SubscriberMenu.d.ts +16 -3
- package/dist/components/app/SubscriberMenu.js +26 -17
- package/dist/components/app/SubscriberMenu.js.map +1 -1
- package/dist/components/app/Unsubscribe.d.ts +31 -0
- package/dist/components/app/Unsubscribe.js +155 -0
- package/dist/components/app/Unsubscribe.js.map +1 -0
- package/dist/components/app/VerifyMagicLink.d.ts +11 -1
- package/dist/components/app/VerifyMagicLink.js +19 -7
- package/dist/components/app/VerifyMagicLink.js.map +1 -1
- package/dist/components/app/helpers.d.ts +8 -0
- package/dist/components/app/helpers.js +8 -1
- package/dist/components/app/helpers.js.map +1 -1
- package/dist/components/app/shared.module.css +10 -1
- package/dist/contexts/SubscriberProvider.d.ts +16 -0
- package/dist/contexts/SubscriberProvider.js +14 -3
- package/dist/contexts/SubscriberProvider.js.map +1 -1
- package/dist/endpoints/getOptInChannels.d.ts +6 -2
- package/dist/endpoints/getOptInChannels.js +6 -2
- package/dist/endpoints/getOptInChannels.js.map +1 -1
- package/dist/endpoints/logout.d.ts +5 -5
- package/dist/endpoints/logout.js +6 -8
- package/dist/endpoints/logout.js.map +1 -1
- package/dist/endpoints/requestMagicLink.d.ts +8 -6
- package/dist/endpoints/requestMagicLink.js +24 -23
- package/dist/endpoints/requestMagicLink.js.map +1 -1
- package/dist/endpoints/subscribe.d.ts +6 -5
- package/dist/endpoints/subscribe.js +34 -21
- package/dist/endpoints/subscribe.js.map +1 -1
- package/dist/endpoints/subscriberAuth.d.ts +5 -5
- package/dist/endpoints/subscriberAuth.js +11 -12
- package/dist/endpoints/subscriberAuth.js.map +1 -1
- package/dist/endpoints/unsubscribe.d.ts +21 -0
- package/dist/endpoints/unsubscribe.js +118 -0
- package/dist/endpoints/unsubscribe.js.map +1 -0
- package/dist/endpoints/verifyMagicLink.d.ts +5 -5
- package/dist/endpoints/verifyMagicLink.js +14 -15
- package/dist/endpoints/verifyMagicLink.js.map +1 -1
- package/dist/exports/ui.d.ts +2 -0
- package/dist/exports/ui.js +1 -0
- package/dist/exports/ui.js.map +1 -1
- package/dist/helpers/token.d.ts +3 -0
- package/dist/helpers/token.js +12 -2
- package/dist/helpers/token.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.js +11 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -50,6 +50,9 @@ export default buildConfig({
|
|
|
50
50
|
|
|
51
51
|
// Provide a custom expiration for magic link tokens. The default is 30 minutes.
|
|
52
52
|
tokenExpiration: 60 * 60,
|
|
53
|
+
|
|
54
|
+
// Provide your unsubscribe route. This route should include the Unsubscribe component.
|
|
55
|
+
unsubscribeUrl?: string
|
|
53
56
|
}),
|
|
54
57
|
],
|
|
55
58
|
})
|
|
@@ -94,7 +97,7 @@ const Page = () => {
|
|
|
94
97
|
}
|
|
95
98
|
```
|
|
96
99
|
|
|
97
|
-
**
|
|
100
|
+
**_IMPORTANT:_** Be sure to create a /verify route
|
|
98
101
|
|
|
99
102
|
```typescript
|
|
100
103
|
// verify/page.tsx
|
|
@@ -263,6 +266,17 @@ Form to input email address and get a magic link email sent.
|
|
|
263
266
|
/>
|
|
264
267
|
```
|
|
265
268
|
|
|
269
|
+
```html
|
|
270
|
+
<!-- The HTML scaffolding with global CSS classes you can use -->
|
|
271
|
+
<div class="subscribers-request subscribers-container">
|
|
272
|
+
<p class="subscribers-message subscribers-error">{result}</p>
|
|
273
|
+
<form class="subscribers-form">
|
|
274
|
+
<input class="subscribers-emailInput" type="email" />
|
|
275
|
+
<button class="subscribers-button">Request magic link</button>
|
|
276
|
+
</form>
|
|
277
|
+
</div>
|
|
278
|
+
```
|
|
279
|
+
|
|
266
280
|
#### **VerifyMagicLink**
|
|
267
281
|
|
|
268
282
|
Component that verifies a magic link using expected url parameters.
|
|
@@ -296,7 +310,7 @@ Component that verifies a magic link using expected url parameters.
|
|
|
296
310
|
verifyUrl={verifyUrl}
|
|
297
311
|
>
|
|
298
312
|
// Provide children to render after link is verified. Optional
|
|
299
|
-
// Since you provide the verifyUrl to any of the plugin components, you can include a forwardUrl
|
|
313
|
+
// Since you provide the verifyUrl to any of the plugin components, you can include a forwardUrl
|
|
300
314
|
// as a search param, which your route can then use here.
|
|
301
315
|
<a href={forwardUrl}>
|
|
302
316
|
<button className={'customCss'} name={'continue'} type="button">
|
|
@@ -306,6 +320,18 @@ Component that verifies a magic link using expected url parameters.
|
|
|
306
320
|
</VerifyMagicLink>
|
|
307
321
|
```
|
|
308
322
|
|
|
323
|
+
```html
|
|
324
|
+
<!-- The HTML scaffolding with global CSS classes you can use -->
|
|
325
|
+
<div class="subscribers-verify subscribers-container">
|
|
326
|
+
<p class="subscribers-loading">verifying...</p>
|
|
327
|
+
<p class="subscribers-message">{result}</p>
|
|
328
|
+
<div class="subscribers-form">
|
|
329
|
+
{renderButton({ name: "request", onClick: handleRequestAnother, text:"Request another magic
|
|
330
|
+
link", })} {children}
|
|
331
|
+
</div>
|
|
332
|
+
</div>
|
|
333
|
+
```
|
|
334
|
+
|
|
309
335
|
#### **Subscribe**
|
|
310
336
|
|
|
311
337
|
Allows a subscriber to select from among all active optInChannels.
|
|
@@ -340,6 +366,38 @@ Allows a subscriber to select from among all active optInChannels.
|
|
|
340
366
|
/>
|
|
341
367
|
```
|
|
342
368
|
|
|
369
|
+
```html
|
|
370
|
+
<!-- The HTML scaffolding with global CSS classes you can use -->
|
|
371
|
+
<div class="subscribers-subscribe subscribers-container">
|
|
372
|
+
<h2>Subscribe</h2>
|
|
373
|
+
<div class="subscribers-section">
|
|
374
|
+
<!-- START: SelectOptInChannels -->
|
|
375
|
+
<div class="subscribers-container">
|
|
376
|
+
<h3>Opt-in Channels</h3>
|
|
377
|
+
<p class="subscribers-loading">verifying...</p>
|
|
378
|
+
<div class="subscribers-optionsGroup">
|
|
379
|
+
<!-- START: FOR EACH CHANNEL -->
|
|
380
|
+
<div class="subscribers-optInCheckboxItem">
|
|
381
|
+
<label class="subscribers-optInCheckboxLabel" ,>
|
|
382
|
+
<input class="subscribers-optInCheckbox" type="checkbox" />
|
|
383
|
+
{channel.title}
|
|
384
|
+
</label>
|
|
385
|
+
</div>
|
|
386
|
+
<!-- END: FOR EACH CHANNEL -->
|
|
387
|
+
</div>
|
|
388
|
+
</div>
|
|
389
|
+
<!-- END: SelectOptInChannels -->
|
|
390
|
+
</div>
|
|
391
|
+
<form class="subscribers-form">
|
|
392
|
+
<div class="subscribers-section">
|
|
393
|
+
<input class="subscribers-emailInput" placeholder="enter your email" type="email" />
|
|
394
|
+
<button class="subscribers-button" type="submit">Save choices</button>
|
|
395
|
+
</div>
|
|
396
|
+
</form>
|
|
397
|
+
<p class="subscribers-message subscribers-error">{result}</p>
|
|
398
|
+
</div>
|
|
399
|
+
```
|
|
400
|
+
|
|
343
401
|
#### **SubscriberMenu**
|
|
344
402
|
|
|
345
403
|
A simple user menu, most useful for testing. Seen in the screenshots above. Includes a "welcome" message, a link to a /subscribe route, and a log out button.
|
|
@@ -347,10 +405,29 @@ A simple user menu, most useful for testing. Seen in the screenshots above. Incl
|
|
|
347
405
|
```typescript
|
|
348
406
|
// classNames prop
|
|
349
407
|
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
408
|
+
<SubscriberMenu
|
|
409
|
+
classNames={{
|
|
410
|
+
button: 'customCssClassNames',
|
|
411
|
+
container: 'customCssClassNames',
|
|
412
|
+
}}
|
|
413
|
+
subscribeUrl={new URL('/subscribe', serverURL)}
|
|
414
|
+
/>
|
|
415
|
+
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
```html
|
|
419
|
+
<!-- The HTML scaffolding with global CSS classes you can use -->
|
|
420
|
+
<div class="subscribers-menu subscribers-container">
|
|
421
|
+
<div class="subscribers-group">
|
|
422
|
+
<div class="subscribers-welcome">Welcome, {subscriber email}</div>
|
|
423
|
+
<div class="subscribers-subs-link">
|
|
424
|
+
<a href="{subscribeUrl}">Manage subscriptions</a>
|
|
425
|
+
</div>
|
|
426
|
+
<div class="subscribers-logout">
|
|
427
|
+
<button class="subscribers-button" type="button">Log out</button>
|
|
428
|
+
</div>
|
|
429
|
+
</div>
|
|
430
|
+
</div>
|
|
354
431
|
```
|
|
355
432
|
|
|
356
433
|
## Contributing
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import type { RequestMagicLinkResponse } from '../../endpoints/requestMagicLink.js';
|
|
2
2
|
export { RequestMagicLinkResponse };
|
|
3
|
+
/**
|
|
4
|
+
* Props for the RequestMagicLink component.
|
|
5
|
+
*/
|
|
3
6
|
export interface IRequestMagicLink {
|
|
4
7
|
classNames?: RequestMagicLinkClasses;
|
|
5
8
|
handleMagicLinkRequested?: (result: RequestMagicLinkResponse) => void;
|
|
6
9
|
props?: any;
|
|
7
|
-
verifyUrl?: URL;
|
|
10
|
+
verifyUrl?: string | URL;
|
|
8
11
|
}
|
|
12
|
+
/** Optional CSS class overrides for RequestMagicLink elements. */
|
|
9
13
|
export type RequestMagicLinkClasses = {
|
|
10
14
|
button?: string;
|
|
11
15
|
container?: string;
|
|
@@ -14,4 +18,11 @@ export type RequestMagicLinkClasses = {
|
|
|
14
18
|
form?: string;
|
|
15
19
|
message?: string;
|
|
16
20
|
};
|
|
21
|
+
/**
|
|
22
|
+
* Form component that lets users request a magic-login link by email. Submits to POST /api/emailToken
|
|
23
|
+
* and shows success or error message. Uses SubscriberProvider for pre-filling email when available.
|
|
24
|
+
*
|
|
25
|
+
* @param props - See IRequestMagicLink
|
|
26
|
+
* @returns Form UI with email input and "Request magic link" button
|
|
27
|
+
*/
|
|
17
28
|
export declare const RequestMagicLink: ({ classNames, handleMagicLinkRequested, verifyUrl, }: IRequestMagicLink) => import("react").JSX.Element;
|
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
-
import { PayloadSDK } from '@payloadcms/sdk';
|
|
4
3
|
import { useEffect, useState } from 'react';
|
|
5
4
|
import { useSubscriber } from '../../contexts/SubscriberProvider.js';
|
|
6
5
|
import { useServerUrl } from '../../react-hooks/useServerUrl.js';
|
|
7
6
|
import { mergeClassNames } from './helpers.js';
|
|
8
7
|
import styles from './shared.module.css';
|
|
9
|
-
|
|
8
|
+
/**
|
|
9
|
+
* Form component that lets users request a magic-login link by email. Submits to POST /api/emailToken
|
|
10
|
+
* and shows success or error message. Uses SubscriberProvider for pre-filling email when available.
|
|
11
|
+
*
|
|
12
|
+
* @param props - See IRequestMagicLink
|
|
13
|
+
* @returns Form UI with email input and "Request magic link" button
|
|
14
|
+
*/ export const RequestMagicLink = ({ classNames = {
|
|
10
15
|
button: '',
|
|
11
16
|
container: '',
|
|
12
17
|
emailInput: '',
|
|
@@ -16,10 +21,15 @@ export const RequestMagicLink = ({ classNames = {
|
|
|
16
21
|
}, handleMagicLinkRequested, verifyUrl })=>{
|
|
17
22
|
const { subscriber } = useSubscriber();
|
|
18
23
|
const { serverURL } = useServerUrl();
|
|
24
|
+
if (!verifyUrl && serverURL) {
|
|
25
|
+
console.log('verifyUrl DEFAULT');
|
|
26
|
+
verifyUrl = `${serverURL ? serverURL : ''}/verify`;
|
|
27
|
+
}
|
|
28
|
+
if (typeof verifyUrl == 'string') {
|
|
29
|
+
console.log('verifyUrl STRING: ', verifyUrl);
|
|
30
|
+
verifyUrl = new URL(verifyUrl);
|
|
31
|
+
}
|
|
19
32
|
const [status, setStatus] = useState('default');
|
|
20
|
-
const sdk = new PayloadSDK({
|
|
21
|
-
baseURL: serverURL || ''
|
|
22
|
-
});
|
|
23
33
|
const [result, setResult] = useState();
|
|
24
34
|
const [email, setEmail] = useState(subscriber?.email || '');
|
|
25
35
|
useEffect(()=>{
|
|
@@ -29,48 +39,63 @@ export const RequestMagicLink = ({ classNames = {
|
|
|
29
39
|
]);
|
|
30
40
|
const handleSubmit = async (e)=>{
|
|
31
41
|
e.preventDefault();
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
|
|
42
|
+
if (!verifyUrl) {
|
|
43
|
+
setStatus('error');
|
|
44
|
+
setResult(`An error occured. Please try again. \n(No verify URL available.)`);
|
|
45
|
+
} else {
|
|
46
|
+
// const emailTokenResponse = await sdk.request({
|
|
47
|
+
// json: {
|
|
48
|
+
// email,
|
|
49
|
+
// verifyUrl: verifyUrl?.href,
|
|
50
|
+
// },
|
|
51
|
+
// method: 'POST',
|
|
52
|
+
// path: '/api/emailToken',
|
|
53
|
+
// })
|
|
54
|
+
const emailTokenResponse = await fetch(`${serverURL ? serverURL : ''}/api/emailToken`, {
|
|
55
|
+
body: JSON.stringify({
|
|
56
|
+
email,
|
|
57
|
+
verifyUrl: verifyUrl?.href
|
|
58
|
+
}),
|
|
59
|
+
method: 'POST'
|
|
60
|
+
});
|
|
61
|
+
if (emailTokenResponse.ok) {
|
|
62
|
+
const emailTokenResponseJson = await emailTokenResponse.json();
|
|
63
|
+
if (handleMagicLinkRequested) {
|
|
64
|
+
handleMagicLinkRequested(emailTokenResponseJson);
|
|
65
|
+
}
|
|
66
|
+
// @ts-expect-error One or the other exists
|
|
67
|
+
const { emailResult, error } = emailTokenResponseJson;
|
|
68
|
+
if (error) {
|
|
69
|
+
setStatus('error');
|
|
70
|
+
setResult(`An error occured. Please try again. \n ${error}`);
|
|
71
|
+
} else if (emailResult) {
|
|
72
|
+
setStatus('sent');
|
|
73
|
+
setResult('An email has been sent containing your magic link.');
|
|
74
|
+
} else {
|
|
75
|
+
setStatus('error');
|
|
76
|
+
setResult(`An error occured. Please try again. \nResult unknown`);
|
|
77
|
+
}
|
|
53
78
|
} else {
|
|
79
|
+
const emailTokenResponseText = await emailTokenResponse.text();
|
|
54
80
|
setStatus('error');
|
|
55
|
-
setResult(`An error occured. Please try again. \
|
|
81
|
+
setResult(`An error occured. Please try again. \n${emailTokenResponseText}`);
|
|
56
82
|
}
|
|
57
|
-
} else {
|
|
58
|
-
const emailTokenResponseText = await emailTokenResponse.text();
|
|
59
|
-
setStatus('error');
|
|
60
|
-
setResult(`An error occured. Please try again. \n${emailTokenResponseText}`);
|
|
61
83
|
}
|
|
62
84
|
};
|
|
63
85
|
return /*#__PURE__*/ _jsxs("div", {
|
|
64
86
|
className: mergeClassNames([
|
|
87
|
+
'subscribers-request subscribers-container',
|
|
65
88
|
styles.container,
|
|
66
89
|
classNames.container
|
|
67
90
|
]),
|
|
68
91
|
children: [
|
|
69
92
|
result ? /*#__PURE__*/ _jsx("p", {
|
|
70
93
|
className: mergeClassNames([
|
|
94
|
+
'subscribers-message',
|
|
71
95
|
styles.message,
|
|
72
96
|
classNames.message,
|
|
73
97
|
status == 'error' ? [
|
|
98
|
+
'subscribers-error',
|
|
74
99
|
styles.error,
|
|
75
100
|
classNames.error
|
|
76
101
|
] : []
|
|
@@ -79,6 +104,7 @@ export const RequestMagicLink = ({ classNames = {
|
|
|
79
104
|
}) : /*#__PURE__*/ _jsx(_Fragment, {}),
|
|
80
105
|
/*#__PURE__*/ _jsxs("form", {
|
|
81
106
|
className: mergeClassNames([
|
|
107
|
+
'subscribers-form',
|
|
82
108
|
styles.form,
|
|
83
109
|
classNames.form
|
|
84
110
|
]),
|
|
@@ -88,6 +114,7 @@ export const RequestMagicLink = ({ classNames = {
|
|
|
88
114
|
/*#__PURE__*/ _jsx("input", {
|
|
89
115
|
"aria-label": "enter your email",
|
|
90
116
|
className: mergeClassNames([
|
|
117
|
+
'subscribers-emailInput',
|
|
91
118
|
styles.emailInput,
|
|
92
119
|
classNames.emailInput
|
|
93
120
|
]),
|
|
@@ -98,6 +125,7 @@ export const RequestMagicLink = ({ classNames = {
|
|
|
98
125
|
}),
|
|
99
126
|
/*#__PURE__*/ _jsx("button", {
|
|
100
127
|
className: mergeClassNames([
|
|
128
|
+
'subscribers-button',
|
|
101
129
|
styles.button,
|
|
102
130
|
classNames.button
|
|
103
131
|
]),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/app/RequestMagicLink.tsx"],"sourcesContent":["'use client'\n\nimport { PayloadSDK } from '@payloadcms/sdk'\nimport { type ChangeEvent, type SubmitEvent, useEffect, useState } from 'react'\n\nimport type { Config } from '../../copied/payload-types.js'\nimport type { RequestMagicLinkResponse } from '../../endpoints/requestMagicLink.js'\n\nimport { useSubscriber } from '../../contexts/SubscriberProvider.js'\nimport { useServerUrl } from '../../react-hooks/useServerUrl.js'\nimport { mergeClassNames } from './helpers.js'\nimport styles from './shared.module.css'\n\nexport { RequestMagicLinkResponse }\n\nexport interface IRequestMagicLink {\n classNames?: RequestMagicLinkClasses\n handleMagicLinkRequested?: (result: RequestMagicLinkResponse) => void\n props?: any\n verifyUrl?: URL\n}\n\nexport type RequestMagicLinkClasses = {\n button?: string\n container?: string\n emailInput?: string\n error?: string\n form?: string\n message?: string\n}\n\ntype statusValues = 'default' | 'error' | 'sent'\n\nexport const RequestMagicLink = ({\n classNames = {\n button: '',\n container: '',\n emailInput: '',\n error: '',\n form: '',\n message: '',\n },\n handleMagicLinkRequested,\n verifyUrl,\n}: IRequestMagicLink) => {\n const { subscriber } = useSubscriber()\n const { serverURL } = useServerUrl()\n
|
|
1
|
+
{"version":3,"sources":["../../../src/components/app/RequestMagicLink.tsx"],"sourcesContent":["'use client'\n\nimport { PayloadSDK } from '@payloadcms/sdk'\nimport { type ChangeEvent, type SubmitEvent, useEffect, useState } from 'react'\n\nimport type { Config } from '../../copied/payload-types.js'\nimport type { RequestMagicLinkResponse } from '../../endpoints/requestMagicLink.js'\n\nimport { useSubscriber } from '../../contexts/SubscriberProvider.js'\nimport { useServerUrl } from '../../react-hooks/useServerUrl.js'\nimport { mergeClassNames } from './helpers.js'\nimport styles from './shared.module.css'\n\nexport { RequestMagicLinkResponse }\n\n/**\n * Props for the RequestMagicLink component.\n */\nexport interface IRequestMagicLink {\n classNames?: RequestMagicLinkClasses\n handleMagicLinkRequested?: (result: RequestMagicLinkResponse) => void\n props?: any\n verifyUrl?: string | URL\n}\n\n/** Optional CSS class overrides for RequestMagicLink elements. */\nexport type RequestMagicLinkClasses = {\n button?: string\n container?: string\n emailInput?: string\n error?: string\n form?: string\n message?: string\n}\n\ntype statusValues = 'default' | 'error' | 'sent'\n\n/**\n * Form component that lets users request a magic-login link by email. Submits to POST /api/emailToken\n * and shows success or error message. Uses SubscriberProvider for pre-filling email when available.\n *\n * @param props - See IRequestMagicLink\n * @returns Form UI with email input and \"Request magic link\" button\n */\nexport const RequestMagicLink = ({\n classNames = {\n button: '',\n container: '',\n emailInput: '',\n error: '',\n form: '',\n message: '',\n },\n handleMagicLinkRequested,\n verifyUrl,\n}: IRequestMagicLink) => {\n const { subscriber } = useSubscriber()\n const { serverURL } = useServerUrl()\n\n if (!verifyUrl && serverURL) {\n console.log('verifyUrl DEFAULT')\n verifyUrl = `${serverURL ? serverURL : ''}/verify`\n }\n if (typeof verifyUrl == 'string') {\n console.log('verifyUrl STRING: ', verifyUrl)\n verifyUrl = new URL(verifyUrl)\n }\n\n const [status, setStatus] = useState<statusValues>('default')\n\n const [result, setResult] = useState<string>()\n const [email, setEmail] = useState(subscriber?.email || '')\n\n useEffect(() => {\n setEmail(subscriber?.email || '')\n }, [subscriber])\n\n const handleSubmit = async (e: SubmitEvent<HTMLFormElement>) => {\n e.preventDefault()\n if (!verifyUrl) {\n setStatus('error')\n setResult(`An error occured. Please try again. \\n(No verify URL available.)`)\n } else {\n // const emailTokenResponse = await sdk.request({\n // json: {\n // email,\n // verifyUrl: verifyUrl?.href,\n // },\n // method: 'POST',\n // path: '/api/emailToken',\n // })\n const emailTokenResponse = await fetch(`${serverURL ? serverURL : ''}/api/emailToken`, {\n body: JSON.stringify({\n email,\n verifyUrl: verifyUrl?.href,\n }),\n method: 'POST',\n })\n if (emailTokenResponse.ok) {\n const emailTokenResponseJson: RequestMagicLinkResponse = await emailTokenResponse.json()\n if (handleMagicLinkRequested) {\n handleMagicLinkRequested(emailTokenResponseJson)\n }\n // @ts-expect-error One or the other exists\n const { emailResult, error } = emailTokenResponseJson\n if (error) {\n setStatus('error')\n setResult(`An error occured. Please try again. \\n ${error}`)\n } else if (emailResult) {\n setStatus('sent')\n setResult('An email has been sent containing your magic link.')\n } else {\n setStatus('error')\n setResult(`An error occured. Please try again. \\nResult unknown`)\n }\n } else {\n const emailTokenResponseText = await emailTokenResponse.text()\n setStatus('error')\n setResult(`An error occured. Please try again. \\n${emailTokenResponseText}`)\n }\n }\n }\n return (\n <div\n className={mergeClassNames([\n 'subscribers-request subscribers-container',\n styles.container,\n classNames.container,\n ])}\n >\n {result ? (\n <p\n className={mergeClassNames([\n 'subscribers-message',\n styles.message,\n classNames.message,\n status == 'error' ? ['subscribers-error', styles.error, classNames.error] : [],\n ])}\n >\n {result}\n </p>\n ) : (\n <></>\n )}\n <form\n className={mergeClassNames(['subscribers-form', styles.form, classNames.form])}\n method=\"POST\"\n onSubmit={handleSubmit}\n >\n <input\n aria-label=\"enter your email\"\n className={mergeClassNames([\n 'subscribers-emailInput',\n styles.emailInput,\n classNames.emailInput,\n ])}\n onChange={(e: ChangeEvent<HTMLInputElement>) => setEmail(e.target.value)}\n placeholder=\"enter your email\"\n type=\"email\"\n value={email}\n />\n <button\n className={mergeClassNames(['subscribers-button', styles.button, classNames.button])}\n type=\"submit\"\n >\n Request magic link\n </button>\n </form>\n </div>\n )\n}\n"],"names":["useEffect","useState","useSubscriber","useServerUrl","mergeClassNames","styles","RequestMagicLink","classNames","button","container","emailInput","error","form","message","handleMagicLinkRequested","verifyUrl","subscriber","serverURL","console","log","URL","status","setStatus","result","setResult","email","setEmail","handleSubmit","e","preventDefault","emailTokenResponse","fetch","body","JSON","stringify","href","method","ok","emailTokenResponseJson","json","emailResult","emailTokenResponseText","text","div","className","p","onSubmit","input","aria-label","onChange","target","value","placeholder","type"],"mappings":"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"}
|
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
import { type RequestMagicLinkResponse, type SubscribeResponse } from '../../exports/ui.js';
|
|
2
2
|
export type { RequestMagicLinkResponse, SubscribeResponse };
|
|
3
|
+
/**
|
|
4
|
+
* Props for the RequestOrSubscribe component.
|
|
5
|
+
*/
|
|
6
|
+
export interface IRequestOrSubscribe {
|
|
7
|
+
classNames?: RequestOrSubscribeClasses;
|
|
8
|
+
handleMagicLinkRequested?: (result: RequestMagicLinkResponse) => void;
|
|
9
|
+
handleSubscribe?: (result: SubscribeResponse) => void;
|
|
10
|
+
verifyUrl?: string | URL;
|
|
11
|
+
}
|
|
12
|
+
/** Optional CSS class overrides for RequestOrSubscribe and its child components. */
|
|
3
13
|
export type RequestOrSubscribeClasses = {
|
|
4
14
|
button?: string;
|
|
5
15
|
container?: string;
|
|
@@ -10,9 +20,14 @@ export type RequestOrSubscribeClasses = {
|
|
|
10
20
|
message?: string;
|
|
11
21
|
section?: string;
|
|
12
22
|
};
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
23
|
+
/**
|
|
24
|
+
* Composite component that shows Subscribe when a subscriber is authenticated, otherwise
|
|
25
|
+
* RequestMagicLink. Used as a single entry point for "sign in or manage subscriptions."
|
|
26
|
+
*
|
|
27
|
+
* @param props.classNames - Optional class overrides passed to child components
|
|
28
|
+
* @param props.handleMagicLinkRequested - Callback when a magic link is requested (no subscriber yet)
|
|
29
|
+
* @param props.handleSubscribe - Callback when subscription/opt-ins are updated (subscriber present)
|
|
30
|
+
* @param props.verifyUrl - Base URL for verify links in emails
|
|
31
|
+
* @returns Either Subscribe or RequestMagicLink based on subscriber context
|
|
32
|
+
*/
|
|
33
|
+
export declare function RequestOrSubscribe({ classNames, handleMagicLinkRequested, handleSubscribe, verifyUrl, }: IRequestOrSubscribe): import("react").JSX.Element;
|
|
@@ -2,7 +2,16 @@
|
|
|
2
2
|
import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
3
|
import { useSubscriber } from '../../contexts/SubscriberProvider.js';
|
|
4
4
|
import { RequestMagicLink, Subscribe } from '../../exports/ui.js';
|
|
5
|
-
|
|
5
|
+
/**
|
|
6
|
+
* Composite component that shows Subscribe when a subscriber is authenticated, otherwise
|
|
7
|
+
* RequestMagicLink. Used as a single entry point for "sign in or manage subscriptions."
|
|
8
|
+
*
|
|
9
|
+
* @param props.classNames - Optional class overrides passed to child components
|
|
10
|
+
* @param props.handleMagicLinkRequested - Callback when a magic link is requested (no subscriber yet)
|
|
11
|
+
* @param props.handleSubscribe - Callback when subscription/opt-ins are updated (subscriber present)
|
|
12
|
+
* @param props.verifyUrl - Base URL for verify links in emails
|
|
13
|
+
* @returns Either Subscribe or RequestMagicLink based on subscriber context
|
|
14
|
+
*/ export function RequestOrSubscribe({ classNames = {
|
|
6
15
|
button: '',
|
|
7
16
|
container: '',
|
|
8
17
|
emailInput: '',
|
|
@@ -12,6 +21,9 @@ export function RequestOrSubscribe({ classNames = {
|
|
|
12
21
|
message: '',
|
|
13
22
|
section: ''
|
|
14
23
|
}, handleMagicLinkRequested, handleSubscribe, verifyUrl }) {
|
|
24
|
+
if (typeof verifyUrl == 'string') {
|
|
25
|
+
verifyUrl = new URL(verifyUrl);
|
|
26
|
+
}
|
|
15
27
|
const { subscriber } = useSubscriber();
|
|
16
28
|
// Example: Conditionally render something or pass the state to children
|
|
17
29
|
return /*#__PURE__*/ _jsx(_Fragment, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/app/RequestOrSubscribe.tsx"],"sourcesContent":["'use client'\n\nimport {
|
|
1
|
+
{"version":3,"sources":["../../../src/components/app/RequestOrSubscribe.tsx"],"sourcesContent":["'use client'\n\nimport { useSubscriber } from '../../contexts/SubscriberProvider.js'\nimport {\n RequestMagicLink,\n type RequestMagicLinkResponse,\n Subscribe,\n type SubscribeResponse,\n} from '../../exports/ui.js'\n\nexport type { RequestMagicLinkResponse, SubscribeResponse }\n\n/**\n * Props for the RequestOrSubscribe component.\n */\nexport interface IRequestOrSubscribe {\n classNames?: RequestOrSubscribeClasses\n handleMagicLinkRequested?: (result: RequestMagicLinkResponse) => void\n handleSubscribe?: (result: SubscribeResponse) => void\n verifyUrl?: string | URL\n}\n\n/** Optional CSS class overrides for RequestOrSubscribe and its child components. */\nexport type RequestOrSubscribeClasses = {\n button?: string\n container?: string\n emailInput?: string\n error?: string\n form?: string\n loading?: string\n message?: string\n section?: string\n}\n\n/**\n * Composite component that shows Subscribe when a subscriber is authenticated, otherwise\n * RequestMagicLink. Used as a single entry point for \"sign in or manage subscriptions.\"\n *\n * @param props.classNames - Optional class overrides passed to child components\n * @param props.handleMagicLinkRequested - Callback when a magic link is requested (no subscriber yet)\n * @param props.handleSubscribe - Callback when subscription/opt-ins are updated (subscriber present)\n * @param props.verifyUrl - Base URL for verify links in emails\n * @returns Either Subscribe or RequestMagicLink based on subscriber context\n */\nexport function RequestOrSubscribe({\n classNames = {\n button: '',\n container: '',\n emailInput: '',\n error: '',\n form: '',\n loading: '',\n message: '',\n section: '',\n },\n handleMagicLinkRequested,\n handleSubscribe,\n verifyUrl,\n}: IRequestOrSubscribe) {\n if (typeof verifyUrl == 'string') {\n verifyUrl = new URL(verifyUrl)\n }\n\n const { subscriber } = useSubscriber()\n\n // Example: Conditionally render something or pass the state to children\n return (\n <>\n {subscriber ? (\n <Subscribe\n classNames={classNames}\n handleSubscribe={handleSubscribe}\n verifyUrl={verifyUrl}\n />\n ) : (\n <RequestMagicLink\n classNames={classNames}\n handleMagicLinkRequested={handleMagicLinkRequested}\n verifyUrl={verifyUrl}\n />\n )}\n {/* <div>subscriber = {JSON.stringify(subscriber)}</div> */}\n </>\n )\n}\n"],"names":["useSubscriber","RequestMagicLink","Subscribe","RequestOrSubscribe","classNames","button","container","emailInput","error","form","loading","message","section","handleMagicLinkRequested","handleSubscribe","verifyUrl","URL","subscriber"],"mappings":"AAAA;;AAEA,SAASA,aAAa,QAAQ,uCAAsC;AACpE,SACEC,gBAAgB,EAEhBC,SAAS,QAEJ,sBAAqB;AA0B5B;;;;;;;;;CASC,GACD,OAAO,SAASC,mBAAmB,EACjCC,aAAa;IACXC,QAAQ;IACRC,WAAW;IACXC,YAAY;IACZC,OAAO;IACPC,MAAM;IACNC,SAAS;IACTC,SAAS;IACTC,SAAS;AACX,CAAC,EACDC,wBAAwB,EACxBC,eAAe,EACfC,SAAS,EACW;IACpB,IAAI,OAAOA,aAAa,UAAU;QAChCA,YAAY,IAAIC,IAAID;IACtB;IAEA,MAAM,EAAEE,UAAU,EAAE,GAAGjB;IAEvB,wEAAwE;IACxE,qBACE;kBACGiB,2BACC,KAACf;YACCE,YAAYA;YACZU,iBAAiBA;YACjBC,WAAWA;2BAGb,KAACd;YACCG,YAAYA;YACZS,0BAA0BA;YAC1BE,WAAWA;;;AAMrB"}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import type { OptInChannel } from '../../copied/payload-types.js';
|
|
2
|
+
/** Props for the SelectOptInChannels component. */
|
|
2
3
|
export interface ISelectOptInChannels {
|
|
3
4
|
classNames?: SelectOptInChannelsClasses;
|
|
4
5
|
handleOptInChannelsSelected?: (result: OptInChannel[]) => void;
|
|
5
6
|
props?: any;
|
|
6
7
|
selectedOptInChannelIDs?: string[];
|
|
7
8
|
}
|
|
9
|
+
/** Optional CSS class overrides for SelectOptInChannels elements. */
|
|
8
10
|
export type SelectOptInChannelsClasses = {
|
|
9
11
|
button?: string;
|
|
10
12
|
container?: string;
|
|
@@ -17,4 +19,11 @@ export type SelectOptInChannelsClasses = {
|
|
|
17
19
|
optInCheckboxLabel?: string;
|
|
18
20
|
optionsGroup?: string;
|
|
19
21
|
};
|
|
22
|
+
/**
|
|
23
|
+
* Fetches active opt-in channels from GET /api/optinchannels and renders a list of checkboxes.
|
|
24
|
+
* Reports selected channels via handleOptInChannelsSelected. Supports pre-selection via selectedOptInChannelIDs.
|
|
25
|
+
*
|
|
26
|
+
* @param props - See ISelectOptInChannels
|
|
27
|
+
* @returns Section titled "Opt-in Channels" with checkboxes and loading/error state
|
|
28
|
+
*/
|
|
20
29
|
export declare const SelectOptInChannels: ({ classNames, handleOptInChannelsSelected, selectedOptInChannelIDs, }: ISelectOptInChannels) => import("react").JSX.Element;
|
|
@@ -5,7 +5,13 @@ import { useEffect, useState } from 'react';
|
|
|
5
5
|
import { useServerUrl } from '../../react-hooks/useServerUrl.js';
|
|
6
6
|
import { mergeClassNames } from './helpers.js';
|
|
7
7
|
import styles from './shared.module.css';
|
|
8
|
-
|
|
8
|
+
/**
|
|
9
|
+
* Fetches active opt-in channels from GET /api/optinchannels and renders a list of checkboxes.
|
|
10
|
+
* Reports selected channels via handleOptInChannelsSelected. Supports pre-selection via selectedOptInChannelIDs.
|
|
11
|
+
*
|
|
12
|
+
* @param props - See ISelectOptInChannels
|
|
13
|
+
* @returns Section titled "Opt-in Channels" with checkboxes and loading/error state
|
|
14
|
+
*/ export const SelectOptInChannels = ({ classNames = {
|
|
9
15
|
button: '',
|
|
10
16
|
container: '',
|
|
11
17
|
error: '',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/app/SelectOptInChannels.tsx"],"sourcesContent":["'use client'\n\nimport { PayloadSDK } from '@payloadcms/sdk'\nimport { useEffect, useState } from 'react'\n\nimport type { Config, OptInChannel } from '../../copied/payload-types.js'\nimport type { GetOptInChannelsResponse } from '../../endpoints/getOptInChannels.js'\n\nimport { useServerUrl } from '../../react-hooks/useServerUrl.js'\nimport { mergeClassNames } from './helpers.js'\nimport styles from './shared.module.css'\n\n
|
|
1
|
+
{"version":3,"sources":["../../../src/components/app/SelectOptInChannels.tsx"],"sourcesContent":["'use client'\n\nimport { PayloadSDK } from '@payloadcms/sdk'\nimport { useEffect, useState } from 'react'\n\nimport type { Config, OptInChannel } from '../../copied/payload-types.js'\nimport type { GetOptInChannelsResponse } from '../../endpoints/getOptInChannels.js'\n\nimport { useServerUrl } from '../../react-hooks/useServerUrl.js'\nimport { mergeClassNames } from './helpers.js'\nimport styles from './shared.module.css'\n\n/** Props for the SelectOptInChannels component. */\nexport interface ISelectOptInChannels {\n classNames?: SelectOptInChannelsClasses\n handleOptInChannelsSelected?: (result: OptInChannel[]) => void\n props?: any\n selectedOptInChannelIDs?: string[]\n}\n\n/** Optional CSS class overrides for SelectOptInChannels elements. */\nexport type SelectOptInChannelsClasses = {\n button?: string\n container?: string\n error?: string\n form?: string\n loading?: string\n message?: string\n optInCheckbox?: string\n optInCheckboxItem?: string\n optInCheckboxLabel?: string\n optionsGroup?: string\n}\n\n/**\n * Fetches active opt-in channels from GET /api/optinchannels and renders a list of checkboxes.\n * Reports selected channels via handleOptInChannelsSelected. Supports pre-selection via selectedOptInChannelIDs.\n *\n * @param props - See ISelectOptInChannels\n * @returns Section titled \"Opt-in Channels\" with checkboxes and loading/error state\n */\nexport const SelectOptInChannels = ({\n classNames = {\n button: '',\n container: '',\n error: '',\n form: '',\n loading: '',\n message: '',\n optInCheckbox: '',\n optInCheckboxItem: '',\n optInCheckboxLabel: '',\n optionsGroup: '',\n },\n handleOptInChannelsSelected,\n selectedOptInChannelIDs,\n}: ISelectOptInChannels) => {\n const { serverURL } = useServerUrl()\n // const { serverURL } = { serverURL: 'http://localhost:3001' }\n type OptInChannelCheckbox = {\n isChecked: boolean\n } & OptInChannel\n const [result, setResult] = useState<any>()\n const [allOptInChannels, setAllOptInChannels] = useState<OptInChannelCheckbox[]>([])\n\n useEffect(() => {\n async function verify() {\n const sdk = new PayloadSDK<Config>({\n baseURL: serverURL || '',\n })\n\n console.log('calling optinchannels endpoint')\n const result = await sdk.request({\n method: 'GET',\n path: '/api/optinchannels',\n })\n if (result.ok) {\n const resultJson: GetOptInChannelsResponse = await result.json()\n setResult(resultJson)\n } else {\n const resultText = await result.text()\n setResult(resultText)\n }\n }\n void verify()\n }, [serverURL])\n\n useEffect(() => {\n const channels = result?.optInChannels?.map((channel: OptInChannel) => ({\n ...channel,\n isChecked: selectedOptInChannelIDs?.includes(channel.id),\n }))\n setAllOptInChannels(channels)\n }, [result, selectedOptInChannelIDs])\n\n return (\n <div className={mergeClassNames([styles.container, classNames.container])}>\n <h3>Opt-in Channels</h3>\n {!result ? (\n <p className={mergeClassNames([styles.loading, classNames.loading])}>verifying...</p>\n ) : (\n <div className={mergeClassNames([styles.optionsGroup, classNames.optionsGroup])}>\n {// Map over the tasks array to render each checkbox\n allOptInChannels?.map((channel) => (\n <div\n className={mergeClassNames([styles.optInCheckboxItem, classNames.optInCheckboxItem])}\n key={channel.id}\n >\n <label\n className={mergeClassNames([\n styles.optInCheckboxLabel,\n classNames.optInCheckboxLabel,\n ])}\n >\n <input\n aria-label={channel.title}\n // The checked prop is controlled by the state\n checked={channel.isChecked}\n className={mergeClassNames([styles.optInCheckbox, classNames.optInCheckbox])}\n // The onChange handler calls the update function with the item's ID\n onChange={(event) => {\n event.preventDefault()\n\n const checked = event.target.checked\n\n if (handleOptInChannelsSelected) {\n handleOptInChannelsSelected(\n allOptInChannels\n .map((channel) => ({\n ...channel,\n isChecked:\n channel.title == event.target.value ? checked : channel.isChecked,\n }))\n .filter((c) => c.isChecked)\n .map((channel) => ({ ...channel, isChecked: undefined })),\n )\n }\n }}\n type=\"checkbox\"\n value={channel.title}\n />\n {channel.title}\n </label>\n </div>\n ))}\n </div>\n )}\n </div>\n )\n}\n"],"names":["PayloadSDK","useEffect","useState","useServerUrl","mergeClassNames","styles","SelectOptInChannels","classNames","button","container","error","form","loading","message","optInCheckbox","optInCheckboxItem","optInCheckboxLabel","optionsGroup","handleOptInChannelsSelected","selectedOptInChannelIDs","serverURL","result","setResult","allOptInChannels","setAllOptInChannels","verify","sdk","baseURL","console","log","request","method","path","ok","resultJson","json","resultText","text","channels","optInChannels","map","channel","isChecked","includes","id","div","className","h3","p","label","input","aria-label","title","checked","onChange","event","preventDefault","target","value","filter","c","undefined","type"],"mappings":"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"}
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import type { SubscribeResponse } from '../../endpoints/subscribe.js';
|
|
2
2
|
export { SubscribeResponse };
|
|
3
|
+
/** Props for the Subscribe component. */
|
|
3
4
|
export interface ISubscribe {
|
|
4
5
|
classNames?: SubscribeClasses;
|
|
5
6
|
handleSubscribe?: (result: SubscribeResponse) => void;
|
|
6
7
|
props?: any;
|
|
7
|
-
verifyUrl?: URL;
|
|
8
|
+
verifyUrl?: string | URL;
|
|
8
9
|
}
|
|
10
|
+
/** Optional CSS class overrides for Subscribe elements. */
|
|
9
11
|
export type SubscribeClasses = {
|
|
10
12
|
button?: string;
|
|
11
13
|
container?: string;
|
|
@@ -16,4 +18,12 @@ export type SubscribeClasses = {
|
|
|
16
18
|
message?: string;
|
|
17
19
|
section?: string;
|
|
18
20
|
};
|
|
21
|
+
/**
|
|
22
|
+
* Subscribe/preferences form for authenticated subscribers. Shows SelectOptInChannels and an email
|
|
23
|
+
* input when not yet authenticated. Submits to POST /api/subscribe to update opt-ins or trigger
|
|
24
|
+
* verification email. Calls refreshSubscriber and handleSubscribe on success.
|
|
25
|
+
*
|
|
26
|
+
* @param props - See ISubscribe
|
|
27
|
+
* @returns Form with channel checkboxes, optional email field, "Save choices" button, and status message
|
|
28
|
+
*/
|
|
19
29
|
export declare const Subscribe: ({ classNames, handleSubscribe, verifyUrl, }: ISubscribe) => import("react").JSX.Element;
|