chore: clean up code by removing trailing whitespace and ensuring consistent formatting across various files = prettier

This commit is contained in:
Julien Froidefond
2025-12-01 08:37:30 +01:00
parent 757b1b84ab
commit e715779de7
98 changed files with 5453 additions and 3126 deletions

View File

@@ -43,12 +43,12 @@ export function AccountFilterCombobox({
// Calculate total amount per account based on filtered transactions
const accountTotals = useMemo(() => {
if (!filteredTransactions) return {};
const totals: Record<string, number> = {};
filteredTransactions.forEach((t) => {
totals[t.accountId] = (totals[t.accountId] || 0) + t.amount;
});
return totals;
}, [filteredTransactions]);
@@ -64,7 +64,7 @@ export function AccountFilterCombobox({
// Get root folders (folders without parent) - same as folders/page.tsx
const rootFolders = useMemo(
() => folders.filter((f) => f.parentId === null),
[folders]
[folders],
);
// Get child folders for a given parent - same as FolderTreeItem
@@ -78,7 +78,7 @@ export function AccountFilterCombobox({
// Get accounts without folder
const orphanAccounts = useMemo(
() => accounts.filter((a) => !a.folderId),
[accounts]
[accounts],
);
const selectedAccounts = accounts.filter((a) => value.includes(a.id));
@@ -89,7 +89,7 @@ export function AccountFilterCombobox({
const directAccounts = getFolderAccounts(folderId);
const childFoldersList = getChildFolders(folderId);
const childAccounts = childFoldersList.flatMap((cf) =>
getAllAccountsInFolder(cf.id)
getAllAccountsInFolder(cf.id),
);
return [...directAccounts, ...childAccounts];
};
@@ -126,7 +126,7 @@ export function AccountFilterCombobox({
if (allSelected) {
const newSelection = value.filter(
(v) => !allFolderAccountIds.includes(v)
(v) => !allFolderAccountIds.includes(v),
);
onChange(newSelection.length > 0 ? newSelection : ["all"]);
} else {
@@ -153,7 +153,7 @@ export function AccountFilterCombobox({
const folderAccounts = getAllAccountsInFolder(folderId);
if (folderAccounts.length === 0) return false;
const selectedCount = folderAccounts.filter((a) =>
value.includes(a.id)
value.includes(a.id),
).length;
return selectedCount > 0 && selectedCount < folderAccounts.length;
};
@@ -162,7 +162,9 @@ export function AccountFilterCombobox({
const renderFolder = (folder: Folder, depth: number, parentPath: string) => {
const folderAccounts = getFolderAccounts(folder.id);
const childFoldersList = getChildFolders(folder.id);
const currentPath = parentPath ? `${parentPath} ${folder.name}` : folder.name;
const currentPath = parentPath
? `${parentPath} ${folder.name}`
: folder.name;
const paddingLeft = depth * 16 + 8;
return (
@@ -183,7 +185,7 @@ export function AccountFilterCombobox({
<Check
className={cn(
"h-4 w-4",
isFolderSelected(folder.id) ? "opacity-100" : "opacity-0"
isFolderSelected(folder.id) ? "opacity-100" : "opacity-0",
)}
/>
</div>
@@ -211,7 +213,7 @@ export function AccountFilterCombobox({
<Check
className={cn(
"ml-auto h-4 w-4 shrink-0",
value.includes(account.id) ? "opacity-100" : "opacity-0"
value.includes(account.id) ? "opacity-100" : "opacity-0",
)}
/>
</CommandItem>
@@ -220,7 +222,7 @@ export function AccountFilterCombobox({
{/* Child folders - recursive */}
{childFoldersList.map((childFolder) =>
renderFolder(childFolder, depth + 1, currentPath)
renderFolder(childFolder, depth + 1, currentPath),
)}
</div>
);
@@ -239,10 +241,15 @@ export function AccountFilterCombobox({
{selectedAccounts.length === 1 ? (
<>
{(() => {
const AccountIcon = accountTypeIcons[selectedAccounts[0].type];
return <AccountIcon className="h-4 w-4 text-muted-foreground shrink-0" />;
const AccountIcon =
accountTypeIcons[selectedAccounts[0].type];
return (
<AccountIcon className="h-4 w-4 text-muted-foreground shrink-0" />
);
})()}
<span className="truncate text-left">{selectedAccounts[0].name}</span>
<span className="truncate text-left">
{selectedAccounts[0].name}
</span>
</>
) : selectedAccounts.length > 1 ? (
<>
@@ -254,7 +261,9 @@ export function AccountFilterCombobox({
) : (
<>
<Wallet className="h-4 w-4 text-muted-foreground shrink-0" />
<span className="text-muted-foreground truncate text-left">Tous les comptes</span>
<span className="text-muted-foreground truncate text-left">
Tous les comptes
</span>
</>
)}
</div>
@@ -290,15 +299,20 @@ export function AccountFilterCombobox({
<span>Tous les comptes</span>
{filteredTransactions && (
<span className="text-xs text-muted-foreground ml-1">
({formatCurrency(
filteredTransactions.reduce((sum, t) => sum + t.amount, 0)
)})
(
{formatCurrency(
filteredTransactions.reduce(
(sum, t) => sum + t.amount,
0,
),
)}
)
</span>
)}
<Check
className={cn(
"ml-auto h-4 w-4",
isAll ? "opacity-100" : "opacity-0"
isAll ? "opacity-100" : "opacity-0",
)}
/>
</CommandItem>
@@ -321,7 +335,9 @@ export function AccountFilterCombobox({
className="min-w-0"
>
<AccountIcon className="h-4 w-4 text-muted-foreground shrink-0" />
<span className="truncate min-w-0 flex-1">{account.name}</span>
<span className="truncate min-w-0 flex-1">
{account.name}
</span>
{total !== undefined && (
<span className="text-xs text-muted-foreground ml-1 shrink-0">
({formatCurrency(total)})
@@ -330,7 +346,9 @@ export function AccountFilterCombobox({
<Check
className={cn(
"ml-auto h-4 w-4 shrink-0",
value.includes(account.id) ? "opacity-100" : "opacity-0"
value.includes(account.id)
? "opacity-100"
: "opacity-0",
)}
/>
</CommandItem>

View File

@@ -115,11 +115,13 @@ export function CategoryCombobox({
onSelect={() => handleSelect(null)}
>
<X className="h-4 w-4 text-muted-foreground" />
<span className="text-muted-foreground">Aucune catégorie</span>
<span className="text-muted-foreground">
Aucune catégorie
</span>
<Check
className={cn(
"ml-auto h-4 w-4",
value === null ? "opacity-100" : "opacity-0"
value === null ? "opacity-100" : "opacity-0",
)}
/>
</CommandItem>
@@ -140,7 +142,7 @@ export function CategoryCombobox({
<Check
className={cn(
"ml-auto h-4 w-4",
value === parent.id ? "opacity-100" : "opacity-0"
value === parent.id ? "opacity-100" : "opacity-0",
)}
/>
</CommandItem>
@@ -160,7 +162,7 @@ export function CategoryCombobox({
<Check
className={cn(
"ml-auto h-4 w-4",
value === child.id ? "opacity-100" : "opacity-0"
value === child.id ? "opacity-100" : "opacity-0",
)}
/>
</CommandItem>
@@ -183,10 +185,7 @@ export function CategoryCombobox({
variant="outline"
role="combobox"
aria-expanded={open}
className={cn(
"justify-between",
buttonWidth || "w-full"
)}
className={cn("justify-between", buttonWidth || "w-full")}
>
{selectedCategory ? (
<div className="flex items-center gap-2">
@@ -213,16 +212,13 @@ export function CategoryCombobox({
<CommandList className="max-h-[250px]">
<CommandEmpty>Aucune catégorie trouvée.</CommandEmpty>
<CommandGroup>
<CommandItem
value="__none__"
onSelect={() => handleSelect(null)}
>
<CommandItem value="__none__" onSelect={() => handleSelect(null)}>
<X className="h-4 w-4 text-muted-foreground" />
<span className="text-muted-foreground">Aucune catégorie</span>
<Check
className={cn(
"ml-auto h-4 w-4",
value === null ? "opacity-100" : "opacity-0"
value === null ? "opacity-100" : "opacity-0",
)}
/>
</CommandItem>
@@ -243,7 +239,7 @@ export function CategoryCombobox({
<Check
className={cn(
"ml-auto h-4 w-4",
value === parent.id ? "opacity-100" : "opacity-0"
value === parent.id ? "opacity-100" : "opacity-0",
)}
/>
</CommandItem>
@@ -263,7 +259,7 @@ export function CategoryCombobox({
<Check
className={cn(
"ml-auto h-4 w-4",
value === child.id ? "opacity-100" : "opacity-0"
value === child.id ? "opacity-100" : "opacity-0",
)}
/>
</CommandItem>
@@ -277,4 +273,3 @@ export function CategoryCombobox({
</Popover>
);
}

View File

@@ -40,13 +40,13 @@ export function CategoryFilterCombobox({
// Calculate transaction counts per category based on filtered transactions
const categoryCounts = useMemo(() => {
if (!filteredTransactions) return {};
const counts: Record<string, number> = {};
filteredTransactions.forEach((t) => {
const catId = t.categoryId || "uncategorized";
counts[catId] = (counts[catId] || 0) + 1;
});
return counts;
}, [filteredTransactions]);
@@ -89,7 +89,7 @@ export function CategoryFilterCombobox({
// Category selection - toggle
let newSelection: string[];
if (isAll || isUncategorized) {
// Start fresh with just this category
newSelection = [newValue];
@@ -115,7 +115,8 @@ export function CategoryFilterCombobox({
if (isAll) return "Toutes catégories";
if (isUncategorized) return "Non catégorisé";
if (selectedCategories.length === 1) return selectedCategories[0].name;
if (selectedCategories.length > 1) return `${selectedCategories.length} catégories`;
if (selectedCategories.length > 1)
return `${selectedCategories.length} catégories`;
return "Catégorie";
};
@@ -137,7 +138,9 @@ export function CategoryFilterCombobox({
size={16}
className="shrink-0"
/>
<span className="truncate text-left">{selectedCategories[0].name}</span>
<span className="truncate text-left">
{selectedCategories[0].name}
</span>
</>
) : selectedCategories.length > 1 ? (
<>
@@ -150,7 +153,9 @@ export function CategoryFilterCombobox({
/>
))}
</div>
<span className="truncate text-left">{selectedCategories.length} catégories</span>
<span className="truncate text-left">
{selectedCategories.length} catégories
</span>
</>
) : isUncategorized ? (
<>
@@ -160,7 +165,9 @@ export function CategoryFilterCombobox({
) : (
<>
<Tags className="h-4 w-4 text-muted-foreground shrink-0" />
<span className="text-muted-foreground truncate text-left">{getDisplayValue()}</span>
<span className="text-muted-foreground truncate text-left">
{getDisplayValue()}
</span>
</>
)}
</div>
@@ -191,9 +198,15 @@ export function CategoryFilterCombobox({
<CommandList className="max-h-[300px]">
<CommandEmpty>Aucune catégorie trouvée.</CommandEmpty>
<CommandGroup>
<CommandItem value="all" onSelect={() => handleSelect("all")} className="min-w-0">
<CommandItem
value="all"
onSelect={() => handleSelect("all")}
className="min-w-0"
>
<Tags className="h-4 w-4 text-muted-foreground shrink-0" />
<span className="truncate min-w-0 flex-1">Toutes catégories</span>
<span className="truncate min-w-0 flex-1">
Toutes catégories
</span>
{filteredTransactions && (
<span className="text-xs text-muted-foreground ml-1 shrink-0">
({filteredTransactions.length})
@@ -202,7 +215,7 @@ export function CategoryFilterCombobox({
<Check
className={cn(
"ml-auto h-4 w-4 shrink-0",
isAll ? "opacity-100" : "opacity-0"
isAll ? "opacity-100" : "opacity-0",
)}
/>
</CommandItem>
@@ -221,7 +234,7 @@ export function CategoryFilterCombobox({
<Check
className={cn(
"ml-auto h-4 w-4 shrink-0",
isUncategorized ? "opacity-100" : "opacity-0"
isUncategorized ? "opacity-100" : "opacity-0",
)}
/>
</CommandItem>
@@ -240,7 +253,9 @@ export function CategoryFilterCombobox({
size={16}
className="shrink-0"
/>
<span className="font-medium truncate min-w-0 flex-1">{parent.name}</span>
<span className="font-medium truncate min-w-0 flex-1">
{parent.name}
</span>
{categoryCounts[parent.id] !== undefined && (
<span className="text-xs text-muted-foreground ml-1 shrink-0">
({categoryCounts[parent.id]})
@@ -249,7 +264,7 @@ export function CategoryFilterCombobox({
<Check
className={cn(
"ml-auto h-4 w-4 shrink-0",
value.includes(parent.id) ? "opacity-100" : "opacity-0"
value.includes(parent.id) ? "opacity-100" : "opacity-0",
)}
/>
</CommandItem>
@@ -266,7 +281,9 @@ export function CategoryFilterCombobox({
size={16}
className="shrink-0"
/>
<span className="truncate min-w-0 flex-1">{child.name}</span>
<span className="truncate min-w-0 flex-1">
{child.name}
</span>
{categoryCounts[child.id] !== undefined && (
<span className="text-xs text-muted-foreground ml-1 shrink-0">
({categoryCounts[child.id]})
@@ -275,7 +292,9 @@ export function CategoryFilterCombobox({
<Check
className={cn(
"ml-auto h-4 w-4 shrink-0",
value.includes(child.id) ? "opacity-100" : "opacity-0"
value.includes(child.id)
? "opacity-100"
: "opacity-0",
)}
/>
</CommandItem>

View File

@@ -20,64 +20,225 @@ import { cn } from "@/lib/utils";
// Group icons by category for better organization
const iconGroups: Record<string, string[]> = {
"Alimentation": [
"shopping-cart", "utensils", "croissant", "coffee", "wine", "beer",
"pizza", "apple", "cherry", "salad", "sandwich", "ice-cream",
"cake", "cup-soda", "milk", "egg", "fish", "beef"
Alimentation: [
"shopping-cart",
"utensils",
"croissant",
"coffee",
"wine",
"beer",
"pizza",
"apple",
"cherry",
"salad",
"sandwich",
"ice-cream",
"cake",
"cup-soda",
"milk",
"egg",
"fish",
"beef",
],
"Transport": [
"fuel", "train", "car", "parking", "bike", "plane", "bus",
"ship", "sailboat", "truck", "car-front", "circle-parking",
"train-front"
Transport: [
"fuel",
"train",
"car",
"parking",
"bike",
"plane",
"bus",
"ship",
"sailboat",
"truck",
"car-front",
"circle-parking",
"train-front",
],
"Logement": [
"home", "zap", "droplet", "hammer", "sofa", "refrigerator",
"washing-machine", "lamp", "lamp-desk", "armchair", "bath",
"shower-head", "door-open", "fence", "trees", "flower",
"leaf", "sun", "snowflake", "wind", "thermometer"
Logement: [
"home",
"zap",
"droplet",
"hammer",
"sofa",
"refrigerator",
"washing-machine",
"lamp",
"lamp-desk",
"armchair",
"bath",
"shower-head",
"door-open",
"fence",
"trees",
"flower",
"leaf",
"sun",
"snowflake",
"wind",
"thermometer",
],
"Santé": [
"pill", "stethoscope", "hospital", "glasses", "dumbbell", "sparkles",
"heart", "heart-pulse", "activity", "syringe", "bandage", "brain",
"eye", "ear", "hand", "footprints", "person-standing"
Santé: [
"pill",
"stethoscope",
"hospital",
"glasses",
"dumbbell",
"sparkles",
"heart",
"heart-pulse",
"activity",
"syringe",
"bandage",
"brain",
"eye",
"ear",
"hand",
"footprints",
"person-standing",
],
"Loisirs": [
"tv", "music", "film", "gamepad", "book", "ticket", "clapperboard",
"headphones", "speaker", "radio", "camera", "image", "palette",
"brush", "pen-tool", "scissors", "drama", "party-popper"
Loisirs: [
"tv",
"music",
"film",
"gamepad",
"book",
"ticket",
"clapperboard",
"headphones",
"speaker",
"radio",
"camera",
"image",
"palette",
"brush",
"pen-tool",
"scissors",
"drama",
"party-popper",
],
"Sport": ["trophy", "medal", "target", "volleyball"],
"Shopping": [
"shirt", "smartphone", "package", "shopping-bag", "store", "gem",
"watch", "sunglasses", "crown", "laptop", "monitor", "keyboard",
"mouse", "printer", "tablet-smartphone", "headset"
Sport: ["trophy", "medal", "target", "volleyball"],
Shopping: [
"shirt",
"smartphone",
"package",
"shopping-bag",
"store",
"gem",
"watch",
"sunglasses",
"crown",
"laptop",
"monitor",
"keyboard",
"mouse",
"printer",
"tablet-smartphone",
"headset",
],
"Services": [
"wifi", "repeat", "landmark", "shield", "receipt", "file-text",
"mail", "phone", "message-square", "send", "globe", "cloud",
"server", "lock", "unlock", "settings", "wrench"
Services: [
"wifi",
"repeat",
"landmark",
"shield",
"receipt",
"file-text",
"mail",
"phone",
"message-square",
"send",
"globe",
"cloud",
"server",
"lock",
"unlock",
"settings",
"wrench",
],
"Finance": [
"piggy-bank", "banknote", "wallet", "hand-coins", "undo", "coins",
"credit-card", "building", "building2", "trending-up", "trending-down",
"bar-chart", "pie-chart", "line-chart", "calculator", "percent",
"dollar-sign", "euro"
Finance: [
"piggy-bank",
"banknote",
"wallet",
"hand-coins",
"undo",
"coins",
"credit-card",
"building",
"building2",
"trending-up",
"trending-down",
"bar-chart",
"pie-chart",
"line-chart",
"calculator",
"percent",
"dollar-sign",
"euro",
],
"Voyage": [
"bed", "luggage", "map", "map-pin", "compass", "mountain",
"tent", "palmtree", "umbrella", "globe2", "flag"
Voyage: [
"bed",
"luggage",
"map",
"map-pin",
"compass",
"mountain",
"tent",
"palmtree",
"umbrella",
"globe2",
"flag",
],
"Famille": [
"graduation-cap", "baby", "paw-print", "users", "user", "user-plus",
"dog", "cat", "bird", "rabbit"
Famille: [
"graduation-cap",
"baby",
"paw-print",
"users",
"user",
"user-plus",
"dog",
"cat",
"bird",
"rabbit",
],
"Autre": [
"heart-handshake", "gift", "cigarette", "arrow-right-left",
"help-circle", "tag", "folder", "key", "star", "bookmark", "clock",
"calendar", "bell", "alert-triangle", "info", "check-circle", "x-circle",
"plus", "minus", "search", "trash", "edit", "download", "upload",
"share", "link", "paperclip", "archive", "box", "boxes", "container",
"briefcase", "education", "award", "lightbulb", "flame", "rocket", "atom"
Autre: [
"heart-handshake",
"gift",
"cigarette",
"arrow-right-left",
"help-circle",
"tag",
"folder",
"key",
"star",
"bookmark",
"clock",
"calendar",
"bell",
"alert-triangle",
"info",
"check-circle",
"x-circle",
"plus",
"minus",
"search",
"trash",
"edit",
"download",
"upload",
"share",
"link",
"paperclip",
"archive",
"box",
"boxes",
"container",
"briefcase",
"education",
"award",
"lightbulb",
"flame",
"rocket",
"atom",
],
};
@@ -94,21 +255,21 @@ export function IconPicker({ value, onChange, color }: IconPickerProps) {
// Filter icons based on search
const filteredGroups = useMemo(() => {
if (!search.trim()) return iconGroups;
const query = search.toLowerCase();
const result: Record<string, string[]> = {};
Object.entries(iconGroups).forEach(([group, icons]) => {
const filtered = icons.filter(
(icon) =>
icon.toLowerCase().includes(query) ||
group.toLowerCase().includes(query)
group.toLowerCase().includes(query),
);
if (filtered.length > 0) {
result[group] = filtered;
}
});
return result;
}, [search]);
@@ -156,7 +317,7 @@ export function IconPicker({ value, onChange, color }: IconPickerProps) {
onClick={() => handleSelect(icon)}
className={cn(
"flex items-center justify-center p-2 rounded-md hover:bg-accent transition-colors",
value === icon && "bg-accent ring-2 ring-primary"
value === icon && "bg-accent ring-2 ring-primary",
)}
title={icon}
>
@@ -172,4 +333,3 @@ export function IconPicker({ value, onChange, color }: IconPickerProps) {
</Popover>
);
}