feat(extraordinary-expenses): Add module for extraordinary expenses

Introduces a new module to manage and track extraordinary expenses within condominiums. This includes defining expense items, sharing arrangements, and attaching relevant documents.

The module adds new types for `ExpenseItem`, `ExpenseShare`, and `ExtraordinaryExpense`. Mock database functions are updated to support fetching, creating, and managing these expenses. UI components in `Layout.tsx` and `Settings.tsx` are modified to include navigation and feature toggling for extraordinary expenses. Additionally, new routes are added in `App.tsx` for both administrative and user-facing views of these expenses.
This commit is contained in:
2025-12-09 23:00:05 +01:00
parent 048180db75
commit fa12a8de85
13 changed files with 918 additions and 77 deletions

View File

@@ -1,5 +1,5 @@
import { Family, Payment, AppSettings, User, AlertDefinition, Condo, Notice, NoticeRead, Ticket, TicketAttachment, TicketComment, SmtpConfig } from '../types';
import { Family, Payment, AppSettings, User, AlertDefinition, Condo, Notice, NoticeRead, Ticket, TicketAttachment, TicketComment, SmtpConfig, ExtraordinaryExpense } from '../types';
// --- CONFIGURATION TOGGLE ---
const FORCE_LOCAL_DB = false;
@@ -343,6 +343,44 @@ export const CondoService = {
});
},
// --- EXTRAORDINARY EXPENSES ---
getExpenses: async (condoId?: string): Promise<ExtraordinaryExpense[]> => {
let url = '/expenses';
const activeId = condoId || CondoService.getActiveCondoId();
if (activeId) url += `?condoId=${activeId}`;
return request<ExtraordinaryExpense[]>(url);
},
getExpenseDetails: async (id: string): Promise<ExtraordinaryExpense> => {
return request<ExtraordinaryExpense>(`/expenses/${id}`);
},
createExpense: async (data: any): Promise<void> => {
const activeId = CondoService.getActiveCondoId();
if (!activeId) throw new Error("No active condo");
return request('/expenses', {
method: 'POST',
body: JSON.stringify({ ...data, condoId: activeId })
});
},
getExpenseAttachment: async (expenseId: string, attachmentId: string): Promise<any> => {
return request(`/expenses/${expenseId}/attachments/${attachmentId}`);
},
getMyExpenses: async (): Promise<any[]> => {
const activeId = CondoService.getActiveCondoId();
return request(`/my-expenses?condoId=${activeId}`);
},
payExpense: async (expenseId: string, amount: number): Promise<void> => {
return request(`/expenses/${expenseId}/pay`, {
method: 'POST',
body: JSON.stringify({ amount, notes: 'PayPal Payment' })
});
},
// --- SEEDING ---
seedPayments: () => {
// No-op in remote mode