diff --git a/app/categories/page.tsx b/app/categories/page.tsx
index ad6ee9c..b492b37 100644
--- a/app/categories/page.tsx
+++ b/app/categories/page.tsx
@@ -11,7 +11,7 @@ import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/components/u
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu"
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
-import { Plus, MoreVertical, Pencil, Trash2, RefreshCw, X, ChevronDown, ChevronRight } from "lucide-react"
+import { Plus, MoreVertical, Pencil, Trash2, RefreshCw, X, ChevronDown, ChevronRight, ChevronsUpDown, Search } from "lucide-react"
import { CategoryIcon } from "@/components/ui/category-icon"
import { autoCategorize, addCategory, updateCategory, deleteCategory } from "@/lib/store-db"
import type { Category } from "@/lib/types"
@@ -35,6 +35,7 @@ export default function CategoriesPage() {
parentId: null as string | null,
})
const [newKeyword, setNewKeyword] = useState("")
+ const [searchQuery, setSearchQuery] = useState("")
// Organiser les catégories par parent
const { parentCategories, childrenByParent, orphanCategories } = useMemo(() => {
@@ -111,6 +112,16 @@ export default function CategoriesPage() {
setExpandedParents(newExpanded)
}
+ const expandAll = () => {
+ setExpandedParents(new Set(parentCategories.map((p) => p.id)))
+ }
+
+ const collapseAll = () => {
+ setExpandedParents(new Set())
+ }
+
+ const allExpanded = parentCategories.length > 0 && expandedParents.size === parentCategories.length
+
const handleNewCategory = (parentId: string | null = null) => {
setEditingCategory(null)
setFormData({ name: "", color: "#22c55e", keywords: [], parentId })
@@ -282,12 +293,66 @@ export default function CategoriesPage() {
+ {/* Barre de recherche et contrôles */}
+
- {parentCategories.map((parent) => {
- const children = childrenByParent[parent.id] || []
+ {parentCategories
+ .filter((parent) => {
+ if (!searchQuery.trim()) return true
+ const query = searchQuery.toLowerCase()
+ // Afficher si le parent matche
+ if (parent.name.toLowerCase().includes(query)) return true
+ if (parent.keywords.some((k) => k.toLowerCase().includes(query))) return true
+ // Ou si un enfant matche
+ const children = childrenByParent[parent.id] || []
+ return children.some(
+ (c) =>
+ c.name.toLowerCase().includes(query) ||
+ c.keywords.some((k) => k.toLowerCase().includes(query))
+ )
+ })
+ .map((parent) => {
+ const allChildren = childrenByParent[parent.id] || []
+ // Filtrer les enfants aussi si recherche active
+ const children = searchQuery.trim()
+ ? allChildren.filter(
+ (c) =>
+ c.name.toLowerCase().includes(searchQuery.toLowerCase()) ||
+ c.keywords.some((k) => k.toLowerCase().includes(searchQuery.toLowerCase())) ||
+ // Garder tous les enfants si le parent matche
+ parent.name.toLowerCase().includes(searchQuery.toLowerCase())
+ )
+ : allChildren
const stats = getCategoryStats(parent.id, true)
- const isExpanded = expandedParents.has(parent.id)
+ const isExpanded = expandedParents.has(parent.id) || (searchQuery.trim() !== "" && children.length > 0)
return (
diff --git a/lib/defaults.ts b/lib/defaults.ts
index fcf53d8..5827378 100644
--- a/lib/defaults.ts
+++ b/lib/defaults.ts
@@ -18,7 +18,7 @@ export const defaultCategories: CategoryDefinition[] = [
// ═══════════════════════════════════════════════════════════════════════════
{
slug: "alimentation",
- name: "🛒 Alimentation",
+ name: "Alimentation",
color: "#22c55e",
icon: "utensils",
keywords: [],
@@ -84,7 +84,7 @@ export const defaultCategories: CategoryDefinition[] = [
// ═══════════════════════════════════════════════════════════════════════════
{
slug: "transport",
- name: "🚗 Transport",
+ name: "Transport",
color: "#3b82f6",
icon: "car",
keywords: [],
@@ -201,7 +201,7 @@ export const defaultCategories: CategoryDefinition[] = [
// ═══════════════════════════════════════════════════════════════════════════
{
slug: "logement",
- name: "🏠 Logement",
+ name: "Logement",
color: "#f59e0b",
icon: "home",
keywords: [],
@@ -291,7 +291,7 @@ export const defaultCategories: CategoryDefinition[] = [
// ═══════════════════════════════════════════════════════════════════════════
{
slug: "sante",
- name: "💊 Santé",
+ name: "Santé",
color: "#ef4444",
icon: "heart",
keywords: [],
@@ -385,7 +385,7 @@ export const defaultCategories: CategoryDefinition[] = [
// ═══════════════════════════════════════════════════════════════════════════
{
slug: "loisirs",
- name: "🎬 Loisirs",
+ name: "Loisirs",
color: "#8b5cf6",
icon: "gamepad",
keywords: [],
@@ -482,7 +482,7 @@ export const defaultCategories: CategoryDefinition[] = [
// ═══════════════════════════════════════════════════════════════════════════
{
slug: "shopping",
- name: "👕 Shopping",
+ name: "Shopping",
color: "#06b6d4",
icon: "shopping-bag",
keywords: [],
@@ -548,7 +548,7 @@ export const defaultCategories: CategoryDefinition[] = [
// ═══════════════════════════════════════════════════════════════════════════
{
slug: "abonnements",
- name: "📱 Abonnements",
+ name: "Abonnements",
color: "#8b5cf6",
icon: "repeat",
keywords: [],
@@ -592,7 +592,7 @@ export const defaultCategories: CategoryDefinition[] = [
// ═══════════════════════════════════════════════════════════════════════════
{
slug: "finance",
- name: "💰 Finance",
+ name: "Finance",
color: "#64748b",
icon: "landmark",
keywords: [],
@@ -691,7 +691,7 @@ export const defaultCategories: CategoryDefinition[] = [
// ═══════════════════════════════════════════════════════════════════════════
{
slug: "revenus",
- name: "💵 Revenus",
+ name: "Revenus",
color: "#10b981",
icon: "wallet",
keywords: [],
@@ -749,7 +749,7 @@ export const defaultCategories: CategoryDefinition[] = [
// ═══════════════════════════════════════════════════════════════════════════
{
slug: "voyage",
- name: "✈️ Voyage",
+ name: "Voyage",
color: "#a855f7",
icon: "plane",
keywords: [],
@@ -793,7 +793,7 @@ export const defaultCategories: CategoryDefinition[] = [
// ═══════════════════════════════════════════════════════════════════════════
{
slug: "education",
- name: "📚 Éducation",
+ name: "Éducation",
color: "#0284c7",
icon: "graduation-cap",
keywords: [],
@@ -836,7 +836,7 @@ export const defaultCategories: CategoryDefinition[] = [
// ═══════════════════════════════════════════════════════════════════════════
{
slug: "animaux",
- name: "🐕 Animaux",
+ name: "Animaux",
color: "#ea580c",
icon: "paw-print",
keywords: [
@@ -857,7 +857,7 @@ export const defaultCategories: CategoryDefinition[] = [
// ═══════════════════════════════════════════════════════════════════════════
{
slug: "auto",
- name: "🔧 Auto & Moto",
+ name: "Auto & Moto",
color: "#78716c",
icon: "car",
keywords: [],
@@ -899,7 +899,7 @@ export const defaultCategories: CategoryDefinition[] = [
// ═══════════════════════════════════════════════════════════════════════════
{
slug: "dons",
- name: "🎁 Dons & Cadeaux",
+ name: "Dons & Cadeaux",
color: "#f43f5e",
icon: "gift",
keywords: [],
@@ -935,7 +935,7 @@ export const defaultCategories: CategoryDefinition[] = [
// ═══════════════════════════════════════════════════════════════════════════
{
slug: "divers",
- name: "❓ Divers",
+ name: "Divers",
color: "#71717a",
icon: "more-horizontal",
keywords: [],