PROFORMAS ISSUE

This commit is contained in:
David Arranz 2026-04-05 22:17:11 +02:00
parent 994417e48f
commit b2dee4ae8b
21 changed files with 225 additions and 184 deletions

View File

@ -96,14 +96,30 @@
} }
}, },
"proformas": { "proformas": {
"issue_proforma_dialog": {
"title": "Issue to invoice",
"description": "Are you sure you want to issue an invoice from proforma {{reference}}?",
"warning": "This action will create a final invoice and the proforma will be marked as \"Issued\". It will no longer be editable or deletable.",
"confirm": "Issue invoice",
"submitting": "Issuing...",
"success_title": "Proforma successfully issued",
"success_description": "Proforma {{reference}} has been successfully issued to an invoice.",
"error_title": "Error issuing proforma",
"not_allowed_title": "Action not allowed",
"not_allowed_description": "Only proformas in \"Approved\" status can be issued.",
"unknown_error": "An unexpected error occurred"
},
"delete_proforma_dialog": { "delete_proforma_dialog": {
"title": "Delete proforma", "single_title": "Delete proforma {{reference}}",
"description": "Are you sure you want to delete proforma <strong>{{proformaRef}}</strong>? This action cannot be undone.", "single_description": "Are you sure you want to delete this proforma? This action cannot be undone.",
"cancel": "Cancel", "second_confirm_single_title": "Additional confirmation",
"delete": "Delete", "second_confirm_single_description": "You are about to delete the proforma. This action cannot be undone. Are you sure you want to continue?",
"multiple_description": "Are you sure you want to delete the {{total}} selected proformas? This action cannot be undone.",
"confirm_delete": "Confirm deletion",
"deleting": "Deleting...", "deleting": "Deleting...",
"success_title": "Proforma deleted", "cancel": "Cancel",
"error_title": "Error deleting proforma" "continue": "Delete",
"list_item": "Proforma {{reference}}"
} }
}, },
"pages": { "pages": {

View File

@ -96,20 +96,30 @@
} }
}, },
"proformas": { "proformas": {
"issue_proforma_dialog": {
"title": "Emitir a factura",
"description": "¿Seguro que quieres emitir la factura desde la proforma {{reference}}?",
"warning": "Esta acción creará una nueva factura definitiva y la proforma pasará al estado \"Emitida\", no pudiendo modificarse ni eliminarse posteriormente.",
"confirm": "Emitir factura",
"submitting": "Emitiendo...",
"success_title": "Proforma emitida correctamente",
"success_description": "La proforma {{reference}} se ha emitido a factura correctamente.",
"error_title": "Error al emitir la proforma",
"not_allowed_title": "Acción no permitida",
"not_allowed_description": "Solo se pueden emitir proformas en estado \"Aprobada\".",
"unknown_error": "Ha ocurrido un error inesperado",
"cancel": "Cancelar"
},
"delete_proforma_dialog": { "delete_proforma_dialog": {
"title": "Eliminar proforma",
"description": "¿Seguro que deseas eliminar la proforma <strong>{{proformaRef}}</strong>? Esta acción no se puede deshacer.",
"cancel": "Cancelar",
"delete": "Eliminar",
"deleting": "Eliminando...",
"success_title": "Proforma eliminada",
"error_title": "Error al eliminar la proforma",
"single_title": "Eliminar proforma {{reference}}", "single_title": "Eliminar proforma {{reference}}",
"second_confirm_title": "Confirmación adicional",
"multiple_title": "Eliminar {{count}} proformas",
"second_confirm_description": "Estás a punto de borrar {{total}} proformas. Esta acción masiva no se puede deshacer. ¿Seguro que quieres continuar?",
"single_description": "¿Seguro que deseas eliminar esta proforma? Esta acción no se puede deshacer.", "single_description": "¿Seguro que deseas eliminar esta proforma? Esta acción no se puede deshacer.",
"second_confirm_single_title": "Confirmación adicional",
"second_confirm_single_description": "Estás a punto de borrar la proforma. Esta acción masiva no se puede deshacer. ¿Seguro que quieres continuar?",
"multiple_description": "¿Seguro que deseas eliminar las {{total}} proformas seleccionadas? Esta acción no se puede deshacer.", "multiple_description": "¿Seguro que deseas eliminar las {{total}} proformas seleccionadas? Esta acción no se puede deshacer.",
"confirm_delete": "Confirmar eliminación",
"deleting": "Eliminando...",
"cancel": "Cancelar",
"continue": "Eliminar",
"list_item": "Proforma {{reference}}" "list_item": "Proforma {{reference}}"
} }
}, },

