From 2cff5051ac6e4d19a55294deb19192c260b66a6a Mon Sep 17 00:00:00 2001
From: "soroush.asadi"
Date: Sun, 21 Jun 2026 05:58:56 +0330
Subject: [PATCH] feat(rbac): gate pages and action buttons in the UI by
permission
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Nav already hides pages a role can't view (NAV_REQUIRED_PERMISSION). This wraps
the sensitive/CRUD action controls in so users only see what
they can do (server still enforces):
- POS/orders: void → VoidOrder, cancel → VoidOrder, transfer → EditOrder,
pay/split → HandlePayments
- menu/inventory/coupons/customers/reservations/expenses/taxes/branches:
add/edit/delete buttons → the matching Create/Edit/Delete permission
- reports CSV export → ExportReports; SMS send → SendSms, settings → ManageSmsSettings
- home dashboard: revenue/orders KPI queries gated on ViewReports so non-report
roles don't 403 on the landing page
(Refund/discount/comp/cash-drawer have no UI control yet — no buttons to gate.)
Co-Authored-By: Claude Opus 4.8
---
.../components/branches/branches-screen.tsx | 45 +++--
.../src/components/coupons/coupons-screen.tsx | 33 ++--
.../src/components/crm/crm-screen.tsx | 57 +++---
.../components/expenses/expenses-screen.tsx | 41 ++--
.../components/inventory/inventory-screen.tsx | 127 +++++++------
.../src/components/menu/menu-admin-screen.tsx | 175 ++++++++++--------
.../components/overview/overview-screen.tsx | 8 +-
.../src/components/pos/pos-pay-panel.tsx | 55 +++---
.../src/components/pos/pos-screen.tsx | 61 +++---
.../src/components/pos2/pos2-prototype.tsx | 21 ++-
.../src/components/pos2/pos2-screen.tsx | 21 ++-
.../src/components/reports/reports-screen.tsx | 21 ++-
.../reservations/reservations-screen.tsx | 75 ++++----
.../src/components/sms/sms-screen.tsx | 33 ++--
.../src/components/taxes/taxes-screen.tsx | 41 ++--
15 files changed, 457 insertions(+), 357 deletions(-)
diff --git a/web/dashboard/src/components/branches/branches-screen.tsx b/web/dashboard/src/components/branches/branches-screen.tsx
index ea9f764..8907c39 100644
--- a/web/dashboard/src/components/branches/branches-screen.tsx
+++ b/web/dashboard/src/components/branches/branches-screen.tsx
@@ -24,6 +24,7 @@ import {
AlertDialogTitle,
} from "@/components/ui/alert-dialog";
import { cn } from "@/lib/utils";
+import { Can } from "@/components/auth/can";
type Branch = {
id: string;
@@ -266,19 +267,21 @@ export function BranchesScreen() {
{t("review")}
-
+
+
+
))}
@@ -327,13 +330,15 @@ export function BranchesScreen() {
/>
-
+
+
+
{t("masterPlanHint")}
{t("branchSelectHint")}
diff --git a/web/dashboard/src/components/coupons/coupons-screen.tsx b/web/dashboard/src/components/coupons/coupons-screen.tsx
index 34584d8..0ab30ca 100644
--- a/web/dashboard/src/components/coupons/coupons-screen.tsx
+++ b/web/dashboard/src/components/coupons/coupons-screen.tsx
@@ -16,6 +16,7 @@ import { LabeledField } from "@/components/ui/labeled-field";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
import { ConfirmDialog } from "@/components/ui/confirm-dialog";
+import { Can } from "@/components/auth/can";
export function CouponsScreen() {
const t = useTranslations("coupons");
@@ -68,10 +69,12 @@ export function CouponsScreen() {
{t("title")}
-
+
+
+
{showForm && (
@@ -148,16 +151,18 @@ export function CouponsScreen() {
{c.usageLimit ? ` / ${formatNumber(c.usageLimit)}` : ""}
-
+
+
+
diff --git a/web/dashboard/src/components/crm/crm-screen.tsx b/web/dashboard/src/components/crm/crm-screen.tsx
index 7b50e87..b2d3b82 100644
--- a/web/dashboard/src/components/crm/crm-screen.tsx
+++ b/web/dashboard/src/components/crm/crm-screen.tsx
@@ -17,6 +17,7 @@ import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
import { ConfirmDialog } from "@/components/ui/confirm-dialog";
import { CustomerWizard, type CustomerWizardMode } from "@/components/crm/customer-wizard";
+import { Can } from "@/components/auth/can";
export function CrmScreen() {
const t = useTranslations("crm");
@@ -67,13 +68,15 @@ export function CrmScreen() {
{t("title")}
-
+
+
+
@@ -120,24 +123,28 @@ export function CrmScreen() {
-
-
+
+
+
+
+
+
diff --git a/web/dashboard/src/components/expenses/expenses-screen.tsx b/web/dashboard/src/components/expenses/expenses-screen.tsx
index 81afb40..90026a0 100644
--- a/web/dashboard/src/components/expenses/expenses-screen.tsx
+++ b/web/dashboard/src/components/expenses/expenses-screen.tsx
@@ -15,6 +15,7 @@ import { MoneyInput } from "@/components/ui/money-input";
import { JalaliDateField } from "@/components/ui/jalali-date-field";
import { LabeledField } from "@/components/ui/labeled-field";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
+import { Can } from "@/components/auth/can";
type Branch = { id: string; name: string };
type ShiftDto = {
@@ -146,14 +147,16 @@ export function ExpensesScreen() {
title={t("title")}
subtitle={t("subtitle")}
action={
-
+
+
+
}
/>
@@ -236,16 +239,18 @@ export function ExpensesScreen() {
{canDelete ? (
-
+
+
+
|
) : null}
diff --git a/web/dashboard/src/components/inventory/inventory-screen.tsx b/web/dashboard/src/components/inventory/inventory-screen.tsx
index 3803c12..1e5fd24 100644
--- a/web/dashboard/src/components/inventory/inventory-screen.tsx
+++ b/web/dashboard/src/components/inventory/inventory-screen.tsx
@@ -21,6 +21,7 @@ import { Badge } from "@/components/ui/badge";
import { cn } from "@/lib/utils";
import { notify } from "@/lib/notify";
import { useApiError } from "@/lib/use-api-error";
+import { Can } from "@/components/auth/can";
type Ingredient = {
id: string;
@@ -369,13 +370,15 @@ export function InventoryScreen() {
setReorder(e.target.value)} dir="ltr" className="text-end" />
-
+
+
+
@@ -458,14 +461,16 @@ export function InventoryScreen() {
{t("quantityEditHint")}
-
+
+
+
@@ -540,29 +549,31 @@ export function InventoryScreen() {
/>
) : null}
- 0}
- onClick={() => {
- const delta = parseFloat(adjustQty[ing.id] ?? "0");
- if (!delta) return;
- const paid = parseFloat(adjustPaid[ing.id] ?? "0");
- if (delta > 0 && paid <= 0) {
- notify.error(t("purchaseRequired"));
- return;
- }
- adjustStock.mutate({
- id: ing.id,
- delta,
- paid: delta > 0 ? paid : undefined,
- });
- setAdjustQty((s) => ({ ...s, [ing.id]: "" }));
- setAdjustPaid((s) => ({ ...s, [ing.id]: "" }));
- }}
- >
- {t("adjust")}
-
+
+ 0}
+ onClick={() => {
+ const delta = parseFloat(adjustQty[ing.id] ?? "0");
+ if (!delta) return;
+ const paid = parseFloat(adjustPaid[ing.id] ?? "0");
+ if (delta > 0 && paid <= 0) {
+ notify.error(t("purchaseRequired"));
+ return;
+ }
+ adjustStock.mutate({
+ id: ing.id,
+ delta,
+ paid: delta > 0 ? paid : undefined,
+ });
+ setAdjustQty((s) => ({ ...s, [ing.id]: "" }));
+ setAdjustPaid((s) => ({ ...s, [ing.id]: "" }));
+ }}
+ >
+ {t("adjust")}
+
+
{parseFloat(adjustQty[ing.id] ?? "0") > 0 ? (
{t("purchaseHint")}
diff --git a/web/dashboard/src/components/menu/menu-admin-screen.tsx b/web/dashboard/src/components/menu/menu-admin-screen.tsx
index f1e2e50..38f54ef 100644
--- a/web/dashboard/src/components/menu/menu-admin-screen.tsx
+++ b/web/dashboard/src/components/menu/menu-admin-screen.tsx
@@ -41,6 +41,7 @@ import { MenuItemMedia } from "@/components/menu/menu-item-media";
import { buildCategoryNameMap, inferMenuItemKind } from "@/lib/menu-item-image";
import { menuItemMatchesSearch } from "@/lib/menu-display";
import { BranchMenuOverrides } from "@/components/menu/branch-menu-overrides";
+import { Can } from "@/components/auth/can";
// ─── Types ────────────────────────────────────────────────────────────────────
@@ -565,27 +566,31 @@ export function MenuAdminScreen() {
{/* Edit category button */}
- openEditCategory(cat)}
- className="absolute end-1 top-1/2 -translate-y-1/2 flex size-6 cursor-pointer items-center justify-center rounded-md text-muted-foreground opacity-0 transition-opacity hover:bg-accent hover:text-foreground group-hover:opacity-100"
- >
-
-
+
+ openEditCategory(cat)}
+ className="absolute end-1 top-1/2 -translate-y-1/2 flex size-6 cursor-pointer items-center justify-center rounded-md text-muted-foreground opacity-0 transition-opacity hover:bg-accent hover:text-foreground group-hover:opacity-100"
+ >
+
+
+
))}
{/* Add category button */}
-
-
- {t("addCategory")}
-
+
+
+
+ {t("addCategory")}
+
+
@@ -632,14 +637,16 @@ export function MenuAdminScreen() {
))}
-
-
- {t("addCategory")}
-
+
+
+
+ {t("addCategory")}
+
+
{/* Search + Add bar */}
@@ -665,14 +672,16 @@ export function MenuAdminScreen() {
) : null}
-
-
- {t("newItem")}
-
+
+
+
+ {t("newItem")}
+
+
{/* Items grid */}
@@ -690,15 +699,17 @@ export function MenuAdminScreen() {
{itemSearch ? t("noItemsMatchSearch") : t("noItemsInCategory")}
{!itemSearch ? (
-
-
- {t("addItem")}
-
+
+
+
+ {t("addItem")}
+
+
) : null}
) : (
@@ -730,14 +741,16 @@ export function MenuAdminScreen() {
{/* Hover overlay — edit button */}
-
openEditItem(item)}
- >
-
- {t("editItem")}
-
+
+ openEditItem(item)}
+ >
+
+ {t("editItem")}
+
+
{/* Discount badge */}
@@ -933,21 +946,23 @@ export function MenuAdminScreen() {
{/* Actions */}
{editingItem ? (
-
- setConfirmDelete({
- kind: "item",
- id: editingItem.id,
- name: editingItem.name,
- })
- }
- >
-
- {tCommon("delete")}
-
+
+
+ setConfirmDelete({
+ kind: "item",
+ id: editingItem.id,
+ name: editingItem.name,
+ })
+ }
+ >
+
+ {tCommon("delete")}
+
+
) : (
)}
@@ -999,21 +1014,23 @@ export function MenuAdminScreen() {
{editingCategory ? (
-
- setConfirmDelete({
- kind: "category",
- id: editingCategory.id,
- name: editingCategory.name,
- })
- }
- >
-
- {tCommon("delete")}
-
+
+
+ setConfirmDelete({
+ kind: "category",
+ id: editingCategory.id,
+ name: editingCategory.name,
+ })
+ }
+ >
+
+ {tCommon("delete")}
+
+
) : (
)}
diff --git a/web/dashboard/src/components/overview/overview-screen.tsx b/web/dashboard/src/components/overview/overview-screen.tsx
index c0a2842..77540e4 100644
--- a/web/dashboard/src/components/overview/overview-screen.tsx
+++ b/web/dashboard/src/components/overview/overview-screen.tsx
@@ -19,6 +19,7 @@ import {
import { Link } from "@/i18n/routing";
import { apiGet } from "@/lib/api/client";
import { useAuthStore } from "@/lib/stores/auth.store";
+import { useHasPermission } from "@/lib/permissions";
import { useLiveClock } from "@/lib/hooks/use-live-clock";
import {
addDaysIso,
@@ -100,6 +101,9 @@ export function OverviewScreen() {
const cafeId = useAuthStore((s) => s.user?.cafeId);
const branchId = useAuthStore((s) => s.user?.branchId ?? null);
const role = useAuthStore((s) => s.user?.role);
+ // KPI cards surface revenue/orders/net income — report data. Don't fetch (and
+ // 403) for roles without ViewReports; the cards simply stay empty for them.
+ const canViewReports = useHasPermission("ViewReports");
const clock = useLiveClock(10_000);
@@ -122,7 +126,7 @@ export function OverviewScreen() {
apiGet(
`/api/cafes/${cafeId}/reports/daily/range?from=${sevenDaysAgo}&to=${today}`
),
- enabled: !!cafeId,
+ enabled: !!cafeId && canViewReports,
staleTime: 60_000,
});
@@ -132,7 +136,7 @@ export function OverviewScreen() {
apiGet(
`/api/cafes/${cafeId}/reports/daily/range?from=${yesterday}&to=${yesterday}`
),
- enabled: !!cafeId,
+ enabled: !!cafeId && canViewReports,
staleTime: 300_000,
});
diff --git a/web/dashboard/src/components/pos/pos-pay-panel.tsx b/web/dashboard/src/components/pos/pos-pay-panel.tsx
index 6a1a8e7..50e3420 100644
--- a/web/dashboard/src/components/pos/pos-pay-panel.tsx
+++ b/web/dashboard/src/components/pos/pos-pay-panel.tsx
@@ -13,6 +13,7 @@ import { formatCurrency, formatNumber } from "@/lib/format";
import { formatPosOrderLabel } from "@/lib/pos-order-label";
import { formatOrderNumber } from "@/lib/order-number";
import { PosTableBoard } from "@/components/pos/pos-table-board";
+import { Can } from "@/components/auth/can";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { LabeledField } from "@/components/ui/labeled-field";
@@ -613,24 +614,26 @@ export function PosPayPanel({ cafeId, numberLocale, branchId = null }: PosPayPan
className="h-9"
maxLength={500}
/>
- {
- if (!selected) return;
- const ok = await confirmDialog({
- description: t("cancelOrderConfirm"),
- variant: "destructive",
- confirmLabel: t("cancelOrder"),
- });
- if (!ok) return;
- cancelOrder.mutate({ orderId: selected.id, reason: cancelReason });
- }}
- >
- {cancelOrder.isPending ? "..." : t("cancelOrder")}
-
+
+ {
+ if (!selected) return;
+ const ok = await confirmDialog({
+ description: t("cancelOrderConfirm"),
+ variant: "destructive",
+ confirmLabel: t("cancelOrder"),
+ });
+ if (!ok) return;
+ cancelOrder.mutate({ orderId: selected.id, reason: cancelReason });
+ }}
+ >
+ {cancelOrder.isPending ? "..." : t("cancelOrder")}
+
+
>
diff --git a/web/dashboard/src/components/pos/pos-screen.tsx b/web/dashboard/src/components/pos/pos-screen.tsx
index 25ebe0e..a47169b 100644
--- a/web/dashboard/src/components/pos/pos-screen.tsx
+++ b/web/dashboard/src/components/pos/pos-screen.tsx
@@ -51,6 +51,7 @@ import {
buildCategoryNameMap,
inferMenuItemKind,
} from "@/lib/menu-item-image";
+import { Can } from "@/components/auth/can";
import { PosPayPanel } from "@/components/pos/pos-pay-panel";
import { PosTableBoard } from "@/components/pos/pos-table-board";
import { PosCustomerPicker } from "@/components/pos/pos-customer-picker";
@@ -1174,15 +1175,17 @@ export function PosScreen() {
{/* Transfer table (for table orders with active session) */}
{activeOrderId && tableId ? (
-
setShowTransferPicker(true)}
- >
- {t("transferTable")}
-
+
+ setShowTransferPicker(true)}
+ >
+ {t("transferTable")}
+
+
) : null}
{/* Assign table button (for counter orders) */}
@@ -1248,14 +1251,16 @@ export function PosScreen() {
line.orderItemId &&
!line.isVoided &&
activeOrderId ? (
-
handleVoidItem(line.orderItemId!)}
- aria-label={t("voidItem")}
- >
- {t("void")}
-
+
+ handleVoidItem(line.orderItemId!)}
+ aria-label={t("voidItem")}
+ >
+ {t("void")}
+
+
) : null}
{!line.isVoided ? (
<>
@@ -1443,16 +1448,18 @@ export function PosScreen() {
) : null}
-
submitOrderAndPay.mutate()}
- >
- {submitOrderAndPay.isPending
- ? "..."
- : t("submitOrderAndPay")}
-
+
+ submitOrderAndPay.mutate()}
+ >
+ {submitOrderAndPay.isPending
+ ? "..."
+ : t("submitOrderAndPay")}
+
+
ارسال
-
- پرداخت
-
+
+
+ پرداخت
+
+
نگهداشتن
-
- تقسیم
-
+
+
+ تقسیم
+
+
);
diff --git a/web/dashboard/src/components/pos2/pos2-screen.tsx b/web/dashboard/src/components/pos2/pos2-screen.tsx
index 105d9b8..dacad91 100644
--- a/web/dashboard/src/components/pos2/pos2-screen.tsx
+++ b/web/dashboard/src/components/pos2/pos2-screen.tsx
@@ -25,6 +25,7 @@ import { apiGet, apiPost, ApiClientError } from "@/lib/api/client";
import { submitOrderToApi, orderAmountDue, isLocalOrder } from "@/lib/pos/submit-order";
import { requestPosPayment, posDeviceErrorMessage } from "@/lib/api/pos-device";
import { PosCustomerPicker } from "@/components/pos/pos-customer-picker";
+import { Can } from "@/components/auth/can";
import type { Customer, MenuItem, Order, TableBoardItem } from "@/lib/api/types";
import { usePos2Categories, usePos2Menu, usePos2Tables, useMenuById } from "@/lib/pos2/use-pos2";
@@ -729,17 +730,21 @@ function Ticket({
className="flex min-h-[56px] items-center justify-center gap-2 rounded-xl bg-primary text-base font-bold text-primary-foreground transition-colors hover:bg-primary/90 disabled:opacity-40 active:scale-[0.98]">
ارسال{pendingCount > 0 ? ` (${fmt(pendingCount)})` : ""}
-
- پرداخت
-
+
+
+ پرداخت
+
+
نگهداشتن
-
- تقسیم
-
+
+
+ تقسیم
+
+
);
diff --git a/web/dashboard/src/components/reports/reports-screen.tsx b/web/dashboard/src/components/reports/reports-screen.tsx
index e16a8d5..64a9639 100644
--- a/web/dashboard/src/components/reports/reports-screen.tsx
+++ b/web/dashboard/src/components/reports/reports-screen.tsx
@@ -33,6 +33,7 @@ import { ReportsChartsFallback } from "@/components/reports/reports-charts-fallb
import type { ReportsChartsProps } from "@/components/reports/reports-charts.types";
import { PaymentCorrectionsTab } from "@/components/reports/payment-corrections-tab";
import { AuditLogsTab } from "@/components/reports/audit-logs-tab";
+import { Can } from "@/components/auth/can";
const LazyReportsCharts = lazy(() =>
import("@/components/reports/reports-charts").then((m) => ({
@@ -218,15 +219,17 @@ export function ReportsScreen() {
subtitle={t("subtitle")}
action={
tab === "performance" ? (
-
-
- {t("exportCsv")}
-
+
+
+
+ {t("exportCsv")}
+
+
) : undefined
}
/>
diff --git a/web/dashboard/src/components/reservations/reservations-screen.tsx b/web/dashboard/src/components/reservations/reservations-screen.tsx
index d6113e2..36d86e8 100644
--- a/web/dashboard/src/components/reservations/reservations-screen.tsx
+++ b/web/dashboard/src/components/reservations/reservations-screen.tsx
@@ -19,6 +19,7 @@ import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
import { cn } from "@/lib/utils";
import type { Table } from "@/lib/api/types";
+import { Can } from "@/components/auth/can";
type ReservationStatus =
| "Pending"
@@ -194,12 +195,14 @@ export function ReservationsScreen() {
/>
- createReservation.mutate()}
- disabled={!guestName.trim() || createReservation.isPending}
- >
- {createReservation.isPending ? "..." : t("create")}
-
+
+ createReservation.mutate()}
+ disabled={!guestName.trim() || createReservation.isPending}
+ >
+ {createReservation.isPending ? "..." : t("create")}
+
+
@@ -228,19 +231,23 @@ export function ReservationsScreen() {
{r.status === "Pending" && (
<>
- updateStatus.mutate({ id: r.id, status: "Confirmed" })}
- >
- {t("confirm")}
-
- updateStatus.mutate({ id: r.id, status: "Cancelled" })}
- >
- {t("cancel")}
-
+
+ updateStatus.mutate({ id: r.id, status: "Confirmed" })}
+ >
+ {t("confirm")}
+
+
+
+ updateStatus.mutate({ id: r.id, status: "Cancelled" })}
+ >
+ {t("cancel")}
+
+
>
)}
{(r.status === "Confirmed" || r.status === "Seated") && (
@@ -249,23 +256,27 @@ export function ReservationsScreen() {
)}
{r.status === "Seated" && (
+
+ updateStatus.mutate({ id: r.id, status: "Completed" })}
+ >
+ {t("markCompleted")}
+
+
+ )}
+
updateStatus.mutate({ id: r.id, status: "Completed" })}
+ variant="ghost"
+ className="text-red-600 hover:bg-red-50 hover:text-red-700"
+ aria-label={tCommon("delete")}
+ onClick={() => setDeleteTarget(r)}
>
- {t("markCompleted")}
+
- )}
- setDeleteTarget(r)}
- >
-
-
+
diff --git a/web/dashboard/src/components/sms/sms-screen.tsx b/web/dashboard/src/components/sms/sms-screen.tsx
index f52829d..51cf7ee 100644
--- a/web/dashboard/src/components/sms/sms-screen.tsx
+++ b/web/dashboard/src/components/sms/sms-screen.tsx
@@ -14,6 +14,7 @@ import { Input } from "@/components/ui/input";
import { LabeledField } from "@/components/ui/labeled-field";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { cn } from "@/lib/utils";
+import { Can } from "@/components/auth/can";
const GROUPS: (CustomerGroup | "all")[] = ["all", "Regular", "Vip", "New", "Employee"];
const MANAGER_ROLES = new Set(["Owner", "Manager"]);
@@ -195,13 +196,15 @@ export function SmsScreen() {
{/* Send button */}
- sendCampaign.mutate()}
- >
- {sendCampaign.isPending ? t("sending") : t("send")}
-
+
+ sendCampaign.mutate()}
+ >
+ {sendCampaign.isPending ? t("sending") : t("send")}
+
+
{/* Result banner */}
{result && (
@@ -314,13 +317,15 @@ function ProviderSettingsCard({
{settings?.isConfigured ? t("configured") : t("notConfigured")}
- save.mutate()}
- >
- {save.isPending ? t("saving") : t("save")}
-
+
+ save.mutate()}
+ >
+ {save.isPending ? t("saving") : t("save")}
+
+
diff --git a/web/dashboard/src/components/taxes/taxes-screen.tsx b/web/dashboard/src/components/taxes/taxes-screen.tsx
index e27d2e0..fe609d3 100644
--- a/web/dashboard/src/components/taxes/taxes-screen.tsx
+++ b/web/dashboard/src/components/taxes/taxes-screen.tsx
@@ -15,6 +15,7 @@ import { LabeledField } from "@/components/ui/labeled-field";
import { Card, CardContent } from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
import { useConfirm } from "@/components/providers/confirm-provider";
+import { Can } from "@/components/auth/can";
interface TaxRow {
id: string;
@@ -89,14 +90,16 @@ export function TaxesScreen() {
subtitle={t("subtitle")}
action={
canEdit ? (
- addTax.mutate()}
- >
-
- {t("addTax")}
-
+
+ addTax.mutate()}
+ >
+
+ {t("addTax")}
+
+
) : undefined
}
/>
@@ -152,16 +155,18 @@ export function TaxesScreen() {
) : null}
{canEdit ? (
- handleRemove(tax)}
- aria-label={t("delete")}
- >
-
-
+
+ handleRemove(tax)}
+ aria-label={t("delete")}
+ >
+
+
+
) : null}