@zachariaz/strapi-plugin-content-variants 0.1.0

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 (43) hide show
  1. package/README.md +600 -0
  2. package/dist/_chunks/Segments-BREqC60L.js +330 -0
  3. package/dist/_chunks/Segments-BgxnvvtR.mjs +330 -0
  4. package/dist/_chunks/en-Bnfrhhim.js +62 -0
  5. package/dist/_chunks/en-e_966kWj.mjs +62 -0
  6. package/dist/_chunks/index-DVoZM8JU.js +1036 -0
  7. package/dist/_chunks/index-Dj2sexmk.mjs +1020 -0
  8. package/dist/admin/index.js +3 -0
  9. package/dist/admin/index.mjs +4 -0
  10. package/dist/admin/src/components/Initializer.d.ts +5 -0
  11. package/dist/admin/src/components/SegmentPickerAction.d.ts +7 -0
  12. package/dist/admin/src/components/VariantInfoAction.d.ts +8 -0
  13. package/dist/admin/src/components/VariantPanel.d.ts +13 -0
  14. package/dist/admin/src/components/VariantPickerAction.d.ts +20 -0
  15. package/dist/admin/src/contentManagerHooks/editView.d.ts +6 -0
  16. package/dist/admin/src/contentManagerHooks/listView.d.ts +22 -0
  17. package/dist/admin/src/hooks/useSegments.d.ts +17 -0
  18. package/dist/admin/src/hooks/useVariantFamily.d.ts +19 -0
  19. package/dist/admin/src/hooks/useVariantLinks.d.ts +44 -0
  20. package/dist/admin/src/index.d.ts +11 -0
  21. package/dist/admin/src/pages/Settings/Segments.d.ts +2 -0
  22. package/dist/admin/src/pluginId.d.ts +2 -0
  23. package/dist/admin/src/utils/batchLinkFetcher.d.ts +11 -0
  24. package/dist/admin/src/utils/variants.d.ts +13 -0
  25. package/dist/server/index.js +895 -0
  26. package/dist/server/index.mjs +896 -0
  27. package/dist/server/src/bootstrap.d.ts +17 -0
  28. package/dist/server/src/config/index.d.ts +5 -0
  29. package/dist/server/src/content-types/index.d.ts +121 -0
  30. package/dist/server/src/controllers/index.d.ts +24 -0
  31. package/dist/server/src/controllers/segment.d.ts +11 -0
  32. package/dist/server/src/controllers/variant-link.d.ts +18 -0
  33. package/dist/server/src/destroy.d.ts +5 -0
  34. package/dist/server/src/index.d.ts +244 -0
  35. package/dist/server/src/register.d.ts +5 -0
  36. package/dist/server/src/routes/admin.d.ts +12 -0
  37. package/dist/server/src/routes/content-api.d.ts +19 -0
  38. package/dist/server/src/routes/index.d.ts +25 -0
  39. package/dist/server/src/services/index.d.ts +62 -0
  40. package/dist/server/src/services/segment.d.ts +14 -0
  41. package/dist/server/src/services/variant-link.d.ts +60 -0
  42. package/dist/server/src/services/variant-resolver.d.ts +23 -0
  43. package/package.json +104 -0
