Files
bigcapital/packages/webapp/src/containers/Expenses/ExpenseForm/ExpenseFormPageProvider.tsx
Ahmed Bouhuolia 3bf2803360 feat(trpc): implement tRPC integration for accounts module
- Add tRPC server setup with NestJS (nestjs-trpc)
- Create AccountsTrpcRouter with CRUD operations
- Add tRPC client configuration in webapp
- Create tRPC React hooks for accounts module
- Replace existing REST hooks with tRPC hooks across 35+ files
- Maintain backward compatibility with existing REST API
- Add proper cache invalidation for mutations

New files:
- packages/server/src/modules/Trpc/*
- packages/webapp/src/trpc.ts
- packages/webapp/src/hooks/trpc/*
- shared/bigcapital-utils/src/trpc.ts

Dependencies added:
- @trpc/server, @trpc/client, @trpc/react-query
- nestjs-trpc, superjson
- @tanstack/react-query

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-24 04:34:04 +02:00

120 lines
3.1 KiB
TypeScript

// @ts-nocheck
import React, { createContext } from 'react';
import { css } from '@emotion/css';
import { DashboardInsider } from '@/components/Dashboard';
import { Features } from '@/constants';
import { useFeatureCan } from '@/hooks/state';
import {
useCurrencies,
useCustomers,
useExpense,
useBranches,
useCreateExpense,
useEditExpense,
} from '@/hooks/query';
import { useAccountsTrpc } from '@/hooks/trpc';
import { useProjects } from '@/containers/Projects/hooks';
const ExpenseFormPageContext = createContext();
/**
* Accounts chart data provider.
*/
function ExpenseFormPageProvider({ query, expenseId, ...props }) {
// Features guard.
const { featureCan } = useFeatureCan();
const isBranchFeatureCan = featureCan(Features.Branches);
const isProjectsFeatureCan = featureCan(Features.Projects);
const { data: currencies, isLoading: isCurrenciesLoading } = useCurrencies();
// Fetches customers list.
const {
data: { customers },
isLoading: isCustomersLoading,
} = useCustomers();
// Fetch the expense details.
const { data: expense, isLoading: isExpenseLoading } = useExpense(expenseId, {
enabled: !!expenseId,
});
// Fetches the branches list.
const {
data: branches,
isLoading: isBranchesLoading,
isSuccess: isBranchesSuccess,
} = useBranches(query, { enabled: isBranchFeatureCan });
// Fetch accounts list.
const { data: accounts, isLoading: isAccountsLoading } = useAccountsTrpc();
// Fetch the projects list.
const {
data: { projects },
isLoading: isProjectsLoading,
} = useProjects({}, { enabled: !!isProjectsFeatureCan });
// Create and edit expense mutate.
const { mutateAsync: createExpenseMutate } = useCreateExpense();
const { mutateAsync: editExpenseMutate } = useEditExpense();
// Submit form payload - using ref for synchronous access.
const submitPayloadRef = React.useRef({});
// Setter to update the ref.
const setSubmitPayload = React.useCallback((payload) => {
submitPayloadRef.current = payload;
}, []);
// Detarmines whether the form in new mode.
const isNewMode = !expenseId;
// Provider payload.
const provider = {
isNewMode,
expenseId,
submitPayloadRef, // Expose ref for synchronous access
currencies,
customers,
expense,
accounts,
branches,
projects,
isCurrenciesLoading,
isExpenseLoading,
isCustomersLoading,
isAccountsLoading,
isBranchesSuccess,
createExpenseMutate,
editExpenseMutate,
setSubmitPayload,
};
return (
<DashboardInsider
loading={
isCurrenciesLoading ||
isExpenseLoading ||
isCustomersLoading ||
isAccountsLoading ||
isProjectsLoading
}
name={'expense-form'}
className={css`
min-height: calc(100vh - var(--top-offset));
max-height: calc(100vh - var(--top-offset));
`}
>
<ExpenseFormPageContext.Provider value={provider} {...props} />
</DashboardInsider>
);
}
const useExpenseFormContext = () => React.useContext(ExpenseFormPageContext);
export { ExpenseFormPageProvider, useExpenseFormContext };