
This commit adds new functionality for tracking user activities within the application, including: - Implementation of a new activity service to fetch and manage group activities. - Creation of a dedicated activity store to handle state management for activities. - Introduction of new API endpoints for retrieving paginated activity data. - Enhancements to the UI with new components for displaying activity feeds and items. - Refactoring of existing components to utilize the new activity features, improving user engagement and interaction. These changes aim to enhance the application's activity tracking capabilities and provide users with a comprehensive view of their interactions.
90 lines
2.8 KiB
Vue
90 lines
2.8 KiB
Vue
<template>
|
|
<Dialog v-model="open" class="z-50">
|
|
<form @submit.prevent="handleSubmit"
|
|
class="bg-white dark:bg-neutral-800 p-6 rounded-lg shadow-xl w-full max-w-md">
|
|
<div class="flex items-center justify-between mb-4">
|
|
<Heading :level="3">{{ $t('expenseCreation.title', 'Add Expense') }}</Heading>
|
|
<Button variant="ghost" size="sm" @click="open = false">
|
|
<BaseIcon name="heroicons:x-mark-20-solid" class="w-5 h-5" />
|
|
</Button>
|
|
</div>
|
|
|
|
<Input v-model="form.description" :label="$t('expenseCreation.description', 'Description')" class="mb-3" />
|
|
<Input type="number" step="0.01" v-model="form.total_amount" :label="$t('expenseCreation.amount', 'Amount')"
|
|
class="mb-3" />
|
|
|
|
<div class="flex justify-end gap-2 mt-6">
|
|
<Button variant="ghost" @click.prevent="open = false">{{ $t('common.cancel', 'Cancel') }}</Button>
|
|
<Button type="submit" :loading="submitting">{{ $t('common.save', 'Save') }}</Button>
|
|
</div>
|
|
</form>
|
|
</Dialog>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { reactive, ref, watch } from 'vue'
|
|
import { Dialog } from '@/components/ui'
|
|
import { Heading, Input, Button } from '@/components/ui'
|
|
import BaseIcon from '@/components/BaseIcon.vue'
|
|
import { useExpenses } from '@/composables/useExpenses'
|
|
import type { Expense } from '@/types/expense'
|
|
import { computed } from 'vue'
|
|
|
|
interface ExpenseForm {
|
|
description: string
|
|
total_amount: string
|
|
}
|
|
|
|
const open = defineModel<boolean>('modelValue', { default: false })
|
|
|
|
// Props
|
|
const props = defineProps<{ expense?: Expense | null }>()
|
|
|
|
const form = reactive<ExpenseForm>({ description: '', total_amount: '' })
|
|
const isEditing = computed(() => !!props.expense)
|
|
|
|
const { createExpense, updateExpense } = useExpenses()
|
|
|
|
// Sync form when editing
|
|
watch(
|
|
() => props.expense,
|
|
(val) => {
|
|
if (val) {
|
|
form.description = val.description
|
|
form.total_amount = val.total_amount
|
|
} else {
|
|
form.description = ''
|
|
form.total_amount = ''
|
|
}
|
|
},
|
|
{ immediate: true },
|
|
)
|
|
|
|
const submitting = ref(false)
|
|
|
|
async function handleSubmit() {
|
|
submitting.value = true
|
|
try {
|
|
if (isEditing.value && props.expense) {
|
|
await updateExpense(props.expense.id, { ...form, version: props.expense.version })
|
|
} else {
|
|
await createExpense({
|
|
...form,
|
|
currency: 'USD',
|
|
split_type: 'EQUAL',
|
|
isRecurring: false,
|
|
paid_by_user_id: 0,
|
|
})
|
|
}
|
|
open.value = false
|
|
} catch (e) {
|
|
console.error('Failed to create expense', e)
|
|
} finally {
|
|
submitting.value = false
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
/* Tailwind styling */
|
|
</style> |