mercury-web/src/features/accounting/CategorizeSheet.tsx

97 lines
3.3 KiB
TypeScript

"use client";
import {
BottomSheetRoot,
BottomSheetBackdrop,
BottomSheetPositioner,
BottomSheetContent,
BottomSheetHeader,
BottomSheetTitle,
BottomSheetCloseButton,
BottomSheetBody,
Icon,
ListRoot,
ListItem,
ListContent,
ListTitle,
} from "@seed-design/react";
import type { Category } from "@/api/schemas";
import { accountingStrings as s } from "./strings";
export interface CategorizeSheetProps {
open: boolean;
onOpenChange: (open: boolean) => void;
categories: Category[];
/** The transaction's current category (main or sub) — highlighted in the list. */
selected?: string;
onSelect: (category: Category) => void;
}
const closeSvg = (
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={1.8} strokeLinecap="round">
<path d="M6 6l12 12M18 6L6 18" />
</svg>
);
const checkSvg = (
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={2} strokeLinecap="round" strokeLinejoin="round">
<path d="M5 12.5l4.5 4.5L19 7" />
</svg>
);
/**
* Category picker bottom sheet (ports `CategoryPickerSheet` from
* `ios/Mercury/Features/Planner/PlannerEditViews.swift`, opened from the
* transaction detail's Ангилал row): a titled list of all categories,
* tap-to-select, checkmark on the current pick.
*/
export function CategorizeSheet({ open, onOpenChange, categories, selected, onSelect }: CategorizeSheetProps) {
return (
<BottomSheetRoot open={open} onOpenChange={onOpenChange}>
<BottomSheetBackdrop />
<BottomSheetPositioner>
<BottomSheetContent>
<BottomSheetHeader style={{ display: "flex", alignItems: "center", justifyContent: "space-between" }}>
<BottomSheetTitle>{s.categoryPicker.title}</BottomSheetTitle>
<BottomSheetCloseButton aria-label={s.categoryPicker.cancel}>
<Icon svg={closeSvg} size="16px" />
</BottomSheetCloseButton>
</BottomSheetHeader>
<BottomSheetBody style={{ maxHeight: "60vh", overflowY: "auto" }}>
<ListRoot>
{categories.map((cat) => {
const isSelected = cat.name === selected;
return (
<ListItem key={cat.name} style={{ padding: 0 }}>
<button
type="button"
onClick={() => onSelect(cat)}
style={{
display: "flex",
width: "100%",
alignItems: "center",
justifyContent: "space-between",
background: "none",
border: "none",
textAlign: "left",
cursor: "pointer",
padding: "12px 4px",
font: "inherit",
color: "inherit",
}}
>
<ListContent>
<ListTitle>{cat.name}</ListTitle>
</ListContent>
{isSelected && <Icon svg={checkSvg} size="18px" />}
</button>
</ListItem>
);
})}
</ListRoot>
</BottomSheetBody>
</BottomSheetContent>
</BottomSheetPositioner>
</BottomSheetRoot>
);
}