feat: implement hierarchical category management with parent-child relationships and enhance category creation dialog
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
|
||||
import { Badge } from "@/components/ui/badge"
|
||||
import { CheckCircle2, Circle } from "lucide-react"
|
||||
import { CategoryIcon } from "@/components/ui/category-icon"
|
||||
import type { BankingData } from "@/lib/types"
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
@@ -86,9 +87,10 @@ export function RecentTransactions({ data }: RecentTransactionsProps) {
|
||||
{category && (
|
||||
<Badge
|
||||
variant="secondary"
|
||||
className="text-xs"
|
||||
className="text-xs gap-1"
|
||||
style={{ backgroundColor: `${category.color}20`, color: category.color }}
|
||||
>
|
||||
<CategoryIcon icon={category.icon} color={category.color} size={12} />
|
||||
{category.name}
|
||||
</Badge>
|
||||
)}
|
||||
|
||||
143
components/ui/category-icon.tsx
Normal file
143
components/ui/category-icon.tsx
Normal file
@@ -0,0 +1,143 @@
|
||||
"use client"
|
||||
|
||||
import {
|
||||
ShoppingCart,
|
||||
Utensils,
|
||||
Croissant,
|
||||
Fuel,
|
||||
Train,
|
||||
Car,
|
||||
SquareParking,
|
||||
Bike,
|
||||
Plane,
|
||||
Home,
|
||||
Zap,
|
||||
Droplet,
|
||||
Hammer,
|
||||
Sofa,
|
||||
Pill,
|
||||
Stethoscope,
|
||||
Hospital,
|
||||
Glasses,
|
||||
Dumbbell,
|
||||
Sparkles,
|
||||
Tv,
|
||||
Music,
|
||||
Film,
|
||||
Gamepad,
|
||||
Book,
|
||||
Ticket,
|
||||
Shirt,
|
||||
Smartphone,
|
||||
Package,
|
||||
Wifi,
|
||||
Repeat,
|
||||
Landmark,
|
||||
Shield,
|
||||
HeartPulse,
|
||||
Receipt,
|
||||
PiggyBank,
|
||||
Banknote,
|
||||
Wallet,
|
||||
HandCoins,
|
||||
Undo,
|
||||
Coins,
|
||||
Bed,
|
||||
Luggage,
|
||||
GraduationCap,
|
||||
Baby,
|
||||
PawPrint,
|
||||
Wrench,
|
||||
HeartHandshake,
|
||||
Gift,
|
||||
Cigarette,
|
||||
ArrowRightLeft,
|
||||
HelpCircle,
|
||||
Tag,
|
||||
Folder,
|
||||
Key,
|
||||
Refrigerator,
|
||||
type LucideIcon,
|
||||
} from "lucide-react"
|
||||
|
||||
// Map icon names to Lucide components
|
||||
const iconMap: Record<string, LucideIcon> = {
|
||||
"shopping-cart": ShoppingCart,
|
||||
"utensils": Utensils,
|
||||
"croissant": Croissant,
|
||||
"fuel": Fuel,
|
||||
"train": Train,
|
||||
"car": Car,
|
||||
"car-taxi": Car, // Using Car as fallback for car-taxi
|
||||
"car-key": Key, // Using Key as fallback
|
||||
"parking": SquareParking,
|
||||
"bike": Bike,
|
||||
"plane": Plane,
|
||||
"home": Home,
|
||||
"zap": Zap,
|
||||
"droplet": Droplet,
|
||||
"hammer": Hammer,
|
||||
"sofa": Sofa,
|
||||
"refrigerator": Refrigerator,
|
||||
"pill": Pill,
|
||||
"stethoscope": Stethoscope,
|
||||
"hospital": Hospital,
|
||||
"glasses": Glasses,
|
||||
"dumbbell": Dumbbell,
|
||||
"sparkles": Sparkles,
|
||||
"tv": Tv,
|
||||
"music": Music,
|
||||
"film": Film,
|
||||
"gamepad": Gamepad,
|
||||
"book": Book,
|
||||
"ticket": Ticket,
|
||||
"shirt": Shirt,
|
||||
"smartphone": Smartphone,
|
||||
"package": Package,
|
||||
"wifi": Wifi,
|
||||
"repeat": Repeat,
|
||||
"landmark": Landmark,
|
||||
"shield": Shield,
|
||||
"heart-pulse": HeartPulse,
|
||||
"receipt": Receipt,
|
||||
"piggy-bank": PiggyBank,
|
||||
"banknote": Banknote,
|
||||
"wallet": Wallet,
|
||||
"hand-coins": HandCoins,
|
||||
"undo": Undo,
|
||||
"coins": Coins,
|
||||
"bed": Bed,
|
||||
"luggage": Luggage,
|
||||
"graduation-cap": GraduationCap,
|
||||
"baby": Baby,
|
||||
"paw-print": PawPrint,
|
||||
"wrench": Wrench,
|
||||
"heart-handshake": HeartHandshake,
|
||||
"gift": Gift,
|
||||
"cigarette": Cigarette,
|
||||
"arrow-right-left": ArrowRightLeft,
|
||||
"help-circle": HelpCircle,
|
||||
"tag": Tag,
|
||||
"folder": Folder,
|
||||
}
|
||||
|
||||
// Get all available icon names
|
||||
export const availableIcons = Object.keys(iconMap)
|
||||
|
||||
// Get the icon component by name
|
||||
export function getIconComponent(iconName: string): LucideIcon {
|
||||
return iconMap[iconName] || Tag
|
||||
}
|
||||
|
||||
interface CategoryIconProps {
|
||||
icon: string
|
||||
color?: string
|
||||
className?: string
|
||||
size?: number
|
||||
}
|
||||
|
||||
export function CategoryIcon({ icon, color, className, size = 20 }: CategoryIconProps) {
|
||||
const IconComponent = getIconComponent(icon)
|
||||
return <IconComponent className={className} style={{ color }} size={size} />
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user