@burdenoff/microfe-channel 2026.510.112

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 (156) hide show
  1. package/README.md +147 -0
  2. package/dist/channel/ChannelRoot.d.ts +32 -0
  3. package/dist/channel/ChannelRoot.d.ts.map +1 -0
  4. package/dist/channel/ChannelRoot.js +81 -0
  5. package/dist/channel/ChannelRoot.js.map +1 -0
  6. package/dist/channel/ChannelRoutes.d.ts +10 -0
  7. package/dist/channel/ChannelRoutes.d.ts.map +1 -0
  8. package/dist/channel/ChannelRoutes.js +104 -0
  9. package/dist/channel/ChannelRoutes.js.map +1 -0
  10. package/dist/channel/components/AdapterCredentialsForm.d.ts +20 -0
  11. package/dist/channel/components/AdapterCredentialsForm.d.ts.map +1 -0
  12. package/dist/channel/components/AdapterCredentialsForm.js +230 -0
  13. package/dist/channel/components/AdapterCredentialsForm.js.map +1 -0
  14. package/dist/channel/components/FeatureNotEnabled.d.ts +10 -0
  15. package/dist/channel/components/FeatureNotEnabled.d.ts.map +1 -0
  16. package/dist/channel/components/FeatureNotEnabled.js +32 -0
  17. package/dist/channel/components/FeatureNotEnabled.js.map +1 -0
  18. package/dist/channel/components/PermissionGuard.d.ts +15 -0
  19. package/dist/channel/components/PermissionGuard.d.ts.map +1 -0
  20. package/dist/channel/components/PermissionGuard.js +23 -0
  21. package/dist/channel/components/PermissionGuard.js.map +1 -0
  22. package/dist/channel/config/adapterCredentials.d.ts +44 -0
  23. package/dist/channel/config/adapterCredentials.d.ts.map +1 -0
  24. package/dist/channel/config/adapterCredentials.js +946 -0
  25. package/dist/channel/config/adapterCredentials.js.map +1 -0
  26. package/dist/channel/constants/permissions.d.ts +32 -0
  27. package/dist/channel/constants/permissions.d.ts.map +1 -0
  28. package/dist/channel/constants/permissions.js +30 -0
  29. package/dist/channel/constants/permissions.js.map +1 -0
  30. package/dist/channel/graphql/global-client.d.ts +11 -0
  31. package/dist/channel/graphql/global-client.d.ts.map +1 -0
  32. package/dist/channel/graphql/global-client.js +56 -0
  33. package/dist/channel/graphql/global-client.js.map +1 -0
  34. package/dist/channel/hooks/useChannelOrgSettings.d.ts +22 -0
  35. package/dist/channel/hooks/useChannelOrgSettings.d.ts.map +1 -0
  36. package/dist/channel/hooks/useChannelOrgSettings.js +61 -0
  37. package/dist/channel/hooks/useChannelOrgSettings.js.map +1 -0
  38. package/dist/channel/hooks/useChannelSubscription.d.ts +36 -0
  39. package/dist/channel/hooks/useChannelSubscription.d.ts.map +1 -0
  40. package/dist/channel/hooks/useChannelSubscription.js +111 -0
  41. package/dist/channel/hooks/useChannelSubscription.js.map +1 -0
  42. package/dist/channel/hooks/useChannels.d.ts +214 -0
  43. package/dist/channel/hooks/useChannels.d.ts.map +1 -0
  44. package/dist/channel/hooks/useChannels.js +416 -0
  45. package/dist/channel/hooks/useChannels.js.map +1 -0
  46. package/dist/channel/index.d.ts +12 -0
  47. package/dist/channel/index.d.ts.map +1 -0
  48. package/dist/channel/index.js +2 -0
  49. package/dist/channel/modules/channels/hooks/useExport.d.ts +45 -0
  50. package/dist/channel/modules/channels/hooks/useExport.d.ts.map +1 -0
  51. package/dist/channel/modules/channels/hooks/useExport.js +195 -0
  52. package/dist/channel/modules/channels/hooks/useExport.js.map +1 -0
  53. package/dist/channel/modules/channels/i18n.d.ts +14 -0
  54. package/dist/channel/modules/channels/i18n.d.ts.map +1 -0
  55. package/dist/channel/modules/channels/i18n.js +110 -0
  56. package/dist/channel/modules/channels/i18n.js.map +1 -0
  57. package/dist/channel/modules/channels/pages/ChannelDashboardPage.d.ts +14 -0
  58. package/dist/channel/modules/channels/pages/ChannelDashboardPage.d.ts.map +1 -0
  59. package/dist/channel/modules/channels/pages/ChannelDashboardPage.js +680 -0
  60. package/dist/channel/modules/channels/pages/ChannelDashboardPage.js.map +1 -0
  61. package/dist/channel/modules/channels/pages/ChannelDetailsPage.d.ts +7 -0
  62. package/dist/channel/modules/channels/pages/ChannelDetailsPage.d.ts.map +1 -0
  63. package/dist/channel/modules/channels/pages/ChannelDetailsPage.js +949 -0
  64. package/dist/channel/modules/channels/pages/ChannelDetailsPage.js.map +1 -0
  65. package/dist/channel/modules/channels/pages/ChannelSettingsPage.d.ts +7 -0
  66. package/dist/channel/modules/channels/pages/ChannelSettingsPage.d.ts.map +1 -0
  67. package/dist/channel/modules/channels/pages/ChannelSettingsPage.js +404 -0
  68. package/dist/channel/modules/channels/pages/ChannelSettingsPage.js.map +1 -0
  69. package/dist/channel/modules/channels/pages/ChannelUsersPage.d.ts +7 -0
  70. package/dist/channel/modules/channels/pages/ChannelUsersPage.d.ts.map +1 -0
  71. package/dist/channel/modules/channels/pages/ChannelUsersPage.js +315 -0
  72. package/dist/channel/modules/channels/pages/ChannelUsersPage.js.map +1 -0
  73. package/dist/channel/modules/channels/pages/ChannelsListPage.d.ts +7 -0
  74. package/dist/channel/modules/channels/pages/ChannelsListPage.d.ts.map +1 -0
  75. package/dist/channel/modules/channels/pages/ChannelsListPage.js +604 -0
  76. package/dist/channel/modules/channels/pages/ChannelsListPage.js.map +1 -0
  77. package/dist/channel/modules/channels/pages/ConnectionDetailsPage.d.ts +7 -0
  78. package/dist/channel/modules/channels/pages/ConnectionDetailsPage.d.ts.map +1 -0
  79. package/dist/channel/modules/channels/pages/ConnectionDetailsPage.js +323 -0
  80. package/dist/channel/modules/channels/pages/ConnectionDetailsPage.js.map +1 -0
  81. package/dist/channel/modules/channels/pages/ConnectionsListPage.d.ts +7 -0
  82. package/dist/channel/modules/channels/pages/ConnectionsListPage.d.ts.map +1 -0
  83. package/dist/channel/modules/channels/pages/ConnectionsListPage.js +276 -0
  84. package/dist/channel/modules/channels/pages/ConnectionsListPage.js.map +1 -0
  85. package/dist/channel/modules/channels/pages/CreateChannelPage.d.ts +12 -0
  86. package/dist/channel/modules/channels/pages/CreateChannelPage.d.ts.map +1 -0
  87. package/dist/channel/modules/channels/pages/CreateChannelPage.js +456 -0
  88. package/dist/channel/modules/channels/pages/CreateChannelPage.js.map +1 -0
  89. package/dist/channel/modules/channels/pages/CreateConnectionPage.d.ts +11 -0
  90. package/dist/channel/modules/channels/pages/CreateConnectionPage.d.ts.map +1 -0
  91. package/dist/channel/modules/channels/pages/CreateConnectionPage.js +219 -0
  92. package/dist/channel/modules/channels/pages/CreateConnectionPage.js.map +1 -0
  93. package/dist/channel/modules/channels/pages/DeliveryHistoryPage.d.ts +7 -0
  94. package/dist/channel/modules/channels/pages/DeliveryHistoryPage.d.ts.map +1 -0
  95. package/dist/channel/modules/channels/pages/DeliveryHistoryPage.js +375 -0
  96. package/dist/channel/modules/channels/pages/DeliveryHistoryPage.js.map +1 -0
  97. package/dist/channel/modules/channels/pages/EditChannelPage.d.ts +8 -0
  98. package/dist/channel/modules/channels/pages/EditChannelPage.d.ts.map +1 -0
  99. package/dist/channel/modules/channels/pages/EditChannelPage.js +459 -0
  100. package/dist/channel/modules/channels/pages/EditChannelPage.js.map +1 -0
  101. package/dist/channel/modules/channels/pages/EditConnectionPage.d.ts +10 -0
  102. package/dist/channel/modules/channels/pages/EditConnectionPage.d.ts.map +1 -0
  103. package/dist/channel/modules/channels/pages/EditConnectionPage.js +199 -0
  104. package/dist/channel/modules/channels/pages/EditConnectionPage.js.map +1 -0
  105. package/dist/channel/modules/channels/pages/SendMessagePage.d.ts +8 -0
  106. package/dist/channel/modules/channels/pages/SendMessagePage.d.ts.map +1 -0
  107. package/dist/channel/modules/channels/pages/SendMessagePage.js +403 -0
  108. package/dist/channel/modules/channels/pages/SendMessagePage.js.map +1 -0
  109. package/dist/channel/modules/channels/pages/WebhookEventsPage.d.ts +7 -0
  110. package/dist/channel/modules/channels/pages/WebhookEventsPage.d.ts.map +1 -0
  111. package/dist/channel/modules/channels/pages/WebhookEventsPage.js +303 -0
  112. package/dist/channel/modules/channels/pages/WebhookEventsPage.js.map +1 -0
  113. package/dist/channel/modules/channels/pages/index.d.ts +18 -0
  114. package/dist/channel/modules/channels/pages/index.d.ts.map +1 -0
  115. package/dist/channel/modules/channels/pages/index.js +14 -0
  116. package/dist/channel/pages/ChannelLandingPage.d.ts +9 -0
  117. package/dist/channel/pages/ChannelLandingPage.d.ts.map +1 -0
  118. package/dist/channel/pages/ChannelLandingPage.js +72 -0
  119. package/dist/channel/pages/ChannelLandingPage.js.map +1 -0
  120. package/dist/channel/providers/ChannelProvider.d.ts +16 -0
  121. package/dist/channel/providers/ChannelProvider.d.ts.map +1 -0
  122. package/dist/channel/providers/ChannelProvider.js +35 -0
  123. package/dist/channel/providers/ChannelProvider.js.map +1 -0
  124. package/dist/channel/types/index.d.ts +89 -0
  125. package/dist/channel/types/index.d.ts.map +1 -0
  126. package/dist/channel/utils/shellBridge.d.ts +59 -0
  127. package/dist/channel/utils/shellBridge.d.ts.map +1 -0
  128. package/dist/channel/utils/shellBridge.js +36 -0
  129. package/dist/channel/utils/shellBridge.js.map +1 -0
  130. package/dist/dev/App.d.ts +6 -0
  131. package/dist/dev/App.d.ts.map +1 -0
  132. package/dist/dev/main.d.ts +2 -0
  133. package/dist/dev/main.d.ts.map +1 -0
  134. package/dist/generated/global-operations.d.ts +1547 -0
  135. package/dist/generated/global-operations.d.ts.map +1 -0
  136. package/dist/generated/global-operations.js +466 -0
  137. package/dist/generated/global-operations.js.map +1 -0
  138. package/dist/generated/global-types.d.ts +21289 -0
  139. package/dist/generated/global-types.d.ts.map +1 -0
  140. package/dist/generated/global-types.js +14 -0
  141. package/dist/generated/global-types.js.map +1 -0
  142. package/dist/generated/wspace-operations.d.ts +2 -0
  143. package/dist/generated/wspace-operations.d.ts.map +1 -0
  144. package/dist/generated/wspace-types.d.ts +55214 -0
  145. package/dist/generated/wspace-types.d.ts.map +1 -0
  146. package/dist/index.d.ts +5 -0
  147. package/dist/index.d.ts.map +1 -0
  148. package/dist/index.js +4 -0
  149. package/dist/node_modules/@apollo/client/errors/CombinedGraphQLErrors.js +24 -0
  150. package/dist/node_modules/@apollo/client/errors/CombinedGraphQLErrors.js.map +1 -0
  151. package/dist/node_modules/@apollo/client/errors/utils.js +16 -0
  152. package/dist/node_modules/@apollo/client/errors/utils.js.map +1 -0
  153. package/dist/utils/nativeBridge.d.ts +3 -0
  154. package/dist/utils/nativeBridge.d.ts.map +1 -0
  155. package/dist/utils/nativeBridge.js +2 -0
  156. package/package.json +116 -0
