payload-subscribers-plugin 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (133) hide show
  1. package/README.md +305 -0
  2. package/dist/collections/OptInChannels.d.ts +3 -0
  3. package/dist/collections/OptInChannels.js +44 -0
  4. package/dist/collections/OptInChannels.js.map +1 -0
  5. package/dist/collections/Subscribers.d.ts +8 -0
  6. package/dist/collections/Subscribers.js +88 -0
  7. package/dist/collections/Subscribers.js.map +1 -0
  8. package/dist/collections/fields/OptedInChannels.d.ts +2 -0
  9. package/dist/collections/fields/OptedInChannels.js +12 -0
  10. package/dist/collections/fields/OptedInChannels.js.map +1 -0
  11. package/dist/components/BeforeDashboardClient.d.ts +1 -0
  12. package/dist/components/BeforeDashboardClient.js +40 -0
  13. package/dist/components/BeforeDashboardClient.js.map +1 -0
  14. package/dist/components/BeforeDashboardServer.d.ts +2 -0
  15. package/dist/components/BeforeDashboardServer.js +22 -0
  16. package/dist/components/BeforeDashboardServer.js.map +1 -0
  17. package/dist/components/BeforeDashboardServer.module.css +5 -0
  18. package/dist/components/app/RequestMagicLink.d.ts +16 -0
  19. package/dist/components/app/RequestMagicLink.js +114 -0
  20. package/dist/components/app/RequestMagicLink.js.map +1 -0
  21. package/dist/components/app/RequestMagicLink.module.css +5 -0
  22. package/dist/components/app/RequestOrSubscribe.d.ts +17 -0
  23. package/dist/components/app/RequestOrSubscribe.js +28 -0
  24. package/dist/components/app/RequestOrSubscribe.js.map +1 -0
  25. package/dist/components/app/SelectOptInChannels.d.ts +20 -0
  26. package/dist/components/app/SelectOptInChannels.js +120 -0
  27. package/dist/components/app/SelectOptInChannels.js.map +1 -0
  28. package/dist/components/app/SelectOptInChannels.module.css +5 -0
  29. package/dist/components/app/Subscribe.d.ts +18 -0
  30. package/dist/components/app/Subscribe.js +169 -0
  31. package/dist/components/app/Subscribe.js.map +1 -0
  32. package/dist/components/app/Subscribe.module.css +5 -0
  33. package/dist/components/app/SubscriberMenu.d.ts +7 -0
  34. package/dist/components/app/SubscriberMenu.js +44 -0
  35. package/dist/components/app/SubscriberMenu.js.map +1 -0
  36. package/dist/components/app/VerifyMagicLink.d.ts +23 -0
  37. package/dist/components/app/VerifyMagicLink.js +169 -0
  38. package/dist/components/app/VerifyMagicLink.js.map +1 -0
  39. package/dist/components/app/VerifyMagicLink.module.css +5 -0
  40. package/dist/components/app/helpers.d.ts +1 -0
  41. package/dist/components/app/helpers.js +5 -0
  42. package/dist/components/app/helpers.js.map +1 -0
  43. package/dist/components/app/shared.module.css +14 -0
  44. package/dist/contexts/SubscriberProvider.d.ts +15 -0
  45. package/dist/contexts/SubscriberProvider.js +105 -0
  46. package/dist/contexts/SubscriberProvider.js.map +1 -0
  47. package/dist/copied/payload-types.d.ts +395 -0
  48. package/dist/copied/payload-types.js +15 -0
  49. package/dist/copied/payload-types.js.map +1 -0
  50. package/dist/copied/payload.config.d.ts +2 -0
  51. package/dist/endpoints/customEndpointHandler.d.ts +2 -0
  52. package/dist/endpoints/customEndpointHandler.js +7 -0
  53. package/dist/endpoints/customEndpointHandler.js.map +1 -0
  54. package/dist/endpoints/getOptInChannels.d.ts +19 -0
  55. package/dist/endpoints/getOptInChannels.js +42 -0
  56. package/dist/endpoints/getOptInChannels.js.map +1 -0
  57. package/dist/endpoints/logout.d.ts +20 -0
  58. package/dist/endpoints/logout.js +60 -0
  59. package/dist/endpoints/logout.js.map +1 -0
  60. package/dist/endpoints/requestMagicLink.d.ts +20 -0
  61. package/dist/endpoints/requestMagicLink.js +122 -0
  62. package/dist/endpoints/requestMagicLink.js.map +1 -0
  63. package/dist/endpoints/subscribe.d.ts +24 -0
  64. package/dist/endpoints/subscribe.js +343 -0
  65. package/dist/endpoints/subscribe.js.map +1 -0
  66. package/dist/endpoints/subscriberAuth.d.ts +22 -0
  67. package/dist/endpoints/subscriberAuth.js +69 -0
  68. package/dist/endpoints/subscriberAuth.js.map +1 -0
  69. package/dist/endpoints/verifyMagicLink.d.ts +20 -0
  70. package/dist/endpoints/verifyMagicLink.js +142 -0
  71. package/dist/endpoints/verifyMagicLink.js.map +1 -0
  72. package/dist/exports/client.d.ts +1 -0
  73. package/dist/exports/client.js +3 -0
  74. package/dist/exports/client.js.map +1 -0
  75. package/dist/exports/index.d.ts +1 -0
  76. package/dist/exports/index.js +3 -0
  77. package/dist/exports/index.js.map +1 -0
  78. package/dist/exports/rsc.d.ts +1 -0
  79. package/dist/exports/rsc.js +3 -0
  80. package/dist/exports/rsc.js.map +1 -0
  81. package/dist/exports/ui.d.ts +11 -0
  82. package/dist/exports/ui.js +9 -0
  83. package/dist/exports/ui.js.map +1 -0
  84. package/dist/helpers/serverConfig.d.ts +4 -0
  85. package/dist/helpers/serverConfig.js +22 -0
  86. package/dist/helpers/serverConfig.js.map +1 -0
  87. package/dist/helpers/testData.d.ts +2 -0
  88. package/dist/helpers/testData.js +4 -0
  89. package/dist/helpers/testData.js.map +1 -0
  90. package/dist/helpers/token.d.ts +9 -0
  91. package/dist/helpers/token.js +20 -0
  92. package/dist/helpers/token.js.map +1 -0
  93. package/dist/helpers/verifyOptIns.d.ts +5 -0
  94. package/dist/helpers/verifyOptIns.js +33 -0
  95. package/dist/helpers/verifyOptIns.js.map +1 -0
  96. package/dist/index.d.ts +26 -0
  97. package/dist/index.js +147 -0
  98. package/dist/index.js.map +1 -0
  99. package/dist/react-hooks/useServerUrl.d.ts +3 -0
  100. package/dist/react-hooks/useServerUrl.js +19 -0
  101. package/dist/react-hooks/useServerUrl.js.map +1 -0
  102. package/dist/server-functions/serverUrl.d.ts +3 -0
  103. package/dist/server-functions/serverUrl.js +31 -0
  104. package/dist/server-functions/serverUrl.js.map +1 -0
  105. package/dist/server-functions/subscriberAuth.d.ts +11 -0
  106. package/package.json +94 -0
  107. package/src/collections/OptInChannels.ts +45 -0
  108. package/src/collections/Subscribers.ts +99 -0
  109. package/src/collections/fields/OptedInChannels.ts +12 -0
  110. package/src/components/app/RequestMagicLink.tsx +129 -0
  111. package/src/components/app/RequestOrSubscribe.tsx +58 -0
  112. package/src/components/app/SelectOptInChannels.tsx +147 -0
  113. package/src/components/app/Subscribe.tsx +190 -0
  114. package/src/components/app/SubscriberMenu.tsx +46 -0
  115. package/src/components/app/VerifyMagicLink.tsx +197 -0
  116. package/src/components/app/helpers.ts +6 -0
  117. package/src/components/app/shared.module.css +14 -0
  118. package/src/contexts/SubscriberProvider.tsx +122 -0
  119. package/src/copied/payload-types.ts +478 -0
  120. package/src/endpoints/getOptInChannels.ts +56 -0
  121. package/src/endpoints/logout.ts +104 -0
  122. package/src/endpoints/requestMagicLink.ts +139 -0
  123. package/src/endpoints/subscribe.ts +435 -0
  124. package/src/endpoints/subscriberAuth.ts +100 -0
  125. package/src/endpoints/verifyMagicLink.ts +164 -0
  126. package/src/exports/index.ts +1 -0
  127. package/src/exports/ui.ts +17 -0
  128. package/src/helpers/testData.ts +2 -0
  129. package/src/helpers/token.ts +14 -0
  130. package/src/helpers/verifyOptIns.ts +39 -0
  131. package/src/index.ts +207 -0
  132. package/src/react-hooks/useServerUrl.tsx +18 -0
  133. package/src/server-functions/serverUrl.ts +38 -0
