@open-mercato/core 0.4.9-develop-b2b88cde69 → 0.4.9-develop-d1d38e26fb

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.
@@ -2,7 +2,11 @@ import { z } from "zod";
2
2
  import { slugify } from "@open-mercato/shared/lib/slugify";
3
3
  import { parseObjectLike } from "@open-mercato/shared/lib/json/parseObjectLike";
4
4
  import type { ReferenceUnitCode } from "@open-mercato/shared/lib/units/unitCodes";
5
- import type { CatalogProductOptionSchema } from "../../data/types";
5
+ import {
6
+ CATALOG_CONFIGURABLE_PRODUCT_TYPES,
7
+ type CatalogProductOptionSchema,
8
+ type CatalogProductType,
9
+ } from "../../data/types";
6
10
  import type { ProductMediaItem } from "./ProductMediaManager";
7
11
 
8
12
  export { slugify };
@@ -83,6 +87,8 @@ export type ProductFormValues = {
83
87
  title: string;
84
88
  subtitle: string;
85
89
  handle: string;
90
+ sku: string;
91
+ productType: CatalogProductType;
86
92
  description: string;
87
93
  useMarkdown: boolean;
88
94
  taxRateId: string | null;
@@ -139,6 +145,16 @@ export const productFormSchema = z
139
145
  )
140
146
  .max(150)
141
147
  .optional(),
148
+ sku: z
149
+ .string()
150
+ .trim()
151
+ .regex(
152
+ /^[A-Za-z0-9\-_\.]*$/,
153
+ "catalog.products.validation.skuFormat",
154
+ )
155
+ .max(191)
156
+ .optional(),
157
+ productType: z.string().optional(),
142
158
  description: z.string().optional(),
143
159
  useMarkdown: z.boolean().optional(),
144
160
  taxRateId: z.string().uuid().nullable().optional(),
