v0.9.1
This commit is contained in:
parent
0129c5963c
commit
a810312f01
@ -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",
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@erp/auth",
|
||||
"version": "0.9.0",
|
||||
"version": "0.9.1",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"sideEffects": false,
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@erp/catalogs",
|
||||
"description": "Catalogs module",
|
||||
"version": "0.9.0",
|
||||
"version": "0.9.1",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"sideEffects": false,
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@erp/companies",
|
||||
"description": "Companies module",
|
||||
"version": "0.9.0",
|
||||
"version": "0.9.1",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"sideEffects": false,
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@erp/core",
|
||||
"version": "0.9.0",
|
||||
"version": "0.9.1",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"sideEffects": false,
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@erp/customer-invoices",
|
||||
"version": "0.9.0",
|
||||
"version": "0.9.1",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"sideEffects": false,
|
||||
|
||||
@ -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<Result<Omit<IProformaCreateProps, "invoiceNumber">, Error>> {
|
||||
): Promise<Result<Omit<IProformaCreateProps, "proformaReference">, 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,
|
||||
});
|
||||
}
|
||||
|
||||
@ -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<CustomerSelectionOption | null>(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<ProformaCreateForm>) => {
|
||||
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.")
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
@ -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,
|
||||
};
|
||||
};
|
||||
|
||||
@ -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<ProformaUpdateForm>) => {
|
||||
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.")
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
@ -230,6 +230,14 @@ export const useUpdateProformaItemsController = ({
|
||||
);
|
||||
|
||||
const itemErrors = React.useMemo<ProformaItemError[]>(() => {
|
||||
//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 ?? {});
|
||||
|
||||
@ -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) => {
|
||||
|
||||
@ -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 (
|
||||
<FormSectionCard
|
||||
className={cn(itemErrors.length ? "bg-red-100" : "")}
|
||||
disabled={disabled}
|
||||
icon={<ListIcon className="size-3" />}
|
||||
title={t("form_groups.items.title", "Líneas de detalle")}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@erp/customers",
|
||||
"description": "Customers",
|
||||
"version": "0.9.0",
|
||||
"version": "0.9.1",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"sideEffects": false,
|
||||
|
||||
@ -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
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@erp/factuges",
|
||||
"version": "0.9.0",
|
||||
"version": "0.9.1",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"sideEffects": false,
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@erp/identity",
|
||||
"description": "Identity module",
|
||||
"version": "0.9.0",
|
||||
"version": "0.9.1",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"sideEffects": false,
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@erp/suppliers",
|
||||
"description": "Suppliers",
|
||||
"version": "0.9.0",
|
||||
"version": "0.9.1",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"sideEffects": false,
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "uecko-erp-2025",
|
||||
"private": true,
|
||||
"version": "0.9.0",
|
||||
"version": "0.9.1",
|
||||
"workspaces": [
|
||||
"apps/*",
|
||||
"modules/*",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@repo/i18next",
|
||||
"version": "0.9.0",
|
||||
"version": "0.9.1",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@repo/rdx-criteria",
|
||||
"version": "0.9.0",
|
||||
"version": "0.9.1",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"sideEffects": false,
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@repo/rdx-ddd",
|
||||
"version": "0.9.0",
|
||||
"version": "0.9.1",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"sideEffects": false,
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@repo/rdx-logger",
|
||||
"version": "0.9.0",
|
||||
"version": "0.9.1",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"sideEffects": false,
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@repo/rdx-ui",
|
||||
"version": "0.9.0",
|
||||
"version": "0.9.1",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"sideEffects": false,
|
||||
|
||||
@ -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 = <T extends FieldValues>(form: UseFormReturn<T>) => {
|
||||
const errors = form.formState.errors;
|
||||
export const focusFirstInputFormError = <T extends FieldValues>(
|
||||
errors: FieldErrors<T>,
|
||||
form: UseFormReturn<T>
|
||||
) => {
|
||||
const firstKey = Object.keys(errors)[0] as keyof T | undefined;
|
||||
|
||||
if (firstKey) {
|
||||
|
||||
@ -0,0 +1,17 @@
|
||||
import type { FieldErrors, FieldValues, UseFormReturn } from "react-hook-form";
|
||||
|
||||
export const getFirstFormErrorMessage = <T extends FieldValues>(
|
||||
errors: FieldErrors<T>,
|
||||
form: UseFormReturn<T>
|
||||
) => {
|
||||
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;
|
||||
};
|
||||
@ -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";
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@repo/rdx-utils",
|
||||
"version": "0.9.0",
|
||||
"version": "0.9.1",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"sideEffects": false,
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@repo/shadcn-ui",
|
||||
"version": "0.9.0",
|
||||
"version": "0.9.1",
|
||||
"type": "module",
|
||||
"private": true,
|
||||
"exports": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@repo/typescript-config",
|
||||
"version": "0.9.0",
|
||||
"version": "0.9.1",
|
||||
"private": true,
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user