diff --git a/modules/catalogs/src/web/settings/payment-methods/ui/components/payment-method-row-actions.tsx b/modules/catalogs/src/web/settings/payment-methods/ui/components/payment-method-row-actions.tsx index da6bb337..a17e9a6c 100644 --- a/modules/catalogs/src/web/settings/payment-methods/ui/components/payment-method-row-actions.tsx +++ b/modules/catalogs/src/web/settings/payment-methods/ui/components/payment-method-row-actions.tsx @@ -1,6 +1,6 @@ -import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@repo/shadcn-ui/components"; -import { Button, Spinner } from "@repo/shadcn-ui/components"; -import { MoreHorizontalIcon } from "lucide-react"; +import { type RdxRowAction, RdxRowActions } from "@repo/rdx-ui/components"; +import { Spinner } from "@repo/shadcn-ui/components"; +import { PencilIcon, PowerIcon, PowerOffIcon, Trash2Icon } from "lucide-react"; import { useTranslation } from "../../../../i18n"; import type { PaymentMethodListRow } from "../../../../payment-methods/shared"; @@ -30,67 +30,52 @@ export const PaymentMethodRowActions = ({ const toggleDisabled = paymentMethod.isSystem || paymentMethod.isDefault || isTogglingActive; const deleteDisabled = paymentMethod.isSystem || paymentMethod.isDefault; + const primaryActions: RdxRowAction[] = [ + { + id: "edit", + label: t("settings.paymentMethods.actions.edit"), + icon: , + disabled: editDisabled, + disabledReason: editDisabled + ? t("settings.paymentMethods.protections.systemEdit") + : undefined, + onSelect: () => onEdit(paymentMethod), + }, + { + id: "toggle-active", + label: paymentMethod.isActive + ? t("settings.paymentMethods.actions.disable") + : t("settings.paymentMethods.actions.enable"), + icon: isTogglingActive ? ( + + ) : paymentMethod.isActive ? ( + + ) : ( + + ), + disabled: toggleDisabled, + disabledReason: toggleDisabled ? activeDisabledReason : undefined, + onSelect: () => onToggleActive(paymentMethod), + }, + ]; + + const overflowActions: RdxRowAction[] = [ + { + id: "delete", + label: t("settings.paymentMethods.actions.delete"), + icon: , + destructive: true, + disabled: deleteDisabled, + disabledReason: deleteDisabled ? deleteDisabledReason : undefined, + onSelect: () => onDelete(paymentMethod), + }, + ]; + return ( -
- - - - - - - - - } - /> - onDelete(paymentMethod)} - title={deleteDisabled ? deleteDisabledReason : undefined} - variant="destructive" - > - {t("settings.paymentMethods.actions.delete")} - - } - /> - -
+ ); }; diff --git a/modules/catalogs/src/web/settings/payment-methods/ui/pages/payment-methods-settings-page.tsx b/modules/catalogs/src/web/settings/payment-methods/ui/pages/payment-methods-settings-page.tsx index cbcd789f..325d1f2c 100644 --- a/modules/catalogs/src/web/settings/payment-methods/ui/pages/payment-methods-settings-page.tsx +++ b/modules/catalogs/src/web/settings/payment-methods/ui/pages/payment-methods-settings-page.tsx @@ -135,7 +135,7 @@ export const PaymentMethodsSettingsPage = () => { id={`payment-method-default-${paymentMethod.id}`} value={paymentMethod.id} /> -
+
diff --git a/modules/customer-invoices/src/web/proformas/list/ui/blocks/proformas-grid/proforma-row-actions.tsx b/modules/customer-invoices/src/web/proformas/list/ui/blocks/proformas-grid/proforma-row-actions.tsx new file mode 100644 index 00000000..345d3111 --- /dev/null +++ b/modules/customer-invoices/src/web/proformas/list/ui/blocks/proformas-grid/proforma-row-actions.tsx @@ -0,0 +1,254 @@ +import { type RdxRowAction, RdxRowActions } from "@repo/rdx-ui/components"; +import { Spinner } from "@repo/shadcn-ui/components"; +import { + CalendarSyncIcon, + CopyIcon, + ExternalLinkIcon, + EyeIcon, + FileDownIcon, + FileTextIcon, + FolderArchiveIcon, + PencilIcon, + RefreshCwIcon, + Trash2Icon, + Undo2Icon, +} from "lucide-react"; +import type { ComponentType } from "react"; + +import { useTranslation } from "../../../../../i18n"; +import { + PROFORMA_STATUS, + PROFORMA_STATUS_TRANSITIONS, + type ProformaListRow, + type ProformaStatus, +} from "../../../../shared"; +import type { ProformaListScope } from "../../../types/proforma-list-filters"; + +export interface ProformaRowActionHandlers { + onViewClick?: (proforma: ProformaListRow) => void; + onEditClick?: (proforma: ProformaListRow) => void; + onIssueClick?: (proforma: ProformaListRow) => void; + onArchiveClick?: (proforma: ProformaListRow) => void; + onDuplicateClick?: (proforma: ProformaListRow) => void; + onCreateRecurringClick?: (proforma: ProformaListRow) => void; + onUnarchiveClick?: (proforma: ProformaListRow) => void; + onDeleteClick?: (proforma: ProformaListRow) => void; + onChangeStatusClick?: (proforma: ProformaListRow, nextStatus: ProformaStatus) => void; + onLinkedInvoiceClick?: (proforma: ProformaListRow) => void; + onDownloadPdf?: (proforma: ProformaListRow) => void; + pdfDownloadingId?: string | null; + isPdfDownloading?: boolean; +} + +interface ProformaRowActionsProps { + proforma: ProformaListRow; + scope: ProformaListScope; + actionHandlers?: ProformaRowActionHandlers; +} + +const renderActionIcon = (Icon: ComponentType<{ className?: string }>, loading?: boolean) => + loading ? : ; + +// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: +export function ProformaRowActions({ + proforma, + scope, + actionHandlers = {}, +}: ProformaRowActionsProps) { + const { t } = useTranslation(); + const isDraft = proforma.status === PROFORMA_STATUS.DRAFT; + const isIssued = proforma.status === PROFORMA_STATUS.ISSUED; + const isApproved = proforma.status === PROFORMA_STATUS.APPROVED; + const isNormalScope = scope === "normal"; + const isArchivedScope = scope === "archived"; + const isDeletedScope = scope === "deleted"; + const isArchivable = + isNormalScope && + !proforma.isArchived && + (proforma.status === PROFORMA_STATUS.DRAFT || proforma.status === PROFORMA_STATUS.REJECTED); + const isUnarchivable = + isArchivedScope && + proforma.isArchived && + (proforma.status === PROFORMA_STATUS.DRAFT || proforma.status === PROFORMA_STATUS.REJECTED); + const availableTransitions = isNormalScope + ? (PROFORMA_STATUS_TRANSITIONS[proforma.status as ProformaStatus] ?? []) + : []; + + const isPDFLoading = + actionHandlers.isPdfDownloading && actionHandlers.pdfDownloadingId === proforma.id; + const nextTransition = availableTransitions[0] ?? null; + + const handleView = () => actionHandlers.onViewClick?.(proforma); + const handleEdit = () => actionHandlers.onEditClick?.(proforma); + const handleDuplicate = () => actionHandlers.onDuplicateClick?.(proforma); + const handleCreateRecurring = () => actionHandlers.onCreateRecurringClick?.(proforma); + const handleArchive = () => actionHandlers.onArchiveClick?.(proforma); + const handleUnarchive = () => actionHandlers.onUnarchiveClick?.(proforma); + const handleIssue = () => actionHandlers.onIssueClick?.(proforma); + const handleDownloadPdf = () => actionHandlers.onDownloadPdf?.(proforma); + const handleDelete = () => actionHandlers.onDeleteClick?.(proforma); + const handleChangeStatus = () => { + if (!nextTransition) { + return; + } + + actionHandlers.onChangeStatusClick?.(proforma, nextTransition); + }; + + const getScopeReason = () => { + if (isArchivedScope) { + return t("pages.proformas.list.actions.disabled_reasons.archived_scope"); + } + + if (isDeletedScope) { + return t("pages.proformas.list.actions.disabled_reasons.deleted_scope"); + } + + return undefined; + }; + + const visibleActions: RdxRowAction[] = [ + { + id: "view", + label: t("pages.proformas.list.actions.view"), + icon: renderActionIcon(EyeIcon), + disabled: !actionHandlers.onViewClick || isDeletedScope, + disabledReason: isDeletedScope + ? t("pages.proformas.list.actions.disabled_reasons.deleted_scope") + : undefined, + onSelect: handleView, + }, + { + id: "edit", + label: t("pages.proformas.list.actions.edit"), + icon: renderActionIcon(PencilIcon), + disabled: !(actionHandlers.onEditClick && isNormalScope) || isIssued, + disabledReason: isNormalScope + ? isIssued + ? t("pages.proformas.list.actions.disabled_reasons.edit_issued") + : undefined + : getScopeReason(), + onSelect: handleEdit, + }, + ]; + + const menuActions: RdxRowAction[] = [ + { + id: "linked-invoice", + label: t("pages.proformas.list.actions.view_linked_invoice"), + icon: renderActionIcon(ExternalLinkIcon), + disabled: !(isIssued && proforma.linkedInvoiceId), + disabledReason: + isIssued && proforma.linkedInvoiceId + ? undefined + : t("pages.proformas.list.actions.disabled_reasons.linked_invoice_unavailable"), + onSelect: () => { + if (proforma.linkedInvoiceId) { + window.location.href = "/customer-invoices"; + } + }, + }, + { + id: "change-status", + label: t("pages.proformas.list.actions.change_status"), + icon: renderActionIcon(RefreshCwIcon), + disabled: + !(actionHandlers.onChangeStatusClick && isNormalScope && nextTransition) || isIssued, + disabledReason: isNormalScope + ? isIssued + ? t("pages.proformas.list.actions.disabled_reasons.status_issued") + : nextTransition + ? undefined + : t("proformas.change_proforma_status_dialog.empty_available_statuses") + : getScopeReason(), + onSelect: handleChangeStatus, + }, + { + id: "issue", + label: t("pages.proformas.list.actions.issue"), + icon: renderActionIcon(FileTextIcon), + disabled: !(actionHandlers.onIssueClick && isNormalScope && isApproved) || isIssued, + disabledReason: isNormalScope + ? isApproved + ? undefined + : t("proformas.issue_proforma_dialog.not_allowed_description") + : getScopeReason(), + onSelect: handleIssue, + }, + { + id: "duplicate", + label: t("pages.proformas.list.actions.duplicate"), + icon: renderActionIcon(CopyIcon), + disabled: !actionHandlers.onDuplicateClick || isDeletedScope, + disabledReason: isDeletedScope + ? t("pages.proformas.list.actions.disabled_reasons.deleted_scope") + : undefined, + onSelect: handleDuplicate, + }, + { + id: "create-recurring", + label: t("pages.proformas.list.actions.create_recurring"), + icon: renderActionIcon(CalendarSyncIcon), + disabled: !(actionHandlers.onCreateRecurringClick && isNormalScope), + disabledReason: isNormalScope ? undefined : getScopeReason(), + onSelect: handleCreateRecurring, + }, + { + id: "archive", + label: t("pages.proformas.list.actions.archive"), + icon: renderActionIcon(FolderArchiveIcon), + disabled: !(actionHandlers.onArchiveClick && isArchivable), + disabledReason: actionHandlers.onArchiveClick + ? isNormalScope + ? t("proformas.archive.error_conflict_message") + : getScopeReason() + : undefined, + onSelect: handleArchive, + }, + { + id: "unarchive", + label: t("pages.proformas.list.actions.unarchive"), + icon: renderActionIcon(Undo2Icon), + disabled: !(actionHandlers.onUnarchiveClick && isUnarchivable), + disabledReason: actionHandlers.onUnarchiveClick + ? isArchivedScope + ? t("proformas.unarchive.error_conflict_message") + : t("pages.proformas.list.actions.disabled_reasons.archived_only") + : undefined, + onSelect: handleUnarchive, + }, + { + id: "download-pdf", + label: t("pages.proformas.list.actions.download_pdf"), + icon: renderActionIcon(FileDownIcon, isPDFLoading), + disabled: Boolean(!actionHandlers.onDownloadPdf || isDeletedScope || isPDFLoading), + disabledReason: isDeletedScope + ? t("pages.proformas.list.actions.disabled_reasons.deleted_scope") + : isPDFLoading + ? t("pages.proformas.list.actions.disabled_reasons.operation_in_progress") + : undefined, + onSelect: handleDownloadPdf, + }, + { + id: "delete", + label: t("pages.proformas.list.actions.delete"), + icon: renderActionIcon(Trash2Icon), + destructive: true, + disabled: !actionHandlers.onDeleteClick || isDeletedScope || !isDraft, + disabledReason: isDeletedScope + ? t("pages.proformas.list.actions.disabled_reasons.deleted_scope") + : isDraft + ? undefined + : t("proformas.delete_proforma_dialog.error_conflict_message"), + onSelect: handleDelete, + }, + ]; + + return ( + + ); +} diff --git a/modules/customer-invoices/src/web/proformas/list/ui/blocks/proformas-grid/use-proforma-grid-columns.test.tsx b/modules/customer-invoices/src/web/proformas/list/ui/blocks/proformas-grid/use-proforma-grid-columns.test.tsx index 9736c495..da68a604 100644 --- a/modules/customer-invoices/src/web/proformas/list/ui/blocks/proformas-grid/use-proforma-grid-columns.test.tsx +++ b/modules/customer-invoices/src/web/proformas/list/ui/blocks/proformas-grid/use-proforma-grid-columns.test.tsx @@ -1,14 +1,15 @@ import assert from "node:assert/strict"; import test from "node:test"; -import { RdxRowActions, type RdxRowActionsProps } from "@repo/rdx-ui/components"; import type { CellContext } from "@tanstack/react-table"; +import type { ComponentProps, ReactElement } from "react"; import { isValidElement } from "react"; import { renderToStaticMarkup } from "react-dom/server"; import type { ProformaListRow } from "../../../../shared"; import { PROFORMA_STATUS } from "../../../../shared"; +import { ProformaRowActions } from "./proforma-row-actions"; import { useProformasGridColumns } from "./use-proforma-grid-columns"; const proformaFixture: ProformaListRow = { @@ -50,17 +51,21 @@ const proformaFixture: ProformaListRow = { linkedInvoiceId: null, }; -const getRowActionsProps = ( +const getRowActionsNode = ( scope: Parameters[0], actionHandlers: Parameters[1] = {} -): RdxRowActionsProps => { +): ReactElement> => { let cellNode: unknown = null; const Harness = () => { const columns = useProformasGridColumns(scope, actionHandlers); const actionsColumn = columns.find((column) => column.id === "actions"); - cellNode = actionsColumn?.cell?.({ + const cell = actionsColumn?.cell as + | ((context: CellContext) => ReactElement) + | undefined; + + cellNode = cell?.({ row: { original: proformaFixture }, } as unknown as CellContext); @@ -70,87 +75,32 @@ const getRowActionsProps = ( renderToStaticMarkup(); if (!isValidElement(cellNode)) { - throw new Error("Expected RdxRowActions cell"); + throw new Error("Expected ProformaRowActions cell"); } - assert.equal(cellNode.type, RdxRowActions); + assert.equal(cellNode.type, ProformaRowActions); - return cellNode.props as RdxRowActionsProps; + return cellNode as ReactElement>; }; -test("mantiene ver y editar como acciones visibles de referencia", () => { - const props = getRowActionsProps("normal", { +test("delegates the action cell to ProformaRowActions", () => { + const handlers = { onEditClick: () => undefined, onViewClick: () => undefined, - }); + }; + const node = getRowActionsNode("normal", handlers); - assert.deepEqual( - props.primaryActions?.map((action) => action.id), - ["view", "edit"] - ); - assert.ok(["Más acciones", "common.more_actions"].includes(props.overflowLabel)); + assert.equal(node.props.proforma, proformaFixture); + assert.equal(node.props.scope, "normal"); + assert.equal(node.props.actionHandlers, handlers); }); -test("mantiene las destructivas en overflow y conserva disabled", () => { - const props = getRowActionsProps("normal", { +test("preserves the supplied handlers for archived and normal scopes", () => { + const handlers = { + onCreateRecurringClick: () => undefined, onDeleteClick: () => undefined, - }); + }; - const deleteAction = props.overflowActions?.find((action) => action.id === "delete"); - const viewAction = props.primaryActions?.find((action) => action.id === "view"); - - assert.ok(deleteAction); - assert.equal(deleteAction?.destructive, true); - assert.equal(deleteAction?.disabled, false); - assert.equal(viewAction?.disabled, true); -}); - -test("preserva callbacks de view, edit, crear recurrencia y delete", () => { - let didView = false; - let didEdit = false; - let didCreateRecurring = false; - let didDelete = false; - - const props = getRowActionsProps("normal", { - onCreateRecurringClick: () => { - didCreateRecurring = true; - }, - onDeleteClick: () => { - didDelete = true; - }, - onEditClick: () => { - didEdit = true; - }, - onViewClick: () => { - didView = true; - }, - }); - - props.primaryActions?.find((action) => action.id === "view")?.onSelect(); - props.primaryActions?.find((action) => action.id === "edit")?.onSelect(); - props.overflowActions?.find((action) => action.id === "create-recurring")?.onSelect(); - props.overflowActions?.find((action) => action.id === "delete")?.onSelect(); - - assert.equal(didView, true); - assert.equal(didEdit, true); - assert.equal(didCreateRecurring, true); - assert.equal(didDelete, true); -}); - -test("solo permite crear recurrencia desde el listado normal", () => { - const normalProps = getRowActionsProps("normal", { - onCreateRecurringClick: () => undefined, - }); - const archivedProps = getRowActionsProps("archived", { - onCreateRecurringClick: () => undefined, - }); - - assert.equal( - normalProps.overflowActions?.find((action) => action.id === "create-recurring")?.disabled, - false - ); - assert.equal( - archivedProps.overflowActions?.find((action) => action.id === "create-recurring")?.disabled, - true - ); + assert.equal(getRowActionsNode("normal", handlers).props.actionHandlers, handlers); + assert.equal(getRowActionsNode("archived", handlers).props.actionHandlers, handlers); }); diff --git a/modules/customer-invoices/src/web/proformas/list/ui/blocks/proformas-grid/use-proforma-grid-columns.tsx b/modules/customer-invoices/src/web/proformas/list/ui/blocks/proformas-grid/use-proforma-grid-columns.tsx index 7afa405d..165b24ec 100644 --- a/modules/customer-invoices/src/web/proformas/list/ui/blocks/proformas-grid/use-proforma-grid-columns.tsx +++ b/modules/customer-invoices/src/web/proformas/list/ui/blocks/proformas-grid/use-proforma-grid-columns.tsx @@ -1,62 +1,20 @@ import { EmptyCellValue } from "@erp/core/components"; -import { DataTableColumnHeader, type RdxRowAction, RdxRowActions } from "@repo/rdx-ui/components"; +import { DataTableColumnHeader } from "@repo/rdx-ui/components"; import { DateHelper } from "@repo/rdx-utils"; -import { Checkbox, Spinner } from "@repo/shadcn-ui/components"; +import { Checkbox } from "@repo/shadcn-ui/components"; import type { ColumnDef } from "@tanstack/react-table"; -import { - CalendarSyncIcon, - CopyIcon, - ExternalLinkIcon, - EyeIcon, - FileDownIcon, - FileTextIcon, - FolderArchiveIcon, - PencilIcon, - RefreshCwIcon, - Trash2Icon, - Undo2Icon, -} from "lucide-react"; -import type { ComponentType } from "react"; import * as React from "react"; import { useTranslation } from "../../../../../i18n"; -import { - PROFORMA_STATUS, - PROFORMA_STATUS_TRANSITIONS, - type ProformaListRow, - type ProformaStatus, -} from "../../../../shared"; +import type { ProformaListRow } from "../../../../shared"; import type { ProformaListScope } from "../../../types/proforma-list-filters"; import { ProformaStatusBadge } from "../../components"; -type GridActionHandlers = { - onViewClick?: (proforma: ProformaListRow) => void; - onEditClick?: (proforma: ProformaListRow) => void; - onIssueClick?: (proforma: ProformaListRow) => void; - onArchiveClick?: (proforma: ProformaListRow) => void; - onDuplicateClick?: (proforma: ProformaListRow) => void; - onCreateRecurringClick?: (proforma: ProformaListRow) => void; - onUnarchiveClick?: (proforma: ProformaListRow) => void; - onDeleteClick?: (proforma: ProformaListRow) => void; - onChangeStatusClick?: (proforma: ProformaListRow, nextStatus: ProformaStatus) => void; - onLinkedInvoiceClick?: (proforma: ProformaListRow) => void; - getNextStatus?: (proforma: ProformaListRow) => ProformaStatus | null; - - canIssue?: (proforma: ProformaListRow) => boolean; - canEdit?: (proforma: ProformaListRow) => boolean; - canDelete?: (proforma: ProformaListRow) => boolean; - - onDownloadPdf?: (proforma: ProformaListRow) => void; - pdfDownloadingId?: string | null; - isPdfDownloading?: boolean; -}; - -const renderActionIcon = (Icon: ComponentType<{ className?: string }>, loading?: boolean) => - loading ? : ; +import { type ProformaRowActionHandlers, ProformaRowActions } from "./proforma-row-actions"; export function useProformasGridColumns( scope: ProformaListScope, - actionHandlers: GridActionHandlers = {} + actionHandlers: ProformaRowActionHandlers = {} ): ColumnDef[] { const { t } = useTranslation(); @@ -280,207 +238,13 @@ export function useProformasGridColumns( header: "Acciones", enableSorting: false, - cell: ({ row }) => { - const proforma = row.original; - const isDraft = proforma.status === PROFORMA_STATUS.DRAFT; - const isIssued = proforma.status === PROFORMA_STATUS.ISSUED; - const isApproved = proforma.status === PROFORMA_STATUS.APPROVED; - const isNormalScope = scope === "normal"; - const isArchivedScope = scope === "archived"; - const isDeletedScope = scope === "deleted"; - const isArchivable = - isNormalScope && - !proforma.isArchived && - (proforma.status === PROFORMA_STATUS.DRAFT || - proforma.status === PROFORMA_STATUS.REJECTED); - const isUnarchivable = - isArchivedScope && - proforma.isArchived && - (proforma.status === PROFORMA_STATUS.DRAFT || - proforma.status === PROFORMA_STATUS.REJECTED); - const availableTransitions = isNormalScope - ? (PROFORMA_STATUS_TRANSITIONS[proforma.status as ProformaStatus] ?? []) - : []; - - const isPDFLoading = - actionHandlers.isPdfDownloading && actionHandlers.pdfDownloadingId === proforma.id; - const nextTransition = availableTransitions[0] ?? null; - - const handleView = () => actionHandlers.onViewClick?.(proforma); - const handleEdit = () => actionHandlers.onEditClick?.(proforma); - const handleDuplicate = () => actionHandlers.onDuplicateClick?.(proforma); - const handleCreateRecurring = () => actionHandlers.onCreateRecurringClick?.(proforma); - const handleArchive = () => actionHandlers.onArchiveClick?.(proforma); - const handleUnarchive = () => actionHandlers.onUnarchiveClick?.(proforma); - const handleIssue = () => actionHandlers.onIssueClick?.(proforma); - const handleDownloadPdf = () => actionHandlers.onDownloadPdf?.(proforma); - const handleDelete = () => actionHandlers.onDeleteClick?.(proforma); - const handleChangeStatus = () => { - if (!nextTransition) { - return; - } - - actionHandlers.onChangeStatusClick?.(proforma, nextTransition); - }; - - const getScopeReason = () => { - if (isArchivedScope) { - return t("pages.proformas.list.actions.disabled_reasons.archived_scope"); - } - - if (isDeletedScope) { - return t("pages.proformas.list.actions.disabled_reasons.deleted_scope"); - } - - return undefined; - }; - - const visibleActions: RdxRowAction[] = [ - { - id: "view", - label: t("pages.proformas.list.actions.view"), - icon: renderActionIcon(EyeIcon), - disabled: !actionHandlers.onViewClick || isDeletedScope, - disabledReason: isDeletedScope - ? t("pages.proformas.list.actions.disabled_reasons.deleted_scope") - : undefined, - onSelect: handleView, - }, - { - id: "edit", - label: t("pages.proformas.list.actions.edit"), - icon: renderActionIcon(PencilIcon), - disabled: !(actionHandlers.onEditClick && isNormalScope) || isIssued, - disabledReason: isNormalScope - ? isIssued - ? t("pages.proformas.list.actions.disabled_reasons.edit_issued") - : undefined - : getScopeReason(), - onSelect: handleEdit, - }, - ]; - - const menuActions: RdxRowAction[] = [ - { - id: "linked-invoice", - label: t("pages.proformas.list.actions.view_linked_invoice"), - icon: renderActionIcon(ExternalLinkIcon), - disabled: !(isIssued && proforma.linkedInvoiceId), - disabledReason: - isIssued && proforma.linkedInvoiceId - ? undefined - : t("pages.proformas.list.actions.disabled_reasons.linked_invoice_unavailable"), - onSelect: () => { - if (proforma.linkedInvoiceId) { - window.location.href = "/customer-invoices"; - } - }, - }, - { - id: "change-status", - label: t("pages.proformas.list.actions.change_status"), - icon: renderActionIcon(RefreshCwIcon), - disabled: - !(actionHandlers.onChangeStatusClick && isNormalScope && nextTransition) || - isIssued, - disabledReason: isNormalScope - ? isIssued - ? t("pages.proformas.list.actions.disabled_reasons.status_issued") - : nextTransition - ? undefined - : t("proformas.change_proforma_status_dialog.empty_available_statuses") - : getScopeReason(), - onSelect: handleChangeStatus, - }, - { - id: "issue", - label: t("pages.proformas.list.actions.issue"), - icon: renderActionIcon(FileTextIcon), - disabled: !(actionHandlers.onIssueClick && isNormalScope && isApproved) || isIssued, - disabledReason: isNormalScope - ? isApproved - ? undefined - : t("proformas.issue_proforma_dialog.not_allowed_description") - : getScopeReason(), - onSelect: handleIssue, - }, - { - id: "duplicate", - label: t("pages.proformas.list.actions.duplicate"), - icon: renderActionIcon(CopyIcon), - disabled: !actionHandlers.onDuplicateClick || isDeletedScope, - disabledReason: isDeletedScope - ? t("pages.proformas.list.actions.disabled_reasons.deleted_scope") - : undefined, - onSelect: handleDuplicate, - }, - { - id: "create-recurring", - label: t("pages.proformas.list.actions.create_recurring"), - icon: renderActionIcon(CalendarSyncIcon), - disabled: !(actionHandlers.onCreateRecurringClick && isNormalScope), - disabledReason: isNormalScope ? undefined : getScopeReason(), - onSelect: handleCreateRecurring, - }, - { - id: "archive", - label: t("pages.proformas.list.actions.archive"), - icon: renderActionIcon(FolderArchiveIcon), - disabled: !(actionHandlers.onArchiveClick && isArchivable), - disabledReason: actionHandlers.onArchiveClick - ? isNormalScope - ? t("proformas.archive.error_conflict_message") - : getScopeReason() - : undefined, - onSelect: handleArchive, - }, - { - id: "unarchive", - label: t("pages.proformas.list.actions.unarchive"), - icon: renderActionIcon(Undo2Icon), - disabled: !(actionHandlers.onUnarchiveClick && isUnarchivable), - disabledReason: actionHandlers.onUnarchiveClick - ? isArchivedScope - ? t("proformas.unarchive.error_conflict_message") - : t("pages.proformas.list.actions.disabled_reasons.archived_only") - : undefined, - onSelect: handleUnarchive, - }, - { - id: "download-pdf", - label: t("pages.proformas.list.actions.download_pdf"), - icon: renderActionIcon(FileDownIcon, isPDFLoading), - disabled: Boolean(!actionHandlers.onDownloadPdf || isDeletedScope || isPDFLoading), - disabledReason: isDeletedScope - ? t("pages.proformas.list.actions.disabled_reasons.deleted_scope") - : isPDFLoading - ? t("pages.proformas.list.actions.disabled_reasons.operation_in_progress") - : undefined, - onSelect: handleDownloadPdf, - }, - { - id: "delete", - label: t("pages.proformas.list.actions.delete"), - icon: renderActionIcon(Trash2Icon), - destructive: true, - disabled: !actionHandlers.onDeleteClick || isDeletedScope || !isDraft, - disabledReason: isDeletedScope - ? t("pages.proformas.list.actions.disabled_reasons.deleted_scope") - : isDraft - ? undefined - : t("proformas.delete_proforma_dialog.error_conflict_message"), - onSelect: handleDelete, - }, - ]; - - return ( - - ); - }, + cell: ({ row }) => ( + + ), }, ], [t, actionHandlers, scope]