feat: Implement expense creation modal and API integration

- Added ExpenseCreateModal component for adding new expenses with form validation.
- Integrated API endpoint for creating expenses, ensuring only authorized users can access it.
- Updated dashboard to include functionality for adding expenses and refreshing the expense list after creation.
- Enhanced UI with Vuetify components for better user experience and responsiveness.
This commit is contained in:
2025-07-09 13:58:38 -04:00
parent ac7176ff17
commit 7ba8c98663
4 changed files with 957 additions and 405 deletions

View File

@@ -0,0 +1,79 @@
import { requireSalesOrAdmin } from '@/server/utils/auth';
import { getNocoDbConfiguration } from '@/server/utils/nocodb';
import type { Expense } from '@/utils/types';
export default defineEventHandler(async (event) => {
try {
// Ensure only sales/admin users can create expenses
await requireSalesOrAdmin(event);
const body = await readBody(event);
console.log('[create-expense] Creating expense with data:', body);
// Validate required fields
const requiredFields = ['Establishment Name', 'Price', 'Category', 'Payer', 'Time'];
for (const field of requiredFields) {
if (!body[field]) {
throw createError({
statusCode: 400,
statusMessage: `Missing required field: ${field}`
});
}
}
// Get NocoDB configuration
const config = getNocoDbConfiguration();
const expenseTableId = "mxfcefkk4dqs6uq"; // Expense table ID from nocodb.ts
// Prepare expense data for NocoDB
const expenseData = {
"Establishment Name": body["Establishment Name"],
Price: body.Price,
Category: body.Category,
Payer: body.Payer,
Time: body.Time,
Contents: body.Contents || null,
"Payment Method": body["Payment Method"] || "Card",
currency: body.currency || "EUR",
Paid: body.Paid || false
};
console.log('[create-expense] Sending to NocoDB:', expenseData);
// Create the expense in NocoDB
const response = await $fetch<Expense>(`${config.url}/api/v2/tables/${expenseTableId}/records`, {
method: 'POST',
headers: {
'xc-token': config.token,
'Content-Type': 'application/json'
},
body: expenseData
});
console.log('[create-expense] Expense created successfully:', response.Id);
return response;
} catch (error: any) {
console.error('[create-expense] Failed to create expense:', error);
if (error.statusCode === 403) {
throw createError({
statusCode: 403,
statusMessage: 'Access denied. This feature requires sales team or administrator privileges.'
});
}
if (error.statusCode === 400) {
throw createError({
statusCode: 400,
statusMessage: error.statusMessage
});
}
throw createError({
statusCode: 500,
statusMessage: 'Failed to create expense. Please try again later.'
});
}
});