payload-subscribers-plugin 0.0.7 → 0.0.8
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 +79 -5
- package/dist/components/app/RequestMagicLink.d.ts +12 -1
- package/dist/components/app/RequestMagicLink.js +16 -1
- 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 +19 -1
- 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/VerifyMagicLink.d.ts +11 -1
- package/dist/components/app/VerifyMagicLink.js +17 -1
- 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 +5 -5
- package/dist/endpoints/requestMagicLink.js +11 -13
- package/dist/endpoints/requestMagicLink.js.map +1 -1
- package/dist/endpoints/subscribe.d.ts +6 -5
- package/dist/endpoints/subscribe.js +12 -13
- 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/verifyMagicLink.d.ts +5 -5
- package/dist/endpoints/verifyMagicLink.js +11 -13
- package/dist/endpoints/verifyMagicLink.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -263,6 +263,17 @@ Form to input email address and get a magic link email sent.
|
|
|
263
263
|
/>
|
|
264
264
|
```
|
|
265
265
|
|
|
266
|
+
```html
|
|
267
|
+
<!-- The HTML scaffolding with global CSS classes you can use -->
|
|
268
|
+
<div class="subscribers-request subscribers-container">
|
|
269
|
+
<p class="subscribers-message subscribers-error">{result}</p>
|
|
270
|
+
<form class="subscribers-form">
|
|
271
|
+
<input class="subscribers-emailInput" type="email" />
|
|
272
|
+
<button class="subscribers-button">Request magic link</button>
|
|
273
|
+
</form>
|
|
274
|
+
</div>
|
|
275
|
+
```
|
|
276
|
+
|
|
266
277
|
#### **VerifyMagicLink**
|
|
267
278
|
|
|
268
279
|
Component that verifies a magic link using expected url parameters.
|
|
@@ -296,7 +307,7 @@ Component that verifies a magic link using expected url parameters.
|
|
|
296
307
|
verifyUrl={verifyUrl}
|
|
297
308
|
>
|
|
298
309
|
// 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
|
|
310
|
+
// Since you provide the verifyUrl to any of the plugin components, you can include a forwardUrl
|
|
300
311
|
// as a search param, which your route can then use here.
|
|
301
312
|
<a href={forwardUrl}>
|
|
302
313
|
<button className={'customCss'} name={'continue'} type="button">
|
|
@@ -306,6 +317,18 @@ Component that verifies a magic link using expected url parameters.
|
|
|
306
317
|
</VerifyMagicLink>
|
|
307
318
|
```
|
|
308
319
|
|
|
320
|
+
```html
|
|
321
|
+
<!-- The HTML scaffolding with global CSS classes you can use -->
|
|
322
|
+
<div class="subscribers-verify subscribers-container">
|
|
323
|
+
<p class="subscribers-loading">verifying...</p>
|
|
324
|
+
<p class="subscribers-message">{result}</p>
|
|
325
|
+
<div class="subscribers-form">
|
|
326
|
+
{renderButton({ name: "request", onClick: handleRequestAnother, text:"Request another magic
|
|
327
|
+
link", })} {children}
|
|
328
|
+
</div>
|
|
329
|
+
</div>
|
|
330
|
+
```
|
|
331
|
+
|
|
309
332
|
#### **Subscribe**
|
|
310
333
|
|
|
311
334
|
Allows a subscriber to select from among all active optInChannels.
|
|
@@ -340,6 +363,38 @@ Allows a subscriber to select from among all active optInChannels.
|
|
|
340
363
|
/>
|
|
341
364
|
```
|
|
342
365
|
|
|
366
|
+
```html
|
|
367
|
+
<!-- The HTML scaffolding with global CSS classes you can use -->
|
|
368
|
+
<div class="subscribers-subscribe subscribers-container">
|
|
369
|
+
<h2>Subscribe</h2>
|
|
370
|
+
<div class="subscribers-section">
|
|
371
|
+
<!-- START: SelectOptInChannels -->
|
|
372
|
+
<div class="subscribers-container">
|
|
373
|
+
<h3>Opt-in Channels</h3>
|
|
374
|
+
<p class="subscribers-loading">verifying...</p>
|
|
375
|
+
<div class="subscribers-optionsGroup">
|
|
376
|
+
<!-- START: FOR EACH CHANNEL -->
|
|
377
|
+
<div class="subscribers-optInCheckboxItem">
|
|
378
|
+
<label class="subscribers-optInCheckboxLabel" ,>
|
|
379
|
+
<input class="subscribers-optInCheckbox" type="checkbox" />
|
|
380
|
+
{channel.title}
|
|
381
|
+
</label>
|
|
382
|
+
</div>
|
|
383
|
+
<!-- END: FOR EACH CHANNEL -->
|
|
384
|
+
</div>
|
|
385
|
+
</div>
|
|
386
|
+
<!-- END: SelectOptInChannels -->
|
|
387
|
+
</div>
|
|
388
|
+
<form class="subscribers-form">
|
|
389
|
+
<div class="subscribers-section">
|
|
390
|
+
<input class="subscribers-emailInput" placeholder="enter your email" type="email" />
|
|
391
|
+
<button class="subscribers-button" type="submit">Save choices</button>
|
|
392
|
+
</div>
|
|
393
|
+
</form>
|
|
394
|
+
<p class="subscribers-message subscribers-error">{result}</p>
|
|
395
|
+
</div>
|
|
396
|
+
```
|
|
397
|
+
|
|
343
398
|
#### **SubscriberMenu**
|
|
344
399
|
|
|
345
400
|
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 +402,29 @@ A simple user menu, most useful for testing. Seen in the screenshots above. Incl
|
|
|
347
402
|
```typescript
|
|
348
403
|
// classNames prop
|
|
349
404
|
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
405
|
+
<SubscriberMenu
|
|
406
|
+
classNames={{
|
|
407
|
+
button: 'customCssClassNames',
|
|
408
|
+
container: 'customCssClassNames',
|
|
409
|
+
}}
|
|
410
|
+
subscribeUrl={new URL('/subscribe', serverURL)}
|
|
411
|
+
/>
|
|
412
|
+
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
```html
|
|
416
|
+
<!-- The HTML scaffolding with global CSS classes you can use -->
|
|
417
|
+
<div class="subscribers-menu subscribers-container">
|
|
418
|
+
<div class="subscribers-group">
|
|
419
|
+
<div class="subscribers-welcome">Welcome, {subscriber email}</div>
|
|
420
|
+
<div class="subscribers-subs-link">
|
|
421
|
+
<a href="{subscribeUrl}">Manage subscriptions</a>
|
|
422
|
+
</div>
|
|
423
|
+
<div class="subscribers-logout">
|
|
424
|
+
<button class="subscribers-button" type="button">Log out</button>
|
|
425
|
+
</div>
|
|
426
|
+
</div>
|
|
427
|
+
</div>
|
|
354
428
|
```
|
|
355
429
|
|
|
356
430
|
## 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;
|
|
@@ -6,7 +6,13 @@ import { useSubscriber } from '../../contexts/SubscriberProvider.js';
|
|
|
6
6
|
import { useServerUrl } from '../../react-hooks/useServerUrl.js';
|
|
7
7
|
import { mergeClassNames } from './helpers.js';
|
|
8
8
|
import styles from './shared.module.css';
|
|
9
|
-
|
|
9
|
+
/**
|
|
10
|
+
* Form component that lets users request a magic-login link by email. Submits to POST /api/emailToken
|
|
11
|
+
* and shows success or error message. Uses SubscriberProvider for pre-filling email when available.
|
|
12
|
+
*
|
|
13
|
+
* @param props - See IRequestMagicLink
|
|
14
|
+
* @returns Form UI with email input and "Request magic link" button
|
|
15
|
+
*/ export const RequestMagicLink = ({ classNames = {
|
|
10
16
|
button: '',
|
|
11
17
|
container: '',
|
|
12
18
|
emailInput: '',
|
|
@@ -14,6 +20,9 @@ export const RequestMagicLink = ({ classNames = {
|
|
|
14
20
|
form: '',
|
|
15
21
|
message: ''
|
|
16
22
|
}, handleMagicLinkRequested, verifyUrl })=>{
|
|
23
|
+
if (typeof verifyUrl == 'string') {
|
|
24
|
+
verifyUrl = new URL(verifyUrl);
|
|
25
|
+
}
|
|
17
26
|
const { subscriber } = useSubscriber();
|
|
18
27
|
const { serverURL } = useServerUrl();
|
|
19
28
|
const [status, setStatus] = useState('default');
|
|
@@ -62,15 +71,18 @@ export const RequestMagicLink = ({ classNames = {
|
|
|
62
71
|
};
|
|
63
72
|
return /*#__PURE__*/ _jsxs("div", {
|
|
64
73
|
className: mergeClassNames([
|
|
74
|
+
'subscribers-request subscribers-container',
|
|
65
75
|
styles.container,
|
|
66
76
|
classNames.container
|
|
67
77
|
]),
|
|
68
78
|
children: [
|
|
69
79
|
result ? /*#__PURE__*/ _jsx("p", {
|
|
70
80
|
className: mergeClassNames([
|
|
81
|
+
'subscribers-message',
|
|
71
82
|
styles.message,
|
|
72
83
|
classNames.message,
|
|
73
84
|
status == 'error' ? [
|
|
85
|
+
'subscribers-error',
|
|
74
86
|
styles.error,
|
|
75
87
|
classNames.error
|
|
76
88
|
] : []
|
|
@@ -79,6 +91,7 @@ export const RequestMagicLink = ({ classNames = {
|
|
|
79
91
|
}) : /*#__PURE__*/ _jsx(_Fragment, {}),
|
|
80
92
|
/*#__PURE__*/ _jsxs("form", {
|
|
81
93
|
className: mergeClassNames([
|
|
94
|
+
'subscribers-form',
|
|
82
95
|
styles.form,
|
|
83
96
|
classNames.form
|
|
84
97
|
]),
|
|
@@ -88,6 +101,7 @@ export const RequestMagicLink = ({ classNames = {
|
|
|
88
101
|
/*#__PURE__*/ _jsx("input", {
|
|
89
102
|
"aria-label": "enter your email",
|
|
90
103
|
className: mergeClassNames([
|
|
104
|
+
'subscribers-emailInput',
|
|
91
105
|
styles.emailInput,
|
|
92
106
|
classNames.emailInput
|
|
93
107
|
]),
|
|
@@ -98,6 +112,7 @@ export const RequestMagicLink = ({ classNames = {
|
|
|
98
112
|
}),
|
|
99
113
|
/*#__PURE__*/ _jsx("button", {
|
|
100
114
|
className: mergeClassNames([
|
|
115
|
+
'subscribers-button',
|
|
101
116
|
styles.button,
|
|
102
117
|
classNames.button
|
|
103
118
|
]),
|
|
@@ -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 const [status, setStatus] = useState<statusValues>('default')\n\n const sdk = new PayloadSDK<Config>({\n baseURL: serverURL || '',\n })\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 const emailTokenResponse = await sdk.request({\n json: {\n email,\n verifyUrl: verifyUrl?.href,\n },\n method: 'POST',\n path: '/api/emailToken',\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
|
|
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 if (typeof verifyUrl == 'string') {\n verifyUrl = new URL(verifyUrl)\n }\n\n const { subscriber } = useSubscriber()\n const { serverURL } = useServerUrl()\n const [status, setStatus] = useState<statusValues>('default')\n\n const sdk = new PayloadSDK<Config>({\n baseURL: serverURL || '',\n })\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 const emailTokenResponse = await sdk.request({\n json: {\n email,\n verifyUrl: verifyUrl?.href,\n },\n method: 'POST',\n path: '/api/emailToken',\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":["PayloadSDK","useEffect","useState","useSubscriber","useServerUrl","mergeClassNames","styles","RequestMagicLink","classNames","button","container","emailInput","error","form","message","handleMagicLinkRequested","verifyUrl","URL","subscriber","serverURL","status","setStatus","sdk","baseURL","result","setResult","email","setEmail","handleSubmit","e","preventDefault","emailTokenResponse","request","json","href","method","path","ok","emailTokenResponseJson","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;
|
|
@@ -7,7 +7,14 @@ import { useServerUrl } from '../../react-hooks/useServerUrl.js';
|
|
|
7
7
|
import { mergeClassNames } from './helpers.js';
|
|
8
8
|
import { SelectOptInChannels } from './SelectOptInChannels.js';
|
|
9
9
|
import styles from './shared.module.css';
|
|
10
|
-
|
|
10
|
+
/**
|
|
11
|
+
* Subscribe/preferences form for authenticated subscribers. Shows SelectOptInChannels and an email
|
|
12
|
+
* input when not yet authenticated. Submits to POST /api/subscribe to update opt-ins or trigger
|
|
13
|
+
* verification email. Calls refreshSubscriber and handleSubscribe on success.
|
|
14
|
+
*
|
|
15
|
+
* @param props - See ISubscribe
|
|
16
|
+
* @returns Form with channel checkboxes, optional email field, "Save choices" button, and status message
|
|
17
|
+
*/ export const Subscribe = ({ classNames = {
|
|
11
18
|
button: '',
|
|
12
19
|
container: '',
|
|
13
20
|
emailInput: '',
|
|
@@ -17,6 +24,9 @@ export const Subscribe = ({ classNames = {
|
|
|
17
24
|
message: '',
|
|
18
25
|
section: ''
|
|
19
26
|
}, handleSubscribe, verifyUrl })=>{
|
|
27
|
+
if (typeof verifyUrl == 'string') {
|
|
28
|
+
verifyUrl = new URL(verifyUrl);
|
|
29
|
+
}
|
|
20
30
|
const { refreshSubscriber, subscriber } = useSubscriber();
|
|
21
31
|
const { serverURL } = useServerUrl();
|
|
22
32
|
const sdk = new PayloadSDK({
|
|
@@ -96,6 +106,7 @@ export const Subscribe = ({ classNames = {
|
|
|
96
106
|
};
|
|
97
107
|
return /*#__PURE__*/ _jsxs("div", {
|
|
98
108
|
className: mergeClassNames([
|
|
109
|
+
'subscribers-subscribe subscribers-container',
|
|
99
110
|
styles.container,
|
|
100
111
|
classNames.container
|
|
101
112
|
]),
|
|
@@ -105,6 +116,7 @@ export const Subscribe = ({ classNames = {
|
|
|
105
116
|
}),
|
|
106
117
|
/*#__PURE__*/ _jsx("div", {
|
|
107
118
|
className: mergeClassNames([
|
|
119
|
+
'subscribers-section',
|
|
108
120
|
styles.section,
|
|
109
121
|
classNames.section
|
|
110
122
|
]),
|
|
@@ -115,6 +127,7 @@ export const Subscribe = ({ classNames = {
|
|
|
115
127
|
}),
|
|
116
128
|
/*#__PURE__*/ _jsx("form", {
|
|
117
129
|
className: mergeClassNames([
|
|
130
|
+
'subscribers-form',
|
|
118
131
|
styles.form,
|
|
119
132
|
classNames.form
|
|
120
133
|
]),
|
|
@@ -125,6 +138,7 @@ export const Subscribe = ({ classNames = {
|
|
|
125
138
|
},
|
|
126
139
|
children: /*#__PURE__*/ _jsxs("div", {
|
|
127
140
|
className: mergeClassNames([
|
|
141
|
+
'subscribers-section',
|
|
128
142
|
styles.section,
|
|
129
143
|
classNames.section
|
|
130
144
|
]),
|
|
@@ -132,6 +146,7 @@ export const Subscribe = ({ classNames = {
|
|
|
132
146
|
!subscriber && /*#__PURE__*/ _jsx("input", {
|
|
133
147
|
"aria-label": "enter your email",
|
|
134
148
|
className: mergeClassNames([
|
|
149
|
+
'subscribers-emailInput',
|
|
135
150
|
styles.emailInput,
|
|
136
151
|
classNames.emailInput
|
|
137
152
|
]),
|
|
@@ -142,6 +157,7 @@ export const Subscribe = ({ classNames = {
|
|
|
142
157
|
}),
|
|
143
158
|
/*#__PURE__*/ _jsx("button", {
|
|
144
159
|
className: mergeClassNames([
|
|
160
|
+
'subscribers-button',
|
|
145
161
|
styles.button,
|
|
146
162
|
classNames.button
|
|
147
163
|
]),
|
|
@@ -153,9 +169,11 @@ export const Subscribe = ({ classNames = {
|
|
|
153
169
|
}),
|
|
154
170
|
!!result && /*#__PURE__*/ _jsx("p", {
|
|
155
171
|
className: mergeClassNames([
|
|
172
|
+
'subscribers-message',
|
|
156
173
|
styles.message,
|
|
157
174
|
classNames.message,
|
|
158
175
|
status == 'error' ? [
|
|
176
|
+
'subscribers-error',
|
|
159
177
|
styles.error,
|
|
160
178
|
classNames.error
|
|
161
179
|
] : []
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/app/Subscribe.tsx"],"sourcesContent":["'use client'\n\nimport { PayloadSDK } from '@payloadcms/sdk'\nimport { type ChangeEvent, useEffect, useState } from 'react'\n\nimport type { Config, OptInChannel } from '../../copied/payload-types.js'\nimport type { SubscribeResponse } from '../../endpoints/subscribe.js'\n\nexport { SubscribeResponse }\n\nimport { useSubscriber } from '../../contexts/SubscriberProvider.js'\nimport { useServerUrl } from '../../react-hooks/useServerUrl.js'\nimport { mergeClassNames } from './helpers.js'\nimport { SelectOptInChannels } from './SelectOptInChannels.js'\nimport styles from './shared.module.css'\n\n// const payload = await getPayload({\n// config: configPromise,\n// })\n\n// Pass your config from generated types as generic\n\nexport interface ISubscribe {\n classNames?: SubscribeClasses\n handleSubscribe?: (result: SubscribeResponse) => void\n props?: any\n verifyUrl?: URL\n}\n\nexport type SubscribeClasses = {\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\ntype statusValues = 'default' | 'error' | 'sent' | 'updated'\n\nexport const Subscribe = ({\n classNames = {\n button: '',\n container: '',\n emailInput: '',\n error: '',\n form: '',\n loading: '',\n message: '',\n section: '',\n },\n handleSubscribe,\n verifyUrl,\n}: ISubscribe) => {\n const { refreshSubscriber, subscriber } = useSubscriber()\n\n const { serverURL } = useServerUrl()\n\n const sdk = new PayloadSDK<Config>({\n baseURL: serverURL || '',\n })\n\n const flattenChannels = (channels: (OptInChannel | string)[] | null | undefined) => {\n if (!channels) {\n return []\n }\n return channels.map((channel: OptInChannel | string) =>\n typeof channel == 'string' ? channel : channel.id,\n )\n }\n\n const [status, setStatus] = useState<statusValues>('default')\n const [result, setResult] = useState<string>()\n const [email, setEmail] = useState(subscriber ? subscriber.email : '')\n const [selectedChannelIDs, setSelectedChannelIDs] = useState<string[]>(() =>\n flattenChannels(subscriber?.optIns),\n )\n\n useEffect(() => {\n setEmail(subscriber?.email || '')\n setSelectedChannelIDs(flattenChannels(subscriber?.optIns))\n }, [subscriber])\n\n const handleOptInChannelsSelected = (result: OptInChannel[]) => {\n setSelectedChannelIDs(result.map((channel) => channel.id))\n }\n\n const handleSubmit = async () => {\n const subscribeResult = await sdk.request({\n json: {\n email,\n optIns: selectedChannelIDs,\n verifyUrl: verifyUrl?.href,\n },\n method: 'POST',\n path: '/api/subscribe',\n })\n if (subscribeResult.ok) {\n const resultJson: SubscribeResponse = await subscribeResult.json()\n // // When subscriber optIns are updated...\n // | {\n // email: string\n // now: string\n // optIns: string[]\n // }\n // // When a verify link is emailed...\n // | {\n // emailResult: any\n // now: string\n // }\n // // When any error occurs...\n // | {\n // error: string\n // now: string\n // }\n // @ts-expect-error Silly type confusion\n const { emailResult, error } = resultJson\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 if (email) {\n setStatus('updated')\n setResult(`You're subscriptions have been updated.`)\n } else {\n setStatus('error')\n setResult(`An error occured. Please try again. \\nResult unknown`)\n }\n\n refreshSubscriber()\n\n if (handleSubscribe) {\n handleSubscribe(resultJson)\n }\n } else {\n // const resultText = await subscribeResult.text()\n setStatus('error')\n setResult(`An error occured. Please try again. \\nResult unknown`)\n }\n }\n\n return (\n <div className={mergeClassNames([styles.container, classNames.container])}>\n <h2>Subscribe</h2>\n <div className={mergeClassNames([styles.section, classNames.section])}>\n <SelectOptInChannels\n handleOptInChannelsSelected={handleOptInChannelsSelected}\n selectedOptInChannelIDs={selectedChannelIDs}\n />\n </div>\n <form\n className={mergeClassNames([styles.form, classNames.form])}\n method=\"POST\"\n onSubmit={async (e) => {\n e.preventDefault()\n await handleSubmit()\n }}\n >\n <div className={mergeClassNames([styles.section, classNames.section])}>\n {!subscriber && (\n <input\n aria-label=\"enter your email\"\n className={mergeClassNames([styles.emailInput, classNames.emailInput])}\n onChange={(e: ChangeEvent<HTMLInputElement>) => setEmail(e.target.value)}\n placeholder=\"enter your email\"\n type=\"email\"\n value={email}\n />\n )}\n <button className={mergeClassNames([styles.button, classNames.button])} type=\"submit\">\n Save choices\n </button>\n </div>\n </form>\n {!!result && (\n <p\n className={mergeClassNames([\n styles.message,\n classNames.message,\n status == 'error' ? [styles.error, classNames.error] : [],\n ])}\n >\n {result}\n </p>\n )}\n </div>\n )\n}\n"],"names":["PayloadSDK","useEffect","useState","useSubscriber","useServerUrl","mergeClassNames","SelectOptInChannels","styles","Subscribe","classNames","button","container","emailInput","error","form","loading","message","section","handleSubscribe","verifyUrl","refreshSubscriber","subscriber","serverURL","sdk","baseURL","flattenChannels","channels","map","channel","id","status","setStatus","result","setResult","email","setEmail","selectedChannelIDs","setSelectedChannelIDs","optIns","handleOptInChannelsSelected","handleSubmit","subscribeResult","request","json","href","method","path","ok","resultJson","emailResult","div","className","h2","selectedOptInChannelIDs","onSubmit","e","preventDefault","input","aria-label","onChange","target","value","placeholder","type","p"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/components/app/Subscribe.tsx"],"sourcesContent":["'use client'\n\nimport { PayloadSDK } from '@payloadcms/sdk'\nimport { type ChangeEvent, useEffect, useState } from 'react'\n\nimport type { Config, OptInChannel } from '../../copied/payload-types.js'\nimport type { SubscribeResponse } from '../../endpoints/subscribe.js'\n\nexport { SubscribeResponse }\n\nimport { useSubscriber } from '../../contexts/SubscriberProvider.js'\nimport { useServerUrl } from '../../react-hooks/useServerUrl.js'\nimport { mergeClassNames } from './helpers.js'\nimport { SelectOptInChannels } from './SelectOptInChannels.js'\nimport styles from './shared.module.css'\n\n/** Props for the Subscribe component. */\nexport interface ISubscribe {\n classNames?: SubscribeClasses\n handleSubscribe?: (result: SubscribeResponse) => void\n props?: any\n verifyUrl?: string | URL\n}\n\n/** Optional CSS class overrides for Subscribe elements. */\nexport type SubscribeClasses = {\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\ntype statusValues = 'default' | 'error' | 'sent' | 'updated'\n\n/**\n * Subscribe/preferences form for authenticated subscribers. Shows SelectOptInChannels and an email\n * input when not yet authenticated. Submits to POST /api/subscribe to update opt-ins or trigger\n * verification email. Calls refreshSubscriber and handleSubscribe on success.\n *\n * @param props - See ISubscribe\n * @returns Form with channel checkboxes, optional email field, \"Save choices\" button, and status message\n */\nexport const Subscribe = ({\n classNames = {\n button: '',\n container: '',\n emailInput: '',\n error: '',\n form: '',\n loading: '',\n message: '',\n section: '',\n },\n handleSubscribe,\n verifyUrl,\n}: ISubscribe) => {\n if (typeof verifyUrl == 'string') {\n verifyUrl = new URL(verifyUrl)\n }\n\n const { refreshSubscriber, subscriber } = useSubscriber()\n\n const { serverURL } = useServerUrl()\n\n const sdk = new PayloadSDK<Config>({\n baseURL: serverURL || '',\n })\n\n const flattenChannels = (channels: (OptInChannel | string)[] | null | undefined) => {\n if (!channels) {\n return []\n }\n return channels.map((channel: OptInChannel | string) =>\n typeof channel == 'string' ? channel : channel.id,\n )\n }\n\n const [status, setStatus] = useState<statusValues>('default')\n const [result, setResult] = useState<string>()\n const [email, setEmail] = useState(subscriber ? subscriber.email : '')\n const [selectedChannelIDs, setSelectedChannelIDs] = useState<string[]>(() =>\n flattenChannels(subscriber?.optIns),\n )\n\n useEffect(() => {\n setEmail(subscriber?.email || '')\n setSelectedChannelIDs(flattenChannels(subscriber?.optIns))\n }, [subscriber])\n\n const handleOptInChannelsSelected = (result: OptInChannel[]) => {\n setSelectedChannelIDs(result.map((channel) => channel.id))\n }\n\n const handleSubmit = async () => {\n const subscribeResult = await sdk.request({\n json: {\n email,\n optIns: selectedChannelIDs,\n verifyUrl: verifyUrl?.href,\n },\n method: 'POST',\n path: '/api/subscribe',\n })\n if (subscribeResult.ok) {\n const resultJson: SubscribeResponse = await subscribeResult.json()\n // // When subscriber optIns are updated...\n // | {\n // email: string\n // now: string\n // optIns: string[]\n // }\n // // When a verify link is emailed...\n // | {\n // emailResult: any\n // now: string\n // }\n // // When any error occurs...\n // | {\n // error: string\n // now: string\n // }\n // @ts-expect-error Silly type confusion\n const { emailResult, error } = resultJson\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 if (email) {\n setStatus('updated')\n setResult(`You're subscriptions have been updated.`)\n } else {\n setStatus('error')\n setResult(`An error occured. Please try again. \\nResult unknown`)\n }\n\n refreshSubscriber()\n\n if (handleSubscribe) {\n handleSubscribe(resultJson)\n }\n } else {\n // const resultText = await subscribeResult.text()\n setStatus('error')\n setResult(`An error occured. Please try again. \\nResult unknown`)\n }\n }\n\n return (\n <div\n className={mergeClassNames([\n 'subscribers-subscribe subscribers-container',\n styles.container,\n classNames.container,\n ])}\n >\n <h2>Subscribe</h2>\n <div className={mergeClassNames(['subscribers-section', styles.section, classNames.section])}>\n <SelectOptInChannels\n handleOptInChannelsSelected={handleOptInChannelsSelected}\n selectedOptInChannelIDs={selectedChannelIDs}\n />\n </div>\n <form\n className={mergeClassNames(['subscribers-form', styles.form, classNames.form])}\n method=\"POST\"\n onSubmit={async (e) => {\n e.preventDefault()\n await handleSubmit()\n }}\n >\n <div\n className={mergeClassNames(['subscribers-section', styles.section, classNames.section])}\n >\n {!subscriber && (\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 )}\n <button\n className={mergeClassNames(['subscribers-button', styles.button, classNames.button])}\n type=\"submit\"\n >\n Save choices\n </button>\n </div>\n </form>\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 </div>\n )\n}\n"],"names":["PayloadSDK","useEffect","useState","useSubscriber","useServerUrl","mergeClassNames","SelectOptInChannels","styles","Subscribe","classNames","button","container","emailInput","error","form","loading","message","section","handleSubscribe","verifyUrl","URL","refreshSubscriber","subscriber","serverURL","sdk","baseURL","flattenChannels","channels","map","channel","id","status","setStatus","result","setResult","email","setEmail","selectedChannelIDs","setSelectedChannelIDs","optIns","handleOptInChannelsSelected","handleSubmit","subscribeResult","request","json","href","method","path","ok","resultJson","emailResult","div","className","h2","selectedOptInChannelIDs","onSubmit","e","preventDefault","input","aria-label","onChange","target","value","placeholder","type","p"],"mappings":"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"}
|
|
@@ -1,7 +1,20 @@
|
|
|
1
|
+
/** Props for the VerifyMagicLink component. */
|
|
2
|
+
export interface ISubscriberMenu {
|
|
3
|
+
classNames?: SubscriberMenuClasses;
|
|
4
|
+
subscribeUrl?: string | URL;
|
|
5
|
+
}
|
|
6
|
+
/** Optional CSS class overrides for SubscriberMenu elements. */
|
|
1
7
|
export type SubscriberMenuClasses = {
|
|
2
8
|
button?: string;
|
|
3
9
|
container?: string;
|
|
10
|
+
group?: string;
|
|
4
11
|
};
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
12
|
+
/**
|
|
13
|
+
* Displays subscriber UI when authenticated: welcome message, optional "Manage subscriptions" link,
|
|
14
|
+
* and a logout button. Renders nothing when no subscriber is in context.
|
|
15
|
+
*
|
|
16
|
+
* @param props.classNames - Optional class overrides for container, group, and button
|
|
17
|
+
* @param props.subscribeUrl - If set, shows a "Manage subscriptions" link to this URL
|
|
18
|
+
* @returns Container with welcome text, subscribe link (if subscribeUrl), and Log out button, or null
|
|
19
|
+
*/
|
|
20
|
+
export declare const SubscriberMenu: ({ classNames, subscribeUrl, }: ISubscriberMenu) => import("react").JSX.Element;
|