@@ -0,0 +1,114 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { PayloadSDK } from '@payloadcms/sdk';
4
+ import { useEffect, useState } from 'react';
5
+ import { useSubscriber } from '../../contexts/SubscriberProvider.js';
6
+ import { useServerUrl } from '../../react-hooks/useServerUrl.js';
7
+ import { mergeClassNames } from './helpers.js';
8
+ import styles from './shared.module.css';
9
+ export const RequestMagicLink = ({ classNames = {
10
+ button: '',
11
+ container: '',
12
+ emailInput: '',
13
+ error: '',
14
+ form: '',
15
+ message: ''
16
+ }, handleMagicLinkRequested })=>{
17
+ const { subscriber } = useSubscriber();
18
+ const { serverURL } = useServerUrl();
19
+ const [status, setStatus] = useState('default');
20
+ const sdk = new PayloadSDK({
21
+ baseURL: serverURL || ''
22
+ });
23
+ const [result, setResult] = useState();
24
+ const [email, setEmail] = useState(subscriber?.email || '');
25
+ useEffect(()=>{
26
+ setEmail(subscriber?.email || '');
27
+ }, [
28
+ subscriber
29
+ ]);
30
+ const handleSubmit = async (e)=>{
31
+ e.preventDefault();
32
+ const forwardUrl = window.location.pathname + '?now=' + new Date().toISOString();
33
+ const emailTokenResponse = await sdk.request({
34
+ json: {
35
+ email,
36
+ forwardUrl
37
+ },
38
+ method: 'POST',
39
+ path: '/api/emailToken'
40
+ });
41
+ if (emailTokenResponse.ok) {
42
+ const emailTokenResponseJson = await emailTokenResponse.json();
43
+ if (handleMagicLinkRequested) {
44
+ handleMagicLinkRequested(emailTokenResponseJson);
45
+ }
46
+ // @ts-expect-error One or the other exists
47
+ const { emailResult, error } = emailTokenResponseJson;
48
+ if (error) {
49
+ setStatus('error');
50
+ setResult(`An error occured. Please try again. \n ${error}`);
51
+ } else if (emailResult) {
52
+ setStatus('sent');
53
+ setResult('An email has been sent containing your magic link.');
54
+ } else {
55
+ setStatus('error');
56
+ setResult(`An error occured. Please try again. \nResult unknown`);
57
+ }
58
+ } else {
59
+ const emailTokenResponseText = await emailTokenResponse.text();
60
+ setStatus('error');
61
+ setResult(`An error occured. Please try again. \n${emailTokenResponseText}`);
62
+ }
63
+ };
64
+ return /*#__PURE__*/ _jsxs("div", {
65
+ className: mergeClassNames([
66
+ styles.container,
67
+ classNames.container
68
+ ]),
69
+ children: [
70
+ result ? /*#__PURE__*/ _jsx("p", {
71
+ className: mergeClassNames([
72
+ styles.message,
73
+ classNames.message,
74
+ status == 'error' ? [
75
+ styles.error,
76
+ classNames.error
77
+ ] : []
78
+ ]),
79
+ children: result
80
+ }) : /*#__PURE__*/ _jsx(_Fragment, {}),
81
+ /*#__PURE__*/ _jsxs("form", {
82
+ className: mergeClassNames([
83
+ styles.form,
84
+ classNames.form
85
+ ]),
86
+ method: "POST",
87
+ onSubmit: handleSubmit,
88
+ children: [
89
+ /*#__PURE__*/ _jsx("input", {
90
+ "aria-label": "enter your email",
91
+ className: mergeClassNames([
92
+ styles.emailInput,
93
+ classNames.emailInput
94
+ ]),
95
+ onChange: (e)=>setEmail(e.target.value),
96
+ placeholder: "enter your email",
97
+ type: "email",
98
+ value: email
99
+ }),
100
+ /*#__PURE__*/ _jsx("button", {
101
+ className: mergeClassNames([
102
+ styles.button,
103
+ classNames.button
104
+ ]),
105
+ type: "submit",
106
+ children: "Request magic link"
107
+ })
108
+ ]
109
+ })
110
+ ]
111
+ });
112
+ };
113
+
114
+ //# sourceMappingURL=RequestMagicLink.js.map
@@ -0,0 +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}\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}: IRequestMagicLink) => {\n const { subscriber } = useSubscriber()\n const { serverURL } = useServerUrl()\n\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 forwardUrl = window.location.pathname + '?now=' + new Date().toISOString()\n const emailTokenResponse = await sdk.request({\n json: {\n email,\n forwardUrl,\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 className={mergeClassNames([styles.container, classNames.container])}>\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 <></>\n )}\n <form\n className={mergeClassNames([styles.form, classNames.form])}\n method=\"POST\"\n onSubmit={handleSubmit}\n >\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 <button className={mergeClassNames([styles.button, classNames.button])} type=\"submit\">\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","subscriber","serverURL","status","setStatus","sdk","baseURL","result","setResult","email","setEmail","handleSubmit","e","preventDefault","forwardUrl","window","location","pathname","Date","toISOString","emailTokenResponse","request","json","method","path","ok","emailTokenResponseJson","emailResult","emailTokenResponseText","text","div","className","p","onSubmit","input","aria-label","onChange","target","value","placeholder","type"],"mappings":"AAAA;;AAEA,SAASA,UAAU,QAAQ,kBAAiB;AAC5C,SAA6CC,SAAS,EAAEC,QAAQ,QAAQ,QAAO;AAK/E,SAASC,aAAa,QAAQ,uCAAsC;AACpE,SAASC,YAAY,QAAQ,oCAAmC;AAChE,SAASC,eAAe,QAAQ,eAAc;AAC9C,OAAOC,YAAY,sBAAqB;AAqBxC,OAAO,MAAMC,mBAAmB,CAAC,EAC/BC,aAAa;IACXC,QAAQ;IACRC,WAAW;IACXC,YAAY;IACZC,OAAO;IACPC,MAAM;IACNC,SAAS;AACX,CAAC,EACDC,wBAAwB,EACN;IAClB,MAAM,EAAEC,UAAU,EAAE,GAAGb;IACvB,MAAM,EAAEc,SAAS,EAAE,GAAGb;IAEtB,MAAM,CAACc,QAAQC,UAAU,GAAGjB,SAAuB;IAEnD,MAAMkB,MAAM,IAAIpB,WAAmB;QACjCqB,SAASJ,aAAa;IACxB;IAEA,MAAM,CAACK,QAAQC,UAAU,GAAGrB;IAC5B,MAAM,CAACsB,OAAOC,SAAS,GAAGvB,SAASc,YAAYQ,SAAS;IAExDvB,UAAU;QACRwB,SAAST,YAAYQ,SAAS;IAChC,GAAG;QAACR;KAAW;IAEf,MAAMU,eAAe,OAAOC;QAC1BA,EAAEC,cAAc;QAChB,MAAMC,aAAaC,OAAOC,QAAQ,CAACC,QAAQ,GAAG,UAAU,IAAIC,OAAOC,WAAW;QAC9E,MAAMC,qBAAqB,MAAMf,IAAIgB,OAAO,CAAC;YAC3CC,MAAM;gBACJb;gBACAK;YACF;YACAS,QAAQ;YACRC,MAAM;QACR;QACA,IAAIJ,mBAAmBK,EAAE,EAAE;YACzB,MAAMC,yBAAmD,MAAMN,mBAAmBE,IAAI;YACtF,IAAItB,0BAA0B;gBAC5BA,yBAAyB0B;YAC3B;YACA,2CAA2C;YAC3C,MAAM,EAAEC,WAAW,EAAE9B,KAAK,EAAE,GAAG6B;YAC/B,IAAI7B,OAAO;gBACTO,UAAU;gBACVI,UAAU,CAAC,uCAAuC,EAAEX,OAAO;YAC7D,OAAO,IAAI8B,aAAa;gBACtBvB,UAAU;gBACVI,UAAU;YACZ,OAAO;gBACLJ,UAAU;gBACVI,UAAU,CAAC,oDAAoD,CAAC;YAClE;QACF,OAAO;YACL,MAAMoB,yBAAyB,MAAMR,mBAAmBS,IAAI;YAC5DzB,UAAU;YACVI,UAAU,CAAC,sCAAsC,EAAEoB,wBAAwB;QAC7E;IACF;IAEA,qBACE,MAACE;QAAIC,WAAWzC,gBAAgB;YAACC,OAAOI,SAAS;YAAEF,WAAWE,SAAS;SAAC;;YACrEY,uBACC,KAACyB;gBACCD,WAAWzC,gBAAgB;oBACzBC,OAAOQ,OAAO;oBACdN,WAAWM,OAAO;oBAClBI,UAAU,UAAU;wBAACZ,OAAOM,KAAK;wBAAEJ,WAAWI,KAAK;qBAAC,GAAG,EAAE;iBAC1D;0BAEAU;+BAGH;0BAEF,MAACT;gBACCiC,WAAWzC,gBAAgB;oBAACC,OAAOO,IAAI;oBAAEL,WAAWK,IAAI;iBAAC;gBACzDyB,QAAO;gBACPU,UAAUtB;;kCAEV,KAACuB;wBACCC,cAAW;wBACXJ,WAAWzC,gBAAgB;4BAACC,OAAOK,UAAU;4BAAEH,WAAWG,UAAU;yBAAC;wBACrEwC,UAAU,CAACxB,IAAqCF,SAASE,EAAEyB,MAAM,CAACC,KAAK;wBACvEC,aAAY;wBACZC,MAAK;wBACLF,OAAO7B;;kCAET,KAACf;wBAAOqC,WAAWzC,gBAAgB;4BAACC,OAAOG,MAAM;4BAAED,WAAWC,MAAM;yBAAC;wBAAG8C,MAAK;kCAAS;;;;;;AAM9F,EAAC"}
@@ -0,0 +1,5 @@
1
+ .wrapper {
2
+ display: flex;
3
+ gap: 5px;
4
+ flex-direction: column;
5
+ }
@@ -0,0 +1,17 @@
1
+ import { type RequestMagicLinkResponse, type SubscribeResponse } from '../../exports/ui.js';
2
+ export type { RequestMagicLinkResponse, SubscribeResponse };
3
+ export type RequestOrSubscribeClasses = {
4
+ button?: string;
5
+ container?: string;
6
+ emailInput?: string;
7
+ error?: string;
8
+ form?: string;
9
+ loading?: string;
10
+ message?: string;
11
+ section?: string;
12
+ };
13
+ export declare function RequestOrSubscribe({ classNames, handleMagicLinkRequested, handleSubscribe, }: {
14
+ classNames?: RequestOrSubscribeClasses;
15
+ handleMagicLinkRequested?: (result: RequestMagicLinkResponse) => void;
16
+ handleSubscribe?: (result: SubscribeResponse) => void;
17
+ }): import("react").JSX.Element;
@@ -0,0 +1,28 @@
1
+ 'use client';
2
+ import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { useSubscriber } from '../../contexts/SubscriberProvider.js';
4
+ import { RequestMagicLink, Subscribe } from '../../exports/ui.js';
5
+ export function RequestOrSubscribe({ classNames = {
6
+ button: '',
7
+ container: '',
8
+ emailInput: '',
9
+ error: '',
10
+ form: '',
11
+ loading: '',
12
+ message: '',
13
+ section: ''
14
+ }, handleMagicLinkRequested, handleSubscribe }) {
15
+ const { subscriber } = useSubscriber();
16
+ // Example: Conditionally render something or pass the state to children
17
+ return /*#__PURE__*/ _jsx(_Fragment, {
18
+ children: subscriber ? /*#__PURE__*/ _jsx(Subscribe, {
19
+ classNames: classNames,
20
+ handleSubscribe: handleSubscribe
21
+ }) : /*#__PURE__*/ _jsx(RequestMagicLink, {
22
+ classNames: classNames,
23
+ handleMagicLinkRequested: handleMagicLinkRequested
24
+ })
25
+ });
26
+ }
27
+
28
+ //# sourceMappingURL=RequestOrSubscribe.js.map
@@ -0,0 +1 @@
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\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\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}: {\n classNames?: RequestOrSubscribeClasses\n handleMagicLinkRequested?: (result: RequestMagicLinkResponse) => void\n handleSubscribe?: (result: SubscribeResponse) => void\n}) {\n const { subscriber } = useSubscriber()\n\n // Example: Conditionally render something or pass the state to children\n return (\n <>\n {subscriber ? (\n <Subscribe classNames={classNames} handleSubscribe={handleSubscribe} />\n ) : (\n <RequestMagicLink\n classNames={classNames}\n handleMagicLinkRequested={handleMagicLinkRequested}\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","subscriber"],"mappings":"AAAA;;AAEA,SAASA,aAAa,QAAQ,uCAAsC;AACpE,SACEC,gBAAgB,EAEhBC,SAAS,QAEJ,sBAAqB;AAe5B,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,EAKhB;IACC,MAAM,EAAEC,UAAU,EAAE,GAAGf;IAEvB,wEAAwE;IACxE,qBACE;kBACGe,2BACC,KAACb;YAAUE,YAAYA;YAAYU,iBAAiBA;2BAEpD,KAACb;YACCG,YAAYA;YACZS,0BAA0BA;;;AAMpC"}
@@ -0,0 +1,20 @@
1
+ import type { OptInChannel } from '../../copied/payload-types.js';
2
+ export interface ISelectOptInChannels {
3
+ classNames?: SelectOptInChannelsClasses;
4
+ handleOptInChannelsSelected?: (result: OptInChannel[]) => void;
5
+ props?: any;
6
+ selectedOptInChannelIDs?: string[];
7
+ }
8
+ export type SelectOptInChannelsClasses = {
9
+ button?: string;
10
+ container?: string;
11
+ error?: string;
12
+ form?: string;
13
+ loading?: string;
14
+ message?: string;
15
+ optInCheckbox?: string;
16
+ optInCheckboxItem?: string;
17
+ optInCheckboxLabel?: string;
18
+ optionsGroup?: string;
19
+ };
20
+ export declare const SelectOptInChannels: ({ classNames, handleOptInChannelsSelected, selectedOptInChannelIDs, }: ISelectOptInChannels) => import("react").JSX.Element;
@@ -0,0 +1,120 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { PayloadSDK } from '@payloadcms/sdk';
4
+ import { useEffect, useState } from 'react';
5
+ import { useServerUrl } from '../../react-hooks/useServerUrl.js';
6
+ import { mergeClassNames } from './helpers.js';
7
+ import styles from './shared.module.css';
8
+ export const SelectOptInChannels = ({ classNames = {
9
+ button: '',
10
+ container: '',
11
+ error: '',
12
+ form: '',
13
+ loading: '',
14
+ message: '',
15
+ optInCheckbox: '',
16
+ optInCheckboxItem: '',
17
+ optInCheckboxLabel: '',
18
+ optionsGroup: ''
19
+ }, handleOptInChannelsSelected, selectedOptInChannelIDs })=>{
20
+ const { serverURL } = useServerUrl();
21
+ const [result, setResult] = useState();
22
+ const [allOptInChannels, setAllOptInChannels] = useState([]);
23
+ useEffect(()=>{
24
+ async function verify() {
25
+ const sdk = new PayloadSDK({
26
+ baseURL: serverURL || ''
27
+ });
28
+ console.log('calling optinchannels endpoint');
29
+ const result = await sdk.request({
30
+ method: 'GET',
31
+ path: '/api/optinchannels'
32
+ });
33
+ if (result.ok) {
34
+ const resultJson = await result.json();
35
+ setResult(resultJson);
36
+ } else {
37
+ const resultText = await result.text();
38
+ setResult(resultText);
39
+ }
40
+ }
41
+ void verify();
42
+ }, [
43
+ serverURL
44
+ ]);
45
+ useEffect(()=>{
46
+ const channels = result?.optInChannels?.map((channel)=>({
47
+ ...channel,
48
+ isChecked: selectedOptInChannelIDs?.includes(channel.id)
49
+ }));
50
+ setAllOptInChannels(channels);
51
+ }, [
52
+ result,
53
+ selectedOptInChannelIDs
54
+ ]);
55
+ return /*#__PURE__*/ _jsxs("div", {
56
+ className: mergeClassNames([
57
+ styles.container,
58
+ classNames.container
59
+ ]),
60
+ children: [
61
+ /*#__PURE__*/ _jsx("h3", {
62
+ children: "Opt-in Channels"
63
+ }),
64
+ !result ? /*#__PURE__*/ _jsx("p", {
65
+ className: mergeClassNames([
66
+ styles.loading,
67
+ classNames.loading
68
+ ]),
69
+ children: "verifying..."
70
+ }) : /*#__PURE__*/ _jsx("div", {
71
+ className: mergeClassNames([
72
+ styles.optionsGroup,
73
+ classNames.optionsGroup
74
+ ]),
75
+ children: allOptInChannels?.map((channel)=>/*#__PURE__*/ _jsx("div", {
76
+ className: mergeClassNames([
77
+ styles.optInCheckboxItem,
78
+ classNames.optInCheckboxItem
79
+ ]),
80
+ children: /*#__PURE__*/ _jsxs("label", {
81
+ className: mergeClassNames([
82
+ styles.optInCheckboxLabel,
83
+ classNames.optInCheckboxLabel
84
+ ]),
85
+ children: [
86
+ /*#__PURE__*/ _jsx("input", {
87
+ "aria-label": channel.title,
88
+ // The checked prop is controlled by the state
89
+ checked: channel.isChecked,
90
+ className: mergeClassNames([
91
+ styles.optInCheckbox,
92
+ classNames.optInCheckbox
93
+ ]),
94
+ // The onChange handler calls the update function with the item's ID
95
+ onChange: (event)=>{
96
+ event.preventDefault();
97
+ const checked = event.target.checked;
98
+ if (handleOptInChannelsSelected) {
99
+ handleOptInChannelsSelected(allOptInChannels.map((channel)=>({
100
+ ...channel,
101
+ isChecked: channel.title == event.target.value ? checked : channel.isChecked
102
+ })).filter((c)=>c.isChecked).map((channel)=>({
103
+ ...channel,
104
+ isChecked: undefined
105
+ })));
106
+ }
107
+ },
108
+ type: "checkbox",
109
+ value: channel.title
110
+ }),
111
+ channel.title
112
+ ]
113
+ })
114
+ }, channel.id))
115
+ })
116
+ ]
117
+ });
118
+ };
119
+
120
+ //# sourceMappingURL=SelectOptInChannels.js.map
@@ -0,0 +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// const payload = await getPayload({\n// config: configPromise,\n// })\n\n// Pass your config from generated types as generic\n\nexport interface ISelectOptInChannels {\n classNames?: SelectOptInChannelsClasses\n handleOptInChannelsSelected?: (result: OptInChannel[]) => void\n props?: any\n selectedOptInChannelIDs?: string[]\n}\n\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\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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"}
@@ -0,0 +1,5 @@
1
+ .wrapper {
2
+ display: flex;
3
+ gap: 5px;
4
+ flex-direction: column;
5
+ }
@@ -0,0 +1,18 @@
1
+ import type { SubscribeResponse } from '../../endpoints/subscribe.js';
2
+ export { SubscribeResponse };
3
+ export interface ISubscribe {
4
+ classNames?: SubscribeClasses;
5
+ handleSubscribe?: (result: SubscribeResponse) => void;
6
+ props?: any;
7
+ }
8
+ export type SubscribeClasses = {
9
+ button?: string;
10
+ container?: string;
11
+ emailInput?: string;
12
+ error?: string;
13
+ form?: string;
14
+ loading?: string;
15
+ message?: string;
16
+ section?: string;
17
+ };
18
+ export declare const Subscribe: ({ classNames, handleSubscribe, }: ISubscribe) => import("react").JSX.Element;
@@ -0,0 +1,169 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { PayloadSDK } from '@payloadcms/sdk';
4
+ import { useEffect, useState } from 'react';
5
+ import { useSubscriber } from '../../contexts/SubscriberProvider.js';
6
+ import { useServerUrl } from '../../react-hooks/useServerUrl.js';
7
+ import { mergeClassNames } from './helpers.js';
8
+ import { SelectOptInChannels } from './SelectOptInChannels.js';
9
+ import styles from './shared.module.css';
10
+ export const Subscribe = ({ classNames = {
11
+ button: '',
12
+ container: '',
13
+ emailInput: '',
14
+ error: '',
15
+ form: '',
16
+ loading: '',
17
+ message: '',
18
+ section: ''
19
+ }, handleSubscribe })=>{
20
+ const { refreshSubscriber, subscriber } = useSubscriber();
21
+ const { serverURL } = useServerUrl();
22
+ const sdk = new PayloadSDK({
23
+ baseURL: serverURL || ''
24
+ });
25
+ const flattenChannels = (channels)=>{
26
+ if (!channels) {
27
+ return [];
28
+ }
29
+ return channels.map((channel)=>typeof channel == 'string' ? channel : channel.id);
30
+ };
31
+ const [status, setStatus] = useState('default');
32
+ const [result, setResult] = useState();
33
+ const [email, setEmail] = useState(subscriber ? subscriber.email : '');
34
+ const [selectedChannelIDs, setSelectedChannelIDs] = useState(()=>flattenChannels(subscriber?.optIns));
35
+ useEffect(()=>{
36
+ setEmail(subscriber?.email || '');
37
+ setSelectedChannelIDs(flattenChannels(subscriber?.optIns));
38
+ }, [
39
+ subscriber
40
+ ]);
41
+ const handleOptInChannelsSelected = (result)=>{
42
+ setSelectedChannelIDs(result.map((channel)=>channel.id));
43
+ };
44
+ const handleSubmit = async ()=>{
45
+ const subscribeResult = await sdk.request({
46
+ json: {
47
+ afterVerifyUrl: window.location.pathname + '?now=' + new Date().toISOString(),
48
+ email,
49
+ optIns: selectedChannelIDs
50
+ },
51
+ method: 'POST',
52
+ path: '/api/subscribe'
53
+ });
54
+ if (subscribeResult.ok) {
55
+ const resultJson = await subscribeResult.json();
56
+ // // When subscriber optIns are updated...
57
+ // | {
58
+ // email: string
59
+ // now: string
60
+ // optIns: string[]
61
+ // }
62
+ // // When a verify link is emailed...
63
+ // | {
64
+ // emailResult: any
65
+ // now: string
66
+ // }
67
+ // // When any error occurs...
68
+ // | {
69
+ // error: string
70
+ // now: string
71
+ // }
72
+ // @ts-expect-error Silly type confusion
73
+ const { emailResult, error } = resultJson;
74
+ if (error) {
75
+ setStatus('error');
76
+ setResult(`An error occured. Please try again. \n ${error}`);
77
+ } else if (emailResult) {
78
+ setStatus('sent');
79
+ setResult('An email has been sent containing your magic link.');
80
+ } else if (email) {
81
+ setStatus('updated');
82
+ setResult(`You're subscriptions have been updated.`);
83
+ } else {
84
+ setStatus('error');
85
+ setResult(`An error occured. Please try again. \nResult unknown`);
86
+ }
87
+ refreshSubscriber();
88
+ if (handleSubscribe) {
89
+ handleSubscribe(resultJson);
90
+ }
91
+ } else {
92
+ // const resultText = await subscribeResult.text()
93
+ setStatus('error');
94
+ setResult(`An error occured. Please try again. \nResult unknown`);
95
+ }
96
+ };
97
+ return /*#__PURE__*/ _jsxs("div", {
98
+ className: mergeClassNames([
99
+ styles.container,
100
+ classNames.container
101
+ ]),
102
+ children: [
103
+ /*#__PURE__*/ _jsx("h2", {
104
+ children: "Subscribe"
105
+ }),
106
+ /*#__PURE__*/ _jsx("div", {
107
+ className: mergeClassNames([
108
+ styles.section,
109
+ classNames.section
110
+ ]),
111
+ children: /*#__PURE__*/ _jsx(SelectOptInChannels, {
112
+ handleOptInChannelsSelected: handleOptInChannelsSelected,
113
+ selectedOptInChannelIDs: selectedChannelIDs
114
+ })
115
+ }),
116
+ /*#__PURE__*/ _jsx("form", {
117
+ className: mergeClassNames([
118
+ styles.form,
119
+ classNames.form
120
+ ]),
121
+ method: "POST",
122
+ onSubmit: async (e)=>{
123
+ e.preventDefault();
124
+ await handleSubmit();
125
+ },
126
+ children: /*#__PURE__*/ _jsxs("div", {
127
+ className: mergeClassNames([
128
+ styles.section,
129
+ classNames.section
130
+ ]),
131
+ children: [
132
+ !subscriber && /*#__PURE__*/ _jsx("input", {
133
+ "aria-label": "enter your email",
134
+ className: mergeClassNames([
135
+ styles.emailInput,
136
+ classNames.emailInput
137
+ ]),
138
+ onChange: (e)=>setEmail(e.target.value),
139
+ placeholder: "enter your email",
140
+ type: "email",
141
+ value: email
142
+ }),
143
+ /*#__PURE__*/ _jsx("button", {
144
+ className: mergeClassNames([
145
+ styles.button,
146
+ classNames.button
147
+ ]),
148
+ type: "submit",
149
+ children: "Save choices"
150
+ })
151
+ ]
152
+ })
153
+ }),
154
+ !!result && /*#__PURE__*/ _jsx("p", {
155
+ className: mergeClassNames([
156
+ styles.message,
157
+ classNames.message,
158
+ status == 'error' ? [
159
+ styles.error,
160
+ classNames.error
161
+ ] : []
162
+ ]),
163
+ children: result
164
+ })
165
+ ]
166
+ });
167
+ };
168
+
169
+ //# sourceMappingURL=Subscribe.js.map
@@ -0,0 +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}\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}: 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 afterVerifyUrl: window.location.pathname + '?now=' + new Date().toISOString(),\n email,\n optIns: selectedChannelIDs,\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","refreshSubscriber","subscriber","serverURL","sdk","baseURL","flattenChannels","channels","map","channel","id","status","setStatus","result","setResult","email","setEmail","selectedChannelIDs","setSelectedChannelIDs","optIns","handleOptInChannelsSelected","handleSubmit","subscribeResult","request","json","afterVerifyUrl","window","location","pathname","Date","toISOString","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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"}
@@ -0,0 +1,5 @@
1
+ .wrapper {
2
+ display: flex;
3
+ gap: 5px;
4
+ flex-direction: column;
5
+ }
@@ -0,0 +1,7 @@
1
+ export type SubscriberMenuClasses = {
2
+ button?: string;
3
+ container?: string;
4
+ };
5
+ export declare const SubscriberMenu: ({ classNames, }: {
6
+ classNames?: SubscriberMenuClasses;
7
+ }) => import("react").JSX.Element;
@@ -0,0 +1,44 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useSubscriber } from '../../contexts/SubscriberProvider.js';
4
+ import { mergeClassNames } from './helpers.js';
5
+ import styles from './shared.module.css';
6
+ export const SubscriberMenu = ({ classNames = {
7
+ button: '',
8
+ container: ''
9
+ } })=>{
10
+ const { logOut, subscriber } = useSubscriber();
11
+ return /*#__PURE__*/ _jsx("div", {
12
+ className: mergeClassNames([
13
+ styles.container,
14
+ classNames.container
15
+ ]),
16
+ children: subscriber && /*#__PURE__*/ _jsxs("div", {
17
+ children: [
18
+ "Welcome, ",
19
+ subscriber?.email,
20
+ " - ",
21
+ /*#__PURE__*/ _jsx("a", {
22
+ href: '/subscribe',
23
+ children: "Manage subscriptions"
24
+ }),
25
+ " -",
26
+ ' ',
27
+ /*#__PURE__*/ _jsx("button", {
28
+ className: mergeClassNames([
29
+ styles.button,
30
+ classNames.button
31
+ ]),
32
+ onClick: (e)=>{
33
+ e.preventDefault();
34
+ logOut();
35
+ },
36
+ type: "button",
37
+ children: "Log out"
38
+ })
39
+ ]
40
+ })
41
+ });
42
+ };
43
+
44
+ //# sourceMappingURL=SubscriberMenu.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/components/app/SubscriberMenu.tsx"],"sourcesContent":["'use client'\n\nimport { useSubscriber } from '../../contexts/SubscriberProvider.js'\n\nimport { mergeClassNames } from './helpers.js'\nimport styles from './shared.module.css'\n\n// interface IAuth {\n// props?: any\n// }\n\nexport type SubscriberMenuClasses = {\n button?: string\n container?: string\n}\n\nexport const SubscriberMenu = ({\n classNames = {\n button: '',\n container: '',\n },\n}: {\n classNames?: SubscriberMenuClasses\n}) => {\n const { logOut, subscriber } = useSubscriber()\n return (\n <div className={mergeClassNames([styles.container, classNames.container])}>\n {/* <pre>{JSON.stringify(result, null, 2)}</pre> */}\n {subscriber && (\n <div>\n Welcome, {subscriber?.email} - <a href={'/subscribe'}>Manage subscriptions</a> -{' '}\n <button\n className={mergeClassNames([styles.button, classNames.button])}\n onClick={(e) => {\n e.preventDefault()\n logOut()\n }}\n type=\"button\"\n >\n Log out\n </button>\n </div>\n )}\n </div>\n )\n}\n"],"names":["useSubscriber","mergeClassNames","styles","SubscriberMenu","classNames","button","container","logOut","subscriber","div","className","email","a","href","onClick","e","preventDefault","type"],"mappings":"AAAA;;AAEA,SAASA,aAAa,QAAQ,uCAAsC;AAEpE,SAASC,eAAe,QAAQ,eAAc;AAC9C,OAAOC,YAAY,sBAAqB;AAWxC,OAAO,MAAMC,iBAAiB,CAAC,EAC7BC,aAAa;IACXC,QAAQ;IACRC,WAAW;AACb,CAAC,EAGF;IACC,MAAM,EAAEC,MAAM,EAAEC,UAAU,EAAE,GAAGR;IAC/B,qBACE,KAACS;QAAIC,WAAWT,gBAAgB;YAACC,OAAOI,SAAS;YAAEF,WAAWE,SAAS;SAAC;kBAErEE,4BACC,MAACC;;gBAAI;gBACOD,YAAYG;gBAAM;8BAAG,KAACC;oBAAEC,MAAM;8BAAc;;gBAAwB;gBAAG;8BACjF,KAACR;oBACCK,WAAWT,gBAAgB;wBAACC,OAAOG,MAAM;wBAAED,WAAWC,MAAM;qBAAC;oBAC7DS,SAAS,CAACC;wBACRA,EAAEC,cAAc;wBAChBT;oBACF;oBACAU,MAAK;8BACN;;;;;AAOX,EAAC"}