@@ -216,6 +232,8 @@ export const BASE_INITIAL_VALUES: ProductFormValues = {
216
232
  title: "",
217
233
  subtitle: "",
218
234
  handle: "",
235
+ sku: "",
236
+ productType: "simple",
219
237
  description: "",
220
238
  useMarkdown: false,
221
239
  mediaDraftId: "",
@@ -245,6 +263,9 @@ export const BASE_INITIAL_VALUES: ProductFormValues = {
245
263
  optionSchemaId: null,
246
264
  };
247
265
 
266
+ export const isConfigurableProductType = (type: string): boolean =>
267
+ (CATALOG_CONFIGURABLE_PRODUCT_TYPES as readonly string[]).includes(type);
268
+
248
269
  export const createInitialProductFormValues = (): ProductFormValues => ({
249
270
  ...BASE_INITIAL_VALUES,
250
271
  mediaDraftId: createLocalId(),
@@ -180,7 +180,7 @@ const productBaseSchema = scoped.extend({
180
180
  title: z.string().trim().min(1).max(255),
181
181
  subtitle: z.string().trim().max(255).optional(),
182
182
  description: z.string().trim().max(4000).optional(),
183
- sku: skuSchema.optional(),
183
+ sku: skuSchema.nullable().optional(),
184
184
  handle: handleSchema.optional(),
185
185
  taxRateId: uuid().nullable().optional(),
186
186
  taxRate: z.coerce.number().min(0).max(100).optional().nullable(),
@@ -245,6 +245,7 @@
245
245
  "catalog.products.create.organize.title": "Kategorisieren",
246
246
  "catalog.products.create.placeholders.description": "Beschreibe das Produkt...",
247
247
  "catalog.products.create.placeholders.handle": "z.B. sommer-sneaker",
248
+ "catalog.products.create.placeholders.sku": "z.B. PROD-001",
248
249
  "catalog.products.create.placeholders.subtitle": "Optionaler Untertitel",
249
250
  "catalog.products.create.placeholders.title": "z.B. Sommer-Sneaker",
250
251
  "catalog.products.create.pricing.addPrice": "Preis hinzufügen",
@@ -288,6 +289,7 @@
288
289
  "catalog.products.create.seoWidget.titleLabel": "Titel ({{count}} Zeichen)",
289
290
  "catalog.products.create.seoWidget.tooLong": "Zu lang",
290
291
  "catalog.products.create.seoWidget.tooShort": "Zu kurz",
292
+ "catalog.products.create.skuHelp": "Eindeutige Produktkennung. Buchstaben, Zahlen, Bindestriche, Unterstriche, Punkte.",
291
293
  "catalog.products.create.steps.continue": "Weiter",
292
294
  "catalog.products.create.steps.general": "Allgemeine Daten",
293
295
  "catalog.products.create.steps.organize": "Organisieren",
@@ -518,6 +520,7 @@
518
520
  "catalog.products.validation.baseUnitRequired": "Basiseinheit ist erforderlich, wenn eine Standard-Verkaufseinheit gesetzt ist.",
519
521
  "catalog.products.validation.handleFormat": "Handle darf nur Kleinbuchstaben, Ziffern, Bindestriche oder Unterstriche enthalten.",
520
522
  "catalog.products.validation.referenceUnitRequired": "Referenzeinheit ist erforderlich, wenn die Grundpreisanzeige aktiviert ist.",
523
+ "catalog.products.validation.skuFormat": "SKU darf Buchstaben, Zahlen, Bindestriche, Unterstriche oder Punkte enthalten.",
521
524
  "catalog.products.validation.titleRequired": "Titel ist erforderlich.",
522
525
  "catalog.search.badge.category": "Kategorie",
523
526
  "catalog.search.badge.offer": "Kanalangebot",
@@ -245,6 +245,7 @@
245
245
  "catalog.products.create.organize.title": "Categorize",
246
246
  "catalog.products.create.placeholders.description": "Describe the product...",
247
247
  "catalog.products.create.placeholders.handle": "e.g., summer-sneaker",
248
+ "catalog.products.create.placeholders.sku": "e.g., PROD-001",
248
249
  "catalog.products.create.placeholders.subtitle": "Optional subtitle",
249
250
  "catalog.products.create.placeholders.title": "e.g., Summer sneaker",
250
251
  "catalog.products.create.pricing.addPrice": "Add price",
@@ -288,6 +289,7 @@
288
289
  "catalog.products.create.seoWidget.titleLabel": "Title ({{count}} chars)",
289
290
  "catalog.products.create.seoWidget.tooLong": "Too long",
290
291
  "catalog.products.create.seoWidget.tooShort": "Too short",
292
+ "catalog.products.create.skuHelp": "Unique product identifier. Letters, numbers, hyphens, underscores, periods.",
291
293
  "catalog.products.create.steps.continue": "Continue",
292
294
  "catalog.products.create.steps.general": "General data",
293
295
  "catalog.products.create.steps.organize": "Organize",
@@ -518,6 +520,7 @@
518
520
  "catalog.products.validation.baseUnitRequired": "Base unit is required when a default sales unit is set.",
519
521
  "catalog.products.validation.handleFormat": "Handle must include lowercase letters, digits, hyphen, or underscore.",
520
522
  "catalog.products.validation.referenceUnitRequired": "Reference unit is required when unit price display is enabled.",
523
+ "catalog.products.validation.skuFormat": "SKU may include letters, numbers, hyphen, underscore, or period.",
521
524
  "catalog.products.validation.titleRequired": "Title is required.",
522
525
  "catalog.search.badge.category": "Category",
523
526
  "catalog.search.badge.offer": "Channel Offer",
@@ -245,6 +245,7 @@
245
245
  "catalog.products.create.organize.title": "Categorizar",
246
246
  "catalog.products.create.placeholders.description": "Describe el producto...",
247
247
  "catalog.products.create.placeholders.handle": "ej. zapatilla-verano",
248
+ "catalog.products.create.placeholders.sku": "ej., PROD-001",
248
249
  "catalog.products.create.placeholders.subtitle": "Subtítulo opcional",
249
250
  "catalog.products.create.placeholders.title": "ej. Zapatilla de verano",
250
251
  "catalog.products.create.pricing.addPrice": "Añadir precio",
@@ -288,6 +289,7 @@
288
289
  "catalog.products.create.seoWidget.titleLabel": "Título ({{count}} caracteres)",
289
290
  "catalog.products.create.seoWidget.tooLong": "Muy largo",
290
291
  "catalog.products.create.seoWidget.tooShort": "Muy corto",
292
+ "catalog.products.create.skuHelp": "Identificador único del producto. Letras, números, guiones, guiones bajos, puntos.",
291
293
  "catalog.products.create.steps.continue": "Continuar",
292
294
  "catalog.products.create.steps.general": "Datos generales",
293
295
  "catalog.products.create.steps.organize": "Organizar",
@@ -518,6 +520,7 @@
518
520
  "catalog.products.validation.baseUnitRequired": "La unidad base es obligatoria cuando se establece una unidad de venta predeterminada.",
519
521
  "catalog.products.validation.handleFormat": "El identificador solo puede contener letras minúsculas, dígitos, guiones o guiones bajos.",
520
522
  "catalog.products.validation.referenceUnitRequired": "La unidad de referencia es obligatoria cuando la visualización del precio unitario está activada.",
523
+ "catalog.products.validation.skuFormat": "El SKU puede incluir letras, números, guión, guión bajo o punto.",
521
524
  "catalog.products.validation.titleRequired": "El título es obligatorio.",
522
525
  "catalog.search.badge.category": "Categoría",
523
526
  "catalog.search.badge.offer": "Oferta de canal",
@@ -245,6 +245,7 @@
245
245
  "catalog.products.create.organize.title": "Kategoryzuj",
246
246
  "catalog.products.create.placeholders.description": "Opisz produkt...",
247
247
  "catalog.products.create.placeholders.handle": "np. letnie-trampki",
248
+ "catalog.products.create.placeholders.sku": "np. PROD-001",
248
249
  "catalog.products.create.placeholders.subtitle": "Opcjonalny podtytuł",
249
250
  "catalog.products.create.placeholders.title": "np. Letnie trampki",
250
251
  "catalog.products.create.pricing.addPrice": "Dodaj cenę",
@@ -288,6 +289,7 @@
288
289
  "catalog.products.create.seoWidget.titleLabel": "Tytuł ({{count}} znaków)",
289
290
  "catalog.products.create.seoWidget.tooLong": "Za długi",
290
291
  "catalog.products.create.seoWidget.tooShort": "Za krótki",
292
+ "catalog.products.create.skuHelp": "Unikalny identyfikator produktu. Litery, cyfry, myślniki, podkreślenia, kropki.",
291
293
  "catalog.products.create.steps.continue": "Dalej",
292
294
  "catalog.products.create.steps.general": "Dane ogólne",
293
295
  "catalog.products.create.steps.organize": "Organizacja",
@@ -518,6 +520,7 @@
518
520
  "catalog.products.validation.baseUnitRequired": "Jednostka bazowa jest wymagana, gdy ustawiona jest domyślna jednostka sprzedaży.",
519
521
  "catalog.products.validation.handleFormat": "Identyfikator może zawierać tylko małe litery, cyfry, myślniki lub podkreślenia.",
520
522
  "catalog.products.validation.referenceUnitRequired": "Jednostka referencyjna jest wymagana, gdy wyświetlanie ceny jednostkowej jest włączone.",
523
+ "catalog.products.validation.skuFormat": "SKU może zawierać litery, cyfry, myślnik, podkreślenie lub kropkę.",
521
524
  "catalog.products.validation.titleRequired": "Tytuł jest wymagany.",
522
525
  "catalog.search.badge.category": "Kategoria",
523
526
  "catalog.search.badge.offer": "Oferta kanału",
@@ -106,7 +106,6 @@ export function exchangeRateGroups(
106
106
  required: false,
107
107
  description: t('exchangeRates.form.field.typeHelp'),
108
108
  options: [
109
- { value: '', label: t('exchangeRates.form.field.typeNone') },
110
109
  { value: 'buy', label: t('exchangeRates.form.field.typeBuy') },
111
110
  { value: 'sell', label: t('exchangeRates.form.field.typeSell') },
112
111
  ],