@feedmepos/mf-miniprogram-v2 0.2.2-dev.20 → 0.2.2-dev.22

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.
@@ -1,475 +0,0 @@
1
- import { defineComponent as G, ref as n, computed as D, resolveComponent as f, openBlock as u, createBlock as x, withCtx as q, createElementVNode as o, createElementBlock as y, Fragment as z, createTextVNode as V, toDisplayString as h, createVNode as s, unref as ae, createCommentVNode as P, onMounted as ie, onScopeDispose as re, renderList as de } from "vue";
2
- import { a as I } from "./routes-Cay_S88s.js";
3
- import { useDialog as ue } from "@feedmepos/ui-library";
4
- import { useRouter as pe } from "vue-router";
5
- import { c as L, e as U } from "./controlPlane-sXaC6pAh.js";
6
- import { _ as H } from "./_plugin-vue_export-helper-CHgC5LLL.js";
7
- import { _ as me } from "./StatusBadge.vue_vue_type_script_setup_true_lang-CMgQ0bd_.js";
8
- const ce = ["qsr", "coffee", "tea"], ve = ["miniprogram-vue"], N = [
9
- // `label` and `description` are MERCHANT-FACING: the portal's picker renders
10
- // them, and they are the only thing a merchant chooses on. Say what the app does
11
- // for their customers, never which package it is built from — the SDK is real and
12
- // load-bearing and means nothing to the person making this decision.
13
- {
14
- id: "miniprogram-vue",
15
- label: "Phone ordering app",
16
- description: "Menu browsing, cart and checkout, membership and rewards, and order history — for customers ordering on their own phone.",
17
- industries: [],
18
- environments: ["dev", "prod"],
19
- default: !0
20
- },
21
- {
22
- id: "miniprogram-vue-v2",
23
- label: "Phone, kiosk and tablet",
24
- description: "Everything in the phone app, plus self-order kiosk and in-store tablet surfaces sharing the same menu, cart and membership.",
25
- industries: [],
26
- // Dev only, deliberately. It has never been provisioned end-to-end: the
27
- // preview proxy, the component-library unpack and the release build have
28
- // only been exercised locally. Add 'prod' after a real merchant has run
29
- // through all three.
30
- environments: ["dev"]
31
- },
32
- // Forked from miniprogram-vue-v2 (2026-09): the coffee and tea styles used
33
- // to be `restaurantStyle` choices sharing that one directory, which meant
34
- // editing one style's components risked changing what the other two
35
- // rendered. Each now has its own independent directory; only
36
- // `templates/block-library/` is still shared across all three.
37
- {
38
- id: "miniprogram-vue-v2-coffee",
39
- label: "Phone, kiosk and tablet — coffee house",
40
- description: "Everything in the phone app, plus self-order kiosk and in-store tablet surfaces, in a calm, image-led layout for habitual pickup and considered customisation.",
41
- industries: ["Food & beverage"],
42
- environments: ["dev"]
43
- },
44
- {
45
- id: "miniprogram-vue-v2-tea",
46
- label: "Phone, kiosk and tablet — tea & beverage",
47
- description: "Everything in the phone app, plus self-order kiosk and in-store tablet surfaces, in a light, compact, option-forward layout for repeat beverage orders.",
48
- industries: ["Food & beverage"],
49
- environments: ["dev"]
50
- }
51
- ], be = ["href"], he = {
52
- key: 0,
53
- class: "portal-error",
54
- role: "alert"
55
- }, ge = /* @__PURE__ */ G({
56
- __name: "ForkTemplateDialog",
57
- emits: ["close"],
58
- setup(R, { emit: $ }) {
59
- var t;
60
- const r = $, E = N.map((a) => ({ label: a.label, value: a.id })), _ = n(((t = N.find((a) => a.id === "miniprogram-vue-v2")) == null ? void 0 : t.id) ?? ""), c = n(""), g = n(""), v = n(""), d = n(!1), k = n(""), T = n(""), w = n(0), F = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/, p = D(
61
- () => !d.value && _.value.length > 0 && F.test(c.value.trim()) && g.value.trim().length > 0 && v.value.trim().length > 0
62
- );
63
- async function A() {
64
- if (p.value) {
65
- d.value = !0, k.value = "";
66
- try {
67
- const a = await L(I.forkAppTemplate(), {
68
- method: "POST",
69
- body: JSON.stringify({
70
- sourceAppTemplateId: _.value,
71
- newAppTemplateId: c.value.trim(),
72
- label: g.value.trim(),
73
- description: v.value.trim()
74
- })
75
- });
76
- T.value = a.pullRequestUrl, w.value = a.fileCount;
77
- } catch (a) {
78
- k.value = U(a);
79
- } finally {
80
- d.value = !1;
81
- }
82
- }
83
- }
84
- return (a, e) => {
85
- const l = f("FmButton"), S = f("FmSelect"), B = f("FmTextField"), O = f("FmTextarea"), j = f("FmCard");
86
- return u(), x(j, { class: "fork-template-dialog" }, {
87
- default: q(() => [
88
- e[9] || (e[9] = o("h2", null, "Fork template", -1)),
89
- T.value ? (u(), y(z, { key: 0 }, [
90
- o("p", null, [
91
- e[6] || (e[6] = V(" Opened a ", -1)),
92
- o("a", {
93
- href: T.value,
94
- target: "_blank",
95
- rel: "noopener"
96
- }, "pull request", 8, be),
97
- V(" copying " + h(w.value) + " file(s) into a brand-new ", 1),
98
- o("code", null, "templates/" + h(c.value) + "/", 1),
99
- e[7] || (e[7] = V(' directory, and registering it in the template catalog. It needs human review and merge — once merged, a workflow syncs it to its own GitHub template repository automatically. A Template Center choice pointing at it can then be created from "New choice". ', -1))
100
- ]),
101
- o("footer", null, [
102
- s(l, {
103
- label: "Done",
104
- onClick: e[0] || (e[0] = (b) => r("close"))
105
- })
106
- ])
107
- ], 64)) : (u(), y(z, { key: 1 }, [
108
- e[8] || (e[8] = o("p", { class: "fork-template-dialog__note" }, " Copies an existing physical template's whole directory into a brand-new, independent one — editing the new one can never affect the source or any other template. Use this to start a new restaurant style rather than editing a style that other merchants already share. ", -1)),
109
- s(S, {
110
- modelValue: _.value,
111
- "onUpdate:modelValue": e[1] || (e[1] = (b) => _.value = b),
112
- label: "Fork from",
113
- items: ae(E),
114
- disabled: d.value
115
- }, null, 8, ["modelValue", "items", "disabled"]),
116
- s(B, {
117
- modelValue: c.value,
118
- "onUpdate:modelValue": e[2] || (e[2] = (b) => c.value = b),
119
- label: "New template id",
120
- placeholder: "e.g. miniprogram-vue-v2-bakery",
121
- "helper-text": "Lowercase, kebab-case. Also becomes the directory name and GitHub repository name.",
122
- disabled: d.value,
123
- rules: [(b) => F.test(b.trim()) || "Lowercase kebab-case, e.g. miniprogram-vue-v2-bakery"]
124
- }, null, 8, ["modelValue", "disabled", "rules"]),
125
- s(B, {
126
- modelValue: g.value,
127
- "onUpdate:modelValue": e[3] || (e[3] = (b) => g.value = b),
128
- label: "Label",
129
- placeholder: "Shown to merchants in the picker",
130
- disabled: d.value
131
- }, null, 8, ["modelValue", "disabled"]),
132
- s(O, {
133
- modelValue: v.value,
134
- "onUpdate:modelValue": e[4] || (e[4] = (b) => v.value = b),
135
- label: "Description",
136
- placeholder: "One or two sentences on what the merchant gets",
137
- disabled: d.value
138
- }, null, 8, ["modelValue", "disabled"]),
139
- k.value ? (u(), y("p", he, h(k.value), 1)) : P("", !0),
140
- o("footer", null, [
141
- s(l, {
142
- label: "Cancel",
143
- variant: "tertiary",
144
- disabled: d.value,
145
- onClick: e[5] || (e[5] = (b) => r("close"))
146
- }, null, 8, ["disabled"]),
147
- s(l, {
148
- label: "Open pull request",
149
- loading: d.value,
150
- disabled: !p.value,
151
- onClick: A
152
- }, null, 8, ["loading", "disabled"])
153
- ])
154
- ], 64))
155
- ]),
156
- _: 1
157
- });
158
- };
159
- }
160
- }), fe = /* @__PURE__ */ H(ge, [["__scopeId", "data-v-41bb02b7"]]), ye = {
161
- key: 2,
162
- class: "portal-error",
163
- role: "alert"
164
- }, _e = /* @__PURE__ */ G({
165
- __name: "TemplateChoiceDialog",
166
- props: {
167
- choice: {}
168
- },
169
- emits: ["saved", "close"],
170
- setup(R, { emit: $ }) {
171
- var O, j, b, J, Y, K, W, Q, X;
172
- const r = R, E = $, _ = N.filter((C) => !ve.includes(C.id)), c = ((O = _[0]) == null ? void 0 : O.id) ?? ((j = N[0]) == null ? void 0 : j.id) ?? "", g = n(((b = r.choice) == null ? void 0 : b.id) ?? ""), v = n(((J = r.choice) == null ? void 0 : J.appTemplateId) ?? c), d = n(((Y = r.choice) == null ? void 0 : Y.restaurantStyle) ?? "qsr"), k = n(((K = r.choice) == null ? void 0 : K.label) ?? ""), T = n(((W = r.choice) == null ? void 0 : W.description) ?? ""), w = n((((Q = r.choice) == null ? void 0 : Q.industries) ?? []).join(", ")), F = n(((X = r.choice) == null ? void 0 : X.default) ?? !1), p = n(!1), A = n(""), t = D(() => !!r.choice), a = D(
173
- () => (t.value ? N : _).map((C) => ({
174
- label: C.label,
175
- value: C.id
176
- }))
177
- ), e = D(() => v.value === "miniprogram-vue-v2"), l = ce.map((C) => ({ label: C, value: C })), S = D(
178
- () => !p.value && k.value.trim().length > 0 && T.value.trim().length > 0 && (t.value ? !0 : /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/.test(g.value.trim()))
179
- );
180
- async function B() {
181
- if (!S.value) return;
182
- p.value = !0, A.value = "";
183
- const C = {
184
- ...t.value ? {} : { id: g.value.trim() },
185
- appTemplateId: v.value,
186
- label: k.value.trim(),
187
- description: T.value.trim(),
188
- industries: w.value.split(",").map((i) => i.trim()).filter(Boolean),
189
- default: F.value,
190
- ...e.value ? { restaurantStyle: d.value } : {}
191
- };
192
- try {
193
- await L(
194
- t.value ? I.appTemplateChoice(r.choice.id) : I.appTemplateChoices(),
195
- { method: t.value ? "PATCH" : "POST", body: JSON.stringify(C) }
196
- ), E("saved");
197
- } catch (i) {
198
- A.value = U(i);
199
- } finally {
200
- p.value = !1;
201
- }
202
- }
203
- return (C, i) => {
204
- const M = f("FmTextField"), Z = f("FmSelect"), le = f("FmTextarea"), oe = f("FmSwitch"), ee = f("FmButton"), ne = f("FmCard"), se = f("FmForm");
205
- return u(), x(se, { onValidationSuccess: B }, {
206
- default: q(() => [
207
- s(ne, { class: "template-choice-dialog" }, {
208
- default: q(() => {
209
- var te;
210
- return [
211
- o("h2", null, h(t.value ? `Edit ${(te = R.choice) == null ? void 0 : te.label}` : "New template choice"), 1),
212
- t.value ? P("", !0) : (u(), x(M, {
213
- key: 0,
214
- modelValue: g.value,
215
- "onUpdate:modelValue": i[0] || (i[0] = (m) => g.value = m),
216
- label: "Choice id",
217
- placeholder: "e.g. miniprogram-vue-v2-bakery",
218
- "helper-text": "Lowercase, kebab-case. Cannot be changed after creation.",
219
- disabled: p.value,
220
- rules: [(m) => /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/.test(m.trim()) || "Lowercase kebab-case, e.g. miniprogram-vue-v2-bakery"]
221
- }, null, 8, ["modelValue", "disabled", "rules"])),
222
- s(Z, {
223
- modelValue: v.value,
224
- "onUpdate:modelValue": i[1] || (i[1] = (m) => v.value = m),
225
- label: "Physical template",
226
- items: a.value,
227
- disabled: p.value || t.value || a.value.length <= 1
228
- }, null, 8, ["modelValue", "items", "disabled"]),
229
- e.value ? (u(), x(Z, {
230
- key: 1,
231
- modelValue: d.value,
232
- "onUpdate:modelValue": i[2] || (i[2] = (m) => d.value = m),
233
- label: "Restaurant style",
234
- "helper-text": "Only styles templates/miniprogram-vue-v2/src/brand/recipes.ts already implements.",
235
- items: ae(l),
236
- disabled: p.value
237
- }, null, 8, ["modelValue", "items", "disabled"])) : P("", !0),
238
- s(M, {
239
- modelValue: k.value,
240
- "onUpdate:modelValue": i[3] || (i[3] = (m) => k.value = m),
241
- label: "Label",
242
- placeholder: "Shown to merchants in the picker",
243
- disabled: p.value
244
- }, null, 8, ["modelValue", "disabled"]),
245
- s(le, {
246
- modelValue: T.value,
247
- "onUpdate:modelValue": i[4] || (i[4] = (m) => T.value = m),
248
- label: "Description",
249
- placeholder: "One or two sentences on what the merchant gets",
250
- disabled: p.value
251
- }, null, 8, ["modelValue", "disabled"]),
252
- s(M, {
253
- modelValue: w.value,
254
- "onUpdate:modelValue": i[5] || (i[5] = (m) => w.value = m),
255
- label: "Industries (comma-separated)",
256
- placeholder: "e.g. Food & beverage",
257
- disabled: p.value
258
- }, null, 8, ["modelValue", "disabled"]),
259
- s(oe, {
260
- modelValue: F.value,
261
- "onUpdate:modelValue": i[6] || (i[6] = (m) => F.value = m),
262
- label: "Default choice",
263
- sublabel: "Used when a provision request names none",
264
- disabled: p.value
265
- }, null, 8, ["modelValue", "disabled"]),
266
- A.value ? (u(), y("p", ye, h(A.value), 1)) : P("", !0),
267
- o("footer", null, [
268
- s(ee, {
269
- label: "Cancel",
270
- variant: "tertiary",
271
- disabled: p.value,
272
- onClick: i[7] || (i[7] = (m) => E("close"))
273
- }, null, 8, ["disabled"]),
274
- s(ee, {
275
- label: t.value ? "Save" : "Create",
276
- type: "submit",
277
- loading: p.value,
278
- disabled: !S.value
279
- }, null, 8, ["label", "loading", "disabled"])
280
- ])
281
- ];
282
- }),
283
- _: 1
284
- })
285
- ]),
286
- _: 1
287
- });
288
- };
289
- }
290
- }), ke = /* @__PURE__ */ H(_e, [["__scopeId", "data-v-776c1a00"]]), Te = { class: "portal-page" }, Ce = { class: "portal-page-inner" }, we = { class: "portal-page-heading" }, Fe = { class: "portal-page-heading__actions" }, Ve = {
291
- key: 0,
292
- class: "portal-error",
293
- role: "alert"
294
- }, Ae = {
295
- key: 1,
296
- role: "status"
297
- }, Se = {
298
- key: 2,
299
- class: "template-choices__list",
300
- "aria-label": "Template choices"
301
- }, Ee = { class: "template-choices__name" }, Ie = { class: "template-choices__label" }, Pe = { key: 0 }, xe = { class: "template-choices__id" }, $e = { class: "template-choices__meta" }, De = ["datetime"], Le = { class: "template-choices__actions" }, Ue = /* @__PURE__ */ G({
302
- __name: "TemplateCenterView",
303
- setup(R) {
304
- const $ = pe(), r = ue(), E = n([]), _ = n(!0), c = n(""), g = new AbortController(), v = n(null);
305
- async function d() {
306
- _.value = !0, c.value = "";
307
- try {
308
- const t = await L(I.appTemplateChoices(), {
309
- signal: g.signal
310
- });
311
- E.value = t.choices;
312
- } catch (t) {
313
- g.signal.aborted || (c.value = U(t));
314
- } finally {
315
- _.value = !1;
316
- }
317
- }
318
- function k() {
319
- r.open({
320
- title: "Fork template",
321
- dialogComponent: fe,
322
- dialogComponentProps: { onClose: () => r.close() }
323
- });
324
- }
325
- async function T(t) {
326
- if (!v.value) {
327
- v.value = t, c.value = "";
328
- try {
329
- const a = await L(
330
- I.appTemplateEditingProject(t),
331
- { method: "POST" }
332
- );
333
- await $.push({
334
- name: "miniprogram-v2-project",
335
- params: { projectId: a.projectId, view: "workspace" },
336
- query: { tpl: "1" }
337
- });
338
- } catch (a) {
339
- c.value = U(a);
340
- } finally {
341
- v.value = null;
342
- }
343
- }
344
- }
345
- function w(t) {
346
- r.open({
347
- title: t ? `Edit ${t.label}` : "New template choice",
348
- dialogComponent: ke,
349
- dialogComponentProps: {
350
- choice: t,
351
- onClose: () => r.close(),
352
- onSaved: () => {
353
- r.close(), d();
354
- }
355
- }
356
- });
357
- }
358
- async function F(t, a) {
359
- try {
360
- await L(
361
- a === "archived" ? I.appTemplateChoiceArchive(t.id) : I.appTemplateChoiceRestore(t.id),
362
- { method: "POST" }
363
- ), await d();
364
- } catch (e) {
365
- c.value = U(e);
366
- }
367
- }
368
- function p(t) {
369
- r.open({
370
- title: `Archive ${t.label}?`,
371
- message: "It stops appearing for new projects. Merchants already provisioned from it are unaffected — it is never consulted again after provisioning.",
372
- primaryActions: { text: "Archive", close: !0, variant: "primary" },
373
- secondaryActions: { text: "Cancel", close: !0, variant: "tertiary" }
374
- }).onPrimary(() => void F(t, "archived"));
375
- }
376
- function A(t) {
377
- return new Intl.DateTimeFormat(void 0, { dateStyle: "medium", timeStyle: "short" }).format(new Date(t));
378
- }
379
- return ie(() => void d()), re(() => g.abort()), (t, a) => {
380
- const e = f("FmButton");
381
- return u(), y("div", Te, [
382
- o("div", Ce, [
383
- o("header", we, [
384
- a[2] || (a[2] = o("div", null, [
385
- o("p", { class: "portal-eyebrow" }, "Internal"),
386
- o("h1", null, "Template library")
387
- ], -1)),
388
- o("div", Fe, [
389
- s(e, {
390
- label: "Fork template",
391
- variant: "secondary",
392
- onClick: a[0] || (a[0] = (l) => k())
393
- }),
394
- s(e, {
395
- label: "New choice",
396
- icon: "add",
397
- onClick: a[1] || (a[1] = (l) => w())
398
- })
399
- ])
400
- ]),
401
- c.value ? (u(), y("p", Ve, [
402
- V(h(c.value) + " ", 1),
403
- s(e, {
404
- label: "Retry",
405
- variant: "tertiary",
406
- onClick: d
407
- })
408
- ])) : P("", !0),
409
- a[3] || (a[3] = o("h2", { class: "template-section-title" }, "Template choices", -1)),
410
- a[4] || (a[4] = o("p", { class: "template-section-note" }, ' "Edit code" opens the physical template a choice provisions from directly — the same chat + live preview a merchant project gets, saving straight to a pull request against this repo instead of a merchant repo. More than one choice can point at the same physical template; editing either reaches the same session. ', -1)),
411
- _.value ? (u(), y("p", Ae, "Loading template choices…")) : (u(), y("section", Se, [
412
- (u(!0), y(z, null, de(E.value, (l) => (u(), y("article", {
413
- key: l.id,
414
- class: "template-choices__row"
415
- }, [
416
- o("div", Ee, [
417
- o("span", Ie, [
418
- V(h(l.label), 1),
419
- l.default ? (u(), y("span", Pe, " · Default")) : P("", !0)
420
- ]),
421
- o("span", xe, h(l.id), 1),
422
- o("span", $e, [
423
- V(h(l.appTemplateId), 1),
424
- l.restaurantStyle ? (u(), y(z, { key: 0 }, [
425
- V(" · " + h(l.restaurantStyle), 1)
426
- ], 64)) : P("", !0),
427
- V(" · " + h(l.industries.join(", ") || "General-purpose") + " · " + h((l.environments ?? []).join(", ")), 1)
428
- ])
429
- ]),
430
- s(me, {
431
- variant: l.status === "active" ? "success" : "neutral"
432
- }, {
433
- default: q(() => [
434
- V(h(l.status === "active" ? "Active" : "Archived"), 1)
435
- ]),
436
- _: 2
437
- }, 1032, ["variant"]),
438
- o("time", {
439
- datetime: l.updatedAt
440
- }, h(A(l.updatedAt)), 9, De),
441
- o("div", Le, [
442
- s(e, {
443
- label: "Edit code",
444
- variant: "secondary",
445
- loading: v.value === l.appTemplateId,
446
- disabled: v.value !== null,
447
- onClick: (S) => T(l.appTemplateId)
448
- }, null, 8, ["loading", "disabled", "onClick"]),
449
- s(e, {
450
- label: "Edit details",
451
- variant: "secondary",
452
- onClick: (S) => w(l)
453
- }, null, 8, ["onClick"]),
454
- l.status === "active" ? (u(), x(e, {
455
- key: 0,
456
- label: "Archive",
457
- variant: "tertiary",
458
- onClick: (S) => p(l)
459
- }, null, 8, ["onClick"])) : (u(), x(e, {
460
- key: 1,
461
- label: "Restore",
462
- variant: "tertiary",
463
- onClick: (S) => F(l, "active")
464
- }, null, 8, ["onClick"]))
465
- ])
466
- ]))), 128))
467
- ]))
468
- ])
469
- ]);
470
- };
471
- }
472
- }), Me = /* @__PURE__ */ H(Ue, [["__scopeId", "data-v-de284b8c"]]);
473
- export {
474
- Me as default
475
- };
@@ -1,59 +0,0 @@
1
- import { a as o } from "./routes-Cay_S88s.js";
2
- import { ref as i } from "vue";
3
- import { c as a } from "./controlPlane-sXaC6pAh.js";
4
- function m(e, t) {
5
- if (typeof window > "u") return t;
6
- try {
7
- const n = window.localStorage.getItem(e);
8
- return n === null ? t : n === "1";
9
- } catch {
10
- return t;
11
- }
12
- }
13
- function w(e, t) {
14
- if (typeof window > "u") return t;
15
- try {
16
- const n = Number(window.localStorage.getItem(e));
17
- return Number.isFinite(n) ? n : t;
18
- } catch {
19
- return t;
20
- }
21
- }
22
- function u(e, t) {
23
- if (!(typeof window > "u"))
24
- try {
25
- window.localStorage.setItem(e, t);
26
- } catch {
27
- }
28
- }
29
- function h(e, t) {
30
- u(e, t ? "1" : "0");
31
- }
32
- let r = null;
33
- function c() {
34
- return r || (r = a(o.adminWhoami()).then((e) => e.isAdmin).catch(() => !1)), r;
35
- }
36
- function p() {
37
- const e = i(!1);
38
- return c().then((t) => {
39
- e.value = t;
40
- }), e;
41
- }
42
- const d = "templatePicker";
43
- function y() {
44
- if (typeof window > "u") return !1;
45
- try {
46
- const e = new URLSearchParams(window.location.search).get(d);
47
- return e !== null && e !== "0" && e !== "false";
48
- } catch {
49
- return !1;
50
- }
51
- }
52
- export {
53
- w as a,
54
- u as b,
55
- m as r,
56
- y as t,
57
- p as u,
58
- h as w
59
- };