View File

@ -59,8 +59,8 @@ export const useDeleteProformaDialogController = () => {
(targets: DeleteProformaTarget[]) => { (targets: DeleteProformaTarget[]) => {
if (targets.length === 1) { if (targets.length === 1) {
showSuccessToast( showSuccessToast(
t("pages.proformas.delete.successTitle"), t("proformas.delete_proforma_dialog.success_title"),
t("pages.proformas.delete.successSingleMessage", { t("proformas.delete_proforma_dialog.success_single_message", {
reference: getProformaLabel(targets[0]), reference: getProformaLabel(targets[0]),
}) })
); );
@ -68,8 +68,8 @@ export const useDeleteProformaDialogController = () => {
} }
showSuccessToast( showSuccessToast(
t("pages.proformas.delete.successTitle"), t("proformas.delete_proforma_dialog.success_title"),
t("pages.proformas.delete.successMultipleMessage", { t("proformas.delete_proforma_dialog.success_multiple_message", {
count: targets.length, count: targets.length,
}) })
); );
@ -81,15 +81,15 @@ export const useDeleteProformaDialogController = () => {
(targets: DeleteProformaTarget[], errorCount: number) => { (targets: DeleteProformaTarget[], errorCount: number) => {
if (targets.length === 1) { if (targets.length === 1) {
showErrorToast( showErrorToast(
t("pages.proformas.delete.errorTitle"), t("proformas.delete_proforma_dialog.error_title"),
t("pages.proformas.delete.errorSingleMessage") t("proformas.delete_proforma_dialog.error_single_message")
); );
return; return;
} }
showErrorToast( showErrorToast(
t("pages.proformas.delete.errorTitle"), t("proformas.delete_proforma_dialog.error_title"),
t("pages.proformas.delete.errorMultipleMessage", { t("proformas.delete_proforma_dialog.error_multiple_message", {
count: errorCount, count: errorCount,
}) })
); );
@ -143,8 +143,8 @@ export const useDeleteProformaDialogController = () => {
await submitDelete(); await submitDelete();
} catch { } catch {
showErrorToast( showErrorToast(
t("pages.proformas.delete.errorTitle"), t("proformas.delete.error_title"),
t("pages.proformas.delete.errorUnexpectedMessage") t("proformas.delete.error_unexpected_message")
); );
} }
}, [deleteMutation.isPending, moveToSecondConfirmStep, state, submitDelete, t]); }, [deleteMutation.isPending, moveToSecondConfirmStep, state, submitDelete, t]);

View File

@ -39,29 +39,29 @@ export const DeleteProformaDialog = ({
const title = isSecondConfirmStep const title = isSecondConfirmStep
? isSingle ? isSingle
? t("components.delete_proforma_dialog.second_confirm_single_title", { ? t("proformas.delete_proforma_dialog.second_confirm_single_title", {
reference: getTargetLabel(firstTarget), reference: getTargetLabel(firstTarget),
}) })
: t("components.delete_proforma_dialog.second_confirm_multiple_title", { : t("proformas.delete_proforma_dialog.second_confirm_multiple_title", {
count: total, count: total,
}) })
: isSingle : isSingle
? t("components.delete_proforma_dialog.single_title", { ? t("proformas.delete_proforma_dialog.single_title", {
reference: getTargetLabel(firstTarget), reference: getTargetLabel(firstTarget),
}) })
: t("components.delete_proforma_dialog.multiple_title", { : t("proformas.delete_proforma_dialog.multiple_title", {
count: total, count: total,
}); });
const description = isSecondConfirmStep const description = isSecondConfirmStep
? isSingle ? isSingle
? t("components.delete_proforma_dialog.second_confirm_single_description") ? t("proformas.delete_proforma_dialog.second_confirm_single_description")
: t("components.delete_proforma_dialog.second_confirm_multiple_description", { : t("proformas.delete_proforma_dialog.second_confirm_multiple_description", {
count: total, count: total,
}) })
: isSingle : isSingle
? t("components.delete_proforma_dialog.single_description") ? t("proformas.delete_proforma_dialog.single_description")
: t("components.delete_proforma_dialog.multiple_description", { : t("proformas.delete_proforma_dialog.multiple_description", {
count: total, count: total,
}); });
@ -84,7 +84,7 @@ export const DeleteProformaDialog = ({
<ul className="space-y-1"> <ul className="space-y-1">
{targets.map((target) => ( {targets.map((target) => (
<li className="text-muted-foreground" key={target.id}> <li className="text-muted-foreground" key={target.id}>
{t("components.delete_proforma_dialog.list_item", { {t("proformas.delete_proforma_dialog.list_item", {
reference: getTargetLabel(target), reference: getTargetLabel(target),
})} })}
</li> </li>
@ -95,19 +95,19 @@ export const DeleteProformaDialog = ({
<AlertDialogFooter className="sm:justify-between"> <AlertDialogFooter className="sm:justify-between">
<Button disabled={isSubmitting} onClick={() => onOpenChange(false)} variant="outline"> <Button disabled={isSubmitting} onClick={() => onOpenChange(false)} variant="outline">
{t("components.delete_proforma_dialog.cancel")} {t("proformas.delete_proforma_dialog.cancel")}
</Button> </Button>
<Button disabled={isSubmitting || total === 0} onClick={onConfirm} variant="destructive"> <Button disabled={isSubmitting || total === 0} onClick={onConfirm} variant="destructive">
{isSubmitting ? ( {isSubmitting ? (
<> <>
<Spinner className="mr-2 size-4" /> <Spinner className="mr-2 size-4" />
{t("components.delete_proforma_dialog.deleting")} {t("proformas.delete_proforma_dialog.deleting")}
</> </>
) : isSecondConfirmStep ? ( ) : isSecondConfirmStep ? (
t("components.delete_proforma_dialog.confirm_delete") t("proformas.delete_proforma_dialog.confirm_delete")
) : ( ) : (
t("components.delete_proforma_dialog.continue") t("proformas.delete_proforma_dialog.continue")
)} )}
</Button> </Button>
</AlertDialogFooter> </AlertDialogFooter>

View File

@ -1,61 +1,91 @@
import { showErrorToast, showSuccessToast } from "@repo/rdx-ui/helpers"; import { showErrorToast, showSuccessToast } from "@repo/rdx-ui/helpers";
import * as React from "react"; import { useState } from "react";
import type { ProformaSummaryData } from "../../types"; import { useTranslation } from "../../../i18n";
import { useIssueProformaMutation } from "../hooks/use-issue-proforma-mutation"; import { useProformaIssueMutation } from "../../shared";
import type { IssueProformaTarget } from "../entities";
interface State { interface IssueDialogState {
open: boolean; open: boolean;
proforma: ProformaSummaryData | null; target: IssueProformaTarget | null;
loading: boolean;
} }
export function useProformaIssueDialogController() { const canIssueProforma = (target: IssueProformaTarget) => target.status === "approved";
const { issueProforma, isPending } = useIssueProformaMutation();
const [state, setState] = React.useState<State>({ export const useIssueProformaDialogController = () => {
const { t } = useTranslation();
const issueMutation = useProformaIssueMutation();
const [state, setState] = useState<IssueDialogState>({
open: false, open: false,
proforma: null, target: null,
loading: false,
}); });
// abrir diálogo const openDialog = (target: IssueProformaTarget) => {
const openDialog = (proforma: ProformaSummaryData) => { if (!canIssueProforma(target)) {
setState({ open: true, proforma: proforma, loading: false }); showErrorToast(
}; t("proformas.issue_proforma_dialog.not_allowed_title"),
t("proformas.issue_proforma_dialog.not_allowed_description")
);
return;
}
// cerrar diálogo setState({
const closeDialog = () => { open: true,
setState((s) => ({ ...s, open: false })); target,
};
// confirmar emisión
const confirmIssue = async () => {
if (!state.proforma) return;
setState((s) => ({ ...s, loading: true }));
await issueProforma(state.proforma.id, {
onSuccess: () => {
showSuccessToast("Proforma emitida a factura");
},
onError: (err: unknown) => {
const error = err as Error;
showErrorToast("Error al emitir la proforma a factura", error.message);
},
}); });
};
setState((s) => ({ ...s, loading: false })); const closeDialog = () => {
closeDialog(); setState((current) => ({
...current,
open: false,
}));
};
const confirmIssue = async () => {
const target = state.target;
if (!target) {
return;
}
if (!canIssueProforma(target)) {
showErrorToast(
t("proformas.issue_proforma_dialog.not_allowed_title"),
t("proformas.issue_proforma_dialog.not_allowed_description")
);
return;
}
try {
await issueMutation.mutateAsync({ id: target.id });
showSuccessToast(
t("proformas.issue_proforma_dialog.success_title"),
t("proformas.issue_proforma_dialog.success_description", {
reference: target.reference,
})
);
setState({
open: false,
target: null,
});
} catch (error) {
const message =
error instanceof Error ? error.message : t("proformas.issue_proforma_dialog.unknown_error");
showErrorToast(t("proformas.issue_proforma_dialog.error_title"), message);
}
}; };
return { return {
open: state.open, open: state.open,
proforma: state.proforma, target: state.target,
isSubmitting: isPending, isSubmitting: issueMutation.isPending,
openDialog, openDialog,
closeDialog, closeDialog,
confirmIssue, confirmIssue,
}; };
} };

View File

@ -0,0 +1 @@
export * from './issue-proforma-target.entity';

View File

@ -0,0 +1,8 @@
import type { ProformaStatus } from "../../shared";
// proformas/issue/entities/issue-proforma-target.entity.ts
export interface IssueProformaTarget {
id: string;
reference: string;
status: ProformaStatus;
}

View File

@ -1 +0,0 @@
export * from "./use-issue-proforma-mutation";

View File

@ -1,48 +0,0 @@
import { useDataSource } from "@erp/core/hooks";
import { type DefaultError, useMutation, useQueryClient } from "@tanstack/react-query";
import { type IssueProformaInvoiceResponse, issueProformaInvoiceApi } from "../api";
interface IssueProformaPayload {
proformaId: string;
}
interface IssueProformaOptions {
onSuccess?: () => void;
onError?: (err: unknown) => void;
onLoadingChange?: (loading: boolean) => void;
}
export function useIssueProformaMutation() {
const dataSource = useDataSource();
const queryClient = useQueryClient();
const mutation = useMutation<IssueProformaInvoiceResponse, DefaultError, IssueProformaPayload>({
mutationFn: ({ proformaId }) => issueProformaInvoiceApi(dataSource, proformaId),
onSuccess(_data, _vars, _ctx) {
// Refresca el listado de proformas
queryClient.invalidateQueries({ queryKey: ["proformas"] });
// Opcional: refrescar facturas si existe la feature
queryClient.invalidateQueries({ queryKey: ["invoices"] });
},
});
async function issueProforma(proformaId: string, opts?: IssueProformaOptions) {
try {
opts?.onLoadingChange?.(true);
await mutation.mutateAsync({ proformaId });
opts?.onSuccess?.();
} catch (err) {
opts?.onError?.(err);
} finally {
opts?.onLoadingChange?.(false);
}
}
return {
issueProforma,
isPending: mutation.isPending,
};
}

View File

@ -1,2 +1,3 @@
export * from "./controllers"; export * from "./controllers";
export * from "./ui"; export * from "./ui";
export * from "./utils";

View File

@ -10,59 +10,58 @@ import {
} from "@repo/shadcn-ui/components"; } from "@repo/shadcn-ui/components";
import { useTranslation } from "../../../i18n"; import { useTranslation } from "../../../i18n";
import type { ProformaSummaryData } from "../../types"; import type { IssueProformaTarget } from "../entities";
interface ProformaIssueDialogProps { interface IssueProformaDialogProps {
open: boolean; open: boolean;
onOpenChange: (open: boolean) => void; onOpenChange: (open: boolean) => void;
proforma: ProformaSummaryData | null; target: IssueProformaTarget | null;
isSubmitting: boolean; isSubmitting: boolean;
onConfirm: (proforma?: ProformaSummaryData) => void; onConfirm: () => void;
} }
export function ProformaIssueDialog({ export const IssueProformaDialog = ({
open, open,
onOpenChange, onOpenChange,
proforma, target,
isSubmitting, isSubmitting,
onConfirm, onConfirm,
}: ProformaIssueDialogProps) { }: IssueProformaDialogProps) => {
const { t } = useTranslation(); const { t } = useTranslation();
return ( return (
<AlertDialog onOpenChange={onOpenChange} open={open}> <AlertDialog onOpenChange={onOpenChange} open={open}>
<AlertDialogContent> <AlertDialogContent>
<AlertDialogHeader> <AlertDialogHeader>
<AlertDialogTitle>Emitir a factura</AlertDialogTitle> <AlertDialogTitle>{t("proformas.issue_proforma_dialog.title")}</AlertDialogTitle>
<AlertDialogDescription className="space-y-4"> <AlertDialogDescription className="space-y-4">
<p> {t("proformas.issue_proforma_dialog.description", {
¿Seguro que quieres emitir la factura desde la proforma{" "} reference: target?.reference ?? "",
<strong>{proforma?.reference}</strong>? })}
</p> <br />
<p> <br />
Esta acción creará una nueva factura definitiva y la proforma pasará al estado {t("proformas.issue_proforma_dialog.warning")}
"Emitida", no pudiendo modificarse ni eliminarse posteriormente.
</p>
</AlertDialogDescription> </AlertDialogDescription>
</AlertDialogHeader> </AlertDialogHeader>
<AlertDialogFooter> <AlertDialogFooter>
<Button disabled={isSubmitting} onClick={() => onOpenChange(false)} variant="outline"> <Button disabled={isSubmitting} onClick={() => onOpenChange(false)} variant="outline">
Cancelar {t("proformas.issue_proforma_dialog.cancel")}
</Button> </Button>
<Button disabled={isSubmitting} onClick={() => onConfirm(proforma)}> <Button disabled={isSubmitting} onClick={onConfirm}>
{isSubmitting ? ( {isSubmitting ? (
<> <>
<Spinner className="mr-2 size-4" /> <Spinner aria-hidden className="mr-2 size-4" />
Emitiendo... <span aria-live="polite">{t("proformas.issue_proforma_dialog.submitting")}</span>
</> </>
) : ( ) : (
<>Emitir factura</> t("proformas.issue_proforma_dialog.confirm")
)} )}
</Button> </Button>
</AlertDialogFooter> </AlertDialogFooter>
</AlertDialogContent> </AlertDialogContent>
</AlertDialog> </AlertDialog>
); );
} };

View File

@ -0,0 +1 @@
export * from './prepare-issue-proforma-targets';

View File

@ -0,0 +1,25 @@
// proformas/issue/utils/prepare-issue-proforma-targets.ts
import type { Proforma, ProformaListRow } from "../../shared";
import type { IssueProformaTarget } from "../entities";
type SupportedIssueSource = Proforma | ProformaListRow;
type SupportedIssueInput = SupportedIssueSource | SupportedIssueSource[];
const mapToIssueProformaTarget = (proforma: SupportedIssueSource): IssueProformaTarget => ({
id: proforma.id,
reference: proforma.reference,
status: proforma.status,
});
export const prepareIssueProformaTargets = (input: SupportedIssueInput): IssueProformaTarget[] => {
const items = Array.isArray(input) ? input : [input];
return items.map(mapToIssueProformaTarget);
};
export const prepareIssueProformaTarget = (
input: Proforma | ProformaListRow
): IssueProformaTarget => ({
id: input.id,
reference: input.reference,
status: input.status,
});

View File

@ -2,6 +2,7 @@ import type { RightPanelMode } from "@repo/rdx-ui/hooks";
import { useSearchParams } from "react-router-dom"; import { useSearchParams } from "react-router-dom";
import { useDeleteProformaDialogController } from "../../delete"; import { useDeleteProformaDialogController } from "../../delete";
import { useIssueProformaDialogController } from "../../issue-proforma";
import { useListProformasController } from "./use-list-proformas.controller"; import { useListProformasController } from "./use-list-proformas.controller";
import { useProformaSummaryPanelController } from "./use-proforma-summary-panel.controller"; import { useProformaSummaryPanelController } from "./use-proforma-summary-panel.controller";
@ -9,6 +10,7 @@ import { useProformaSummaryPanelController } from "./use-proforma-summary-panel.
export const useListProformasPageController = () => { export const useListProformasPageController = () => {
const listCtrl = useListProformasController(); const listCtrl = useListProformasController();
const deleteDialogCtrl = useDeleteProformaDialogController(); const deleteDialogCtrl = useDeleteProformaDialogController();
const issueDialogCtrl = useIssueProformaDialogController();
const [searchParams] = useSearchParams(); const [searchParams] = useSearchParams();
@ -26,5 +28,6 @@ export const useListProformasPageController = () => {
panelCtrl, panelCtrl,
deleteDialogCtrl, deleteDialogCtrl,
issueDialogCtrl,
}; };
}; };

View File

@ -53,6 +53,7 @@ export const ProformasGrid = ({
manualPagination manualPagination
onPageChange={onPageChange} onPageChange={onPageChange}
onPageSizeChange={onPageSizeChange} onPageSizeChange={onPageSizeChange}
//onRowClick={(row) => onRowClick?.(row.id)}
pageIndex={pageIndex} pageIndex={pageIndex}
pageSize={pageSize} pageSize={pageSize}
totalItems={totalItems} totalItems={totalItems}

View File

@ -18,6 +18,7 @@ import * as React from "react";
import { useTranslation } from "../../../../../i18n"; import { useTranslation } from "../../../../../i18n";
import { import {
PROFORMA_STATUS,
PROFORMA_STATUS_TRANSITIONS, PROFORMA_STATUS_TRANSITIONS,
type ProformaListRow, type ProformaListRow,
type ProformaStatus, type ProformaStatus,
@ -227,12 +228,12 @@ export function useProformasGridColumns(
enableSorting: false, enableSorting: false,
cell: ({ row }) => { cell: ({ row }) => {
const proforma = row.original; const proforma = row.original;
const isIssued = proforma.status === "issued"; const isIssued = proforma.status === PROFORMA_STATUS.ISSUED;
const isApproved = proforma.status === "approved"; const isApproved = proforma.status === PROFORMA_STATUS.APPROVED;
const availableTransitions = const availableTransitions =
PROFORMA_STATUS_TRANSITIONS[proforma.status as ProformaStatus] ?? []; PROFORMA_STATUS_TRANSITIONS[proforma.status as ProformaStatus] ?? [];
console.log(availableTransitions); console.log(availableTransitions, proforma.status);
return ( return (
<div className="flex items-center gap-1"> <div className="flex items-center gap-1">
@ -280,7 +281,7 @@ export function useProformasGridColumns(
)} )}
{/* Emitir factura: solo si approved */} {/* Emitir factura: solo si approved */}
{!isIssued && proforma.status === "approved" && actionHandlers.onIssueClick && ( {!isIssued && isApproved && actionHandlers.onIssueClick && (
<TooltipProvider> <TooltipProvider>
<Tooltip> <Tooltip>
<TooltipTrigger asChild> <TooltipTrigger asChild>

View File

@ -17,6 +17,8 @@ import { useNavigate } from "react-router-dom";
import { useTranslation } from "../../../../i18n"; import { useTranslation } from "../../../../i18n";
import { DeleteProformaDialog } from "../../../delete"; import { DeleteProformaDialog } from "../../../delete";
import { prepareDeleteProformaTargets } from "../../../delete/utils"; import { prepareDeleteProformaTargets } from "../../../delete/utils";
import { IssueProformaDialog } from "../../../issue-proforma";
import { prepareIssueProformaTarget } from "../../../issue-proforma/utils";
import type { ProformaListRow } from "../../../shared"; import type { ProformaListRow } from "../../../shared";
import { useListProformasPageController } from "../../controllers"; import { useListProformasPageController } from "../../controllers";
import { ProformaSummaryPanel, ProformasGrid, useProformasGridColumns } from "../blocks"; import { ProformaSummaryPanel, ProformasGrid, useProformasGridColumns } from "../blocks";
@ -25,16 +27,15 @@ export const ListProformasPage = () => {
const { t } = useTranslation(); const { t } = useTranslation();
const navigate = useNavigate(); const navigate = useNavigate();
const { listCtrl, panelCtrl, deleteDialogCtrl } = useListProformasPageController(); const { listCtrl, panelCtrl, deleteDialogCtrl, issueDialogCtrl } =
useListProformasPageController();
const handleDeleteProforma = (proformaRow: ProformaListRow) => {
deleteDialogCtrl.openDialog(prepareDeleteProformaTargets(proformaRow));
};
const columns = useProformasGridColumns({ const columns = useProformasGridColumns({
onEditClick: (proforma) => navigate(`/proformas/${proforma.id}/edit`), onEditClick: (proforma) => navigate(`/proformas/${proforma.id}/edit`),
//onIssueClick: handleIssueProforma, onIssueClick: (proformaRow) =>
onDeleteClick: handleDeleteProforma, issueDialogCtrl.openDialog(prepareIssueProformaTarget(proformaRow)),
onDeleteClick: (proformaRow: ProformaListRow) =>
deleteDialogCtrl.openDialog(prepareDeleteProformaTargets(proformaRow)),
//onChangeStatusClick: handleChangeStatusProforma, //onChangeStatusClick: handleChangeStatusProforma,
}); });
@ -148,6 +149,19 @@ export const ListProformasPage = () => {
<div className="flex min-h-0 flex-1 overflow-hidden">{listContent}</div> <div className="flex min-h-0 flex-1 overflow-hidden">{listContent}</div>
)} )}
<> <>
{/* Issue */}
<IssueProformaDialog
isSubmitting={issueDialogCtrl.isSubmitting}
onConfirm={issueDialogCtrl.confirmIssue}
onOpenChange={(open) => {
if (!open) {
issueDialogCtrl.closeDialog();
}
}}
open={issueDialogCtrl.open}
target={issueDialogCtrl.target}
/>
{/* Eliminar */} {/* Eliminar */}
<DeleteProformaDialog <DeleteProformaDialog
isSecondConfirmStep={deleteDialogCtrl.isSecondConfirmStep} isSecondConfirmStep={deleteDialogCtrl.isSecondConfirmStep}

View File

@ -1,6 +1,8 @@
export * from "./keys"; export * from "./keys";
export * from "./use-proforma-change-status-mutation";
export * from "./use-proforma-create-mutation"; export * from "./use-proforma-create-mutation";
export * from "./use-proforma-delete-mutation"; export * from "./use-proforma-delete-mutation";
export * from "./use-proforma-get-query"; export * from "./use-proforma-get-query";
export * from "./use-proforma-issue-mutation";
export * from "./use-proforma-update-mutation"; export * from "./use-proforma-update-mutation";
export * from "./use-proformas-list-query"; export * from "./use-proformas-list-query";

View File

@ -16,7 +16,7 @@ export const useProformaIssueMutation = () => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const dataSource = useDataSource(); const dataSource = useDataSource();
useMutation< return useMutation<
IssueProformaByIdResult, IssueProformaByIdResult,
DefaultError, DefaultError,
IssueProformaByIdParams, IssueProformaByIdParams,

View File

@ -192,16 +192,6 @@
} }
}, },
"components": { "components": {
"delete_proforma_dialog": {
"single_title": "Eliminar proforoma",
"single_description": "",
"second_confirm_single_title": "Confirmar eliminación",
"second_confirm_single_description": "",
"confirm_delete": "Confirmar eliminación",
"deleting": "Eliminando...",
"cancel": "Cancelar",
"continue": "Eliminar"
},
"entity_selector": { "entity_selector": {
"close": "Close", "close": "Close",
"select_entity": "Select entity", "select_entity": "Select entity",

View File

@ -194,18 +194,6 @@
} }
}, },
"components": { "components": {
"delete_proforma_dialog": {
"single_title": "Eliminar proforoma",
"single_description": "",
"second_confirm_single_title": "Confirmar eliminación",
"second_confirm_single_description": "",
"multiple_description": "",
"confirm_delete": "Confirmar eliminación",
"deleting": "Eliminando...",
"cancel": "Cancelar",
"continue": "Eliminar",
"list_item": ""
},
"entity_selector": { "entity_selector": {
"close": "Cerrar", "close": "Cerrar",
"select_entity": "Seleccionar entidad", "select_entity": "Seleccionar entidad",