diff --git a/src/dashboard/DashboardGrids.tsx b/src/dashboard/DashboardGrids.tsx
index ba23661..e7d8a55 100644
--- a/src/dashboard/DashboardGrids.tsx
+++ b/src/dashboard/DashboardGrids.tsx
@@ -10,6 +10,7 @@ import {
readyToPayColumns,
} from "@/dashboard/columns";
import { EMPTY_INVOICE_FILTERS, type InvoiceFilterState } from "@/dashboard/invoice-filters";
+import { InvoiceTabLabel } from "@/dashboard/invoice-tabs";
import { countSelectedRows } from "@/dashboard/selection";
import { useInvoices, useUpdateInvoicePayDate } from "@/domain/invoices/use-invoices";
import { areMocksEnabled, type MockInvoice } from "@/mocks";
@@ -24,6 +25,27 @@ const emptySelection: GridRowSelectionModel = {
const emptyFilters = EMPTY_INVOICE_FILTERS;
+const invoiceTabsSx = {
+ minHeight: 44,
+ "& .MuiTab-root": {
+ bgcolor: "rgba(47,128,237,0.12)",
+ mr: 0.5,
+ borderTopLeftRadius: 6,
+ borderTopRightRadius: 6,
+ color: "text.primary",
+ textTransform: "none",
+ },
+ "& .Mui-selected": {
+ bgcolor: "#fff !important",
+ color: "text.primary !important",
+ },
+ "& .MuiTabs-indicator": {
+ height: 3,
+ borderRadius: 1,
+ backgroundColor: "#7B61FF",
+ },
+} as const;
+
const rowClickSx = {
border: 1,
borderColor: "divider",
@@ -134,47 +156,87 @@ export function DashboardGrids() {
}}
variant="scrollable"
aria-label="Invoice Processing tabs"
- sx={{
- minHeight: 44,
- "& .MuiTab-root": {
- bgcolor: "rgba(47,128,237,0.12)",
- mr: 0.5,
- borderTopLeftRadius: 6,
- borderTopRightRadius: 6,
- color: "text.primary",
- },
- "& .Mui-selected": {
- bgcolor: "#fff !important",
- color: "text.primary !important",
- },
- "& .MuiTabs-indicator": { display: "none" },
- }}
+ sx={invoiceTabsSx}
>
+ }
value="attention"
data-testid="tab-pending"
/>
-
+ }
+ value="all"
+ data-testid="tab-all"
+ />
+
+ }
value="approved"
data-testid="tab-ready"
/>
+ }
value="rejected"
data-testid="tab-rejected"
/>
-
+
+ }
+ value="late"
+ data-testid="tab-late"
+ />
{attentionRows.length > 0 && tab === "attention" ? (
-
- {attentionRows.length} invoices require approval. Show Invoices ready to approve.
-
+
+ {attentionRows.length} invoices require approval. Show invoices ready to approve.
+
) : null}
-
-
+
+
+ onFiltersChange({ ...filters, action: value })}
+ renderInput={(params) => (
+
+ )}
+ />
+
+ onFiltersChange({ ...filters, action: value })}
- renderInput={(params) => }
+ name="vendor"
+ id="vendor"
+ placeholder="Vendor"
+ value={filters.vendorQuery}
+ onChange={(event) => onFiltersChange({ ...filters, vendorQuery: event.target.value })}
+ sx={fieldSx}
+ slotProps={{
+ htmlInput: { "data-testid": "vendor-filter", "aria-label": "Vendor" },
+ input: {
+ endAdornment: filters.vendorQuery ? (
+
+
+
+ ) : undefined,
+ },
+ }}
/>
-
- onFiltersChange({ ...filters, vendorQuery: event.target.value })}
- sx={{ minWidth: 180 }}
- slotProps={{
- htmlInput: { "data-testid": "vendor-filter" },
- input: {
- endAdornment: filters.vendorQuery ? (
-
-
-
- ) : undefined,
- },
- }}
- />
-
-
-
-
-
-
-
-
-
-
-
- {trailingActions}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {trailingActions}
+
);
}
diff --git a/src/dashboard/invoice-tabs.tsx b/src/dashboard/invoice-tabs.tsx
new file mode 100644
index 0000000..6e18d1f
--- /dev/null
+++ b/src/dashboard/invoice-tabs.tsx
@@ -0,0 +1,40 @@
+import ErrorOutlineIcon from "@mui/icons-material/ErrorOutline";
+import { Box, Stack } from "@mui/material";
+import type { ReactElement } from "react";
+
+export function InvoiceTabLabel({
+ title,
+ count,
+ active = false,
+ urgency = false,
+}: {
+ title: string;
+ count: number;
+ active?: boolean;
+ urgency?: boolean;
+}): ReactElement {
+ return (
+
+ {title}
+ {urgency ? : null}
+
+ {count}
+
+
+ );
+}