|
74 | 74 | let editDateValue: DateValue | undefined = undefined;
|
75 | 75 |
|
76 | 76 | // For edit form
|
77 |
| - let parsedCustomers: Array<{ value: string, label: string }> = []; |
78 |
| - let parsedExpenseTypes: Array<{ value: string, label: string }> = []; |
| 77 | + let parsedCustomers: Array<{ value: string, label: string, frequency: number }> = []; |
| 78 | + let parsedExpenseTypes: Array<{ value: string, label: string, frequency: number }> = []; |
79 | 79 | let editCustomerOpen = false;
|
80 | 80 | let editExpenseTypeOpen = false;
|
81 | 81 |
|
82 |
| - $: parsedCustomers = $customers.map((customer) => { |
83 |
| - return { |
| 82 | + let customerOpen = false; |
| 83 | + let customerValue = ""; |
| 84 | + let expenseTypeOpen = false; |
| 85 | + let expenseTypeValue = ""; |
| 86 | +
|
| 87 | + // For frequency tracking |
| 88 | + $: { |
| 89 | + // Count frequency of customers in expenses |
| 90 | + const customerFrequency = $expenses.reduce((acc, expense) => { |
| 91 | + const customerId = expense.customer; |
| 92 | + acc[customerId] = (acc[customerId] || 0) + 1; |
| 93 | + return acc; |
| 94 | + }, {} as Record<string, number>); |
| 95 | +
|
| 96 | + // Count frequency of expense types per customer |
| 97 | + const customerTypeFrequency = $expenses.reduce((acc, expense) => { |
| 98 | + const customerId = expense.customer; |
| 99 | + const typeId = expense.expense_type; |
| 100 | + if (!acc[customerId]) { |
| 101 | + acc[customerId] = {}; |
| 102 | + } |
| 103 | + acc[customerId][typeId] = (acc[customerId][typeId] || 0) + 1; |
| 104 | + return acc; |
| 105 | + }, {} as Record<string, Record<string, number>>); |
| 106 | +
|
| 107 | + // Count frequency of customers per type |
| 108 | + const typeCustomerFrequency = $expenses.reduce((acc, expense) => { |
| 109 | + const typeId = expense.expense_type; |
| 110 | + const customerId = expense.customer; |
| 111 | + if (!acc[typeId]) { |
| 112 | + acc[typeId] = {}; |
| 113 | + } |
| 114 | + acc[typeId][customerId] = (acc[typeId][customerId] || 0) + 1; |
| 115 | + return acc; |
| 116 | + }, {} as Record<string, Record<string, number>>); |
| 117 | +
|
| 118 | + // Map and sort customers based on context |
| 119 | + parsedCustomers = $customers.map((customer) => ({ |
84 | 120 | value: customer.id,
|
85 |
| - label: customer.name |
86 |
| - }; |
87 |
| - }); |
| 121 | + label: customer.name, |
| 122 | + frequency: customerFrequency[customer.id] || 0, |
| 123 | + // If a type is selected, use the frequency of this customer with that type |
| 124 | + contextFrequency: expenseTypeValue ? (typeCustomerFrequency[expenseTypeValue]?.[customer.id] || 0) : 0 |
| 125 | + })).sort((a, b) => { |
| 126 | + // If we have a type selected, sort by context frequency first |
| 127 | + if (expenseTypeValue) { |
| 128 | + const contextDiff = b.contextFrequency - a.contextFrequency; |
| 129 | + if (contextDiff !== 0) return contextDiff; |
| 130 | + } |
| 131 | + // Fall back to overall frequency |
| 132 | + return b.frequency - a.frequency; |
| 133 | + }); |
88 | 134 |
|
89 |
| - $: parsedExpenseTypes = $expenseTypes.map((expenseType) => { |
90 |
| - return { |
| 135 | + // Map and sort expense types based on context |
| 136 | + parsedExpenseTypes = $expenseTypes.map((expenseType) => ({ |
91 | 137 | value: expenseType.id,
|
92 |
| - label: expenseType.name |
93 |
| - }; |
94 |
| - }); |
| 138 | + label: expenseType.name, |
| 139 | + frequency: customerFrequency[expenseType.id] || 0, |
| 140 | + // If a customer is selected, use the frequency of this type with that customer |
| 141 | + contextFrequency: customerValue ? (customerTypeFrequency[customerValue]?.[expenseType.id] || 0) : 0 |
| 142 | + })).sort((a, b) => { |
| 143 | + // If we have a customer selected, sort by context frequency first |
| 144 | + if (customerValue) { |
| 145 | + const contextDiff = b.contextFrequency - a.contextFrequency; |
| 146 | + if (contextDiff !== 0) return contextDiff; |
| 147 | + } |
| 148 | + // Fall back to overall frequency |
| 149 | + return b.frequency - a.frequency; |
| 150 | + }); |
| 151 | + } |
95 | 152 |
|
96 |
| - function closeEditCustomerCombobox(triggerId: string) { |
97 |
| - editCustomerOpen = false; |
| 153 | + function closeCustomerCombobox(triggerId: string) { |
| 154 | + customerOpen = false; |
98 | 155 | tick().then(() => {
|
99 | 156 | document.getElementById(triggerId)?.focus();
|
100 | 157 | });
|
101 | 158 | }
|
102 | 159 |
|
103 |
| - function closeEditExpenseTypeCombobox(triggerId: string) { |
104 |
| - editExpenseTypeOpen = false; |
| 160 | + function closeExpenseTypeCombobox(triggerId: string) { |
| 161 | + expenseTypeOpen = false; |
105 | 162 | tick().then(() => {
|
106 | 163 | document.getElementById(triggerId)?.focus();
|
107 | 164 | });
|
|
570 | 627 | if (editingExpense) {
|
571 | 628 | editingExpense.customer_id = customer.value;
|
572 | 629 | editingExpense.customer = customer.label;
|
573 |
| - closeEditCustomerCombobox(ids.trigger); |
| 630 | + closeCustomerCombobox(ids.trigger); |
574 | 631 | }
|
575 | 632 | }}
|
576 | 633 | >
|
|
580 | 637 | editingExpense.customer_id !== customer.value && "text-transparent"
|
581 | 638 | )}
|
582 | 639 | />
|
583 |
| - {customer.label} |
| 640 | + <span class="flex-1">{customer.label}</span> |
| 641 | + {#if customer.frequency > 0} |
| 642 | + <span class="text-xs text-muted-foreground ml-2">{customer.frequency}x</span> |
| 643 | + {/if} |
584 | 644 | </Command.Item>
|
585 | 645 | {/each}
|
586 | 646 | </Command.Group>
|
|
613 | 673 | if (editingExpense) {
|
614 | 674 | editingExpense.expense_type = expenseType.value;
|
615 | 675 | editingExpense.type = expenseType.label;
|
616 |
| - closeEditExpenseTypeCombobox(ids.trigger); |
| 676 | + closeExpenseTypeCombobox(ids.trigger); |
617 | 677 | }
|
618 | 678 | }}
|
619 | 679 | >
|
|
623 | 683 | editingExpense.expense_type !== expenseType.value && "text-transparent"
|
624 | 684 | )}
|
625 | 685 | />
|
626 |
| - {expenseType.label} |
| 686 | + <span class="flex-1">{expenseType.label}</span> |
| 687 | + {#if expenseType.frequency > 0} |
| 688 | + <span class="text-xs text-muted-foreground ml-2">{expenseType.frequency}x</span> |
| 689 | + {/if} |
627 | 690 | </Command.Item>
|
628 | 691 | {/each}
|
629 | 692 | </Command.Group>
|
|
0 commit comments