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:
parent
9c8b696f06
commit
8dad92f0e5
2 changed files with 82 additions and 5 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue