@stapel/listings-react 0.10.0 → 0.12.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 (80) hide show
  1. package/CHANGELOG.md +197 -0
  2. package/dist/api/types.d.ts +10 -0
  3. package/dist/api/types.d.ts.map +1 -1
  4. package/dist/api/types.js.map +1 -1
  5. package/dist/default/ListingCard.d.ts +2 -2
  6. package/dist/default/ListingCard.d.ts.map +1 -1
  7. package/dist/default/ListingCard.js +8 -2
  8. package/dist/default/ListingCard.js.map +1 -1
  9. package/dist/default/ListingComposerPage.d.ts +22 -62
  10. package/dist/default/ListingComposerPage.d.ts.map +1 -1
  11. package/dist/default/ListingComposerPage.js +228 -56
  12. package/dist/default/ListingComposerPage.js.map +1 -1
  13. package/dist/default/ListingDetailPane.d.ts +2 -2
  14. package/dist/default/ListingDetailPane.d.ts.map +1 -1
  15. package/dist/default/ListingDetailPane.js +6 -1
  16. package/dist/default/ListingDetailPane.js.map +1 -1
  17. package/dist/default/ListingSerpCard.d.ts +2 -2
  18. package/dist/default/ListingSerpCard.d.ts.map +1 -1
  19. package/dist/default/ListingSerpCard.js +7 -2
  20. package/dist/default/ListingSerpCard.js.map +1 -1
  21. package/dist/default/index.d.ts +2 -2
  22. package/dist/default/index.d.ts.map +1 -1
  23. package/dist/default/index.js +1 -1
  24. package/dist/default/index.js.map +1 -1
  25. package/dist/default/types.d.ts +21 -0
  26. package/dist/default/types.d.ts.map +1 -1
  27. package/dist/headless/ListingComposer.d.ts +11 -0
  28. package/dist/headless/ListingComposer.d.ts.map +1 -1
  29. package/dist/headless/ListingComposer.js +31 -6
  30. package/dist/headless/ListingComposer.js.map +1 -1
  31. package/dist/headless/ListingDetail.d.ts +16 -1
  32. package/dist/headless/ListingDetail.d.ts.map +1 -1
  33. package/dist/headless/ListingDetail.js +13 -4
  34. package/dist/headless/ListingDetail.js.map +1 -1
  35. package/dist/i18n/es.d.ts.map +1 -1
  36. package/dist/i18n/es.js +4 -0
  37. package/dist/i18n/es.js.map +1 -1
  38. package/dist/i18n/keys.d.ts +10 -0
  39. package/dist/i18n/keys.d.ts.map +1 -1
  40. package/dist/i18n/keys.js +16 -0
  41. package/dist/i18n/keys.js.map +1 -1
  42. package/dist/i18n/ru.d.ts.map +1 -1
  43. package/dist/i18n/ru.js +4 -0
  44. package/dist/i18n/ru.js.map +1 -1
  45. package/dist/index.d.ts +2 -1
  46. package/dist/index.d.ts.map +1 -1
  47. package/dist/index.js +1 -1
  48. package/dist/index.js.map +1 -1
  49. package/dist/model/features.d.ts +90 -20
  50. package/dist/model/features.d.ts.map +1 -1
  51. package/dist/model/features.js +148 -17
  52. package/dist/model/features.js.map +1 -1
  53. package/dist/model/validation.d.ts +32 -0
  54. package/dist/model/validation.d.ts.map +1 -1
  55. package/dist/model/validation.js +82 -1
  56. package/dist/model/validation.js.map +1 -1
  57. package/dist/nav/manifest.d.ts.map +1 -1
  58. package/dist/nav/manifest.js +2 -0
  59. package/dist/nav/manifest.js.map +1 -1
  60. package/llms.txt +1 -1
  61. package/manifest.json +8 -1
  62. package/nav-manifest.json +3 -1
  63. package/package.json +7 -7
  64. package/src/analytics/generated/events.json +1 -1
  65. package/src/api/types.ts +10 -0
  66. package/src/default/ListingCard.tsx +17 -4
  67. package/src/default/ListingComposerPage.tsx +221 -36
  68. package/src/default/ListingDetailPane.tsx +10 -6
  69. package/src/default/ListingSerpCard.tsx +13 -4
  70. package/src/default/index.ts +7 -2
  71. package/src/default/types.ts +22 -0
  72. package/src/headless/ListingComposer.tsx +47 -6
  73. package/src/headless/ListingDetail.tsx +37 -10
  74. package/src/i18n/es.ts +5 -0
  75. package/src/i18n/keys.ts +17 -0
  76. package/src/i18n/ru.ts +5 -0
  77. package/src/index.ts +3 -0
  78. package/src/model/features.ts +253 -35
  79. package/src/model/validation.ts +84 -1
  80. package/src/nav/manifest.ts +2 -0
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -74,7 +74,7 @@ export { EMPTY_LOCATION, createDraftBody, draftPatchFromValues, draftValuesFromD
74
74
  // ── model: the stored feature projection ─────────────────────────────────────
75
75
  export { asFeatureDaoList, featureFromDao, featuresDtoFromDaoList, featuresFromDaoList, unreadableFeatureCount, } from "./model/features.js";
76
76
  // ── model: validation, the mirror and the publish-400 split ──────────────────
77
- export { CATEGORY_FIELD, DEFAULT_DRAFT_LIMITS, DESCRIPTION_FIELD, IMAGES_FIELD, PRICE_FIELD, TITLE_FIELD, failedResults, isBatchValid, listingFieldErrors, mirrorDraft, mirrorListingFields, publishRefusal, } from "./model/validation.js";
77
+ export { CATEGORY_FIELD, DEFAULT_DRAFT_LIMITS, DESCRIPTION_FIELD, IMAGES_FIELD, LOCATION_FIELD, PRICE_FIELD, TITLE_FIELD, envelopeFieldErrors, failedResults, isBatchValid, listingFieldErrors, mirrorDraft, mirrorListingFields, publishRefusal, } from "./model/validation.js";
78
78
  // ── model: runtime wiring, query keys, context, hooks ────────────────────────
79
79
  export { createListingsRuntime } from "./model/runtime.js";
80
80
  export { ListingsRuntimeContext, useListingsAnalytics, useListingsApi, useListingsRuntime, } from "./model/context.js";
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -22,31 +22,101 @@
22
22
  * `order`, `title`, `badge`) are simply ignored by every formatter. Copying a
