includio-cms 0.34.0 → 0.35.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 (46) hide show
  1. package/API.md +5 -2
  2. package/CHANGELOG.md +27 -0
  3. package/DOCS.md +1 -1
  4. package/dist/admin/client/index.d.ts +1 -0
  5. package/dist/admin/client/index.js +1 -0
  6. package/dist/admin/client/shop/coupon-edit-page.svelte +1 -0
  7. package/dist/admin/client/shop/coupon-form.svelte +62 -2
  8. package/dist/admin/client/shop/coupon-schema.d.ts +5 -0
  9. package/dist/admin/client/shop/coupon-schema.js +2 -0
  10. package/dist/admin/client/shop/shop-order-detail-page.svelte +72 -2
  11. package/dist/admin/components/fields/date-field.svelte +81 -27
  12. package/dist/admin/components/fields/date-field.svelte.d.ts +3 -0
  13. package/dist/admin/components/fields/datetime-field.svelte +142 -29
  14. package/dist/admin/components/fields/datetime-field.svelte.d.ts +3 -0
  15. package/dist/admin/remote/shop.remote.d.ts +6 -0
  16. package/dist/admin/remote/shop.remote.js +4 -0
  17. package/dist/cli/scaffold/admin.js +1 -1
  18. package/dist/core/server/generator/generator.js +3 -2
  19. package/dist/db-postgres/schema/shop/coupons.d.ts +20 -0
  20. package/dist/db-postgres/schema/shop/coupons.js +3 -0
  21. package/dist/paraglide/messages/_index.d.ts +36 -3
  22. package/dist/paraglide/messages/_index.js +71 -3
  23. package/dist/paraglide/messages/en.d.ts +5 -0
  24. package/dist/paraglide/messages/en.js +14 -0
  25. package/dist/paraglide/messages/pl.d.ts +5 -0
  26. package/dist/paraglide/messages/pl.js +14 -0
  27. package/dist/shop/client/index.d.ts +1 -0
  28. package/dist/shop/http/order-handler.js +2 -1
  29. package/dist/shop/pricing.d.ts +18 -6
  30. package/dist/shop/pricing.js +33 -8
  31. package/dist/shop/server/coupons.js +3 -2
  32. package/dist/shop/server/email.js +30 -0
  33. package/dist/shop/templates/_partials/items.en.html +10 -0
  34. package/dist/shop/templates/_partials/items.pl.html +10 -0
  35. package/dist/updates/0.34.1/index.d.ts +2 -0
  36. package/dist/updates/0.34.1/index.js +11 -0
  37. package/dist/updates/0.35.0/index.d.ts +2 -0
  38. package/dist/updates/0.35.0/index.js +16 -0
  39. package/dist/updates/index.js +5 -1
  40. package/package.json +1 -1
  41. package/dist/paraglide/messages/hello_world.d.ts +0 -5
  42. package/dist/paraglide/messages/hello_world.js +0 -33
  43. package/dist/paraglide/messages/login_hello.d.ts +0 -16
  44. package/dist/paraglide/messages/login_hello.js +0 -34
  45. package/dist/paraglide/messages/login_please_login.d.ts +0 -16
  46. package/dist/paraglide/messages/login_please_login.js +0 -34
