From a810312f0117886ebd42f90e5d8b94eb8bdae68f Mon Sep 17 00:00:00 2001 From: david Date: Wed, 15 Jul 2026 13:10:26 +0200 Subject: [PATCH] v0.9.1 --- apps/server/package.json | 2 +- apps/web/package.json | 2 +- modules/auth/package.json | 2 +- modules/catalogs/package.json | 2 +- modules/companies/package.json | 2 +- modules/core/package.json | 2 +- modules/customer-invoices/package.json | 2 +- .../proformas/services/proforma-creator.ts | 28 +++++---- .../use-create-proforma-controller.ts | 24 ++++--- ...roforma-to-proforma-update-form.adapter.ts | 62 ++++++++++++------- .../use-update-proforma-controller.ts | 18 +++--- .../use-update-proforma-items-controller.ts | 8 +++ .../entities/proforma-update-form.schema.ts | 5 +- .../editors/proforma-update-items-editor.tsx | 4 ++ modules/customers/package.json | 2 +- .../models/sequelize-customer.model.ts | 9 +-- modules/factuges/package.json | 2 +- modules/identity/package.json | 2 +- modules/supplier-invoices/package.json | 2 +- modules/supplier/package.json | 2 +- package.json | 2 +- packages/i18n/package.json | 2 +- packages/rdx-criteria/package.json | 2 +- packages/rdx-ddd/package.json | 2 +- packages/rdx-logger/package.json | 2 +- packages/rdx-ui/package.json | 2 +- .../forms/focus-first-input-form-error.ts | 8 ++- .../forms/get-first-form-error-message.ts | 17 +++++ packages/rdx-ui/src/helpers/forms/index.ts | 1 + packages/rdx-utils/package.json | 2 +- packages/shadcn-ui/package.json | 2 +- packages/typescript-config/package.json | 2 +- 32 files changed, 149 insertions(+), 77 deletions(-) create mode 100644 packages/rdx-ui/src/helpers/forms/get-first-form-error-message.ts diff --git a/apps/server/package.json b/apps/server/package.json index f1400aa5..c9e48a0f 100644 --- a/apps/server/package.json +++ b/apps/server/package.json @@ -1,6 +1,6 @@ { "name": "@erp/factuges-server", - "version": "0.9.0", + "version": "0.9.1", "private": true, "scripts": { "build": "tsup src/index.ts --config tsup.config.ts", diff --git a/apps/web/package.json b/apps/web/package.json index 48eb9827..c0ecdfce 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -1,7 +1,7 @@ { "name": "@erp/factuges-web", "private": true, - "version": "0.9.0", + "version": "0.9.1", "type": "module", "scripts": { "typecheck": "tsc -p tsconfig.json --noEmit", diff --git a/modules/auth/package.json b/modules/auth/package.json index 96e41fd0..5ec19879 100644 --- a/modules/auth/package.json +++ b/modules/auth/package.json @@ -1,6 +1,6 @@ { "name": "@erp/auth", - "version": "0.9.0", + "version": "0.9.1", "private": true, "type": "module", "sideEffects": false, diff --git a/modules/catalogs/package.json b/modules/catalogs/package.json index 381c9fb9..682209cc 100644 --- a/modules/catalogs/package.json +++ b/modules/catalogs/package.json @@ -1,7 +1,7 @@ { "name": "@erp/catalogs", "description": "Catalogs module", - "version": "0.9.0", + "version": "0.9.1", "private": true, "type": "module", "sideEffects": false, diff --git a/modules/companies/package.json b/modules/companies/package.json index cb452ffd..7ddb3588 100644 --- a/modules/companies/package.json +++ b/modules/companies/package.json @@ -1,7 +1,7 @@ { "name": "@erp/companies", "description": "Companies module", - "version": "0.9.0", + "version": "0.9.1", "private": true, "type": "module", "sideEffects": false, diff --git a/modules/core/package.json b/modules/core/package.json index 05d31b2a..212440b7 100644 --- a/modules/core/package.json +++ b/modules/core/package.json @@ -1,6 +1,6 @@ { "name": "@erp/core", - "version": "0.9.0", + "version": "0.9.1", "private": true, "type": "module", "sideEffects": false, diff --git a/modules/customer-invoices/package.json b/modules/customer-invoices/package.json index a65a13f8..6c89ea5a 100644 --- a/modules/customer-invoices/package.json +++ b/modules/customer-invoices/package.json @@ -1,6 +1,6 @@ { "name": "@erp/customer-invoices", - "version": "0.9.0", + "version": "0.9.1", "private": true, "type": "module", "sideEffects": false, diff --git a/modules/customer-invoices/src/api/application/proformas/services/proforma-creator.ts b/modules/customer-invoices/src/api/application/proformas/services/proforma-creator.ts index db7af722..4fe72ee2 100644 --- a/modules/customer-invoices/src/api/application/proformas/services/proforma-creator.ts +++ b/modules/customer-invoices/src/api/application/proformas/services/proforma-creator.ts @@ -1,5 +1,5 @@ import type { UniqueID } from "@repo/rdx-ddd"; -import { Result } from "@repo/rdx-utils"; +import { Maybe, Result } from "@repo/rdx-utils"; import { type IProformaCreateProps, @@ -55,11 +55,11 @@ export class ProformaCreator implements IProformaCreator { return Result.fail(numberResult.error); } - const invoiceNumber = numberResult.data; + const proformaReference = numberResult.data; // 2. Crear agregado const proformaResult = Proforma.create( - { ...resolvedProps.data, proformaReference: invoiceNumber, companyId }, + { ...resolvedProps.data, proformaReference, companyId }, id ); @@ -81,11 +81,17 @@ export class ProformaCreator implements IProformaCreator { private async resolveCreateProps( props: ProformaCreateInputProps - ): Promise, Error>> { + ): Promise, Error>> { + // TODO: Esto hay que cambiarlo en el futuro para buscar valores por defecto, desde la empresa o desde el cliente + const _newProps = { + ...props, + taxRegimeCode: props.taxRegimeCode.isNone() ? Maybe.some("01") : props.taxRegimeCode, + }; + // Tax Regime => comprobar que existe const taxRegimeResult = await this.deps.taxResolver.ensureTaxRegimeByCode({ - companyId: props.companyId, - code: props.taxRegimeCode, + companyId: _newProps.companyId, + code: _newProps.taxRegimeCode, }); if (taxRegimeResult.isFailure) { @@ -94,8 +100,8 @@ export class ProformaCreator implements IProformaCreator { // Payment method => comprobar que existe const paymentMethodResult = await this.deps.paymentResolver.ensurePaymentMethodById({ - companyId: props.companyId, - id: props.paymentMethodId, + companyId: _newProps.companyId, + id: _newProps.paymentMethodId, }); if (paymentMethodResult.isFailure) { @@ -107,8 +113,8 @@ export class ProformaCreator implements IProformaCreator { for (const item of props.items) { const taxes = await this.deps.taxResolver.ensureItemTaxes({ - companyId: props.companyId, - atDate: props.proformaDate, + companyId: _newProps.companyId, + atDate: _newProps.proformaDate, taxCodes: item.taxes, }); @@ -123,7 +129,7 @@ export class ProformaCreator implements IProformaCreator { } return Result.ok({ - ...props, + ..._newProps, items: resolvedItems, }); } diff --git a/modules/customer-invoices/src/web/proformas/create/controllers/use-create-proforma-controller.ts b/modules/customer-invoices/src/web/proformas/create/controllers/use-create-proforma-controller.ts index 982f6e9a..19b3a21c 100644 --- a/modules/customer-invoices/src/web/proformas/create/controllers/use-create-proforma-controller.ts +++ b/modules/customer-invoices/src/web/proformas/create/controllers/use-create-proforma-controller.ts @@ -8,6 +8,7 @@ import { } from "@repo/rdx-ddd"; import { focusFirstInputFormError, + getFirstFormErrorMessage, showErrorToast, showSuccessToast, showWarningToast, @@ -15,6 +16,7 @@ import { import { useEffect, useId, useMemo, useState } from "react"; import type { FieldErrors } from "react-hook-form"; +import { useTranslation } from "../../../i18n"; import type { Proforma } from "../../shared"; import { buildInvoiceSeriesSelectItems, @@ -42,6 +44,7 @@ const normalizeSubmitError = (error: unknown): Error | ValidationErrorCollection }; export const useCreateProformaController = (options?: UseCreateProformaControllerOptions) => { + const { t } = useTranslation(); const formId = useId(); const [selectedCustomer, setSelectedCustomer] = useState(null); @@ -70,9 +73,7 @@ export const useCreateProformaController = (options?: UseCreateProformaControlle const defaultSeries = useMemo(() => { const invoiceSeries = seriesQuery.data ?? []; - return ( - invoiceSeries.find((series) => series.isDefault)?.code ?? invoiceSeries[0]?.code ?? "" - ); + return invoiceSeries.find((series) => series.isDefault)?.code ?? invoiceSeries[0]?.code ?? ""; }, [seriesQuery.data]); useEffect(() => { @@ -140,8 +141,13 @@ export const useCreateProformaController = (options?: UseCreateProformaControlle if (isValidationErrorCollection(normalizedError)) { applyValidationErrorCollection(form, normalizedError); - focusFirstInputFormError(form); - showWarningToast("Revisa los campos", "Hay errores de validación en el formulario."); + focusFirstInputFormError(form.formState.errors, form); + const errorMessage = getFirstFormErrorMessage(form.formState.errors, form); + showWarningToast( + "Revisa los campos", + errorMessage ?? + t("forms.validation.message", "Hay errores de validación en el formulario.") + ); return; } @@ -149,8 +155,12 @@ export const useCreateProformaController = (options?: UseCreateProformaControlle } }, (_errors: FieldErrors) => { - focusFirstInputFormError(form); - showWarningToast("Revisa los campos", "Hay errores de validación en el formulario."); + focusFirstInputFormError(_errors, form); + const errorMessage = getFirstFormErrorMessage(_errors, form); + showWarningToast( + "Revisa los campos", + errorMessage ?? t("forms.validation.message", "Hay errores de validación en el formulario.") + ); } ); diff --git a/modules/customer-invoices/src/web/proformas/update/adapters/map-proforma-to-proforma-update-form.adapter.ts b/modules/customer-invoices/src/web/proformas/update/adapters/map-proforma-to-proforma-update-form.adapter.ts index dcbf629a..196a5d88 100644 --- a/modules/customer-invoices/src/web/proformas/update/adapters/map-proforma-to-proforma-update-form.adapter.ts +++ b/modules/customer-invoices/src/web/proformas/update/adapters/map-proforma-to-proforma-update-form.adapter.ts @@ -4,9 +4,13 @@ import { buildProformaUpdateDefault } from "../utils"; import { mapProformaItemsToProformaItemsUpdateForm } from "./map-proforma-items-to-proforma-items-update-form.adapter"; -interface FiscalDefaults { +interface FiscalState { taxMode: ProformaTaxMode; + hasTaxPercentage: boolean; + hasRecPercentage: boolean; + hasRetentionPercentage: boolean; + defaultTaxPercentage: number | null; defaultRecPercentage: number | null; defaultRetentionPercentage: number | null; @@ -18,7 +22,7 @@ interface FiscalDefaults { export const mapProformaToProformaUpdateForm = (proforma: Proforma): ProformaUpdateForm => { const proformaDefaults = buildProformaUpdateDefault(); - const fiscalDefaults = resolveFiscalDefaults(proforma, proformaDefaults); + const fiscalState = resolveFiscalState(proforma, proformaDefaults); return { proformaReference: proforma.proformaReference, @@ -40,18 +44,17 @@ export const mapProformaToProformaUpdateForm = (proforma: Proforma): ProformaUpd globalDiscountPercentage: proforma.globalDiscountPercentage ?? proformaDefaults.globalDiscountPercentage, - taxMode: fiscalDefaults.taxMode, + taxMode: fiscalState.taxMode, taxRegimeCode: proforma.taxRegimeCode ?? proformaDefaults.taxRegimeCode, - hasTaxPercentage: - fiscalDefaults.taxMode === "single" && fiscalDefaults.defaultTaxPercentage !== null, - taxPercentage: fiscalDefaults.defaultTaxPercentage, + hasTaxPercentage: fiscalState.hasTaxPercentage, + taxPercentage: fiscalState.defaultTaxPercentage, - hasRecPercentage: fiscalDefaults.defaultRecPercentage !== null, - recPercentage: fiscalDefaults.defaultRecPercentage, + hasRecPercentage: fiscalState.hasRecPercentage, + recPercentage: fiscalState.defaultRecPercentage, - hasRetentionPercentage: fiscalDefaults.defaultRetentionPercentage !== null, - retentionPercentage: fiscalDefaults.defaultRetentionPercentage, + hasRetentionPercentage: fiscalState.defaultRetentionPercentage !== null, + retentionPercentage: fiscalState.defaultRetentionPercentage, paymentMethodId: proforma.paymentMethodId, paymentTermId: proforma.paymentTermId, @@ -60,20 +63,26 @@ export const mapProformaToProformaUpdateForm = (proforma: Proforma): ProformaUpd }; }; -const resolveFiscalDefaults = ( +const resolveFiscalState = ( proforma: Proforma, proformaDefaults: ProformaUpdateForm -): FiscalDefaults => { +): FiscalState => { // Caso habitual: una sola combinación de impuestos if (proforma.taxes.length === 1) { const taxSummary = proforma.taxes[0]; + const hasTaxPercentage = taxSummary.ivaCode !== null; + const hasRecPercentage = taxSummary.recCode !== null; + const hasRetentionPercentage = taxSummary.retentionCode !== null; + return { taxMode: "single", - defaultTaxPercentage: taxSummary.ivaCode === null ? null : taxSummary.ivaPercentage, - defaultRecPercentage: taxSummary.recCode === null ? null : taxSummary.recPercentage, - defaultRetentionPercentage: - taxSummary.retentionCode === null ? null : taxSummary.retentionPercentage, + defaultTaxPercentage: hasTaxPercentage ? taxSummary.ivaPercentage : null, + defaultRecPercentage: hasRecPercentage ? taxSummary.recPercentage : null, + defaultRetentionPercentage: hasRetentionPercentage ? taxSummary.retentionPercentage : null, + hasTaxPercentage, + hasRecPercentage, + hasRetentionPercentage, }; } @@ -81,17 +90,26 @@ const resolveFiscalDefaults = ( if (proforma.taxes.length === 0) { return { taxMode: "single", - defaultTaxPercentage: proformaDefaults.taxPercentage, - defaultRecPercentage: proformaDefaults.recPercentage, - defaultRetentionPercentage: proformaDefaults.retentionPercentage, + defaultTaxPercentage: null, + defaultRecPercentage: null, + defaultRetentionPercentage: null, + hasTaxPercentage: false, + hasRecPercentage: false, + hasRetentionPercentage: false, }; } // Proforma con varias combinaciones de impuestos + const taxSummary = proforma.taxes[0]; + const hasRecPercentage = taxSummary.recCode !== null; + return { taxMode: "perLine", - defaultTaxPercentage: proformaDefaults.taxPercentage, - defaultRecPercentage: proformaDefaults.recPercentage, - defaultRetentionPercentage: proformaDefaults.retentionPercentage, + defaultTaxPercentage: null, + defaultRecPercentage: hasRecPercentage ? taxSummary.recPercentage : null, + defaultRetentionPercentage: null, + hasTaxPercentage: false, + hasRecPercentage, + hasRetentionPercentage: false, }; }; diff --git a/modules/customer-invoices/src/web/proformas/update/controllers/use-update-proforma-controller.ts b/modules/customer-invoices/src/web/proformas/update/controllers/use-update-proforma-controller.ts index a73b2c54..21ed529c 100644 --- a/modules/customer-invoices/src/web/proformas/update/controllers/use-update-proforma-controller.ts +++ b/modules/customer-invoices/src/web/proformas/update/controllers/use-update-proforma-controller.ts @@ -5,6 +5,7 @@ import type { CustomerSelectionOption } from "@erp/customers"; import { type ValidationErrorCollection, isValidationErrorCollection } from "@repo/rdx-ddd"; import { focusFirstInputFormError, + getFirstFormErrorMessage, showErrorToast, showSuccessToast, showWarningToast, @@ -14,7 +15,6 @@ import type { FieldErrors } from "react-hook-form"; import { useTranslation } from "../../../i18n"; import type { UpdateProformaByIdParams } from "../../shared"; -import type { Proforma } from "../../shared/entities"; import { buildInvoiceSeriesSelectItems, ensureCurrentValueInSelectItems, @@ -22,6 +22,7 @@ import { useProformaGetQuery, useProformaUpdateMutation, } from "../../shared"; +import type { Proforma } from "../../shared/entities"; import { mapProformaToProformaUpdateForm, mapProformaToSelectedCustomer } from "../adapters"; import { type ProformaUpdateForm, ProformaUpdateFormSchema } from "../entities"; import { @@ -147,8 +148,8 @@ export const useUpdateProformaController = ( if (!formHasAnyDirty(form.formState.dirtyFields)) { showWarningToast( - t("proformas.update.no_changes.title"), - t("proformas.update.no_changes.message") + t("pages.update.no_changes.title", "Sin cambios"), + t("pages.update.no_changes.message", "No has realizado ningún cambio.") ); return; } @@ -181,8 +182,8 @@ export const useUpdateProformaController = ( if (options?.successToasts !== false) { showSuccessToast( - t("proformas.update.success.title"), - t("proformas.update.success.message") + t("pages.update.success.title", "Guardado"), + t("pages.update.success.message", "Los cambios se han guardado correctamente.") ); } @@ -208,7 +209,7 @@ export const useUpdateProformaController = ( console.log("Errores de validación aplicados al form:", form.formState.errors); - focusFirstInputFormError(form); + focusFirstInputFormError(form.formState.errors, form); if (options?.errorToasts !== false) { showWarningToast( @@ -230,11 +231,12 @@ export const useUpdateProformaController = ( } }, (_errors: FieldErrors) => { - focusFirstInputFormError(form); + focusFirstInputFormError(_errors, form); + const errorMessage = getFirstFormErrorMessage(_errors, form); showWarningToast( t("forms.validation.title", "Revisa los campos"), - t("forms.validation.message", "Hay errores de validación en el formulario.") + errorMessage ?? t("forms.validation.message", "Hay errores de validación en el formulario.") ); } ); diff --git a/modules/customer-invoices/src/web/proformas/update/controllers/use-update-proforma-items-controller.ts b/modules/customer-invoices/src/web/proformas/update/controllers/use-update-proforma-items-controller.ts index a4f34463..9c6c5f5b 100644 --- a/modules/customer-invoices/src/web/proformas/update/controllers/use-update-proforma-items-controller.ts +++ b/modules/customer-invoices/src/web/proformas/update/controllers/use-update-proforma-items-controller.ts @@ -230,6 +230,14 @@ export const useUpdateProformaItemsController = ({ ); const itemErrors = React.useMemo(() => { + //console.log("itemErrors => ", errors.items); + if (!errors.items) return []; + + if (errors.items.root) { + return [errors.items.root]; + //console.error("Errores de validación en items.root:", errors.items.root); + } + if (!Array.isArray(errors.items)) return []; return errors.items.map((error) => error ?? {}); diff --git a/modules/customer-invoices/src/web/proformas/update/entities/proforma-update-form.schema.ts b/modules/customer-invoices/src/web/proformas/update/entities/proforma-update-form.schema.ts index eb077658..80c9ba17 100644 --- a/modules/customer-invoices/src/web/proformas/update/entities/proforma-update-form.schema.ts +++ b/modules/customer-invoices/src/web/proformas/update/entities/proforma-update-form.schema.ts @@ -19,6 +19,7 @@ import { ProformaItemUpdateFormSchema } from "./proforma-item-update-form.schema export const ProformaUpdateFormSchema = z .object({ + proformaReference: z.string(), series: z.string(), proformaDate: z.string().min(1), @@ -50,7 +51,9 @@ export const ProformaUpdateFormSchema = z paymentMethodId: z.string().nullable(), paymentTermId: z.string().nullable(), - items: z.array(ProformaItemUpdateFormSchema).min(1), + items: z + .array(ProformaItemUpdateFormSchema) + .min(1, "Debe haber al menos un item en la proforma"), }) .refine( (formValues) => { diff --git a/modules/customer-invoices/src/web/proformas/update/ui/editors/proforma-update-items-editor.tsx b/modules/customer-invoices/src/web/proformas/update/ui/editors/proforma-update-items-editor.tsx index 30869a14..6f630832 100644 --- a/modules/customer-invoices/src/web/proformas/update/ui/editors/proforma-update-items-editor.tsx +++ b/modules/customer-invoices/src/web/proformas/update/ui/editors/proforma-update-items-editor.tsx @@ -1,4 +1,5 @@ import { FormSectionCard } from "@repo/rdx-ui/components"; +import { cn } from "@repo/shadcn-ui/lib/utils"; import { ListIcon } from "lucide-react"; import type { ComponentProps } from "react"; @@ -24,10 +25,13 @@ export const ProformaUpdateItemsEditor = ({ ...props }: ProformaUpdateItemsEditorProps) => { const { t } = useTranslation(); + const { totals } = totalsCtrl; + const { itemErrors } = itemsCtrl; return ( } title={t("form_groups.items.title", "Líneas de detalle")} diff --git a/modules/customers/package.json b/modules/customers/package.json index 9a8ce29c..9cf99e93 100644 --- a/modules/customers/package.json +++ b/modules/customers/package.json @@ -1,7 +1,7 @@ { "name": "@erp/customers", "description": "Customers", - "version": "0.9.0", + "version": "0.9.1", "private": true, "type": "module", "sideEffects": false, diff --git a/modules/customers/src/api/infrastructure/persistence/sequelize/models/sequelize-customer.model.ts b/modules/customers/src/api/infrastructure/persistence/sequelize/models/sequelize-customer.model.ts index 5467914b..714537f1 100644 --- a/modules/customers/src/api/infrastructure/persistence/sequelize/models/sequelize-customer.model.ts +++ b/modules/customers/src/api/infrastructure/persistence/sequelize/models/sequelize-customer.model.ts @@ -274,12 +274,13 @@ export default (database: Sequelize) => { { name: "idx_company_idx", fields: ["id", "company_id"], unique: true }, // <- para consulta get { name: "idx_factuges", fields: ["factuges_id"], unique: true }, // <- para el proceso python - // Para búsquedas simples => se hace con el "CriteriaToSequelizeConverter" - /*{ - name: "ft_customer", + // Quiksearch => "CriteriaToSequelizeConverter" construye la sentencia SQL de búsqueda FULLTEXT + // a partir de este índice. Las columnas deben coincidir con los campos de búsqueda rápida definidos en el repositorio. + { + name: "idx_qs_customer", type: "FULLTEXT", fields: ["name", "trade_name", "reference", "tin", "email_primary", "mobile_primary"], - },*/ + }, ], whereMergeStrategy: "and", // <- cómo tratar el merge de un scope diff --git a/modules/factuges/package.json b/modules/factuges/package.json index 658c38bb..05feec4f 100644 --- a/modules/factuges/package.json +++ b/modules/factuges/package.json @@ -1,6 +1,6 @@ { "name": "@erp/factuges", - "version": "0.9.0", + "version": "0.9.1", "private": true, "type": "module", "sideEffects": false, diff --git a/modules/identity/package.json b/modules/identity/package.json index 9e508a63..4c55f3f5 100644 --- a/modules/identity/package.json +++ b/modules/identity/package.json @@ -1,7 +1,7 @@ { "name": "@erp/identity", "description": "Identity module", - "version": "0.9.0", + "version": "0.9.1", "private": true, "type": "module", "sideEffects": false, diff --git a/modules/supplier-invoices/package.json b/modules/supplier-invoices/package.json index 7999b781..b3a938c5 100644 --- a/modules/supplier-invoices/package.json +++ b/modules/supplier-invoices/package.json @@ -1,7 +1,7 @@ { "name": "@erp/supplier-invoices", "description": "Supplier invoices", - "version": "0.9.0", + "version": "0.9.1", "private": true, "type": "module", "sideEffects": false, diff --git a/modules/supplier/package.json b/modules/supplier/package.json index 84da3747..f5255cd0 100644 --- a/modules/supplier/package.json +++ b/modules/supplier/package.json @@ -1,7 +1,7 @@ { "name": "@erp/suppliers", "description": "Suppliers", - "version": "0.9.0", + "version": "0.9.1", "private": true, "type": "module", "sideEffects": false, diff --git a/package.json b/package.json index 55e52b9f..0b9761df 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "uecko-erp-2025", "private": true, - "version": "0.9.0", + "version": "0.9.1", "workspaces": [ "apps/*", "modules/*", diff --git a/packages/i18n/package.json b/packages/i18n/package.json index 648a0de8..cf506537 100644 --- a/packages/i18n/package.json +++ b/packages/i18n/package.json @@ -1,6 +1,6 @@ { "name": "@repo/i18next", - "version": "0.9.0", + "version": "0.9.1", "private": true, "type": "module", "scripts": { diff --git a/packages/rdx-criteria/package.json b/packages/rdx-criteria/package.json index f3458c56..6c9e6a14 100644 --- a/packages/rdx-criteria/package.json +++ b/packages/rdx-criteria/package.json @@ -1,6 +1,6 @@ { "name": "@repo/rdx-criteria", - "version": "0.9.0", + "version": "0.9.1", "private": true, "type": "module", "sideEffects": false, diff --git a/packages/rdx-ddd/package.json b/packages/rdx-ddd/package.json index 643b86da..44011479 100644 --- a/packages/rdx-ddd/package.json +++ b/packages/rdx-ddd/package.json @@ -1,6 +1,6 @@ { "name": "@repo/rdx-ddd", - "version": "0.9.0", + "version": "0.9.1", "private": true, "type": "module", "sideEffects": false, diff --git a/packages/rdx-logger/package.json b/packages/rdx-logger/package.json index 24e5e935..7350cc99 100644 --- a/packages/rdx-logger/package.json +++ b/packages/rdx-logger/package.json @@ -1,6 +1,6 @@ { "name": "@repo/rdx-logger", - "version": "0.9.0", + "version": "0.9.1", "private": true, "type": "module", "sideEffects": false, diff --git a/packages/rdx-ui/package.json b/packages/rdx-ui/package.json index c7a002be..3e2dc7e5 100644 --- a/packages/rdx-ui/package.json +++ b/packages/rdx-ui/package.json @@ -1,6 +1,6 @@ { "name": "@repo/rdx-ui", - "version": "0.9.0", + "version": "0.9.1", "private": true, "type": "module", "sideEffects": false, diff --git a/packages/rdx-ui/src/helpers/forms/focus-first-input-form-error.ts b/packages/rdx-ui/src/helpers/forms/focus-first-input-form-error.ts index 1dc35cef..5e1d7d23 100644 --- a/packages/rdx-ui/src/helpers/forms/focus-first-input-form-error.ts +++ b/packages/rdx-ui/src/helpers/forms/focus-first-input-form-error.ts @@ -1,7 +1,9 @@ -import type { FieldValues, Path, UseFormReturn } from "react-hook-form"; +import type { FieldErrors, FieldValues, Path, UseFormReturn } from "react-hook-form"; -export const focusFirstInputFormError = (form: UseFormReturn) => { - const errors = form.formState.errors; +export const focusFirstInputFormError = ( + errors: FieldErrors, + form: UseFormReturn +) => { const firstKey = Object.keys(errors)[0] as keyof T | undefined; if (firstKey) { diff --git a/packages/rdx-ui/src/helpers/forms/get-first-form-error-message.ts b/packages/rdx-ui/src/helpers/forms/get-first-form-error-message.ts new file mode 100644 index 00000000..c05118e9 --- /dev/null +++ b/packages/rdx-ui/src/helpers/forms/get-first-form-error-message.ts @@ -0,0 +1,17 @@ +import type { FieldErrors, FieldValues, UseFormReturn } from "react-hook-form"; + +export const getFirstFormErrorMessage = ( + errors: FieldErrors, + form: UseFormReturn +) => { + const firstKey = Object.keys(errors)[0] as keyof T | undefined; + const firstError = errors[firstKey] as + | { message?: string; root?: { message?: string } } + | undefined; + + return firstError?.message + ? firstError.message + : firstError?.root?.message + ? firstError.root?.message + : undefined; +}; diff --git a/packages/rdx-ui/src/helpers/forms/index.ts b/packages/rdx-ui/src/helpers/forms/index.ts index a9afeb23..79cc1364 100644 --- a/packages/rdx-ui/src/helpers/forms/index.ts +++ b/packages/rdx-ui/src/helpers/forms/index.ts @@ -1,2 +1,3 @@ export * from "./focus-first-input-form-error.ts"; +export * from "./get-first-form-error-message.ts"; export * from "./prevent-enter-key-submit-form.ts"; diff --git a/packages/rdx-utils/package.json b/packages/rdx-utils/package.json index 7333e149..e69cee91 100644 --- a/packages/rdx-utils/package.json +++ b/packages/rdx-utils/package.json @@ -1,6 +1,6 @@ { "name": "@repo/rdx-utils", - "version": "0.9.0", + "version": "0.9.1", "private": true, "type": "module", "sideEffects": false, diff --git a/packages/shadcn-ui/package.json b/packages/shadcn-ui/package.json index eb216ccd..1898ba3b 100644 --- a/packages/shadcn-ui/package.json +++ b/packages/shadcn-ui/package.json @@ -1,6 +1,6 @@ { "name": "@repo/shadcn-ui", - "version": "0.9.0", + "version": "0.9.1", "type": "module", "private": true, "exports": { diff --git a/packages/typescript-config/package.json b/packages/typescript-config/package.json index 68257ff2..bf31054d 100644 --- a/packages/typescript-config/package.json +++ b/packages/typescript-config/package.json @@ -1,6 +1,6 @@ { "name": "@repo/typescript-config", - "version": "0.9.0", + "version": "0.9.1", "private": true, "publishConfig": { "access": "public"