23
23
  * hand-picked subset instead would be a list to keep in step with ten types.
24
24
  *
25
- * ── What a DAO does NOT carry, and the one line that repairs it ────────────
25
+ * ── What a DAO does NOT carry, and the tables that repair it ───────────────
26
26
  *
27
27
  * `select`'s `options`. `SelectType.dto_to_dao` stores the chosen VALUES and
28
28
  * the ui config, never the option table — the table lives on the CATEGORY, and
29
29
  * not needing it is the whole point of the projection.
30
30
  *
31
- * The consequence was a defect the visual pass caught on every card and every
32
- * spec row: `formatFeatureValue` resolves an option's copy by looking the
33
- * value up in `config.options`, and with no table it falls through to
34
- * `String(value)`. The stored value of a translatable catalogue IS a
35
- * translation key, so a listing page printed `demo.condition.used` and
36
- * `demo.brand.bosch` at people. (The server does not have this problem: its
37
- * own `format_value` has the category's config in hand.)
38
- *
39
- * So the split below synthesizes the IDENTITY table — `{value: v, label: v}`
40
- * for each stored value which is exactly the table a translatable catalogue
41
- * would have produced, since its labels ARE the keys. `formatFeatureValue`
42
- * then runs the value through the host's `t` and a bundle carrying the
43
- * catalogue copy reads "Used". A bundle that does not still shows the key, on
44
- * purpose: a visible `option.condition.used` gets fixed, an invented "Used"
45
- * ships wrong. A NON-translatable catalogue stores literal labels, `t` returns
46
- * an unknown key unchanged, and the output is what it always was.
31
+ * `formatFeatureValue` resolves an option's copy by looking the value up in
32
+ * `config.options`, so with no table at all it falls through to
33
+ * `String(value)` and the STORAGE SLUG reaches the screen: a live classified
34
+ * deployment printed "Condition: b-u" on its spec rows and a three-slug
35
+ * subtitle on its cards. (The server never had this problem: its own
36
+ * `format_value` has the category's config in hand.)
37
+ *
38
+ * So the split below rebuilds the table, from the best of three sources:
39
+ *
40
+ * 1. The LABEL SNAPSHOT. A `select` DAO written by a stapel-attributes that
41
+ * snapshots labels carries `labels`, a `string[]` positionally aligned
42
+ * with `value` the same device `ref_select` has always used for its
43
+ * vocabulary terms, and the reason a published listing keeps printing the
44
+ * copy it was published with however the category is edited afterwards.
45
+ * 2. The CATEGORY's own option table, when the display surface has it —
46
+ * `GET /categories/api/v1/categories/{id}/features/` answers with
47
+ * `{"slug":"condition","config":{"type":"select","options":[…]}}`, labels
48
+ * and all. It is handed in through {@link FeatureCopySource}, because a
49
+ * library may not fetch another module's endpoint and a card grid has no
50
+ * category to fetch one FOR.
51
+ * 3. The IDENTITY table — `{value: v, label: v}` — for a value neither of the
52
+ * first two names. That is exactly the table a TRANSLATABLE catalogue
53
+ * would have produced, since its labels ARE its keys, so such a value
54
+ * still reads out of the host's bundle; a NON-translatable one keeps
55
+ * showing the slug. A visible `b-u` gets fixed by rung 1 or 2, and an
56
+ * invented "Used" ships wrong, so the floor stays the value itself.
57
+ *
58
+ * ── Which rung wins, and why that order and not the other one ──────────────
59
+ *
60
+ * The SNAPSHOT outranks the category. The snapshot is what the listing was
61
+ * PUBLISHED with; the category is what the catalogue says today. A category
62
+ * whose option copy was rewritten after a listing went live must not silently
63
+ * restate that listing — the person reading it is reading an advert somebody
64
+ * else wrote, not a form. The category outranks identity, which is the whole
65
+ * point: every listing published before the snapshot release, and every row
66
+ * written by an older server, has no snapshot to outrank it and prints its
67
+ * slug today.
68
+ *
69
+ * A category def that does not describe the STORED row — a different value
70
+ * type, or no such slug — is ignored rather than forced. A category edited
71
+ * from `select` to `string` is a different question, and pairing its options
72
+ * against this row's values would print one question's copy under another
73
+ * question's answer, which does not even LOOK wrong.
74
+ *
75
+ * With no category defs supplied, every rung above 1 is absent and the
76
+ * projection behaves exactly as it did.
77
+ *
78
+ * ── The category path is the REPAIR path, not the mechanism ────────────────
79
+ *
80
+ * The primary mechanism is the server's, and it is the snapshot: stapel-
81
+ * attributes writes `labels` beside a `select`'s codes exactly as it always
82
+ * has for `ref_select`, and stapel-listings ships a reprojection command that
83
+ * back-fills rows written before it. Nothing here competes with that. Rung 2
84
+ * exists for the three states that outlive that deploy:
85
+ *
86
+ * - a row written before the snapshot existed and not yet reprojected;
87
+ * - a deployment that never runs the reprojection;
88
+ * - a category whose option copy was edited AFTER publication — where the
89
+ * snapshot is deliberately the older and correct answer, which is exactly
90
+ * why the precedence runs the way it does above.
91
+ *
92
+ * The resulting table is then read the one way `formatFeatureValue` reads any
93
+ * option table — literal when the config says `translatable_options: false`,
94
+ * through the host's `t` otherwise, where a translatable catalogue's label IS
95
+ * the key and an unknown key comes back unchanged. The flag stays the ROW's:
96
+ * it describes how the listing's own stored config wants its copy resolved,
97
+ * and an unknown key resolves to itself either way.
47
98
  */
48
- import type { FeatureValueDto } from "@stapel/attributes-react";
99
+ import type { FeatureDef, FeatureValueDto } from "@stapel/attributes-react";
49
100
  import type { ListingFeatureDao, ListingFeatureView } from "../api/types.js";
101
+ /**
102
+ * The category's feature defs, for a display surface that has them.
103
+ *
104
+ * A detail page reads one listing of one category and its container usually
105
+ * holds that category's schema already (it is the same read the composer is
106
+ * given); a card grid spanning forty categories does not, and passes nothing.
107
+ * Optional for exactly that reason: the seam adds a source of copy, it never
108
+ * becomes a requirement, and a host that wires nothing keeps the behaviour it
109
+ * has.
110
+ */
111
+ export interface FeatureCopySource {
112
+ /**
113
+ * The chosen category's features, as
114
+ * `GET /categories/api/v1/categories/{id}/features/` answers — the same
115
+ * `readonly FeatureDef[]` `<ListingComposerPage>` already takes. Defs are
116
+ * matched to stored rows by slug AND value type; anything else is ignored.
117
+ */
118
+ readonly categoryFeatures?: readonly FeatureDef[];
119
+ }
50
120
  /**
51
121
  * One DAO row → the definition/value pair the display half consumes.
52
122
  *
@@ -55,12 +125,12 @@ import type { ListingFeatureDao, ListingFeatureView } from "../api/types.js";
55
125
  * is a malformed record, and a synthesized index would key a badge to a
56
126
  * position that changes whenever the category does.
57
127
  */
58
- export declare function featureFromDao(dao: ListingFeatureDao): ListingFeatureView | undefined;
128
+ export declare function featureFromDao(dao: ListingFeatureDao, source?: FeatureCopySource): ListingFeatureView | undefined;
59
129
  /** A stored projection → the pairs a display component iterates. Malformed
60
130
  * rows are dropped HERE, in one place, and counted by {@link
61
131
  * unreadableFeatureCount} so a skin can say how many rather than pretend the
62
132
  * listing had fewer attributes. */
63
- export declare function featuresFromDaoList(daos: readonly ListingFeatureDao[] | null | undefined): readonly ListingFeatureView[];
133
+ export declare function featuresFromDaoList(daos: readonly ListingFeatureDao[] | null | undefined, source?: FeatureCopySource): readonly ListingFeatureView[];
64
134
  /** How many rows of a stored projection this build could not key. */
65
135
  export declare function unreadableFeatureCount(daos: readonly ListingFeatureDao[] | null | undefined): number;
66
136
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"features.d.ts","sourceRoot":"","sources":["../../src/model/features.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AACH,OAAO,KAAK,EAAc,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC5E,OAAO,KAAK,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAmC7E;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,GAAG,EAAE,iBAAiB,GACrB,kBAAkB,GAAG,SAAS,CA2BhC;AAED;;;mCAGmC;AACnC,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,SAAS,iBAAiB,EAAE,GAAG,IAAI,GAAG,SAAS,GACpD,SAAS,kBAAkB,EAAE,CAO/B;AAED,qEAAqE;AACrE,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,SAAS,iBAAiB,EAAE,GAAG,IAAI,GAAG,SAAS,GACpD,MAAM,CAER;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,SAAS,iBAAiB,EAAE,GAAG,IAAI,GAAG,SAAS,GACpD,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC,CAM3C;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,SAAS,iBAAiB,EAAE,CAE7E"}
1
+ {"version":3,"file":"features.d.ts","sourceRoot":"","sources":["../../src/model/features.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiGG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAE5E,OAAO,KAAK,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAyC7E;;;;;;;;;GASG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;;;OAKG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,SAAS,UAAU,EAAE,CAAC;CACnD;AAiID;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,GAAG,EAAE,iBAAiB,EACtB,MAAM,GAAE,iBAAsB,GAC7B,kBAAkB,GAAG,SAAS,CAEhC;AAqCD;;;mCAGmC;AACnC,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,SAAS,iBAAiB,EAAE,GAAG,IAAI,GAAG,SAAS,EACrD,MAAM,GAAE,iBAAsB,GAC7B,SAAS,kBAAkB,EAAE,CAQ/B;AAED,qEAAqE;AACrE,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,SAAS,iBAAiB,EAAE,GAAG,IAAI,GAAG,SAAS,GACpD,MAAM,CAER;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,SAAS,iBAAiB,EAAE,GAAG,IAAI,GAAG,SAAS,GACpD,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC,CAM3C;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,SAAS,iBAAiB,EAAE,CAE7E"}
@@ -1,31 +1,156 @@
1
- /** Keys that belong to the DAO envelope rather than to the type's config. */
1
+ import { featureType } from "@stapel/attributes-react";
2
+ /**
3
+ * Keys that belong to the DAO envelope rather than to the type's config.
4
+ *
5
+ * `labels` is deliberately NOT one of them, even though this module now reads
6
+ * it: `ref_select` and `ref_hierarchical_select` resolve their vocabulary
7
+ * terms from `config.labels` (attributes-react's `refLabels` reads the value
8
+ * envelope first and the config second, and this split hands the formatter a
9
+ * bare `{type, value}`), so envelope-ing the key would blank every term those
10
+ * two types print. For `select` the key is simply inert — its formatter reads
11
+ * `options` and nothing else — so carrying it costs a reference.
12
+ */
2
13
  const ENVELOPE = new Set(["slug", "value", "name", "order", "title", "badge"]);
3
- /** The two types whose stored `value` is an option key rather than the thing
4
- * itself. `hierarchical_select` is deliberately absent: its formatter joins
5
- * the path with " / " and never consults an option table at all. */
14
+ /** The type whose stored `value` is a flat list of option keys rather than the
15
+ * things themselves, and whose copy therefore has to be repaired pairwise.
16
+ * `ref_select` is absent because it repairs itself: its `labels` snapshot has
17
+ * always been mandatory (no display package can reach a vocabulary term). */
6
18
  const OPTION_VALUED = new Set(["select"]);
19
+ /**
20
+ * The type whose copy lives in a TREE on the category rather than in a flat
21
+ * table: `hierarchical_select` stores a path of option keys and
22
+ * `formatFeatureValue` walks `config.options` level by level to name each
23
+ * step, so a row without that tree prints "passenger / sedan" — the storage
24
+ * keys — exactly as a table-less `select` prints `b-u`.
25
+ *
26
+ * It is kept apart from {@link OPTION_VALUED} because the two repairs are not
27
+ * the same repair: a flat positional `labels` list cannot describe a tree, so
28
+ * there is nothing to merge and the category's tree is adopted whole or not at
29
+ * all. `formatFeatureValue` already keeps a step the tree does not contain as
30
+ * its raw value, so an adopted tree can only add copy, never blank one out.
31
+ */
32
+ const TREE_VALUED = new Set(["hierarchical_select"]);
7
33
  /** The canon's `FeatureDef.translate` vocabulary — three values, closed. */
8
34
  function isTranslateMode(value) {
9
35
  return value === "all" || value === "title" || value === "none";
10
36
  }
37
+ function categoryDefs(source) {
38
+ const defs = source.categoryFeatures;
39
+ if (defs === undefined || defs.length === 0)
40
+ return undefined;
41
+ const index = new Map();
42
+ for (const def of defs) {
43
+ // First wins: a duplicate slug in a category is a catalogue defect, and
44
+ // silently preferring the last one would make the copy depend on the
45
+ // order the endpoint happened to serialize.
46
+ if (typeof def.slug === "string" && def.slug.length > 0 && !index.has(def.slug)) {
47
+ index.set(def.slug, def);
48
+ }
49
+ }
50
+ return index.size === 0 ? undefined : index;
51
+ }
11
52
  /**
12
- * The identity option table for a stored `select` — see the module header.
53
+ * The category's definition OF THIS ROW, or `undefined`.
54
+ *
55
+ * Same slug and same value type, or it is not a definition of this row — see
56
+ * the module header on why a mismatch is ignored rather than forced.
57
+ */
58
+ function categoryDefFor(dao, defs) {
59
+ if (defs === undefined)
60
+ return undefined;
61
+ const def = defs.get(dao.slug);
62
+ if (def === undefined)
63
+ return undefined;
64
+ return featureType(def) === dao.type ? def : undefined;
65
+ }
66
+ /** A category def's declared option list, when it declares one. */
67
+ function declaredOptions(def) {
68
+ const raw = def?.config?.["options"];
69
+ return Array.isArray(raw) ? raw : undefined;
70
+ }
71
+ /** One entry of an option list → its `(value, label)` pair, when it is one. */
72
+ function optionPair(entry) {
73
+ if (entry === null || typeof entry !== "object")
74
+ return undefined;
75
+ const option = entry;
76
+ if (typeof option.value !== "string" || option.value.length === 0)
77
+ return undefined;
78
+ return {
79
+ value: option.value,
80
+ label: typeof option.label === "string" && option.label.length > 0 ? option.label : option.value,
81
+ };
82
+ }
83
+ /**
84
+ * The option table a stored `select` needs and does not carry — see the
85
+ * module header. The category's table underneath, the row's own `labels`
86
+ * snapshot on top, the values themselves as the floor.
87
+ *
88
+ * The alignment rule is the engine's own (`labels if len(labels) ==
89
+ * len(codes) else codes`): a snapshot of a different length than `value` is a
90
+ * snapshot of some other value list, and pairing the two anyway would print
91
+ * one option's copy against another option's value — worse than a slug,
92
+ * because it does not LOOK wrong. So a length mismatch drops the whole
93
+ * snapshot rather than pairing the overlap, and the row falls back to the
94
+ * category (or to identity). Within a usable snapshot, a missing or empty
95
+ * entry falls back to whatever the category, then the value itself, offers for
96
+ * that one pair.
13
97
  *
14
98
  * Returns `undefined` when there is nothing to add (another type, a config
15
- * that already carries a table, a value that is not a list of strings), so the
16
- * common path allocates nothing and a DAO that DOES carry options is left
17
- * exactly as it arrived.
99
+ * that already carries a table, a value that is not a list of strings and no
100
+ * category table either), so the common path allocates nothing and a DAO that
101
+ * DOES carry options is left exactly as it arrived — a stored table is a
102
+ * write-time snapshot of the whole question, which is a stronger statement
103
+ * about this listing than either the per-value snapshot or today's category.
18
104
  */
19
- function synthesizedOptions(dao, config) {
105
+ function selectOptions(dao, config, categoryDef) {
20
106
  if (typeof dao.type !== "string" || !OPTION_VALUED.has(dao.type))
21
107
  return undefined;
22
108
  if (Array.isArray(config["options"]))
23
109
  return undefined;
24
- const raw = Array.isArray(dao.value) ? dao.value : [dao.value];
25
- const values = raw.filter((item) => typeof item === "string");
26
- if (values.length === 0)
110
+ const raw = Array.isArray(dao.value)
111
+ ? dao.value
112
+ : [dao.value];
113
+ const snapshot = dao.labels;
114
+ const labels = Array.isArray(snapshot) && snapshot.length === raw.length
115
+ ? snapshot
116
+ : undefined;
117
+ // A Map so the three rungs can overwrite one another by value instead of
118
+ // the reader having to scan a list that carries the same value twice —
119
+ // `labelOf` takes the FIRST match, so a duplicate would make the losing
120
+ // rung win.
121
+ const table = new Map();
122
+ for (const entry of declaredOptions(categoryDef) ?? []) {
123
+ const pair = optionPair(entry);
124
+ if (pair !== undefined)
125
+ table.set(pair.value, pair.label);
126
+ }
127
+ raw.forEach((value, index) => {
128
+ if (typeof value !== "string")
129
+ return;
130
+ const label = labels?.[index];
131
+ if (typeof label === "string" && label.length > 0)
132
+ table.set(value, label);
133
+ else if (!table.has(value))
134
+ table.set(value, value);
135
+ });
136
+ if (table.size === 0)
27
137
  return undefined;
28
- return values.map((value) => ({ value, label: value }));
138
+ return [...table].map(([value, label]) => ({ value, label }));
139
+ }
140
+ /**
141
+ * The category's option TREE, adopted whole for a `hierarchical_select` that
142
+ * stored none — see {@link TREE_VALUED}.
143
+ *
144
+ * Nothing is merged and nothing is rewritten: the tree is the category's
145
+ * structure, and this projection has no per-level snapshot with which to
146
+ * disagree about it.
147
+ */
148
+ function adoptedTree(dao, config, categoryDef) {
149
+ if (typeof dao.type !== "string" || !TREE_VALUED.has(dao.type))
150
+ return undefined;
151
+ if (Array.isArray(config["options"]))
152
+ return undefined;
153
+ return declaredOptions(categoryDef);
29
154
  }
30
155
  /**
31
156
  * One DAO row → the definition/value pair the display half consumes.
@@ -35,7 +160,11 @@ function synthesizedOptions(dao, config) {
35
160
  * is a malformed record, and a synthesized index would key a badge to a
36
161
  * position that changes whenever the category does.
37
162
  */
38
- export function featureFromDao(dao) {
163
+ export function featureFromDao(dao, source = {}) {
164
+ return featureView(dao, categoryDefs(source));
165
+ }
166
+ /** The work of {@link featureFromDao}, against an already-built index. */
167
+ function featureView(dao, defs) {
39
168
  if (typeof dao.slug !== "string" || dao.slug.length === 0)
40
169
  return undefined;
41
170
  const config = {};
@@ -43,7 +172,8 @@ export function featureFromDao(dao) {
43
172
  if (!ENVELOPE.has(key))
44
173
  config[key] = value;
45
174
  }
46
- const options = synthesizedOptions(dao, config);
175
+ const categoryDef = categoryDefFor(dao, defs);
176
+ const options = selectOptions(dao, config, categoryDef) ?? adoptedTree(dao, config, categoryDef);
47
177
  if (options !== undefined)
48
178
  config["options"] = options;
49
179
  const feature = {
@@ -65,10 +195,11 @@ export function featureFromDao(dao) {
65
195
  * rows are dropped HERE, in one place, and counted by {@link
66
196
  * unreadableFeatureCount} so a skin can say how many rather than pretend the
67
197
  * listing had fewer attributes. */
68
- export function featuresFromDaoList(daos) {
198
+ export function featuresFromDaoList(daos, source = {}) {
199
+ const defs = categoryDefs(source);
69
200
  const out = [];
70
201
  for (const dao of daos ?? []) {
71
- const view = featureFromDao(dao);
202
+ const view = featureView(dao, defs);
72
203
  if (view !== undefined)
73
204
  out.push(view);
74
205
  }
@@ -1 +1 @@
1
- {"version":3,"file":"features.js","sourceRoot":"","sources":["../../src/model/features.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"features.js","sourceRoot":"","sources":["../../src/model/features.ts"],"names":[],"mappings":"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"}
@@ -73,6 +73,20 @@ export declare const TITLE_FIELD = "title";
73
73
  export declare const PRICE_FIELD = "price";
74
74
  export declare const IMAGES_FIELD = "images";
75
75
  export declare const CATEGORY_FIELD = "category_id";
76
+ /** The coordinate pair, as one control: a latitude alone is not a place. */
77
+ export declare const LOCATION_FIELD = "location";
78
+ /**
79
+ * The composer's OWN controls, in the order the draft declares them.
80
+ *
81
+ * The mirror is a `Record`, and a record has no order worth trusting — its
82
+ * feature refusals happen to come first because of a spread. "Which field is
83
+ * the first unsatisfied one?" is a question a person asks about a FORM, so the
84
+ * answer is written down as a list rather than read off an object: the
85
+ * category (nothing else can be answered until it is chosen), then the
86
+ * listing's own fields, then — appended by the caller — the category's
87
+ * features in the order the schema declares them.
88
+ */
89
+ export declare const LISTING_FIELD_ORDER: readonly string[];
76
90
  /**
77
91
  * The listing-level half of the mirror: everything that is not a feature
78
92
  * value. Returns refusals keyed by control, empty when nothing is wrong.
@@ -116,6 +130,24 @@ export type PublishRefusal = {
116
130
  * `error.400.image_required` under a feature control.
117
131
  */
118
132
  export declare function publishRefusal(thrown: unknown): PublishRefusal;
133
+ /**
134
+ * A per-field refusal in the ORDINARY envelope → the control it belongs to.
135
+ *
136
+ * `save-draft` and `create` do not answer a batch: DRF's field validation
137
+ * raises, and stapel-core's handler folds it into one envelope carrying
138
+ * `params.field` — the field name, and often the ONLY thing in the response
139
+ * that says what went wrong, because a DRF code the registry does not know
140
+ * (`max_decimal_places`, say) collapses to the generic
141
+ * `error.400.validation_error`, whose sentence is "Validation error" and
142
+ * nothing else.
143
+ *
144
+ * So the field name is the payload. Put on the control, it is the difference
145
+ * between a red banner the person cannot act on and a red field they can.
146
+ * Returns `{}` for anything that names no field, or names one this composer
147
+ * does not draw — a banner is right for those, and a refusal routed to a
148
+ * control that does not exist would vanish.
149
+ */
150
+ export declare function envelopeFieldErrors(thrown: unknown): Readonly<Record<string, FlowError>>;
119
151
  /**
120
152
  * A server batch → refusals keyed by CONTROL.
121
153
  *
@@ -1 +1 @@
1
- {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/model/validation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,OAAO,EAAE,cAAc,EAAoB,MAAM,cAAc,CAAC;AAChE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EACV,UAAU,EACV,WAAW,EACX,uBAAuB,EACvB,qBAAqB,EACtB,MAAM,0BAA0B,CAAC;AAOlC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAErD;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB;IACjC,mDAAmD;IACnD,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,mDAAmD;IACnD,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC;2EACuE;IACvE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B;;;qEAGiE;IACjE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;;;oEAGgE;IAChE,QAAQ,CAAC,qBAAqB,EAAE,OAAO,CAAC;CACzC;AAED,eAAO,MAAM,oBAAoB,EAAE,kBAMlC,CAAC;AAEF;;4EAE4E;AAC5E,eAAO,MAAM,iBAAiB,gBAAgB,CAAC;AAC/C,eAAO,MAAM,WAAW,UAAU,CAAC;AACnC,eAAO,MAAM,WAAW,UAAU,CAAC;AACnC,eAAO,MAAM,YAAY,WAAW,CAAC;AACrC,eAAO,MAAM,cAAc,gBAAgB,CAAC;AAU5C;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,kBAAkB,EAC1B,MAAM,EAAE,kBAAkB,GACzB,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAmDrC;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CACzB,MAAM,EAAE,kBAAkB,EAC1B,QAAQ,EAAE,SAAS,UAAU,EAAE,EAC/B,WAAW,EAAE,WAAW,EACxB,MAAM,EAAE,kBAAkB,GACzB,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAKrC;AAED;+EAC+E;AAC/E,wBAAgB,YAAY,CAAC,KAAK,EAAE,qBAAqB,GAAG,OAAO,CAElE;AAQD,0CAA0C;AAC1C,MAAM,MAAM,cAAc,GACtB;IACE,wEAAwE;IACxE,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;IAC/B,QAAQ,CAAC,KAAK,EAAE,qBAAqB,CAAC;IACtC,QAAQ,CAAC,WAAW,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC;CAC3D,GACD;IACE;iEAC6D;IAC7D,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;CAChC,CAAC;AAEN;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,OAAO,GAAG,cAAc,CAoB9D;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,qBAAqB,GAC3B,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAErC;AAED;qEACqE;AACrE,wBAAgB,aAAa,CAC3B,KAAK,EAAE,qBAAqB,GAC3B,SAAS,uBAAuB,EAAE,CAEpC"}
1
+ {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/model/validation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,OAAO,EAAE,cAAc,EAAoB,MAAM,cAAc,CAAC;AAChE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EACV,UAAU,EACV,WAAW,EACX,uBAAuB,EACvB,qBAAqB,EACtB,MAAM,0BAA0B,CAAC;AAOlC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAErD;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB;IACjC,mDAAmD;IACnD,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,mDAAmD;IACnD,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC;2EACuE;IACvE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B;;;qEAGiE;IACjE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;;;oEAGgE;IAChE,QAAQ,CAAC,qBAAqB,EAAE,OAAO,CAAC;CACzC;AAED,eAAO,MAAM,oBAAoB,EAAE,kBAMlC,CAAC;AAEF;;4EAE4E;AAC5E,eAAO,MAAM,iBAAiB,gBAAgB,CAAC;AAC/C,eAAO,MAAM,WAAW,UAAU,CAAC;AACnC,eAAO,MAAM,WAAW,UAAU,CAAC;AACnC,eAAO,MAAM,YAAY,WAAW,CAAC;AACrC,eAAO,MAAM,cAAc,gBAAgB,CAAC;AAC5C,4EAA4E;AAC5E,eAAO,MAAM,cAAc,aAAa,CAAC;AAEzC;;;;;;;;;;GAUG;AACH,eAAO,MAAM,mBAAmB,EAAE,SAAS,MAAM,EAOhD,CAAC;AAiCF;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,kBAAkB,EAC1B,MAAM,EAAE,kBAAkB,GACzB,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAmDrC;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CACzB,MAAM,EAAE,kBAAkB,EAC1B,QAAQ,EAAE,SAAS,UAAU,EAAE,EAC/B,WAAW,EAAE,WAAW,EACxB,MAAM,EAAE,kBAAkB,GACzB,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAKrC;AAED;+EAC+E;AAC/E,wBAAgB,YAAY,CAAC,KAAK,EAAE,qBAAqB,GAAG,OAAO,CAElE;AAQD,0CAA0C;AAC1C,MAAM,MAAM,cAAc,GACtB;IACE,wEAAwE;IACxE,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;IAC/B,QAAQ,CAAC,KAAK,EAAE,qBAAqB,CAAC;IACtC,QAAQ,CAAC,WAAW,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC;CAC3D,GACD;IACE;iEAC6D;IAC7D,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;CAChC,CAAC;AAEN;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,OAAO,GAAG,cAAc,CAoB9D;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,OAAO,GACd,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAiBrC;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,qBAAqB,GAC3B,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAErC;AAED;qEACqE;AACrE,wBAAgB,aAAa,CAC3B,KAAK,EAAE,qBAAqB,GAC3B,SAAS,uBAAuB,EAAE,CAEpC"}
@@ -53,6 +53,49 @@ export const TITLE_FIELD = "title";
53
53
  export const PRICE_FIELD = "price";
54
54
  export const IMAGES_FIELD = "images";
55
55
  export const CATEGORY_FIELD = "category_id";
56
+ /** The coordinate pair, as one control: a latitude alone is not a place. */
57
+ export const LOCATION_FIELD = "location";
58
+ /**
59
+ * The composer's OWN controls, in the order the draft declares them.
60
+ *
61
+ * The mirror is a `Record`, and a record has no order worth trusting — its
62
+ * feature refusals happen to come first because of a spread. "Which field is
63
+ * the first unsatisfied one?" is a question a person asks about a FORM, so the
64
+ * answer is written down as a list rather than read off an object: the
65
+ * category (nothing else can be answered until it is chosen), then the
66
+ * listing's own fields, then — appended by the caller — the category's
67
+ * features in the order the schema declares them.
68
+ */
69
+ export const LISTING_FIELD_ORDER = [
70
+ CATEGORY_FIELD,
71
+ TITLE_FIELD,
72
+ DESCRIPTION_FIELD,
73
+ PRICE_FIELD,
74
+ LOCATION_FIELD,
75
+ IMAGES_FIELD,
76
+ ];
77
+ /**
78
+ * The API's own field names → the control that holds them.
79
+ *
80
+ * The draft serializer writes `*_draft` columns, and the two coordinates are
81
+ * one field on screen. Without this table a per-field 400 has nowhere to land
82
+ * and becomes a banner nobody can act on — which is the whole of blocker C2's
83
+ * second half: a save refused for `lat_draft` painted "Validation error" over
84
+ * the footer while the location control, the only thing the person could have
85
+ * changed, stayed clean.
86
+ */
87
+ const CONTROL_OF_API_FIELD = {
88
+ title_draft: TITLE_FIELD,
89
+ description_draft: DESCRIPTION_FIELD,
90
+ price_draft: PRICE_FIELD,
91
+ images_draft: IMAGES_FIELD,
92
+ category_id: CATEGORY_FIELD,
93
+ lat_draft: LOCATION_FIELD,
94
+ lon_draft: LOCATION_FIELD,
95
+ location_id_draft: LOCATION_FIELD,
96
+ location_label_draft: LOCATION_FIELD,
97
+ stock_quantity: "stockQuantity",
98
+ };
56
99
  /** A client-side refusal. `status: 0` on purpose: a rule this build applied
57
100
  * must never be indistinguishable from one that came over the wire. */
58
101
  function mirrored(code, params = {}) {
@@ -111,7 +154,7 @@ export function mirrorListingFields(values, limits) {
111
154
  const hasLat = lat !== null && lat.length > 0;
112
155
  const hasLon = lon !== null && lon.length > 0;
113
156
  if (hasLat !== hasLon) {
114
- out["location"] = mirrored(LISTINGS_I18N_KEYS.composeGeoIncomplete);
157
+ out[LOCATION_FIELD] = mirrored(LISTINGS_I18N_KEYS.composeGeoIncomplete);
115
158
  }
116
159
  return out;
117
160
  }
@@ -168,6 +211,44 @@ export function publishRefusal(thrown) {
168
211
  }),
169
212
  };
170
213
  }
214
+ /**
215
+ * A per-field refusal in the ORDINARY envelope → the control it belongs to.
216
+ *
217
+ * `save-draft` and `create` do not answer a batch: DRF's field validation
218
+ * raises, and stapel-core's handler folds it into one envelope carrying
219
+ * `params.field` — the field name, and often the ONLY thing in the response
220
+ * that says what went wrong, because a DRF code the registry does not know
221
+ * (`max_decimal_places`, say) collapses to the generic
222
+ * `error.400.validation_error`, whose sentence is "Validation error" and
223
+ * nothing else.
224
+ *
225
+ * So the field name is the payload. Put on the control, it is the difference
226
+ * between a red banner the person cannot act on and a red field they can.
227
+ * Returns `{}` for anything that names no field, or names one this composer
228
+ * does not draw — a banner is right for those, and a refusal routed to a
229
+ * control that does not exist would vanish.
230
+ */
231
+ export function envelopeFieldErrors(thrown) {
232
+ if (!isStapelApiError(thrown))
233
+ return {};
234
+ const named = thrown.params["field"];
235
+ if (typeof named !== "string" || named.length === 0)
236
+ return {};
237
+ const control = CONTROL_OF_API_FIELD[named];
238
+ if (control === undefined)
239
+ return {};
240
+ return {
241
+ [control]: {
242
+ code: thrown.code,
243
+ // `field` is the fleet's routing param; the control key is what a
244
+ // sentence should name, not the column the server happened to use.
245
+ params: { ...thrown.params, field: control },
246
+ status: thrown.status,
247
+ message: thrown.message,
248
+ language: thrown.language,
249
+ },
250
+ };
251
+ }
171
252
  /**
172
253
  * A server batch → refusals keyed by CONTROL.
173
254
  *
@@ -1 +1 @@
1
- {"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/model/validation.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/model/validation.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/nav/manifest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAE7C;;iEAEiE;AACjE,eAAO,MAAM,eAAe,iBAAiB,CAAC;AAE9C,eAAO,MAAM,UAAU,EAAE,SAAS,QAAQ,EAkDzC,CAAC"}
1
+ {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/nav/manifest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAE7C;;iEAEiE;AACjE,eAAO,MAAM,eAAe,iBAAiB,CAAC;AAE9C,eAAO,MAAM,UAAU,EAAE,SAAS,QAAQ,EAoDzC,CAAC"}
@@ -18,6 +18,7 @@ export const navEntries = [
18
18
  {
19
19
  id: "listings.compose",
20
20
  labelKey: "listings.nav.compose",
21
+ shortLabelKey: "listings.nav.compose.short",
21
22
  icon: "PlusOutlined",
22
23
  route: { path: "/new" },
23
24
  component: { export: "ListingComposerPage", subpath: "default" },
@@ -31,6 +32,7 @@ export const navEntries = [
31
32
  // Relative path: a child of the container's `/account` layout route.
32
33
  id: "listings.mine",
33
34
  labelKey: "listings.nav.mine",
35
+ shortLabelKey: "listings.nav.mine.short",
34
36
  icon: "ProfileOutlined",
35
37
  route: { path: "listings" },
36
38
  component: { export: "MyListingsPane", subpath: "default" },