@@ -70,6 +70,30 @@ export async function sendOrderStatusEmail(orderId, status) {
70
70
  catch (err) {
71
71
  console.error('[shop] Failed to load order coupon for email context:', err);
72
72
  }
73
+ let participants = [];
74
+ if (order.notes) {
75
+ try {
76
+ const parsed = JSON.parse(order.notes);
77
+ if (Array.isArray(parsed?.participants)) {
78
+ participants = parsed.participants
79
+ .map((p) => {
80
+ const fn = typeof p?.firstName === 'string'
81
+ ? p.firstName.trim()
82
+ : '';
83
+ const ln = typeof p?.lastName === 'string'
84
+ ? p.lastName.trim()
85
+ : '';
86
+ if (!fn && !ln)
87
+ return null;
88
+ return { firstName: fn, lastName: ln };
89
+ })
90
+ .filter((p) => p !== null);
91
+ }
92
+ }
93
+ catch {
94
+ // notes nie jest JSON-em (legacy free-form) — pomijamy
95
+ }
96
+ }
73
97
  const lang = (order.language || cms.languages[0] || 'pl');
74
98
  const subjectKey = (lang in STATUS_SUBJECTS[status] ? lang : 'pl');
75
99
  const viewUrl = /^https?:\/\//i.test(shop.orderViewUrl)
@@ -121,6 +145,12 @@ export async function sendOrderStatusEmail(orderId, status) {
121
145
  discountAmount: coupon ? formatPrice(coupon.discountAmount, order.currency) : null,
122
146
  hasDiscount: Boolean(coupon && coupon.discountAmount > 0)
123
147
  },
148
+ participants: participants.map((p, idx) => ({
149
+ number: idx + 1,
150
+ firstName: p.firstName,
151
+ lastName: p.lastName
152
+ })),
153
+ hasParticipants: participants.length > 0,
124
154
  items: items.map((i) => ({
125
155
  name: resolveI18n(i.nameSnapshot?.product
126
156
  ? { pl: i.nameSnapshot.product }
@@ -1,3 +1,13 @@
1
+ {{#if hasParticipants}}
2
+ <table style="width:100%;border-collapse:collapse;font-size:14px;margin-bottom:16px;">
3
+ <thead><tr style="background:#f4f2fa;"><th align="left" colspan="2" style="padding:8px;">Participants</th></tr></thead>
4
+ <tbody>
5
+ {{#each participants}}
6
+ <tr><td style="padding:6px 8px;border-bottom:1px solid #eee;width:24px;color:#5B4A9E;font-weight:700;text-align:right;">{{number}}.</td><td style="padding:6px 8px;border-bottom:1px solid #eee;font-weight:600;">{{firstName}} {{lastName}}</td></tr>
7
+ {{/each}}
8
+ </tbody>
9
+ </table>
10
+ {{/if}}
1
11
  <table style="width:100%;border-collapse:collapse;font-size:14px;">
2
12
  <thead><tr style="background:#f4f2fa;"><th align="left" style="padding:8px;">Item</th><th style="padding:8px;">Qty</th><th align="right" style="padding:8px;">Total</th></tr></thead>
3
13
  <tbody>
@@ -1,3 +1,13 @@
1
+ {{#if hasParticipants}}
2
+ <table style="width:100%;border-collapse:collapse;font-size:14px;margin-bottom:16px;">
3
+ <thead><tr style="background:#f4f2fa;"><th align="left" colspan="2" style="padding:8px;">Uczestnicy</th></tr></thead>
4
+ <tbody>
5
+ {{#each participants}}
6
+ <tr><td style="padding:6px 8px;border-bottom:1px solid #eee;width:24px;color:#5B4A9E;font-weight:700;text-align:right;">{{number}}.</td><td style="padding:6px 8px;border-bottom:1px solid #eee;font-weight:600;">{{firstName}} {{lastName}}</td></tr>
7
+ {{/each}}
8
+ </tbody>
9
+ </table>
10
+ {{/if}}
1
11
  <table style="width:100%;border-collapse:collapse;font-size:14px;">
2
12
  <thead><tr style="background:#f4f2fa;"><th align="left" style="padding:8px;">Pozycja</th><th style="padding:8px;">Ilość</th><th align="right" style="padding:8px;">Suma</th></tr></thead>
3
13
  <tbody>
@@ -0,0 +1,2 @@
1
+ import type { CmsUpdate } from '../index.js';
2
+ export declare const update: CmsUpdate;
@@ -0,0 +1,11 @@
1
+ export const update = {
2
+ version: '0.34.1',
3
+ date: '2026-06-03',
4
+ description: 'Fix: `AccountPage` eksportowany z głównego barrela `includio-cms/admin/client` (wcześniej brakowało go w eksportach, a scaffold importował z nieistniejącego subpath `includio-cms/admin/client/account`). Generowany `+page.svelte` dla konta importuje teraz z `includio-cms/admin/client`. Additive only.',
5
+ features: [],
6
+ fixes: [
7
+ '`AccountPage` dodany do eksportów `includio-cms/admin/client`.',
8
+ 'Scaffold (`admin/(afterLogin)/account/+page.svelte`) importuje `AccountPage` z `includio-cms/admin/client` zamiast nieistniejącego `includio-cms/admin/client/account`.'
9
+ ],
10
+ breakingChanges: []
11
+ };
@@ -0,0 +1,2 @@
1
+ import type { CmsUpdate } from '../index.js';
2
+ export declare const update: CmsUpdate;
@@ -0,0 +1,16 @@
1
+ export const update = {
2
+ version: '0.35.0',
3
+ date: '2026-06-05',
4
+ description: 'Kupon `appliesTo` (netto/brutto), uczestnicy w `notes` (admin + email), Calendar+Popover w polach `date`/`datetime` (admin), `api.ts` bez `FormEntryMap` gdy projekt nie ma form. Additive only — domyślne zachowania bez zmian.',
5
+ features: [
6
+ '`shop_coupons` dostaje kolumnę `applies_to` (enum `net`/`gross`, default `net`). `calculateCouponDiscountNet()` (`$lib/shop/pricing.ts`) liczy zniżkę od brutto (konwersja do netto przez średnią ważoną VAT) gdy `appliesTo="gross"` — działa zarówno dla `percent`, jak i `fixed`. Storage rabatu w bazie nadal w netto (canonical). Domyślnie `net` — istniejące kupony zachowują obecne zachowanie.',
7
+ 'Admin coupon form (`coupon-form.svelte`) zyskuje toggle „Rabat dotyczy: netto / brutto" wzorowany na `inputMode` w `shop-field.svelte` — z helper textem objaśniającym wpływ na cenę zamówienia.',
8
+ '`order.notes` jest teraz traktowane jako opcjonalny JSON (`{ org?, orgName?, participants?: Array<{firstName, lastName}> }`) w admin order detail (`shop-order-detail-page.svelte`) oraz w kontekście emaila (`items.pl.html`/`items.en.html` przez `email.ts`). Plain-text notatki nadal renderują się raw — JSON wykrywany przez `try/catch` parse + shape guard.',
9
+ 'Admin pola `date` i `datetime` (`date-field.svelte`, `datetime-field.svelte`) używają `bits-ui` Calendar w `Popover` zamiast natywnych `<input type="date|datetime-local">` — kalendarz z dropdownem miesiąca/roku, dwa Selecty (godzina 00–23, minuta 00/15/30/45) dla datetime, locale `pl-PL`/`en-GB` z `interfaceLanguage`. Output bez zmian: ISO datetime (`datetime`) / `YYYY-MM-DDT00:00:00.000Z` (`date`).'
10
+ ],
11
+ fixes: [
12
+ '`generateAPI()` (`src/lib/core/server/generator/generator.ts`) nie wstrzykuje już importu `FormEntryMap` / `createFormSubmission` w wygenerowanym `api.ts`, gdy projekt nie ma zdefiniowanych form (`config.forms` puste). Wcześniej projekty bez form miały martwy import, który psuł type-check / build.'
13
+ ],
14
+ breakingChanges: [],
15
+ sql: `ALTER TABLE shop_coupons ADD COLUMN IF NOT EXISTS applies_to text NOT NULL DEFAULT 'net';`
16
+ };
@@ -64,6 +64,8 @@ import { update as update0261 } from './0.26.1/index.js';
64
64
  import { update as update0270 } from './0.27.0/index.js';
65
65
  import { update as update0280 } from './0.28.0/index.js';
66
66
  import { update as update0340 } from './0.34.0/index.js';
67
+ import { update as update0341 } from './0.34.1/index.js';
68
+ import { update as update0350 } from './0.35.0/index.js';
67
69
  export const updates = [
68
70
  update0065,
69
71
  update0066,
@@ -130,7 +132,9 @@ export const updates = [
130
132
  update0261,
131
133
  update0270,
132
134
  update0280,
133
- update0340
135
+ update0340,
136
+ update0341,
137
+ update0350
134
138
  ];
135
139
  export const getUpdatesFrom = (fromVersion) => {
136
140
  const fromParts = fromVersion.split('.').map(Number);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "includio-cms",
3
- "version": "0.34.0",
3
+ "version": "0.35.0",
4
4
  "scripts": {
5
5
  "dev": "vite dev",
6
6
  "build": "vite build && npm run prepack",
@@ -1,5 +0,0 @@
1
- export function hello_world(inputs: {
2
- name: NonNullable<unknown>;
3
- }, options?: {
4
- locale?: "en" | "pl";
5
- }): string;
@@ -1,33 +0,0 @@
1
- /* eslint-disable */
2
- import { getLocale, trackMessageCall, experimentalMiddlewareLocaleSplitting, isServer } from '../runtime.js';
3
-
4
- const en_hello_world = /** @type {(inputs: { name: NonNullable<unknown> }) => string} */ (i) => {
5
- return `Hello, ${i.name} from en!`
6
- };
7
-
8
- const pl_hello_world = /** @type {(inputs: { name: NonNullable<unknown> }) => string} */ (i) => {
9
- return `Hello, ${i.name} from pl!`
10
- };
11
-
12
- /**
13
- * This function has been compiled by [Paraglide JS](https://inlang.com/m/gerre34r).
14
- *
15
- * - Changing this function will be over-written by the next build.
16
- *
17
- * - If you want to change the translations, you can either edit the source files e.g. `en.json`, or
18
- * use another inlang app like [Fink](https://inlang.com/m/tdozzpar) or the [VSCode extension Sherlock](https://inlang.com/m/r7kp499g).
19
- *
20
- * @param {{ name: NonNullable<unknown> }} inputs
21
- * @param {{ locale?: "en" | "pl" }} options
22
- * @returns {string}
23
- */
24
- /* @__NO_SIDE_EFFECTS__ */
25
- export const hello_world = (inputs, options = {}) => {
26
- if (experimentalMiddlewareLocaleSplitting && isServer === false) {
27
- return /** @type {any} */ (globalThis).__paraglide_ssr.hello_world(inputs)
28
- }
29
- const locale = options.locale ?? getLocale()
30
- trackMessageCall("hello_world", locale)
31
- if (locale === "en") return en_hello_world(inputs)
32
- return pl_hello_world(inputs)
33
- };
@@ -1,16 +0,0 @@
1
- export { login_hello as login.hello };
2
- /**
3
- * This function has been compiled by [Paraglide JS](https://inlang.com/m/gerre34r).
4
- *
5
- * - Changing this function will be over-written by the next build.
6
- *
7
- * - If you want to change the translations, you can either edit the source files e.g. `en.json`, or
8
- * use another inlang app like [Fink](https://inlang.com/m/tdozzpar) or the [VSCode extension Sherlock](https://inlang.com/m/r7kp499g).
9
- *
10
- * @param {{}} inputs
11
- * @param {{ locale?: "en" | "pl" }} options
12
- * @returns {string}
13
- */
14
- declare function login_hello(inputs?: {}, options?: {
15
- locale?: "en" | "pl";
16
- }): string;
@@ -1,34 +0,0 @@
1
- /* eslint-disable */
2
- import { getLocale, trackMessageCall, experimentalMiddlewareLocaleSplitting, isServer } from '../runtime.js';
3
-
4
- const en_login_hello = /** @type {(inputs: {}) => string} */ () => {
5
- return `Welcome back`
6
- };
7
-
8
- const pl_login_hello = /** @type {(inputs: {}) => string} */ () => {
9
- return `Witaj ponownie`
10
- };
11
-
12
- /**
13
- * This function has been compiled by [Paraglide JS](https://inlang.com/m/gerre34r).
14
- *
15
- * - Changing this function will be over-written by the next build.
16
- *
17
- * - If you want to change the translations, you can either edit the source files e.g. `en.json`, or
18
- * use another inlang app like [Fink](https://inlang.com/m/tdozzpar) or the [VSCode extension Sherlock](https://inlang.com/m/r7kp499g).
19
- *
20
- * @param {{}} inputs
21
- * @param {{ locale?: "en" | "pl" }} options
22
- * @returns {string}
23
- */
24
- /* @__NO_SIDE_EFFECTS__ */
25
- const login_hello = (inputs = {}, options = {}) => {
26
- if (experimentalMiddlewareLocaleSplitting && isServer === false) {
27
- return /** @type {any} */ (globalThis).__paraglide_ssr.login_hello(inputs)
28
- }
29
- const locale = options.locale ?? getLocale()
30
- trackMessageCall("login_hello", locale)
31
- if (locale === "en") return en_login_hello(inputs)
32
- return pl_login_hello(inputs)
33
- };
34
- export { login_hello as "login.hello" }
@@ -1,16 +0,0 @@
1
- export { login_please_login as login.please_login };
2
- /**
3
- * This function has been compiled by [Paraglide JS](https://inlang.com/m/gerre34r).
4
- *
5
- * - Changing this function will be over-written by the next build.
6
- *
7
- * - If you want to change the translations, you can either edit the source files e.g. `en.json`, or
8
- * use another inlang app like [Fink](https://inlang.com/m/tdozzpar) or the [VSCode extension Sherlock](https://inlang.com/m/r7kp499g).
9
- *
10
- * @param {{}} inputs
11
- * @param {{ locale?: "en" | "pl" }} options
12
- * @returns {string}
13
- */
14
- declare function login_please_login(inputs?: {}, options?: {
15
- locale?: "en" | "pl";
16
- }): string;
@@ -1,34 +0,0 @@
1
- /* eslint-disable */
2
- import { getLocale, trackMessageCall, experimentalMiddlewareLocaleSplitting, isServer } from '../runtime.js';
3
-
4
- const en_login_please_login = /** @type {(inputs: {}) => string} */ () => {
5
- return `Login to your account`
6
- };
7
-
8
- const pl_login_please_login = /** @type {(inputs: {}) => string} */ () => {
9
- return `Zaloguj się na swoje konto`
10
- };
11
-
12
- /**
13
- * This function has been compiled by [Paraglide JS](https://inlang.com/m/gerre34r).
14
- *
15
- * - Changing this function will be over-written by the next build.
16
- *
17
- * - If you want to change the translations, you can either edit the source files e.g. `en.json`, or
18
- * use another inlang app like [Fink](https://inlang.com/m/tdozzpar) or the [VSCode extension Sherlock](https://inlang.com/m/r7kp499g).
19
- *
20
- * @param {{}} inputs
21
- * @param {{ locale?: "en" | "pl" }} options
22
- * @returns {string}
23
- */
24
- /* @__NO_SIDE_EFFECTS__ */
25
- const login_please_login = (inputs = {}, options = {}) => {
26
- if (experimentalMiddlewareLocaleSplitting && isServer === false) {
27
- return /** @type {any} */ (globalThis).__paraglide_ssr.login_please_login(inputs)
28
- }
29
- const locale = options.locale ?? getLocale()
30
- trackMessageCall("login_please_login", locale)
31
- if (locale === "en") return en_login_please_login(inputs)
32
- return pl_login_please_login(inputs)
33
- };
34
- export { login_please_login as "login.please_login" }