Enables currency selection for expenses

Allows users to select a currency when adding an expense.

Fetches available currencies from the backend and displays them
in a dropdown menu, defaulting to EUR if the fetch fails.
The expense submission process now includes the selected currency.
This commit is contained in:
padreug 2025-11-07 21:39:16 +01:00
parent 9c8b696f06
commit 8dad92f0e5
2 changed files with 82 additions and 5 deletions

View file

@ -80,7 +80,7 @@
<!-- Amount -->
<FormField v-slot="{ componentField }" name="amount">
<FormItem>
<FormLabel>Amount (EUR) *</FormLabel>
<FormLabel>Amount *</FormLabel>
<FormControl>
<Input
type="number"
@ -91,7 +91,34 @@
/>
</FormControl>
<FormDescription>
Amount in Euros
Amount in selected currency
</FormDescription>
<FormMessage />
</FormItem>
</FormField>
<!-- Currency -->
<FormField v-slot="{ componentField }" name="currency">
<FormItem>
<FormLabel>Currency *</FormLabel>
<Select v-bind="componentField">
<FormControl>
<SelectTrigger>
<SelectValue placeholder="Select currency" />
</SelectTrigger>
</FormControl>
<SelectContent>
<SelectItem
v-for="currency in availableCurrencies"
:key="currency"
:value="currency"
>
{{ currency }}
</SelectItem>
</SelectContent>
</Select>
<FormDescription>
Currency for this expense
</FormDescription>
<FormMessage />
</FormItem>
@ -179,7 +206,7 @@
</template>
<script setup lang="ts">
import { ref, computed } from 'vue'
import { ref, computed, onMounted } from 'vue'
import { useForm } from 'vee-validate'
import { toTypedSchema } from '@vee-validate/zod'
import * as z from 'zod'
@ -195,6 +222,13 @@ import {
FormLabel,
FormMessage,
} from '@/components/ui/form'
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from '@/components/ui/select'
import { DollarSign, X, ChevronLeft, Loader2 } from 'lucide-vue-next'
import { injectService, SERVICE_TOKENS } from '@/core/di-container'
import { useAuth } from '@/composables/useAuthService'
@ -220,12 +254,15 @@ const toast = useToast()
const currentStep = ref(1)
const selectedAccount = ref<Account | null>(null)
const isSubmitting = ref(false)
const availableCurrencies = ref<string[]>([])
const loadingCurrencies = ref(true)
// Form schema
const formSchema = toTypedSchema(
z.object({
description: z.string().min(1, 'Description is required').max(500, 'Description too long'),
amount: z.coerce.number().min(0.01, 'Amount must be at least €0.01'),
amount: z.coerce.number().min(0.01, 'Amount must be at least 0.01'),
currency: z.string().min(1, 'Currency is required'),
reference: z.string().max(100, 'Reference too long').optional(),
isEquity: z.boolean().default(false)
})
@ -237,6 +274,7 @@ const form = useForm({
initialValues: {
description: '',
amount: 0,
currency: 'EUR',
reference: '',
isEquity: false
}
@ -245,6 +283,24 @@ const form = useForm({
const { resetForm, meta } = form
const isFormValid = computed(() => meta.value.valid)
/**
* Fetch available currencies on component mount
*/
onMounted(async () => {
try {
loadingCurrencies.value = true
const currencies = await expensesAPI.getCurrencies()
availableCurrencies.value = currencies
console.log('[AddExpense] Loaded currencies:', currencies)
} catch (error) {
console.error('[AddExpense] Failed to load currencies:', error)
toast.error('Failed to load currencies', { description: 'Please check your connection and try again' })
availableCurrencies.value = []
} finally {
loadingCurrencies.value = false
}
})
/**
* Handle account selection
*/
@ -280,7 +336,7 @@ const onSubmit = form.handleSubmit(async (values) => {
is_equity: values.isEquity,
user_wallet: wallet.id,
reference: values.reference,
currency: 'EUR'
currency: values.currency
})
// Show success message

View file

@ -207,4 +207,25 @@ export class ExpensesAPI extends BaseService {
throw error
}
}
/**
* Get available currencies from LNbits instance
*/
async getCurrencies(): Promise<string[]> {
try {
const response = await fetch(`${this.baseUrl}/api/v1/currencies`, {
method: 'GET',
signal: AbortSignal.timeout(this.config?.apiConfig?.timeout || 30000)
})
if (!response.ok) {
throw new Error(`Failed to fetch currencies: ${response.statusText}`)
}
return await response.json()
} catch (error) {
console.error('[ExpensesAPI] Error fetching currencies:', error)
throw error
}
}
}