feat: categorizar transações no preview de importação

Select de categoria em cada linha da prévia; category_id salvo no
BulkInsert. Duplicatas ficam desabilitadas.

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
This commit is contained in:
2026-05-27 16:04:19 -03:00
co-authored by Claude Sonnet 4.6
parent 54d5a03604
commit 482bae698a
4 changed files with 27 additions and 4 deletions
+1
View File
@@ -6,6 +6,7 @@ export interface ImportRow {
amount: number
description: string
type: string
category_id?: number | null
external_id?: string
is_duplicate: boolean
}
+22 -1
View File
@@ -1,9 +1,12 @@
<script setup lang="ts">
import { ref, computed, watch } from 'vue'
import { ref, computed, watch, onMounted } from 'vue'
import { useImportStore, type CSVMapping } from '@/stores/import'
import { useCategoriesStore } from '@/stores/categories'
import NeonPanel from '@/components/NeonPanel.vue'
const store = useImportStore()
const catStore = useCategoriesStore()
onMounted(() => catStore.fetchAll())
const fileInput = ref<HTMLInputElement | null>(null)
const selectedFile = ref<File | null>(null)
@@ -192,6 +195,7 @@ function fmt(amount: number) {
<th class="fc-pixel">DESCRIÇÃO</th>
<th class="fc-pixel">VALOR</th>
<th class="fc-pixel">TIPO</th>
<th class="fc-pixel">CATEGORIA</th>
<th class="fc-pixel">STATUS</th>
</tr>
</thead>
@@ -203,6 +207,16 @@ function fmt(amount: number) {
{{ fmt(row.amount) }}
</td>
<td class="fc-mono">{{ row.type === 'income' ? 'Receita' : 'Gasto' }}</td>
<td>
<select
v-model="row.category_id"
class="fc-select fc-import-cat-select"
:disabled="row.is_duplicate"
>
<option :value="null"></option>
<option v-for="c in catStore.categories" :key="c.id" :value="c.id">{{ c.name }}</option>
</select>
</td>
<td>
<span v-if="row.is_duplicate" class="fc-pixel fc-import-status fc-import-status--dup">DUP</span>
<span v-else class="fc-pixel fc-import-status fc-import-status--new">NOVO</span>
@@ -334,6 +348,13 @@ function fmt(amount: number) {
.fc-import-status--new { background: rgba(57,255,122,.15); color: var(--fc-green); }
.fc-import-status--dup { background: rgba(255,216,77,.15); color: var(--fc-gold); }
.fc-import-cat-select {
font-size: 10px;
padding: 2px 4px;
min-width: 110px;
height: 26px;
}
.fc-import-confirm {
display: flex;
gap: var(--fc-space-3);