@@ -0,0 +1,456 @@
1
+ import { useChannel as e } from "../../../providers/ChannelProvider.js";
2
+ import { useChannels as t } from "../../../hooks/useChannels.js";
3
+ import { PermissionGuard as n } from "../../../components/PermissionGuard.js";
4
+ import { CHANNEL_PERMISSIONS as r } from "../../../constants/permissions.js";
5
+ import { useState as i } from "react";
6
+ import { useI18n as a } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
7
+ import { AlertCircle as o, ArrowLeft as s, Bell as c, CheckCircle2 as l, Globe as u, Hash as d, Inbox as f, Loader2 as p, Mail as m, MessageCircle as h, MessageSquare as g, Radio as _, Save as v, Send as y, Smartphone as b, Users as x } from "lucide-react";
8
+ import { useNavigate as S } from "react-router-dom";
9
+ import { jsx as C, jsxs as w } from "react/jsx-runtime";
10
+ //#region src/channel/modules/channels/pages/CreateChannelPage.tsx
11
+ var T = [
12
+ {
13
+ value: "EMAIL",
14
+ label: "Email",
15
+ description: "Send emails via various providers",
16
+ icon: m,
17
+ color: "text-accent-blue bg-accent-blue-subtle border-accent-blue-subtle",
18
+ adapters: [{
19
+ value: "AWS_SES",
20
+ label: "AWS SES"
21
+ }, {
22
+ value: "AZURE_ACS",
23
+ label: "Azure Communication Services"
24
+ }]
25
+ },
26
+ {
27
+ value: "SMS",
28
+ label: "SMS",
29
+ description: "Send text messages",
30
+ icon: b,
31
+ color: "text-status-success-text bg-status-success-bg-subtle border-status-success-bg-subtle",
32
+ adapters: [{
33
+ value: "AWS_SNS",
34
+ label: "AWS SNS"
35
+ }, {
36
+ value: "TWILIO_SMS",
37
+ label: "Twilio SMS"
38
+ }]
39
+ },
40
+ {
41
+ value: "PUSH",
42
+ label: "Push",
43
+ description: "Mobile & web push",
44
+ icon: c,
45
+ color: "text-accent-purple bg-accent-purple-subtle border-accent-purple-subtle",
46
+ adapters: [{
47
+ value: "FCM",
48
+ label: "Firebase Cloud Messaging"
49
+ }]
50
+ },
51
+ {
52
+ value: "INAPP",
53
+ label: "In-App",
54
+ description: "In-app notifications",
55
+ icon: f,
56
+ color: "text-accent-indigo bg-accent-indigo-subtle border-accent-indigo-subtle",
57
+ adapters: [{
58
+ value: "INAPP_NATIVE",
59
+ label: "Native In-App"
60
+ }]
61
+ },
62
+ {
63
+ value: "SLACK",
64
+ label: "Slack",
65
+ description: "Workspace notifications",
66
+ icon: d,
67
+ color: "text-accent-pink bg-accent-pink-subtle border-accent-pink-subtle",
68
+ adapters: [{
69
+ value: "SLACK_BOT",
70
+ label: "Slack Bot"
71
+ }]
72
+ },
73
+ {
74
+ value: "TEAMS",
75
+ label: "Teams",
76
+ description: "Teams notifications",
77
+ icon: x,
78
+ color: "text-accent-cyan bg-accent-cyan-subtle border-accent-cyan-subtle",
79
+ adapters: [{
80
+ value: "TEAMS_BOT",
81
+ label: "Teams Bot"
82
+ }]
83
+ },
84
+ {
85
+ value: "DISCORD",
86
+ label: "Discord",
87
+ description: "Server notifications",
88
+ icon: h,
89
+ color: "text-accent-violet bg-accent-violet-subtle border-accent-violet-subtle",
90
+ adapters: [{
91
+ value: "DISCORD_BOT",
92
+ label: "Discord Bot"
93
+ }]
94
+ },
95
+ {
96
+ value: "WHATSAPP",
97
+ label: "WhatsApp",
98
+ description: "Business messaging",
99
+ icon: y,
100
+ color: "text-accent-emerald bg-accent-emerald-subtle border-accent-emerald-subtle",
101
+ adapters: [{
102
+ value: "WHATSAPP_CLOUD",
103
+ label: "WhatsApp Cloud API"
104
+ }, {
105
+ value: "WHATSAPP_TWILIO",
106
+ label: "WhatsApp via Twilio"
107
+ }]
108
+ },
109
+ {
110
+ value: "WEBCHAT",
111
+ label: "Webchat",
112
+ description: "Chat widgets",
113
+ icon: g,
114
+ color: "text-accent-teal bg-accent-teal-subtle border-accent-teal-subtle",
115
+ adapters: []
116
+ },
117
+ {
118
+ value: "WEBHOOK",
119
+ label: "Webhook",
120
+ description: "HTTP webhooks",
121
+ icon: u,
122
+ color: "text-accent-orange bg-accent-orange-subtle border-accent-orange-subtle",
123
+ adapters: [{
124
+ value: "WEBHOOK_HTTP",
125
+ label: "HTTP Webhook"
126
+ }]
127
+ }
128
+ ];
129
+ function E() {
130
+ let c = S(), { organizationId: u } = e(), { createChannel: d } = t(), { t: f } = a(), m = (e, t) => {
131
+ let n = f(e);
132
+ return n === e ? t : n;
133
+ }, [h, g] = i(!1), [y, b] = i(null), [x, E] = i(!1), [D, O] = i({
134
+ name: "",
135
+ platform: "EMAIL",
136
+ description: "",
137
+ adapterType: "AWS_SES",
138
+ status: "ACTIVE",
139
+ priority: 100,
140
+ platformConfig: ""
141
+ }), k = T.find((e) => e.value === D.platform)?.adapters || [], A = T.find((e) => e.value === D.platform), j = (e) => {
142
+ O((t) => ({
143
+ ...t,
144
+ platform: e,
145
+ adapterType: ""
146
+ }));
147
+ };
148
+ return /* @__PURE__ */ C(n, {
149
+ permission: r.CHANNEL_CREATE,
150
+ children: /* @__PURE__ */ w("div", {
151
+ className: "p-3 sm:p-6 space-y-6 max-w-5xl mx-auto",
152
+ children: [
153
+ /* @__PURE__ */ C("div", {
154
+ className: "flex items-center justify-between",
155
+ children: /* @__PURE__ */ w("div", {
156
+ className: "flex items-center gap-3",
157
+ children: [/* @__PURE__ */ C("button", {
158
+ onClick: () => c(-1),
159
+ className: "p-2 text-muted-foreground hover:text-foreground hover:bg-surface-hover rounded-lg transition-colors",
160
+ children: /* @__PURE__ */ C(s, { size: 20 })
161
+ }), /* @__PURE__ */ w("div", { children: [/* @__PURE__ */ w("h1", {
162
+ className: "text-xl font-bold text-foreground flex items-center gap-2",
163
+ children: [/* @__PURE__ */ C(_, {
164
+ size: 22,
165
+ className: "text-accent-primary"
166
+ }), m("channel.createChannel", "Create Channel")]
167
+ }), /* @__PURE__ */ C("p", {
168
+ className: "text-sm text-muted-foreground mt-0.5",
169
+ children: m("channel.createChannelSubtitle", "Set up a new communication channel")
170
+ })] })]
171
+ })
172
+ }),
173
+ y && /* @__PURE__ */ w("div", {
174
+ className: "flex items-center gap-3 p-3 bg-error-500/10 border border-error-500/30 rounded-lg",
175
+ children: [/* @__PURE__ */ C(o, {
176
+ size: 16,
177
+ className: "text-error-500 shrink-0"
178
+ }), /* @__PURE__ */ C("p", {
179
+ className: "text-sm text-error-400",
180
+ children: y
181
+ })]
182
+ }),
183
+ /* @__PURE__ */ w("form", {
184
+ onSubmit: async (e) => {
185
+ if (e.preventDefault(), b(null), !D.name.trim()) {
186
+ b(m("channel.validation.nameRequired", "Channel name is required"));
187
+ return;
188
+ }
189
+ if (!u) {
190
+ b(m("channel.validation.organizationRequired", "Organization context is required. Please ensure an organization is selected."));
191
+ return;
192
+ }
193
+ let t;
194
+ if (D.platformConfig.trim()) try {
195
+ t = JSON.parse(D.platformConfig);
196
+ } catch {
197
+ b(m("channel.validation.platformConfigJson", "Platform Config must be valid JSON"));
198
+ return;
199
+ }
200
+ g(!0);
201
+ try {
202
+ let e = await d({
203
+ name: D.name.trim(),
204
+ platform: D.platform,
205
+ organizationId: u,
206
+ description: D.description.trim() || void 0,
207
+ adapterType: D.adapterType || void 0,
208
+ status: D.status,
209
+ priority: D.priority,
210
+ platformConfig: t
211
+ });
212
+ e ? c(`../${e.id}`) : b(m("channel.createFailed", "Failed to create channel"));
213
+ } catch (e) {
214
+ b(e instanceof Error ? e.message : m("channel.createFailed", "Failed to create channel"));
215
+ } finally {
216
+ g(!1);
217
+ }
218
+ },
219
+ className: "space-y-6",
220
+ children: [
221
+ /* @__PURE__ */ w("div", {
222
+ className: "grid gap-5 lg:grid-cols-2",
223
+ children: [/* @__PURE__ */ w("div", {
224
+ className: "p-5 bg-surface border border-border rounded-lg space-y-4",
225
+ children: [
226
+ /* @__PURE__ */ C("h2", {
227
+ className: "text-sm font-semibold text-foreground uppercase tracking-wider",
228
+ children: m("channel.basicInformation", "Basic Information")
229
+ }),
230
+ /* @__PURE__ */ w("div", { children: [/* @__PURE__ */ w("label", {
231
+ className: "block text-sm font-medium text-foreground mb-1.5",
232
+ children: [
233
+ m("channel.name", "Name"),
234
+ " ",
235
+ /* @__PURE__ */ C("span", {
236
+ className: "text-error-500",
237
+ children: "*"
238
+ })
239
+ ]
240
+ }), /* @__PURE__ */ C("input", {
241
+ type: "text",
242
+ value: D.name,
243
+ onChange: (e) => O((t) => ({
244
+ ...t,
245
+ name: e.target.value
246
+ })),
247
+ className: "w-full px-3 py-2 text-sm bg-surface border border-border rounded-lg focus:outline-none focus:ring-2 focus:ring-action-primary-bg/50 placeholder:text-muted-foreground",
248
+ placeholder: m("channel.namePlaceholder", "e.g., Primary Email, SMS Alerts")
249
+ })] }),
250
+ /* @__PURE__ */ w("div", { children: [/* @__PURE__ */ C("label", {
251
+ className: "block text-sm font-medium text-foreground mb-1.5",
252
+ children: m("channel.description", "Description")
253
+ }), /* @__PURE__ */ C("textarea", {
254
+ value: D.description,
255
+ onChange: (e) => O((t) => ({
256
+ ...t,
257
+ description: e.target.value
258
+ })),
259
+ rows: 3,
260
+ className: "w-full px-3 py-2 text-sm bg-surface border border-border rounded-lg focus:outline-none focus:ring-2 focus:ring-action-primary-bg/50 resize-none placeholder:text-muted-foreground",
261
+ placeholder: m("channel.descriptionPlaceholder", "Optional description of this channel's purpose")
262
+ })] })
263
+ ]
264
+ }), /* @__PURE__ */ w("div", {
265
+ className: "p-5 bg-surface border border-border rounded-lg space-y-4",
266
+ children: [
267
+ /* @__PURE__ */ C("h2", {
268
+ className: "text-sm font-semibold text-foreground uppercase tracking-wider",
269
+ children: m("channel.providerStatus", "Provider & Status")
270
+ }),
271
+ /* @__PURE__ */ w("div", { children: [
272
+ /* @__PURE__ */ C("label", {
273
+ className: "block text-sm font-medium text-foreground mb-1.5",
274
+ children: m("channel.providerAdapter", "Provider / Adapter")
275
+ }),
276
+ /* @__PURE__ */ w("select", {
277
+ value: D.adapterType,
278
+ onChange: (e) => O((t) => ({
279
+ ...t,
280
+ adapterType: e.target.value
281
+ })),
282
+ className: "w-full px-3 py-2 text-sm bg-surface border border-border rounded-lg focus:outline-none focus:ring-2 focus:ring-action-primary-bg/50 text-foreground",
283
+ children: [/* @__PURE__ */ C("option", {
284
+ value: "",
285
+ children: m("channel.selectProvider", "Select a provider (optional)")
286
+ }), k.map((e) => /* @__PURE__ */ C("option", {
287
+ value: e.value,
288
+ children: e.label
289
+ }, e.value))]
290
+ }),
291
+ /* @__PURE__ */ C("p", {
292
+ className: "mt-1 text-[11px] text-muted-foreground",
293
+ children: A ? m("channel.providersAvailableForPlatform", `${k.length} providers available for ${A.label}`) : m("channel.selectPlatformFirst", "Select a platform first")
294
+ })
295
+ ] }),
296
+ /* @__PURE__ */ w("div", {
297
+ className: "grid gap-4 sm:grid-cols-2",
298
+ children: [/* @__PURE__ */ w("div", { children: [
299
+ /* @__PURE__ */ C("label", {
300
+ className: "block text-sm font-medium text-foreground mb-1.5",
301
+ children: m("channel.status", "Status")
302
+ }),
303
+ /* @__PURE__ */ w("select", {
304
+ value: D.status,
305
+ onChange: (e) => O((t) => ({
306
+ ...t,
307
+ status: e.target.value
308
+ })),
309
+ className: "w-full px-3 py-2 text-sm bg-surface border border-border rounded-lg focus:outline-none focus:ring-2 focus:ring-action-primary-bg/50 text-foreground",
310
+ children: [/* @__PURE__ */ C("option", {
311
+ value: "ACTIVE",
312
+ children: m("channel.status.active", "Active")
313
+ }), /* @__PURE__ */ C("option", {
314
+ value: "INACTIVE",
315
+ children: m("channel.status.inactive", "Inactive")
316
+ })]
317
+ }),
318
+ /* @__PURE__ */ C("p", {
319
+ className: "mt-1 text-[11px] text-muted-foreground",
320
+ children: D.status === "ACTIVE" ? m("channel.statusHint.active", "Ready to send immediately") : m("channel.statusHint.inactive", "Configure before activating")
321
+ })
322
+ ] }), /* @__PURE__ */ w("div", { children: [
323
+ /* @__PURE__ */ C("label", {
324
+ className: "block text-sm font-medium text-foreground mb-1.5",
325
+ children: m("channel.priority", "Priority")
326
+ }),
327
+ /* @__PURE__ */ C("input", {
328
+ type: "number",
329
+ value: D.priority,
330
+ onChange: (e) => O((t) => ({
331
+ ...t,
332
+ priority: parseInt(e.target.value) || 0
333
+ })),
334
+ min: 0,
335
+ max: 100,
336
+ className: "w-full px-3 py-2 text-sm bg-surface border border-border rounded-lg focus:outline-none focus:ring-2 focus:ring-action-primary-bg/50"
337
+ }),
338
+ /* @__PURE__ */ C("p", {
339
+ className: "mt-1 text-[11px] text-muted-foreground",
340
+ children: m("channel.priorityHint", "Lower = higher priority (0-100)")
341
+ })
342
+ ] })]
343
+ })
344
+ ]
345
+ })]
346
+ }),
347
+ /* @__PURE__ */ w("div", {
348
+ className: "p-5 bg-surface border border-border rounded-lg space-y-4",
349
+ children: [/* @__PURE__ */ w("h2", {
350
+ className: "text-sm font-semibold text-foreground uppercase tracking-wider",
351
+ children: [
352
+ m("channel.platform", "Platform"),
353
+ " ",
354
+ /* @__PURE__ */ C("span", {
355
+ className: "text-error-500",
356
+ children: "*"
357
+ })
358
+ ]
359
+ }), /* @__PURE__ */ C("div", {
360
+ className: "grid gap-2 grid-cols-2 sm:grid-cols-3 lg:grid-cols-5",
361
+ children: T.map((e) => {
362
+ let t = e.icon, n = D.platform === e.value;
363
+ return /* @__PURE__ */ w("button", {
364
+ type: "button",
365
+ onClick: () => j(e.value),
366
+ className: `relative flex flex-col items-center gap-1.5 p-3 rounded-lg border transition-all text-center ${n ? `${e.color} border-current ring-1 ring-current` : "border-border hover:bg-surface-hover text-muted-foreground hover:text-foreground"}`,
367
+ children: [
368
+ n && /* @__PURE__ */ C(l, {
369
+ size: 14,
370
+ className: "absolute top-1.5 right-1.5 text-current"
371
+ }),
372
+ /* @__PURE__ */ C(t, { size: 20 }),
373
+ /* @__PURE__ */ C("span", {
374
+ className: "text-xs font-semibold",
375
+ children: e.label
376
+ }),
377
+ /* @__PURE__ */ C("span", {
378
+ className: "text-[10px] leading-tight opacity-70",
379
+ children: e.description
380
+ })
381
+ ]
382
+ }, e.value);
383
+ })
384
+ })]
385
+ }),
386
+ /* @__PURE__ */ w("div", {
387
+ className: "p-5 bg-surface border border-border rounded-lg",
388
+ children: [/* @__PURE__ */ w("button", {
389
+ type: "button",
390
+ onClick: () => E(!x),
391
+ className: "w-full flex items-center justify-between text-left",
392
+ children: [/* @__PURE__ */ C("h2", {
393
+ className: "text-sm font-semibold text-foreground uppercase tracking-wider",
394
+ children: m("channel.advancedOptions", "Advanced Options")
395
+ }), /* @__PURE__ */ C("span", {
396
+ className: "text-xs text-muted-foreground",
397
+ children: x ? m("channel.hide", "Hide") : m("channel.show", "Show")
398
+ })]
399
+ }), x && /* @__PURE__ */ C("div", {
400
+ className: "mt-4 grid gap-4 lg:grid-cols-2",
401
+ children: /* @__PURE__ */ w("div", { children: [
402
+ /* @__PURE__ */ w("label", {
403
+ className: "block text-sm font-medium text-foreground mb-1.5",
404
+ children: [
405
+ m("channel.platformConfig", "Platform Config"),
406
+ " ",
407
+ /* @__PURE__ */ C("span", {
408
+ className: "text-[10px] text-muted-foreground",
409
+ children: "(JSON)"
410
+ })
411
+ ]
412
+ }),
413
+ /* @__PURE__ */ C("textarea", {
414
+ value: D.platformConfig,
415
+ onChange: (e) => O((t) => ({
416
+ ...t,
417
+ platformConfig: e.target.value
418
+ })),
419
+ rows: 3,
420
+ className: "w-full px-3 py-2 text-sm bg-surface border border-border rounded-lg focus:outline-none focus:ring-2 focus:ring-action-primary-bg/50 resize-none font-mono placeholder:text-muted-foreground",
421
+ placeholder: m("channel.platformConfigPlaceholder", "{\"fromEmail\": \"noreply@example.com\"}")
422
+ }),
423
+ /* @__PURE__ */ C("p", {
424
+ className: "mt-1 text-[11px] text-muted-foreground",
425
+ children: m("channel.platformConfigHint", "Platform-specific configuration as JSON")
426
+ })
427
+ ] })
428
+ })]
429
+ }),
430
+ /* @__PURE__ */ w("div", {
431
+ className: "flex items-center justify-between pt-2",
432
+ children: [/* @__PURE__ */ C("button", {
433
+ type: "button",
434
+ onClick: () => c("/channels/list"),
435
+ className: "px-4 py-2 text-sm text-muted-foreground hover:text-foreground hover:bg-surface-hover border border-border rounded-lg transition-colors",
436
+ children: m("channel.cancel", "Cancel")
437
+ }), /* @__PURE__ */ w("button", {
438
+ type: "submit",
439
+ disabled: h || !D.name.trim(),
440
+ className: "inline-flex items-center gap-2 px-5 py-2 text-sm font-medium text-action-primary-text bg-action-primary-bg hover:bg-action-primary-bg-hover rounded-lg transition-colors disabled:opacity-50 disabled:cursor-not-allowed",
441
+ children: [h ? /* @__PURE__ */ C(p, {
442
+ size: 16,
443
+ className: "animate-spin"
444
+ }) : /* @__PURE__ */ C(v, { size: 16 }), m("channel.createChannel", "Create Channel")]
445
+ })]
446
+ })
447
+ ]
448
+ })
449
+ ]
450
+ })
451
+ });
452
+ }
453
+ //#endregion
454
+ export { E as CreateChannelPage };
455
+
456
+ //# sourceMappingURL=CreateChannelPage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CreateChannelPage.js","names":[],"sources":["../../../../../src/channel/modules/channels/pages/CreateChannelPage.tsx"],"sourcesContent":["/**\n * Create Channel Page\n *\n * Form fields match the exact CreateChannelInput from global-channel-svc:\n * name (required), platform (required), organizationId (auto), description,\n * adapterType, status, priority, platformConfig\n *\n * organizationId is injected from shell context — not shown in form.\n * Credentials belong to createConnection mutation — not part of channel creation.\n */\n\nimport { useState } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport {\n Radio,\n ArrowLeft,\n Save,\n Loader2,\n AlertCircle,\n Mail,\n Smartphone,\n Bell,\n Inbox,\n Globe,\n Hash,\n Users,\n MessageCircle,\n Send,\n MessageSquare,\n CheckCircle2,\n} from 'lucide-react';\nimport { useChannel } from '../../../providers/ChannelProvider';\nimport {\n useChannels,\n type ChannelPlatform,\n type AdapterType,\n type ChannelStatus,\n type CreateChannelInput,\n} from '../../../hooks/useChannels';\nimport { PermissionGuard } from '../../../components/PermissionGuard';\nimport { CHANNEL_PERMISSIONS } from '../../../constants/permissions';\n\n// ============================================================================\n// PLATFORM CONFIG\n// ============================================================================\n\n// NOTE: AdapterType values MUST match the backend Prisma schema exactly.\n// See: global-channel-svc/prisma/schema/schema.prisma (enum AdapterType)\nconst PLATFORM_OPTIONS: {\n value: ChannelPlatform;\n label: string;\n description: string;\n icon: typeof Mail;\n color: string;\n adapters: { value: AdapterType; label: string }[];\n}[] = [\n {\n value: 'EMAIL',\n label: 'Email',\n description: 'Send emails via various providers',\n icon: Mail,\n color: 'text-accent-blue bg-accent-blue-subtle border-accent-blue-subtle',\n adapters: [\n { value: 'AWS_SES', label: 'AWS SES' },\n { value: 'AZURE_ACS', label: 'Azure Communication Services' },\n ],\n },\n {\n value: 'SMS',\n label: 'SMS',\n description: 'Send text messages',\n icon: Smartphone,\n color: 'text-status-success-text bg-status-success-bg-subtle border-status-success-bg-subtle',\n adapters: [\n { value: 'AWS_SNS', label: 'AWS SNS' },\n { value: 'TWILIO_SMS', label: 'Twilio SMS' },\n ],\n },\n {\n value: 'PUSH',\n label: 'Push',\n description: 'Mobile & web push',\n icon: Bell,\n color: 'text-accent-purple bg-accent-purple-subtle border-accent-purple-subtle',\n adapters: [{ value: 'FCM', label: 'Firebase Cloud Messaging' }],\n },\n {\n value: 'INAPP',\n label: 'In-App',\n description: 'In-app notifications',\n icon: Inbox,\n color: 'text-accent-indigo bg-accent-indigo-subtle border-accent-indigo-subtle',\n adapters: [{ value: 'INAPP_NATIVE', label: 'Native In-App' }],\n },\n {\n value: 'SLACK',\n label: 'Slack',\n description: 'Workspace notifications',\n icon: Hash,\n color: 'text-accent-pink bg-accent-pink-subtle border-accent-pink-subtle',\n adapters: [{ value: 'SLACK_BOT', label: 'Slack Bot' }],\n },\n {\n value: 'TEAMS',\n label: 'Teams',\n description: 'Teams notifications',\n icon: Users,\n color: 'text-accent-cyan bg-accent-cyan-subtle border-accent-cyan-subtle',\n adapters: [{ value: 'TEAMS_BOT', label: 'Teams Bot' }],\n },\n {\n value: 'DISCORD',\n label: 'Discord',\n description: 'Server notifications',\n icon: MessageCircle,\n color: 'text-accent-violet bg-accent-violet-subtle border-accent-violet-subtle',\n adapters: [{ value: 'DISCORD_BOT', label: 'Discord Bot' }],\n },\n {\n value: 'WHATSAPP',\n label: 'WhatsApp',\n description: 'Business messaging',\n icon: Send,\n color: 'text-accent-emerald bg-accent-emerald-subtle border-accent-emerald-subtle',\n adapters: [\n { value: 'WHATSAPP_CLOUD', label: 'WhatsApp Cloud API' },\n { value: 'WHATSAPP_TWILIO', label: 'WhatsApp via Twilio' },\n ],\n },\n {\n value: 'WEBCHAT',\n label: 'Webchat',\n description: 'Chat widgets',\n icon: MessageSquare,\n color: 'text-accent-teal bg-accent-teal-subtle border-accent-teal-subtle',\n adapters: [], // No WEBCHAT adapters in backend Prisma schema yet\n },\n {\n value: 'WEBHOOK',\n label: 'Webhook',\n description: 'HTTP webhooks',\n icon: Globe,\n color: 'text-accent-orange bg-accent-orange-subtle border-accent-orange-subtle',\n adapters: [{ value: 'WEBHOOK_HTTP', label: 'HTTP Webhook' }],\n },\n];\n\n// ============================================================================\n// COMPONENT\n// ============================================================================\n\nexport function CreateChannelPage() {\n const navigate = useNavigate();\n const { organizationId } = useChannel();\n const { createChannel } = useChannels();\n const { t } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const value = t(key);\n return value === key ? fallback : value;\n };\n\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [showAdvanced, setShowAdvanced] = useState(false);\n\n // Form state — matches CreateChannelInput exactly\n const [formData, setFormData] = useState<{\n name: string; // required\n platform: ChannelPlatform; // required\n description: string; // optional\n adapterType: AdapterType | ''; // required (auto-selected based on platform)\n status: ChannelStatus; // optional — default ACTIVE on server\n priority: number; // optional — default 100 on server\n platformConfig: string; // optional — JSON string\n }>({\n name: '',\n platform: 'EMAIL',\n description: '',\n adapterType: 'AWS_SES', // Default to AWS SES for Email platform\n status: 'ACTIVE',\n priority: 100,\n platformConfig: '',\n });\n\n const availableAdapters =\n PLATFORM_OPTIONS.find((p) => p.value === formData.platform)?.adapters || [];\n\n const selectedPlatform = PLATFORM_OPTIONS.find((p) => p.value === formData.platform);\n\n const handlePlatformChange = (platform: ChannelPlatform) => {\n setFormData((prev) => ({ ...prev, platform, adapterType: '' }));\n };\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n setError(null);\n\n if (!formData.name.trim()) {\n setError(tr('channel.validation.nameRequired', 'Channel name is required'));\n return;\n }\n\n if (!organizationId) {\n setError(\n tr(\n 'channel.validation.organizationRequired',\n 'Organization context is required. Please ensure an organization is selected.'\n )\n );\n return;\n }\n\n // Validate platformConfig JSON if provided\n let parsedPlatformConfig: Record<string, unknown> | undefined;\n if (formData.platformConfig.trim()) {\n try {\n parsedPlatformConfig = JSON.parse(formData.platformConfig);\n } catch {\n setError(tr('channel.validation.platformConfigJson', 'Platform Config must be valid JSON'));\n return;\n }\n }\n\n setIsSubmitting(true);\n try {\n const input: CreateChannelInput = {\n name: formData.name.trim(),\n platform: formData.platform,\n organizationId,\n description: formData.description.trim() || undefined,\n adapterType: (formData.adapterType as AdapterType) || undefined,\n status: formData.status,\n priority: formData.priority,\n platformConfig: parsedPlatformConfig,\n };\n\n const result = await createChannel(input);\n if (result) {\n navigate(`../${result.id}`);\n } else {\n setError(tr('channel.createFailed', 'Failed to create channel'));\n }\n } catch (err: unknown) {\n setError(\n err instanceof Error ? err.message : tr('channel.createFailed', 'Failed to create channel')\n );\n } finally {\n setIsSubmitting(false);\n }\n };\n\n // ── Render ────────────────────────────────────────────────────────────\n return (\n <PermissionGuard permission={CHANNEL_PERMISSIONS.CHANNEL_CREATE}>\n <div className=\"p-3 sm:p-6 space-y-6 max-w-5xl mx-auto\">\n {/* ── Header ───────────────────────────────────────────────────── */}\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-3\">\n <button\n onClick={() => navigate(-1)}\n className=\"p-2 text-muted-foreground hover:text-foreground hover:bg-surface-hover rounded-lg transition-colors\"\n >\n <ArrowLeft size={20} />\n </button>\n <div>\n <h1 className=\"text-xl font-bold text-foreground flex items-center gap-2\">\n <Radio size={22} className=\"text-accent-primary\" />\n {tr('channel.createChannel', 'Create Channel')}\n </h1>\n <p className=\"text-sm text-muted-foreground mt-0.5\">\n {tr('channel.createChannelSubtitle', 'Set up a new communication channel')}\n </p>\n </div>\n </div>\n </div>\n\n {/* ── Error ────────────────────────────────────────────────────── */}\n {error && (\n <div className=\"flex items-center gap-3 p-3 bg-error-500/10 border border-error-500/30 rounded-lg\">\n <AlertCircle size={16} className=\"text-error-500 shrink-0\" />\n <p className=\"text-sm text-error-400\">{error}</p>\n </div>\n )}\n\n <form onSubmit={handleSubmit} className=\"space-y-6\">\n {/* ── Row 1: Name + Description | Status + Provider (2-col) ─── */}\n <div className=\"grid gap-5 lg:grid-cols-2\">\n {/* Left: Name & Description */}\n <div className=\"p-5 bg-surface border border-border rounded-lg space-y-4\">\n <h2 className=\"text-sm font-semibold text-foreground uppercase tracking-wider\">\n {tr('channel.basicInformation', 'Basic Information')}\n </h2>\n\n <div>\n <label className=\"block text-sm font-medium text-foreground mb-1.5\">\n {tr('channel.name', 'Name')} <span className=\"text-error-500\">*</span>\n </label>\n <input\n type=\"text\"\n value={formData.name}\n onChange={(e) => setFormData((prev) => ({ ...prev, name: e.target.value }))}\n className=\"w-full px-3 py-2 text-sm bg-surface border border-border rounded-lg focus:outline-none focus:ring-2 focus:ring-action-primary-bg/50 placeholder:text-muted-foreground\"\n placeholder={tr('channel.namePlaceholder', 'e.g., Primary Email, SMS Alerts')}\n />\n </div>\n\n <div>\n <label className=\"block text-sm font-medium text-foreground mb-1.5\">\n {tr('channel.description', 'Description')}\n </label>\n <textarea\n value={formData.description}\n onChange={(e) =>\n setFormData((prev) => ({ ...prev, description: e.target.value }))\n }\n rows={3}\n className=\"w-full px-3 py-2 text-sm bg-surface border border-border rounded-lg focus:outline-none focus:ring-2 focus:ring-action-primary-bg/50 resize-none placeholder:text-muted-foreground\"\n placeholder={tr(\n 'channel.descriptionPlaceholder',\n \"Optional description of this channel's purpose\"\n )}\n />\n </div>\n </div>\n\n {/* Right: Status + Provider / Adapter */}\n <div className=\"p-5 bg-surface border border-border rounded-lg space-y-4\">\n <h2 className=\"text-sm font-semibold text-foreground uppercase tracking-wider\">\n {tr('channel.providerStatus', 'Provider & Status')}\n </h2>\n\n <div>\n <label className=\"block text-sm font-medium text-foreground mb-1.5\">\n {tr('channel.providerAdapter', 'Provider / Adapter')}\n </label>\n <select\n value={formData.adapterType}\n onChange={(e) =>\n setFormData((prev) => ({\n ...prev,\n adapterType: e.target.value as AdapterType | '',\n }))\n }\n className=\"w-full px-3 py-2 text-sm bg-surface border border-border rounded-lg focus:outline-none focus:ring-2 focus:ring-action-primary-bg/50 text-foreground\"\n >\n <option value=\"\">\n {tr('channel.selectProvider', 'Select a provider (optional)')}\n </option>\n {availableAdapters.map((a) => (\n <option key={a.value} value={a.value}>\n {a.label}\n </option>\n ))}\n </select>\n <p className=\"mt-1 text-[11px] text-muted-foreground\">\n {selectedPlatform\n ? tr(\n 'channel.providersAvailableForPlatform',\n `${availableAdapters.length} providers available for ${selectedPlatform.label}`\n )\n : tr('channel.selectPlatformFirst', 'Select a platform first')}\n </p>\n </div>\n\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <div>\n <label className=\"block text-sm font-medium text-foreground mb-1.5\">\n {tr('channel.status', 'Status')}\n </label>\n <select\n value={formData.status}\n onChange={(e) =>\n setFormData((prev) => ({ ...prev, status: e.target.value as ChannelStatus }))\n }\n className=\"w-full px-3 py-2 text-sm bg-surface border border-border rounded-lg focus:outline-none focus:ring-2 focus:ring-action-primary-bg/50 text-foreground\"\n >\n <option value=\"ACTIVE\">{tr('channel.status.active', 'Active')}</option>\n <option value=\"INACTIVE\">{tr('channel.status.inactive', 'Inactive')}</option>\n </select>\n <p className=\"mt-1 text-[11px] text-muted-foreground\">\n {formData.status === 'ACTIVE'\n ? tr('channel.statusHint.active', 'Ready to send immediately')\n : tr('channel.statusHint.inactive', 'Configure before activating')}\n </p>\n </div>\n\n <div>\n <label className=\"block text-sm font-medium text-foreground mb-1.5\">\n {tr('channel.priority', 'Priority')}\n </label>\n <input\n type=\"number\"\n value={formData.priority}\n onChange={(e) =>\n setFormData((prev) => ({\n ...prev,\n priority: parseInt(e.target.value) || 0,\n }))\n }\n min={0}\n max={100}\n className=\"w-full px-3 py-2 text-sm bg-surface border border-border rounded-lg focus:outline-none focus:ring-2 focus:ring-action-primary-bg/50\"\n />\n <p className=\"mt-1 text-[11px] text-muted-foreground\">\n {tr('channel.priorityHint', 'Lower = higher priority (0-100)')}\n </p>\n </div>\n </div>\n </div>\n </div>\n\n {/* ── Row 2: Platform selection (full width) ─────────────────── */}\n <div className=\"p-5 bg-surface border border-border rounded-lg space-y-4\">\n <h2 className=\"text-sm font-semibold text-foreground uppercase tracking-wider\">\n {tr('channel.platform', 'Platform')} <span className=\"text-error-500\">*</span>\n </h2>\n\n <div className=\"grid gap-2 grid-cols-2 sm:grid-cols-3 lg:grid-cols-5\">\n {PLATFORM_OPTIONS.map((platform) => {\n const Icon = platform.icon;\n const isSelected = formData.platform === platform.value;\n return (\n <button\n key={platform.value}\n type=\"button\"\n onClick={() => handlePlatformChange(platform.value)}\n className={`relative flex flex-col items-center gap-1.5 p-3 rounded-lg border transition-all text-center ${\n isSelected\n ? `${platform.color} border-current ring-1 ring-current`\n : 'border-border hover:bg-surface-hover text-muted-foreground hover:text-foreground'\n }`}\n >\n {isSelected && (\n <CheckCircle2 size={14} className=\"absolute top-1.5 right-1.5 text-current\" />\n )}\n <Icon size={20} />\n <span className=\"text-xs font-semibold\">{platform.label}</span>\n <span className=\"text-[10px] leading-tight opacity-70\">\n {platform.description}\n </span>\n </button>\n );\n })}\n </div>\n </div>\n\n {/* ── Row 3: Advanced (collapsible) — platformConfig */}\n <div className=\"p-5 bg-surface border border-border rounded-lg\">\n <button\n type=\"button\"\n onClick={() => setShowAdvanced(!showAdvanced)}\n className=\"w-full flex items-center justify-between text-left\"\n >\n <h2 className=\"text-sm font-semibold text-foreground uppercase tracking-wider\">\n {tr('channel.advancedOptions', 'Advanced Options')}\n </h2>\n <span className=\"text-xs text-muted-foreground\">\n {showAdvanced ? tr('channel.hide', 'Hide') : tr('channel.show', 'Show')}\n </span>\n </button>\n\n {showAdvanced && (\n <div className=\"mt-4 grid gap-4 lg:grid-cols-2\">\n <div>\n <label className=\"block text-sm font-medium text-foreground mb-1.5\">\n {tr('channel.platformConfig', 'Platform Config')}{' '}\n <span className=\"text-[10px] text-muted-foreground\">(JSON)</span>\n </label>\n <textarea\n value={formData.platformConfig}\n onChange={(e) =>\n setFormData((prev) => ({ ...prev, platformConfig: e.target.value }))\n }\n rows={3}\n className=\"w-full px-3 py-2 text-sm bg-surface border border-border rounded-lg focus:outline-none focus:ring-2 focus:ring-action-primary-bg/50 resize-none font-mono placeholder:text-muted-foreground\"\n placeholder={tr(\n 'channel.platformConfigPlaceholder',\n '{\"fromEmail\": \"noreply@example.com\"}'\n )}\n />\n <p className=\"mt-1 text-[11px] text-muted-foreground\">\n {tr('channel.platformConfigHint', 'Platform-specific configuration as JSON')}\n </p>\n </div>\n </div>\n )}\n </div>\n\n {/* ── Actions ────────────────────────────────────────────────── */}\n <div className=\"flex items-center justify-between pt-2\">\n <button\n type=\"button\"\n onClick={() => navigate('/channels/list')}\n className=\"px-4 py-2 text-sm text-muted-foreground hover:text-foreground hover:bg-surface-hover border border-border rounded-lg transition-colors\"\n >\n {tr('channel.cancel', 'Cancel')}\n </button>\n <button\n type=\"submit\"\n disabled={isSubmitting || !formData.name.trim()}\n className=\"inline-flex items-center gap-2 px-5 py-2 text-sm font-medium text-action-primary-text bg-action-primary-bg hover:bg-action-primary-bg-hover rounded-lg transition-colors disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n {isSubmitting ? <Loader2 size={16} className=\"animate-spin\" /> : <Save size={16} />}\n {tr('channel.createChannel', 'Create Channel')}\n </button>\n </div>\n </form>\n </div>\n </PermissionGuard>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Create Connection Page
3
+ *
4
+ * Standalone page mounted at /channels/connections/create.
5
+ * User picks a target channel, then provides auth details.
6
+ *
7
+ * Form fields match CreateConnectionInput exactly (less channelId which is
8
+ * resolved from the selector).
9
+ */
10
+ export declare function CreateConnectionPage(): import("react/jsx-runtime").JSX.Element;
11
+ //# sourceMappingURL=CreateConnectionPage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CreateConnectionPage.d.ts","sourceRoot":"","sources":["../../../../../src/channel/modules/channels/pages/CreateConnectionPage.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAmBH,wBAAgB,oBAAoB,4CAwPnC"}