Adds equity eligibility check for expenses

Improves the expense tracking component by fetching user information to determine equity eligibility.

This allows displaying the "Convert to equity" checkbox only to eligible users, enhancing the user experience and ensuring accurate expense categorization.

Also includes error handling to prevent the form from breaking if user information cannot be loaded.
This commit is contained in:
padreug 2025-11-08 00:10:40 +01:00
parent 53c14044ef
commit fff42d170e
3 changed files with 60 additions and 7 deletions

View file

@ -138,8 +138,8 @@
</FormItem> </FormItem>
</FormField> </FormField>
<!-- Convert to equity checkbox --> <!-- Convert to equity checkbox (only show if user is equity eligible) -->
<FormField v-slot="{ value, handleChange }" name="isEquity"> <FormField v-if="userInfo?.is_equity_eligible" v-slot="{ value, handleChange }" name="isEquity">
<FormItem> <FormItem>
<div class="flex items-center space-x-2"> <div class="flex items-center space-x-2">
<FormControl> <FormControl>
@ -239,7 +239,7 @@ import { injectService, SERVICE_TOKENS } from '@/core/di-container'
import { useAuth } from '@/composables/useAuthService' import { useAuth } from '@/composables/useAuthService'
import { useToast } from '@/core/composables/useToast' import { useToast } from '@/core/composables/useToast'
import type { ExpensesAPI } from '../services/ExpensesAPI' import type { ExpensesAPI } from '../services/ExpensesAPI'
import type { Account } from '../types' import type { Account, UserInfo } from '../types'
import AccountSelector from './AccountSelector.vue' import AccountSelector from './AccountSelector.vue'
interface Emits { interface Emits {
@ -261,6 +261,7 @@ const selectedAccount = ref<Account | null>(null)
const isSubmitting = ref(false) const isSubmitting = ref(false)
const availableCurrencies = ref<string[]>([]) const availableCurrencies = ref<string[]>([])
const loadingCurrencies = ref(true) const loadingCurrencies = ref(true)
const userInfo = ref<UserInfo | null>(null)
// Form schema // Form schema
const formSchema = toTypedSchema( const formSchema = toTypedSchema(
@ -289,12 +290,19 @@ const { resetForm, meta } = form
const isFormValid = computed(() => meta.value.valid) const isFormValid = computed(() => meta.value.valid)
/** /**
* Fetch available currencies and default currency on component mount * Fetch available currencies, default currency, and user info on component mount
*/ */
onMounted(async () => { onMounted(async () => {
try { try {
loadingCurrencies.value = true loadingCurrencies.value = true
// Get wallet key
const wallet = user.value?.wallets?.[0]
if (!wallet || !wallet.inkey) {
console.warn('[AddExpense] No wallet available for loading data')
return
}
// Fetch available currencies // Fetch available currencies
const currencies = await expensesAPI.getCurrencies() const currencies = await expensesAPI.getCurrencies()
availableCurrencies.value = currencies availableCurrencies.value = currencies
@ -307,9 +315,16 @@ onMounted(async () => {
const initialCurrency = defaultCurrency || currencies[0] || 'EUR' const initialCurrency = defaultCurrency || currencies[0] || 'EUR'
form.setFieldValue('currency', initialCurrency) form.setFieldValue('currency', initialCurrency)
console.log('[AddExpense] Default currency set to:', initialCurrency) console.log('[AddExpense] Default currency set to:', initialCurrency)
// Fetch user info to check equity eligibility
userInfo.value = await expensesAPI.getUserInfo(wallet.inkey)
console.log('[AddExpense] User info loaded:', {
is_equity_eligible: userInfo.value.is_equity_eligible,
equity_account: userInfo.value.equity_account_name
})
} catch (error) { } catch (error) {
console.error('[AddExpense] Failed to load currencies:', error) console.error('[AddExpense] Failed to load data:', error)
toast.error('Failed to load currencies', { description: 'Please check your connection and try again' }) toast.error('Failed to load form data', { description: 'Please check your connection and try again' })
availableCurrencies.value = [] availableCurrencies.value = []
} finally { } finally {
loadingCurrencies.value = false loadingCurrencies.value = false

View file

@ -7,7 +7,8 @@ import type {
Account, Account,
ExpenseEntryRequest, ExpenseEntryRequest,
ExpenseEntry, ExpenseEntry,
AccountNode AccountNode,
UserInfo
} from '../types' } from '../types'
import { appConfig } from '@/app.config' import { appConfig } from '@/app.config'
@ -263,4 +264,32 @@ export class ExpensesAPI extends BaseService {
throw error throw error
} }
} }
/**
* Get user information including equity eligibility
*
* @param walletKey - Wallet key for authentication (invoice key)
*/
async getUserInfo(walletKey: string): Promise<UserInfo> {
try {
const response = await fetch(`${this.baseUrl}/castle/api/v1/user/info`, {
method: 'GET',
headers: this.getHeaders(walletKey),
signal: AbortSignal.timeout(this.config?.apiConfig?.timeout || 30000)
})
if (!response.ok) {
throw new Error(`Failed to fetch user info: ${response.statusText}`)
}
return await response.json()
} catch (error) {
console.error('[ExpensesAPI] Error fetching user info:', error)
// Return default non-eligible user on error
return {
user_id: '',
is_equity_eligible: false
}
}
}
} }

View file

@ -86,6 +86,15 @@ export interface AccountNode {
children: AccountNode[] children: AccountNode[]
} }
/**
* User information including equity eligibility
*/
export interface UserInfo {
user_id: string
is_equity_eligible: boolean
equity_account_name?: string
}
/** /**
* Module configuration * Module configuration
*/ */