Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions apps/web/src/components/app/AppSidebar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ function NavigationPanel({ mobile = false }) {
return (
<>
<SidebarHeader className="border-b border-sidebar-border">
<div className="flex h-11 items-center px-1">
<div className={`flex h-11 items-center ${expanded ? 'px-1' : 'justify-center'}`}>
<AppBrand compact={!expanded} />
</div>
</SidebarHeader>
Expand All @@ -75,7 +75,7 @@ function NavigationPanel({ mobile = false }) {
return (
<Tooltip key={to}>
<TooltipTrigger asChild>
<SidebarMenuButton asChild active={active}>
<SidebarMenuButton asChild active={active} className={!expanded ? 'justify-center px-0' : undefined}>
<NavLink
to={to}
end={to === '/'}
Expand All @@ -100,7 +100,7 @@ function NavigationPanel({ mobile = false }) {
<SidebarMenu>
<Tooltip>
<TooltipTrigger asChild>
<SidebarMenuButton asChild>
<SidebarMenuButton asChild className={!expanded ? 'justify-center px-0' : undefined}>
<a href="/public-display" target="_blank" rel="noreferrer">
<IconScreenShare aria-hidden="true" stroke={1.8} />
{expanded && (
Expand All @@ -120,7 +120,7 @@ function NavigationPanel({ mobile = false }) {
</SidebarContent>

<SidebarFooter>
<div className={expanded ? 'rounded-md bg-sidebar-accent/35' : 'flex justify-center'}>
<div className={expanded ? 'rounded-md bg-sidebar-accent/35' : 'flex w-full justify-center'}>
<UserMenu compact={!expanded} sidebar />
</div>
</SidebarFooter>
Expand Down
7 changes: 4 additions & 3 deletions apps/web/src/components/app/UserMenu.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,13 @@ export function UserMenu({ compact = false, sidebar = false }) {
className={
sidebar
? compact
? 'size-10 min-h-10 p-0 text-sidebar-foreground hover:bg-sidebar-accent hover:text-sidebar-accent-foreground'
: 'h-auto min-h-10 w-full justify-start gap-3 px-2.5 py-2 text-left text-sidebar-foreground hover:bg-sidebar-accent hover:text-sidebar-accent-foreground'
? 'size-10 min-h-10 bg-transparent p-0 text-sidebar-foreground hover:bg-sidebar-accent hover:text-sidebar-accent-foreground'
: 'h-auto min-h-10 w-full justify-start gap-3 bg-transparent px-2.5 py-2 text-left text-sidebar-foreground hover:bg-sidebar-accent hover:text-sidebar-accent-foreground'
: compact
? 'size-10 min-h-10 p-0'
: 'h-auto min-h-10 justify-start gap-3 px-2.5 py-2 text-left'
}
aria-label={compact ? `Menu akun ${user?.name ?? ''}` : undefined}
>
<Avatar className="size-8">
<AvatarFallback className={sidebar ? 'bg-sidebar-accent text-sidebar-accent-foreground' : undefined}>{initials}</AvatarFallback>
Expand All @@ -49,7 +50,7 @@ export function UserMenu({ compact = false, sidebar = false }) {
)}
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end" className="w-56">
<DropdownMenuContent align={sidebar ? "start" : "end"} side={sidebar ? "right" : "bottom"} sideOffset={8} className="w-56">
<DropdownMenuLabel>
<span className="block text-xs font-semibold text-foreground">{user?.name}</span>
<span className="mt-0.5 block text-[11px] font-normal text-muted-foreground">{role}</span>
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/components/ui/alert-dialog.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ function AlertDialogContent({
data-slot="alert-dialog-content"
data-size={size}
className={cn(
"group/alert-dialog-content fixed top-1/2 left-1/2 z-50 grid w-full -translate-x-1/2 -translate-y-1/2 gap-4 rounded-xl bg-popover p-4 text-popover-foreground ring-1 ring-foreground/10 duration-100 outline-none data-[size=default]:max-w-xs data-[size=sm]:max-w-xs data-[size=default]:sm:max-w-sm data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",
"group/alert-dialog-content fixed top-1/2 left-1/2 z-[60] grid w-full -translate-x-1/2 -translate-y-1/2 gap-4 rounded-xl bg-popover p-4 text-popover-foreground ring-1 ring-foreground/10 duration-100 outline-none data-[size=default]:max-w-xs data-[size=sm]:max-w-xs data-[size=default]:sm:max-w-sm data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",
className
)}
{...props}
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/components/ui/dialog.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const DialogContent = React.forwardRef(function DialogContent({ className, child
<DialogPrimitive.Content
ref={ref}
className={cn(
'fixed left-1/2 top-1/2 z-50 grid w-[min(94vw,520px)] -translate-x-1/2 -translate-y-1/2 gap-4 rounded-xl border bg-card p-5 text-card-foreground shadow-xl outline-none',
'fixed left-1/2 top-1/2 z-[60] grid w-[min(94vw,520px)] -translate-x-1/2 -translate-y-1/2 gap-4 rounded-xl border bg-card p-5 text-card-foreground shadow-xl outline-none',
className
)}
{...props}
Expand Down
4 changes: 2 additions & 2 deletions apps/web/src/components/ui/dropdown-menu.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ const DropdownMenuSubContent = React.forwardRef(function DropdownMenuSubContent(
return (
<DropdownMenuPrimitive.SubContent
ref={ref}
className={cn('min-w-40 rounded-md border bg-popover p-1 text-popover-foreground shadow-lg', className)}
className={cn('z-[70] min-w-40 rounded-md border bg-popover p-1 text-popover-foreground shadow-lg', className)}
{...props}
/>
);
Expand All @@ -52,7 +52,7 @@ const DropdownMenuContent = React.forwardRef(function DropdownMenuContent(
<DropdownMenuPrimitive.Content
ref={ref}
sideOffset={sideOffset}
className={cn('min-w-48 rounded-md border bg-popover p-1 text-popover-foreground shadow-lg', className)}
className={cn('z-[70] min-w-48 rounded-md border bg-popover p-1 text-popover-foreground shadow-lg', className)}
{...props}
/>
</DropdownMenuPortal>
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/components/ui/select.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ function SelectContent({
<SelectPrimitive.Content
data-slot="select-content"
data-align-trigger={position === "item-aligned"}
className={cn("relative z-50 max-h-(--radix-select-content-available-height) min-w-36 origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-lg bg-popover text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 data-[align-trigger=true]:animate-none data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95", position ==="popper"&&"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1", className )}
className={cn("relative z-[70] max-h-(--radix-select-content-available-height) min-w-36 origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-lg bg-popover text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 data-[align-trigger=true]:animate-none data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95", position ==="popper"&&"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1", className )}
position={position}
align={align}
{...props}
Expand Down
4 changes: 2 additions & 2 deletions apps/web/src/components/ui/sheet.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const SheetClose = DialogPrimitive.Close;
const SheetPortal = DialogPrimitive.Portal;

function SheetOverlay({ className, ...props }) {
return <DialogPrimitive.Overlay className={cn('fixed inset-0 bg-black/40 backdrop-blur-[2px]', className)} {...props} />;
return <DialogPrimitive.Overlay className={cn('fixed inset-0 z-50 bg-black/40 backdrop-blur-[2px]', className)} {...props} />;
}

const SheetContent = React.forwardRef(function SheetContent(
Expand All @@ -27,7 +27,7 @@ const SheetContent = React.forwardRef(function SheetContent(
<SheetOverlay />
<DialogPrimitive.Content
ref={ref}
className={cn('fixed bg-card text-card-foreground shadow-xl outline-none', sideClasses[side], className)}
className={cn('fixed z-[60] bg-card text-card-foreground shadow-xl outline-none', sideClasses[side], className)}
{...props}
>
{children}
Expand Down
13 changes: 7 additions & 6 deletions apps/web/src/components/ui/sidebar.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as React from 'react';
import { Slot } from '@radix-ui/react-slot';
import { IconLayoutSidebarLeftCollapse, IconMenu2 } from '@tabler/icons-react';
import { IconLayoutSidebarLeftCollapse, IconLayoutSidebarLeftExpand, IconMenu2 } from '@tabler/icons-react';
import { cn } from '@/lib/utils';
import { Button } from '@/components/ui/button';
import { Sheet, SheetContent, SheetTitle } from '@/components/ui/sheet';
Expand Down Expand Up @@ -45,7 +45,7 @@ function Sidebar({ className, children }) {
<aside
data-state={open ? 'expanded' : 'collapsed'}
className={cn(
'hidden min-h-screen shrink-0 border-r border-sidebar-border bg-sidebar text-sidebar-foreground transition-[width] duration-200 lg:flex lg:w-64 lg:flex-col data-[state=collapsed]:lg:w-[72px]',
'hidden min-h-screen shrink-0 border-r border-sidebar-border bg-sidebar text-sidebar-foreground transition-[width] duration-200 lg:flex lg:w-64 lg:flex-col lg:data-[state=collapsed]:w-[72px]',
className
)}
>
Expand Down Expand Up @@ -73,7 +73,8 @@ function SidebarContent({ className, ...props }) {
return <div className={cn('flex min-h-0 flex-1 flex-col gap-5 overflow-y-auto p-3', className)} {...props} />;
}
function SidebarFooter({ className, ...props }) {
return <div className={cn('border-t border-sidebar-border p-3', className)} {...props} />;
const { open } = useSidebar();
return <div className={cn('border-t border-sidebar-border p-3', !open && 'px-2', className)} {...props} />;
}
function SidebarGroup({ className, ...props }) {
return <div className={cn('flex flex-col gap-1', className)} {...props} />;
Expand Down Expand Up @@ -108,7 +109,7 @@ function SidebarInset({ className, ...props }) {
return <div className={cn('min-w-0 flex-1 bg-background', className)} {...props} />;
}
function SidebarTrigger({ className, mobile = false, ...props }) {
const { toggleSidebar, setOpenMobile } = useSidebar();
const { open, toggleSidebar, setOpenMobile } = useSidebar();
return (
<Button
variant="ghost"
Expand All @@ -117,8 +118,8 @@ function SidebarTrigger({ className, mobile = false, ...props }) {
onClick={() => mobile ? setOpenMobile(true) : toggleSidebar()}
{...props}
>
{mobile ? <IconMenu2 /> : <IconLayoutSidebarLeftCollapse />}
<span className="sr-only">{mobile ? 'Buka navigasi' : 'Ciutkan navigasi'}</span>
{mobile ? <IconMenu2 /> : open ? <IconLayoutSidebarLeftCollapse /> : <IconLayoutSidebarLeftExpand />}
<span className="sr-only">{mobile ? 'Buka navigasi' : open ? 'Ciutkan navigasi' : 'Lebarkan navigasi'}</span>
</Button>
);
}
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/components/ui/tooltip.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ function TooltipContent({ className, sideOffset = 6, ...props }) {
<TooltipPrimitive.Portal>
<TooltipPrimitive.Content
sideOffset={sideOffset}
className={cn('rounded-md bg-foreground px-2.5 py-1.5 text-xs text-background shadow-md', className)}
className={cn('z-[80] rounded-md bg-foreground px-2.5 py-1.5 text-xs text-background shadow-md', className)}
{...props}
/>
</TooltipPrimitive.Portal>
Expand Down
27 changes: 15 additions & 12 deletions apps/web/src/pages/Dashboard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,17 @@ import { Skeleton } from '@/components/ui/skeleton';
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table';

const chartConfig = {
income: { label: 'Kas masuk', color: 'var(--color-chart-1)' },
expense: { label: 'Kas keluar', color: 'var(--color-chart-2)' }
income: { label: 'Kas masuk', color: 'var(--ui-chart-1)' },
expense: { label: 'Kas keluar', color: 'var(--ui-chart-2)' }
};

function compactRupiah(value) {
function formatAxisAmount(value) {
const number = Number(value ?? 0);
if (Math.abs(number) >= 1_000_000_000) return `Rp ${(number / 1_000_000_000).toFixed(number % 1_000_000_000 ? 1 : 0)} M`;
if (Math.abs(number) >= 1_000_000) return `Rp ${(number / 1_000_000).toFixed(number % 1_000_000 ? 1 : 0)} jt`;
if (Math.abs(number) >= 1_000) return `Rp ${Math.round(number / 1_000)} rb`;
return `Rp ${number}`;
const compact = (amount) => new Intl.NumberFormat('id-ID', { maximumFractionDigits: 1 }).format(amount);
if (Math.abs(number) >= 1_000_000_000) return `${compact(number / 1_000_000_000)} M`;
if (Math.abs(number) >= 1_000_000) return `${compact(number / 1_000_000)} jt`;
if (Math.abs(number) >= 1_000) return `${compact(number / 1_000)} rb`;
return new Intl.NumberFormat('id-ID', { maximumFractionDigits: 0 }).format(number);
}

function Metric({ label, value, tone = 'default', caption }) {
Expand Down Expand Up @@ -152,7 +153,7 @@ export default function Dashboard() {
</Button>
</CardHeader>
<CardContent>
<ChartContainer config={chartConfig} className="h-[300px] min-h-[260px]">
<ChartContainer config={chartConfig} className="h-[280px] min-h-[260px]">
<AreaChart data={data.cashflow} margin={{ left: 0, right: 8, top: 8, bottom: 0 }}>
<defs>
<linearGradient id="incomeFill" x1="0" y1="0" x2="0" y2="1">
Expand All @@ -174,19 +175,21 @@ export default function Dashboard() {
tickFormatter={(value) => new Intl.DateTimeFormat('id-ID', { day: 'numeric', month: 'short' }).format(new Date(`${value}T00:00:00`))}
/>
<YAxis
width={58}
width={54}
axisLine={false}
tickLine={false}
tickFormatter={compactRupiah}
tickMargin={8}
tick={{ fontSize: 11 }}
tickFormatter={formatAxisAmount}
/>
<ChartTooltip
content={<ChartTooltipContent
labelFormatter={(value) => formatDate(value)}
formatter={(value) => formatRupiah(value)}
/>}
/>
<Area type="monotone" dataKey="income" stroke="var(--color-income)" strokeWidth={2} fill="url(#incomeFill)" />
<Area type="monotone" dataKey="expense" stroke="var(--color-expense)" strokeWidth={2} fill="url(#expenseFill)" />
<Area type="monotone" dataKey="income" stroke="var(--color-income)" strokeWidth={2.5} fill="url(#incomeFill)" dot={false} activeDot={{ r: 4 }} isAnimationActive={false} />
<Area type="monotone" dataKey="expense" stroke="var(--color-expense)" strokeWidth={2.5} fill="url(#expenseFill)" dot={false} activeDot={{ r: 4 }} isAnimationActive={false} />
</AreaChart>
</ChartContainer>
</CardContent>
Expand Down
21 changes: 11 additions & 10 deletions apps/web/src/pages/Reports.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,13 @@ function shiftDate(date, days) {
return toInputDate(value);
}

function compactRupiah(value) {
function formatAxisAmount(value) {
const number = Number(value ?? 0);
if (Math.abs(number) >= 1_000_000_000) return `Rp ${(number / 1_000_000_000).toFixed(1)} M`;
if (Math.abs(number) >= 1_000_000) return `Rp ${(number / 1_000_000).toFixed(1)} jt`;
if (Math.abs(number) >= 1_000) return `Rp ${Math.round(number / 1_000)} rb`;
return `Rp ${number}`;
const compact = (amount) => new Intl.NumberFormat('id-ID', { maximumFractionDigits: 1 }).format(amount);
if (Math.abs(number) >= 1_000_000_000) return `${compact(number / 1_000_000_000)} M`;
if (Math.abs(number) >= 1_000_000) return `${compact(number / 1_000_000)} jt`;
if (Math.abs(number) >= 1_000) return `${compact(number / 1_000)} rb`;
return new Intl.NumberFormat('id-ID', { maximumFractionDigits: 0 }).format(number);
}

function Metric({ icon: Icon, label, value, tone = 'default', caption }) {
Expand Down Expand Up @@ -188,15 +189,15 @@ export default function Reports() {
tickMargin={10}
tickFormatter={(value) => new Intl.DateTimeFormat('id-ID', { day: 'numeric', month: 'short' }).format(new Date(`${value}T00:00:00`))}
/>
<YAxis width={58} axisLine={false} tickLine={false} tickFormatter={compactRupiah} />
<YAxis width={54} axisLine={false} tickLine={false} tickMargin={8} tick={{ fontSize: 11 }} tickFormatter={formatAxisAmount} />
<ChartTooltip
content={<ChartTooltipContent
labelFormatter={(value) => formatDate(value)}
formatter={(value) => formatRupiah(value)}
/>}
/>
<Bar dataKey="income" fill="var(--color-income)" radius={[4, 4, 0, 0]} maxBarSize={18} />
<Bar dataKey="expense" fill="var(--color-expense)" radius={[4, 4, 0, 0]} maxBarSize={18} />
<Bar dataKey="income" fill="var(--color-income)" radius={[4, 4, 0, 0]} maxBarSize={22} isAnimationActive={false} />
<Bar dataKey="expense" fill="var(--color-expense)" radius={[4, 4, 0, 0]} maxBarSize={22} isAnimationActive={false} />
</BarChart>
</ChartContainer>
</CardContent>
Expand All @@ -212,15 +213,15 @@ export default function Reports() {
<ChartContainer config={categoryConfig} className="h-[310px] min-h-[280px]">
<BarChart data={categoryData} layout="vertical" margin={{ left: 8, right: 24, top: 8, bottom: 0 }}>
<CartesianGrid horizontal={false} strokeDasharray="3 3" stroke="var(--ui-border)" />
<XAxis type="number" axisLine={false} tickLine={false} tickFormatter={compactRupiah} />
<XAxis type="number" axisLine={false} tickLine={false} tickMargin={8} tick={{ fontSize: 11 }} tickFormatter={formatAxisAmount} />
<YAxis type="category" dataKey="category" axisLine={false} tickLine={false} width={110} tick={{ fontSize: 11 }} />
<ChartTooltip
content={<ChartTooltipContent
labelFormatter={(value) => value}
formatter={(value) => formatRupiah(value)}
/>}
/>
<Bar dataKey="total" radius={[0, 4, 4, 0]} maxBarSize={20}>
<Bar dataKey="total" radius={[0, 4, 4, 0]} maxBarSize={22} isAnimationActive={false}>
{categoryData.map((item) => (
<Cell key={`${item.type}-${item.category}`} fill={item.type === 'INCOME' ? 'var(--ui-chart-1)' : 'var(--ui-chart-2)'} />
))}
Expand Down
Loading
Loading