@@ -0,0 +1,330 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const jsxRuntime = require("react/jsx-runtime");
4
+ const React = require("react");
5
+ const designSystem = require("@strapi/design-system");
6
+ const icons = require("@strapi/icons");
7
+ const admin = require("@strapi/strapi/admin");
8
+ const reactIntl = require("react-intl");
9
+ const index = require("./index-DVoZM8JU.js");
10
+ function slugify(text) {
11
+ return text.toLowerCase().trim().replace(/[^\w\s-]/g, "").replace(/[\s_]+/g, "-").replace(/-+/g, "-");
12
+ }
13
+ const SegmentsSettingsPage = () => {
14
+ const { formatMessage } = reactIntl.useIntl();
15
+ const { segments, isLoading, error, createSegment, updateSegment, deleteSegment } = index.useSegments();
16
+ const [isFormVisible, setIsFormVisible] = React.useState(false);
17
+ const [editingSegment, setEditingSegment] = React.useState(null);
18
+ const [formData, setFormData] = React.useState({
19
+ name: "",
20
+ slug: "",
21
+ description: "",
22
+ externalId: ""
23
+ });
24
+ const [slugManuallyEdited, setSlugManuallyEdited] = React.useState(false);
25
+ const resetForm = () => {
26
+ setFormData({ name: "", slug: "", description: "", externalId: "" });
27
+ setEditingSegment(null);
28
+ setSlugManuallyEdited(false);
29
+ };
30
+ const handleOpenCreate = () => {
31
+ resetForm();
32
+ setIsFormVisible(true);
33
+ };
34
+ const handleOpenEdit = (segment) => {
35
+ setEditingSegment(segment);
36
+ setFormData({
37
+ name: segment.name,
38
+ slug: segment.slug,
39
+ description: segment.description ?? "",
40
+ externalId: segment.externalId ?? ""
41
+ });
42
+ setSlugManuallyEdited(true);
43
+ setIsFormVisible(true);
44
+ };
45
+ const handleCancel = () => {
46
+ setIsFormVisible(false);
47
+ resetForm();
48
+ };
49
+ const handleNameChange = (e) => {
50
+ const name = e.target.value;
51
+ setFormData((prev) => ({
52
+ ...prev,
53
+ name,
54
+ slug: slugManuallyEdited ? prev.slug : slugify(name)
55
+ }));
56
+ };
57
+ const handleSlugChange = (e) => {
58
+ setSlugManuallyEdited(true);
59
+ setFormData((prev) => ({ ...prev, slug: e.target.value }));
60
+ };
61
+ const handleSubmit = async () => {
62
+ if (!formData.name.trim() || !formData.slug.trim()) return;
63
+ try {
64
+ const payload = {
65
+ name: formData.name,
66
+ slug: formData.slug,
67
+ description: formData.description || null,
68
+ externalId: formData.externalId || null
69
+ };
70
+ if (editingSegment) {
71
+ await updateSegment(editingSegment.documentId, payload);
72
+ } else {
73
+ await createSegment(payload);
74
+ }
75
+ handleCancel();
76
+ } catch (err) {
77
+ console.error("Failed to save segment", err);
78
+ }
79
+ };
80
+ const handleDelete = async (segment) => {
81
+ if (window.confirm(
82
+ formatMessage(
83
+ {
84
+ id: `${index.PLUGIN_ID}.segment.delete-confirm`,
85
+ defaultMessage: 'Delete segment "{name}"?'
86
+ },
87
+ { name: segment.name }
88
+ )
89
+ )) {
90
+ await deleteSegment(segment.documentId);
91
+ }
92
+ };
93
+ if (isLoading) {
94
+ return /* @__PURE__ */ jsxRuntime.jsx(admin.Page.Loading, {});
95
+ }
96
+ return /* @__PURE__ */ jsxRuntime.jsxs(admin.Layouts.Root, { children: [
97
+ /* @__PURE__ */ jsxRuntime.jsx(admin.Page.Title, { children: formatMessage({
98
+ id: `${index.PLUGIN_ID}.settings.page-title`,
99
+ defaultMessage: "Content Variants - Segments"
100
+ }) }),
101
+ /* @__PURE__ */ jsxRuntime.jsxs(admin.Page.Main, { children: [
102
+ /* @__PURE__ */ jsxRuntime.jsx(
103
+ admin.Layouts.Header,
104
+ {
105
+ title: formatMessage({
106
+ id: `${index.PLUGIN_ID}.settings.title`,
107
+ defaultMessage: "Segments"
108
+ }),
109
+ subtitle: formatMessage({
110
+ id: `${index.PLUGIN_ID}.settings.subtitle`,
111
+ defaultMessage: "Define audience segments for content personalization"
112
+ }),
113
+ primaryAction: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.Plus, {}), onClick: handleOpenCreate, children: formatMessage({
114
+ id: `${index.PLUGIN_ID}.segment.create`,
115
+ defaultMessage: "Add Segment"
116
+ }) })
117
+ }
118
+ ),
119
+ /* @__PURE__ */ jsxRuntime.jsxs(admin.Layouts.Content, { children: [
120
+ error && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { paddingBottom: 4, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "danger600", children: error }) }),
121
+ isFormVisible && /* @__PURE__ */ jsxRuntime.jsxs(
122
+ designSystem.Box,
123
+ {
124
+ background: "neutral0",
125
+ padding: 6,
126
+ shadow: "filterShadow",
127
+ hasRadius: true,
128
+ marginBottom: 4,
129
+ children: [
130
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "delta", tag: "h2", children: editingSegment ? formatMessage({
131
+ id: `${index.PLUGIN_ID}.segment.edit`,
132
+ defaultMessage: "Edit Segment"
133
+ }) : formatMessage({
134
+ id: `${index.PLUGIN_ID}.segment.new`,
135
+ defaultMessage: "New Segment"
136
+ }) }),
137
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { paddingTop: 4, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 4, children: [
138
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 4, children: [
139
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { flex: "1", children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Field.Root, { name: "name", required: true, children: [
140
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: formatMessage({
141
+ id: `${index.PLUGIN_ID}.segment.form.name`,
142
+ defaultMessage: "Name"
143
+ }) }),
144
+ /* @__PURE__ */ jsxRuntime.jsx(
145
+ designSystem.TextInput,
146
+ {
147
+ value: formData.name,
148
+ onChange: handleNameChange,
149
+ placeholder: formatMessage({
150
+ id: `${index.PLUGIN_ID}.segment.form.name-placeholder`,
151
+ defaultMessage: "e.g., Club Members"
152
+ })
153
+ }
154
+ )
155
+ ] }) }),
156
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { flex: "1", children: /* @__PURE__ */ jsxRuntime.jsxs(
157
+ designSystem.Field.Root,
158
+ {
159
+ name: "slug",
160
+ required: true,
161
+ hint: formatMessage({
162
+ id: `${index.PLUGIN_ID}.segment.form.slug-hint`,
163
+ defaultMessage: "Auto-generated from name, or edit manually"
164
+ }),
165
+ children: [
166
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: formatMessage({
167
+ id: `${index.PLUGIN_ID}.segment.form.slug`,
168
+ defaultMessage: "Slug"
169
+ }) }),
170
+ /* @__PURE__ */ jsxRuntime.jsx(
171
+ designSystem.TextInput,
172
+ {
173
+ value: formData.slug,
174
+ onChange: handleSlugChange,
175
+ placeholder: formatMessage({
176
+ id: `${index.PLUGIN_ID}.segment.form.slug-placeholder`,
177
+ defaultMessage: "e.g., club-members"
178
+ })
179
+ }
180
+ ),
181
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Hint, {})
182
+ ]
183
+ }
184
+ ) })
185
+ ] }),
186
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 4, children: [
187
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { flex: "1", children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Field.Root, { name: "description", children: [
188
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: formatMessage({
189
+ id: `${index.PLUGIN_ID}.segment.form.description`,
190
+ defaultMessage: "Description"
191
+ }) }),
192
+ /* @__PURE__ */ jsxRuntime.jsx(
193
+ designSystem.Textarea,
194
+ {
195
+ value: formData.description,
196
+ onChange: (e) => setFormData((prev) => ({ ...prev, description: e.target.value })),
197
+ placeholder: formatMessage({
198
+ id: `${index.PLUGIN_ID}.segment.form.description-placeholder`,
199
+ defaultMessage: "Optional description of this segment"
200
+ })
201
+ }
202
+ )
203
+ ] }) }),
204
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { flex: "1", children: /* @__PURE__ */ jsxRuntime.jsxs(
205
+ designSystem.Field.Root,
206
+ {
207
+ name: "externalId",
208
+ hint: formatMessage({
209
+ id: `${index.PLUGIN_ID}.segment.form.external-id-hint`,
210
+ defaultMessage: "CDP or external system identifier"
211
+ }),
212
+ children: [
213
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: formatMessage({
214
+ id: `${index.PLUGIN_ID}.segment.form.external-id`,
215
+ defaultMessage: "External ID"
216
+ }) }),
217
+ /* @__PURE__ */ jsxRuntime.jsx(
218
+ designSystem.TextInput,
219
+ {
220
+ value: formData.externalId,
221
+ onChange: (e) => setFormData((prev) => ({ ...prev, externalId: e.target.value })),
222
+ placeholder: formatMessage({
223
+ id: `${index.PLUGIN_ID}.segment.form.external-id-placeholder`,
224
+ defaultMessage: "Optional external ID"
225
+ })
226
+ }
227
+ ),
228
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Hint, {})
229
+ ]
230
+ }
231
+ ) })
232
+ ] }),
233
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, justifyContent: "flex-end", children: [
234
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "tertiary", onClick: handleCancel, startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.Cross, {}), children: formatMessage({
235
+ id: `${index.PLUGIN_ID}.segment.form.cancel`,
236
+ defaultMessage: "Cancel"
237
+ }) }),
238
+ /* @__PURE__ */ jsxRuntime.jsx(
239
+ designSystem.Button,
240
+ {
241
+ onClick: handleSubmit,
242
+ startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.Check, {}),
243
+ disabled: !formData.name.trim() || !formData.slug.trim(),
244
+ children: editingSegment ? formatMessage({
245
+ id: `${index.PLUGIN_ID}.segment.form.update`,
246
+ defaultMessage: "Update"
247
+ }) : formatMessage({
248
+ id: `${index.PLUGIN_ID}.segment.form.create-submit`,
249
+ defaultMessage: "Create"
250
+ })
251
+ }
252
+ )
253
+ ] })
254
+ ] }) })
255
+ ]
256
+ }
257
+ ),
258
+ segments.length === 0 && !isFormVisible ? /* @__PURE__ */ jsxRuntime.jsx(
259
+ designSystem.EmptyStateLayout,
260
+ {
261
+ content: formatMessage({
262
+ id: `${index.PLUGIN_ID}.segment.empty`,
263
+ defaultMessage: "No segments defined yet. Create your first audience segment."
264
+ }),
265
+ action: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "secondary", startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.Plus, {}), onClick: handleOpenCreate, children: formatMessage({
266
+ id: `${index.PLUGIN_ID}.segment.empty-action`,
267
+ defaultMessage: "Add your first segment"
268
+ }) })
269
+ }
270
+ ) : segments.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { background: "neutral0", padding: 6, shadow: "filterShadow", hasRadius: true, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Table, { colCount: 5, rowCount: segments.length, children: [
271
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Thead, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tr, { children: [
272
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", children: formatMessage({
273
+ id: `${index.PLUGIN_ID}.segment.table.name`,
274
+ defaultMessage: "Name"
275
+ }) }) }),
276
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", children: formatMessage({
277
+ id: `${index.PLUGIN_ID}.segment.table.slug`,
278
+ defaultMessage: "Slug"
279
+ }) }) }),
280
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", children: formatMessage({
281
+ id: `${index.PLUGIN_ID}.segment.table.external-id`,
282
+ defaultMessage: "External ID"
283
+ }) }) }),
284
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", children: formatMessage({
285
+ id: `${index.PLUGIN_ID}.segment.table.description`,
286
+ defaultMessage: "Description"
287
+ }) }) }),
288
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", children: formatMessage({
289
+ id: `${index.PLUGIN_ID}.segment.table.actions`,
290
+ defaultMessage: "Actions"
291
+ }) }) })
292
+ ] }) }),
293
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tbody, { children: segments.map((segment) => /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tr, { children: [
294
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { fontWeight: "bold", children: segment.name }) }),
295
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: segment.slug }) }),
296
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "neutral600", children: segment.externalId || "--" }) }),
297
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "neutral600", children: segment.description || "--" }) }),
298
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 1, children: [
299
+ /* @__PURE__ */ jsxRuntime.jsx(
300
+ designSystem.IconButton,
301
+ {
302
+ onClick: () => handleOpenEdit(segment),
303
+ label: formatMessage({
304
+ id: `${index.PLUGIN_ID}.segment.table.edit`,
305
+ defaultMessage: "Edit"
306
+ }),
307
+ variant: "ghost",
308
+ children: /* @__PURE__ */ jsxRuntime.jsx(icons.Pencil, {})
309
+ }
310
+ ),
311
+ /* @__PURE__ */ jsxRuntime.jsx(
312
+ designSystem.IconButton,
313
+ {
314
+ onClick: () => handleDelete(segment),
315
+ label: formatMessage({
316
+ id: `${index.PLUGIN_ID}.segment.table.delete`,
317
+ defaultMessage: "Delete"
318
+ }),
319
+ variant: "ghost",
320
+ children: /* @__PURE__ */ jsxRuntime.jsx(icons.Trash, {})
321
+ }
322
+ )
323
+ ] }) })
324
+ ] }, segment.documentId)) })
325
+ ] }) }) : null
326
+ ] })
327
+ ] })
328
+ ] });
329
+ };
330
+ exports.default = SegmentsSettingsPage;
@@ -0,0 +1,330 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { useState } from "react";
3
+ import { Button, Box, Typography, Flex, Field, TextInput, Textarea, EmptyStateLayout, Table, Thead, Tr, Th, Tbody, Td, IconButton } from "@strapi/design-system";
4
+ import { Plus, Cross, Check, Pencil, Trash } from "@strapi/icons";
5
+ import { Page, Layouts } from "@strapi/strapi/admin";
6
+ import { useIntl } from "react-intl";
7
+ import { u as useSegments, P as PLUGIN_ID } from "./index-Dj2sexmk.mjs";
8
+ function slugify(text) {
9
+ return text.toLowerCase().trim().replace(/[^\w\s-]/g, "").replace(/[\s_]+/g, "-").replace(/-+/g, "-");
10
+ }
11
+ const SegmentsSettingsPage = () => {
12
+ const { formatMessage } = useIntl();
13
+ const { segments, isLoading, error, createSegment, updateSegment, deleteSegment } = useSegments();
14
+ const [isFormVisible, setIsFormVisible] = useState(false);
15
+ const [editingSegment, setEditingSegment] = useState(null);
16
+ const [formData, setFormData] = useState({
17
+ name: "",
18
+ slug: "",
19
+ description: "",
20
+ externalId: ""
21
+ });
22
+ const [slugManuallyEdited, setSlugManuallyEdited] = useState(false);
23
+ const resetForm = () => {
24
+ setFormData({ name: "", slug: "", description: "", externalId: "" });
25
+ setEditingSegment(null);
26
+ setSlugManuallyEdited(false);
27
+ };
28
+ const handleOpenCreate = () => {
29
+ resetForm();
30
+ setIsFormVisible(true);
31
+ };
32
+ const handleOpenEdit = (segment) => {
33
+ setEditingSegment(segment);
34
+ setFormData({
35
+ name: segment.name,
36
+ slug: segment.slug,
37
+ description: segment.description ?? "",
38
+ externalId: segment.externalId ?? ""
39
+ });
40
+ setSlugManuallyEdited(true);
41
+ setIsFormVisible(true);
42
+ };
43
+ const handleCancel = () => {
44
+ setIsFormVisible(false);
45
+ resetForm();
46
+ };
47
+ const handleNameChange = (e) => {
48
+ const name = e.target.value;
49
+ setFormData((prev) => ({
50
+ ...prev,
51
+ name,
52
+ slug: slugManuallyEdited ? prev.slug : slugify(name)
53
+ }));
54
+ };
55
+ const handleSlugChange = (e) => {
56
+ setSlugManuallyEdited(true);
57
+ setFormData((prev) => ({ ...prev, slug: e.target.value }));
58
+ };
59
+ const handleSubmit = async () => {
60
+ if (!formData.name.trim() || !formData.slug.trim()) return;
61
+ try {
62
+ const payload = {
63
+ name: formData.name,
64
+ slug: formData.slug,
65
+ description: formData.description || null,
66
+ externalId: formData.externalId || null
67
+ };
68
+ if (editingSegment) {
69
+ await updateSegment(editingSegment.documentId, payload);
70
+ } else {
71
+ await createSegment(payload);
72
+ }
73
+ handleCancel();
74
+ } catch (err) {
75
+ console.error("Failed to save segment", err);
76
+ }
77
+ };
78
+ const handleDelete = async (segment) => {
79
+ if (window.confirm(
80
+ formatMessage(
81
+ {
82
+ id: `${PLUGIN_ID}.segment.delete-confirm`,
83
+ defaultMessage: 'Delete segment "{name}"?'
84
+ },
85
+ { name: segment.name }
86
+ )
87
+ )) {
88
+ await deleteSegment(segment.documentId);
89
+ }
90
+ };
91
+ if (isLoading) {
92
+ return /* @__PURE__ */ jsx(Page.Loading, {});
93
+ }
94
+ return /* @__PURE__ */ jsxs(Layouts.Root, { children: [
95
+ /* @__PURE__ */ jsx(Page.Title, { children: formatMessage({
96
+ id: `${PLUGIN_ID}.settings.page-title`,
97
+ defaultMessage: "Content Variants - Segments"
98
+ }) }),
99
+ /* @__PURE__ */ jsxs(Page.Main, { children: [
100
+ /* @__PURE__ */ jsx(
101
+ Layouts.Header,
102
+ {
103
+ title: formatMessage({
104
+ id: `${PLUGIN_ID}.settings.title`,
105
+ defaultMessage: "Segments"
106
+ }),
107
+ subtitle: formatMessage({
108
+ id: `${PLUGIN_ID}.settings.subtitle`,
109
+ defaultMessage: "Define audience segments for content personalization"
110
+ }),
111
+ primaryAction: /* @__PURE__ */ jsx(Button, { startIcon: /* @__PURE__ */ jsx(Plus, {}), onClick: handleOpenCreate, children: formatMessage({
112
+ id: `${PLUGIN_ID}.segment.create`,
113
+ defaultMessage: "Add Segment"
114
+ }) })
115
+ }
116
+ ),
117
+ /* @__PURE__ */ jsxs(Layouts.Content, { children: [
118
+ error && /* @__PURE__ */ jsx(Box, { paddingBottom: 4, children: /* @__PURE__ */ jsx(Typography, { textColor: "danger600", children: error }) }),
119
+ isFormVisible && /* @__PURE__ */ jsxs(
120
+ Box,
121
+ {
122
+ background: "neutral0",
123
+ padding: 6,
124
+ shadow: "filterShadow",
125
+ hasRadius: true,
126
+ marginBottom: 4,
127
+ children: [
128
+ /* @__PURE__ */ jsx(Typography, { variant: "delta", tag: "h2", children: editingSegment ? formatMessage({
129
+ id: `${PLUGIN_ID}.segment.edit`,
130
+ defaultMessage: "Edit Segment"
131
+ }) : formatMessage({
132
+ id: `${PLUGIN_ID}.segment.new`,
133
+ defaultMessage: "New Segment"
134
+ }) }),
135
+ /* @__PURE__ */ jsx(Box, { paddingTop: 4, children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 4, children: [
136
+ /* @__PURE__ */ jsxs(Flex, { gap: 4, children: [
137
+ /* @__PURE__ */ jsx(Box, { flex: "1", children: /* @__PURE__ */ jsxs(Field.Root, { name: "name", required: true, children: [
138
+ /* @__PURE__ */ jsx(Field.Label, { children: formatMessage({
139
+ id: `${PLUGIN_ID}.segment.form.name`,
140
+ defaultMessage: "Name"
141
+ }) }),
142
+ /* @__PURE__ */ jsx(
143
+ TextInput,
144
+ {
145
+ value: formData.name,
146
+ onChange: handleNameChange,
147
+ placeholder: formatMessage({
148
+ id: `${PLUGIN_ID}.segment.form.name-placeholder`,
149
+ defaultMessage: "e.g., Club Members"
150
+ })
151
+ }
152
+ )
153
+ ] }) }),
154
+ /* @__PURE__ */ jsx(Box, { flex: "1", children: /* @__PURE__ */ jsxs(
155
+ Field.Root,
156
+ {
157
+ name: "slug",
158
+ required: true,
159
+ hint: formatMessage({
160
+ id: `${PLUGIN_ID}.segment.form.slug-hint`,
161
+ defaultMessage: "Auto-generated from name, or edit manually"
162
+ }),
163
+ children: [
164
+ /* @__PURE__ */ jsx(Field.Label, { children: formatMessage({
165
+ id: `${PLUGIN_ID}.segment.form.slug`,
166
+ defaultMessage: "Slug"
167
+ }) }),
168
+ /* @__PURE__ */ jsx(
169
+ TextInput,
170
+ {
171
+ value: formData.slug,
172
+ onChange: handleSlugChange,
173
+ placeholder: formatMessage({
174
+ id: `${PLUGIN_ID}.segment.form.slug-placeholder`,
175
+ defaultMessage: "e.g., club-members"
176
+ })
177
+ }
178
+ ),
179
+ /* @__PURE__ */ jsx(Field.Hint, {})
180
+ ]
181
+ }
182
+ ) })
183
+ ] }),
184
+ /* @__PURE__ */ jsxs(Flex, { gap: 4, children: [
185
+ /* @__PURE__ */ jsx(Box, { flex: "1", children: /* @__PURE__ */ jsxs(Field.Root, { name: "description", children: [
186
+ /* @__PURE__ */ jsx(Field.Label, { children: formatMessage({
187
+ id: `${PLUGIN_ID}.segment.form.description`,
188
+ defaultMessage: "Description"
189
+ }) }),
190
+ /* @__PURE__ */ jsx(
191
+ Textarea,
192
+ {
193
+ value: formData.description,
194
+ onChange: (e) => setFormData((prev) => ({ ...prev, description: e.target.value })),
195
+ placeholder: formatMessage({
196
+ id: `${PLUGIN_ID}.segment.form.description-placeholder`,
197
+ defaultMessage: "Optional description of this segment"
198
+ })
199
+ }
200
+ )
201
+ ] }) }),
202
+ /* @__PURE__ */ jsx(Box, { flex: "1", children: /* @__PURE__ */ jsxs(
203
+ Field.Root,
204
+ {
205
+ name: "externalId",
206
+ hint: formatMessage({
207
+ id: `${PLUGIN_ID}.segment.form.external-id-hint`,
208
+ defaultMessage: "CDP or external system identifier"
209
+ }),
210
+ children: [
211
+ /* @__PURE__ */ jsx(Field.Label, { children: formatMessage({
212
+ id: `${PLUGIN_ID}.segment.form.external-id`,
213
+ defaultMessage: "External ID"
214
+ }) }),
215
+ /* @__PURE__ */ jsx(
216
+ TextInput,
217
+ {
218
+ value: formData.externalId,
219
+ onChange: (e) => setFormData((prev) => ({ ...prev, externalId: e.target.value })),
220
+ placeholder: formatMessage({
221
+ id: `${PLUGIN_ID}.segment.form.external-id-placeholder`,
222
+ defaultMessage: "Optional external ID"
223
+ })
224
+ }
225
+ ),
226
+ /* @__PURE__ */ jsx(Field.Hint, {})
227
+ ]
228
+ }
229
+ ) })
230
+ ] }),
231
+ /* @__PURE__ */ jsxs(Flex, { gap: 2, justifyContent: "flex-end", children: [
232
+ /* @__PURE__ */ jsx(Button, { variant: "tertiary", onClick: handleCancel, startIcon: /* @__PURE__ */ jsx(Cross, {}), children: formatMessage({
233
+ id: `${PLUGIN_ID}.segment.form.cancel`,
234
+ defaultMessage: "Cancel"
235
+ }) }),
236
+ /* @__PURE__ */ jsx(
237
+ Button,
238
+ {
239
+ onClick: handleSubmit,
240
+ startIcon: /* @__PURE__ */ jsx(Check, {}),
241
+ disabled: !formData.name.trim() || !formData.slug.trim(),
242
+ children: editingSegment ? formatMessage({
243
+ id: `${PLUGIN_ID}.segment.form.update`,
244
+ defaultMessage: "Update"
245
+ }) : formatMessage({
246
+ id: `${PLUGIN_ID}.segment.form.create-submit`,
247
+ defaultMessage: "Create"
248
+ })
249
+ }
250
+ )
251
+ ] })
252
+ ] }) })
253
+ ]
254
+ }
255
+ ),
256
+ segments.length === 0 && !isFormVisible ? /* @__PURE__ */ jsx(
257
+ EmptyStateLayout,
258
+ {
259
+ content: formatMessage({
260
+ id: `${PLUGIN_ID}.segment.empty`,
261
+ defaultMessage: "No segments defined yet. Create your first audience segment."
262
+ }),
263
+ action: /* @__PURE__ */ jsx(Button, { variant: "secondary", startIcon: /* @__PURE__ */ jsx(Plus, {}), onClick: handleOpenCreate, children: formatMessage({
264
+ id: `${PLUGIN_ID}.segment.empty-action`,
265
+ defaultMessage: "Add your first segment"
266
+ }) })
267
+ }
268
+ ) : segments.length > 0 ? /* @__PURE__ */ jsx(Box, { background: "neutral0", padding: 6, shadow: "filterShadow", hasRadius: true, children: /* @__PURE__ */ jsxs(Table, { colCount: 5, rowCount: segments.length, children: [
269
+ /* @__PURE__ */ jsx(Thead, { children: /* @__PURE__ */ jsxs(Tr, { children: [
270
+ /* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: formatMessage({
271
+ id: `${PLUGIN_ID}.segment.table.name`,
272
+ defaultMessage: "Name"
273
+ }) }) }),
274
+ /* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: formatMessage({
275
+ id: `${PLUGIN_ID}.segment.table.slug`,
276
+ defaultMessage: "Slug"
277
+ }) }) }),
278
+ /* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: formatMessage({
279
+ id: `${PLUGIN_ID}.segment.table.external-id`,
280
+ defaultMessage: "External ID"
281
+ }) }) }),
282
+ /* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: formatMessage({
283
+ id: `${PLUGIN_ID}.segment.table.description`,
284
+ defaultMessage: "Description"
285
+ }) }) }),
286
+ /* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: formatMessage({
287
+ id: `${PLUGIN_ID}.segment.table.actions`,
288
+ defaultMessage: "Actions"
289
+ }) }) })
290
+ ] }) }),
291
+ /* @__PURE__ */ jsx(Tbody, { children: segments.map((segment) => /* @__PURE__ */ jsxs(Tr, { children: [
292
+ /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", children: segment.name }) }),
293
+ /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { children: segment.slug }) }),
294
+ /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { textColor: "neutral600", children: segment.externalId || "--" }) }),
295
+ /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { textColor: "neutral600", children: segment.description || "--" }) }),
296
+ /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsxs(Flex, { gap: 1, children: [
297
+ /* @__PURE__ */ jsx(
298
+ IconButton,
299
+ {
300
+ onClick: () => handleOpenEdit(segment),
301
+ label: formatMessage({
302
+ id: `${PLUGIN_ID}.segment.table.edit`,
303
+ defaultMessage: "Edit"
304
+ }),
305
+ variant: "ghost",
306
+ children: /* @__PURE__ */ jsx(Pencil, {})
307
+ }
308
+ ),
309
+ /* @__PURE__ */ jsx(
310
+ IconButton,
311
+ {
312
+ onClick: () => handleDelete(segment),
313
+ label: formatMessage({
314
+ id: `${PLUGIN_ID}.segment.table.delete`,
315
+ defaultMessage: "Delete"
316
+ }),
317
+ variant: "ghost",
318
+ children: /* @__PURE__ */ jsx(Trash, {})
319
+ }
320
+ )
321
+ ] }) })
322
+ ] }, segment.documentId)) })
323
+ ] }) }) : null
324
+ ] })
325
+ ] })
326
+ ] });
327
+ };
328
+ export {
329
+ SegmentsSettingsPage as default
330
+ };