price adjustment and stock adjustments
This commit is contained in:
@@ -25,7 +25,10 @@ import {
|
||||
HelpCircle,
|
||||
IdCard,
|
||||
Inbox,
|
||||
ClipboardCheck,
|
||||
Landmark,
|
||||
PiggyBank,
|
||||
Tag,
|
||||
LayoutGrid,
|
||||
LayoutList,
|
||||
LayoutTemplate,
|
||||
@@ -38,7 +41,6 @@ import {
|
||||
PackageCheck,
|
||||
PackageSearch,
|
||||
PackageX,
|
||||
Percent,
|
||||
PlayCircle,
|
||||
PieChart,
|
||||
Receipt,
|
||||
@@ -50,6 +52,7 @@ import {
|
||||
ShieldCheck,
|
||||
ShoppingCart,
|
||||
SlidersHorizontal,
|
||||
Tags,
|
||||
Truck,
|
||||
Undo2,
|
||||
Users,
|
||||
@@ -59,6 +62,7 @@ import {
|
||||
type LucideIcon,
|
||||
} from "lucide-react"
|
||||
|
||||
import { approvalsApi } from "@/lib/api/approvals"
|
||||
import { cn } from "@/lib/utils"
|
||||
import { useAuth } from "@/components/auth/AuthProvider"
|
||||
import { useTrackingSettings } from "@/hooks/use-tracking-settings"
|
||||
@@ -102,9 +106,11 @@ const navItems: {
|
||||
icon: ListTree,
|
||||
altCodes: ["products.brand", "products.uom"],
|
||||
},
|
||||
{ title: "Tax Rates", code: "products.tax-rates", href: "/dashboard/products/tax-rates", icon: Percent },
|
||||
{ title: "Price Adjustments", code: "products.price-adjustments", href: "/dashboard/products/price-adjustments", icon: Tag },
|
||||
],
|
||||
},
|
||||
// Open to everyone signed in: the inbox only lists what the user may approve and their own requests.
|
||||
{ title: "Approvals", code: "approvals", href: "/dashboard/approvals", icon: ClipboardCheck },
|
||||
{
|
||||
title: "Procurement",
|
||||
code: "procurement",
|
||||
@@ -135,7 +141,8 @@ const navItems: {
|
||||
{ title: "Customers", code: "sales.invoices", href: "/dashboard/customers", icon: Users },
|
||||
{ title: "Bundle Templates", code: "sales.bundle-templates", href: "/dashboard/sales/bundles/templates", icon: LayoutList },
|
||||
{ title: "Free Issues", code: "sales.free-issues", href: "/dashboard/sales/free-issues", icon: PackageX },
|
||||
{ title: "Day End", code: "sales.day-end", href: "/dashboard/sales/day-end", icon: Lock },
|
||||
{ title: "Approved Invoices", code: "sales.day-end", href: "/dashboard/sales/day-end", icon: Lock },
|
||||
{ title: "Day-End Report", code: "sales.day-end-report", href: "/dashboard/sales/day-end-report", icon: LineChart },
|
||||
// { title: "Reports", code: "sales.reports", href: "/dashboard/sales/reports", icon: FileBarChart },
|
||||
],
|
||||
},
|
||||
@@ -215,6 +222,9 @@ const navItems: {
|
||||
{ title: "Cash / Bank Accounts", code: "accounts.bank-accounts", href: "/dashboard/accounts/bank-accounts", icon: Wallet },
|
||||
{ title: "Cheque Books", code: "accounts.cheque-books", href: "/dashboard/accounts/cheque-books", icon: BookText },
|
||||
{ title: "Received Cheques", code: "accounts.received-cheques", href: "/dashboard/accounts/received-cheques", icon: Inbox },
|
||||
{ title: "Expenses", code: "accounts.expenses", href: "/dashboard/accounts/expenses", icon: ReceiptText },
|
||||
{ title: "Expense Setup", code: "accounts.expense-setup", href: "/dashboard/accounts/expense-setup", icon: Tags },
|
||||
{ title: "Bank Deposits", code: "accounts.bank-deposits", href: "/dashboard/accounts/bank-deposits", icon: PiggyBank },
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -226,6 +236,7 @@ const navItems: {
|
||||
{ title: "Branches", code: "settings.branches", href: "/dashboard/settings/branches", icon: MapPin },
|
||||
{ title: "Roles", code: "settings.roles", href: "/dashboard/settings/roles", icon: ShieldCheck },
|
||||
{ title: "Users", code: "settings.users", href: "/dashboard/settings/users", icon: Users },
|
||||
{ title: "Approvals", code: "settings.approvals", href: "/dashboard/settings/approvals", icon: ClipboardCheck },
|
||||
{ title: "Configuration", code: "products.configuration", href: "/dashboard/settings/configuration", icon: SlidersHorizontal },
|
||||
],
|
||||
},
|
||||
@@ -239,6 +250,7 @@ function SidebarContent({
|
||||
onClose,
|
||||
pathname,
|
||||
isMobile,
|
||||
approvalCount,
|
||||
}: {
|
||||
items: typeof navItems
|
||||
collapsed: boolean
|
||||
@@ -246,6 +258,8 @@ function SidebarContent({
|
||||
onClose?: () => void
|
||||
pathname: string
|
||||
isMobile: boolean
|
||||
/** Requests the user can approve — the badge on Approvals. */
|
||||
approvalCount: number
|
||||
}) {
|
||||
const iconOnly = !isMobile && collapsed
|
||||
|
||||
@@ -367,6 +381,11 @@ function SidebarContent({
|
||||
className={cn("size-3.5 shrink-0", isActive ? "text-primary" : "text-muted-foreground")}
|
||||
/>
|
||||
{!iconOnly && <span className="flex-1">{item.title}</span>}
|
||||
{item.code === "approvals" && approvalCount > 0 && (
|
||||
<span className="ml-auto rounded-full bg-primary px-1.5 text-[10px] font-semibold leading-4 text-primary-foreground tabular-nums">
|
||||
{approvalCount}
|
||||
</span>
|
||||
)}
|
||||
</Link>
|
||||
)}
|
||||
</div>
|
||||
@@ -449,7 +468,16 @@ export function AppSidebar() {
|
||||
// seed grants it. This is also flagged in 02-SECURITY.md as the AR-09 sidebar-visibility
|
||||
// stopgap for HRM's salary/PII data — it hides HRM from the UI but doesn't enforce
|
||||
// anything server-side.
|
||||
const bypassCodes = new Set(["procurement", "sales", "sales-returns", "hrm", "production", "stock"])
|
||||
// "approvals" is not a permission at all — the inbox is for everyone (see its nav entry).
|
||||
const bypassCodes = new Set(["procurement", "sales", "sales-returns", "hrm", "production", "stock", "approvals"])
|
||||
|
||||
// Requests waiting for this user — the Approvals badge. Refreshed on navigation, which is when
|
||||
// someone has most likely just approved or submitted something.
|
||||
const [approvalCount, setApprovalCount] = useState(0)
|
||||
useEffect(() => {
|
||||
if (loading) return
|
||||
approvalsApi.pending().then((p) => setApprovalCount(p.actionableCount)).catch(() => setApprovalCount(0))
|
||||
}, [loading, pathname])
|
||||
const visibleItems = loading
|
||||
? []
|
||||
: navItems
|
||||
@@ -489,6 +517,7 @@ export function AppSidebar() {
|
||||
onCollapse={() => setCollapsed((v) => !v)}
|
||||
pathname={pathname}
|
||||
isMobile={false}
|
||||
approvalCount={approvalCount}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -525,6 +554,7 @@ export function AppSidebar() {
|
||||
onClose={() => setMobileOpen(false)}
|
||||
pathname={pathname}
|
||||
isMobile={true}
|
||||
approvalCount={approvalCount}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
|
||||
@@ -72,6 +72,9 @@ const ACCOUNTS_TITLES: Record<string, string> = {
|
||||
"/dashboard/accounts/cheque-books/new": "New Cheque Book",
|
||||
"/dashboard/accounts/received-cheques": "Received Cheques",
|
||||
"/dashboard/accounts/received-cheques/new": "New Received Cheque",
|
||||
"/dashboard/accounts/expenses": "Expenses",
|
||||
"/dashboard/accounts/expenses/new": "New Expense",
|
||||
"/dashboard/accounts/expense-setup": "Expense Setup",
|
||||
}
|
||||
|
||||
const STOCK_TITLES: Record<string, string> = {
|
||||
@@ -104,6 +107,7 @@ function titleFromPath(pathname: string) {
|
||||
if (pathname === "/dashboard/sales/invoices") return "Sales"
|
||||
if (pathname === "/dashboard/sales/invoices/new") return "New Sale"
|
||||
if (pathname === "/dashboard/sales/warranties") return "Warranties"
|
||||
if (pathname === "/dashboard/sales/day-end-report") return "Day-End Report"
|
||||
|
||||
if (pathname === "/dashboard/receiving/grn") return "Goods Receipt Notes"
|
||||
if (pathname === "/dashboard/receiving/grn/new") return "Create Goods Receipt Note"
|
||||
@@ -113,6 +117,8 @@ function titleFromPath(pathname: string) {
|
||||
|
||||
if (ACCOUNTS_TITLES[pathname]) return ACCOUNTS_TITLES[pathname]
|
||||
if (/^\/dashboard\/accounts\/cheque-books\/[^/]+$/.test(pathname)) return "Cheque Book"
|
||||
if (/^\/dashboard\/accounts\/expenses\/[^/]+\/edit$/.test(pathname)) return "Edit Expense"
|
||||
if (/^\/dashboard\/accounts\/expenses\/[^/]+$/.test(pathname)) return "Expense"
|
||||
|
||||
if (STOCK_TITLES[pathname]) return STOCK_TITLES[pathname]
|
||||
if (/^\/dashboard\/stock\/transfers\/[^/]+$/.test(pathname)) return "Stock Transfer"
|
||||
|
||||
Reference in New Issue
Block a user