Project details: cost & breakdown section display cost type for each team cost entry
This commit is contained in:
@@ -141,6 +141,17 @@ const EXPENSE_TYPE_CONFIG = {
|
|||||||
|
|
||||||
const SUBCONTRACTOR_WORK_TYPES = ['Plumbing', 'Electrical', 'Painting', 'Roofing', 'Civil work', 'HVAC', 'Carpentry', 'Other'];
|
const SUBCONTRACTOR_WORK_TYPES = ['Plumbing', 'Electrical', 'Painting', 'Roofing', 'Civil work', 'HVAC', 'Carpentry', 'Other'];
|
||||||
|
|
||||||
|
// Short labels for team cost types — shown inline in the Type badge (e.g. "Team Cost · Comm")
|
||||||
|
const COST_TYPE_ABBR = {
|
||||||
|
'Commission': 'Comm',
|
||||||
|
'Salary': 'Salary',
|
||||||
|
'Bonus': 'Bonus',
|
||||||
|
'Hourly Wage': 'Hourly',
|
||||||
|
'Per Diem': 'Per Diem',
|
||||||
|
'Referral Fee': 'Referral',
|
||||||
|
'Overtime': 'OT',
|
||||||
|
};
|
||||||
|
|
||||||
const inferExpenseType = (category = '') => {
|
const inferExpenseType = (category = '') => {
|
||||||
const c = (category || '').toLowerCase();
|
const c = (category || '').toLowerCase();
|
||||||
if (c.includes('material')) return 'material';
|
if (c.includes('material')) return 'material';
|
||||||
@@ -166,9 +177,9 @@ function seedExpenseRowsMock(project) {
|
|||||||
});
|
});
|
||||||
const seed = (project?.id || '').charCodeAt((project?.id || 'x').length - 1) % 3;
|
const seed = (project?.id || '').charCodeAt((project?.id || 'x').length - 1) % 3;
|
||||||
const teamRows = [
|
const teamRows = [
|
||||||
{ id: 'exp_team_1', type: 'team', name: 'Jesus Gonzales', category: 'Sales Rep', allocated: 4200, actual: 4200, paid: true },
|
{ id: 'exp_team_1', type: 'team', name: 'Jesus Gonzales', category: 'Sales Rep', costType: 'Commission', allocated: 4200, actual: 4200, paid: true },
|
||||||
{ id: 'exp_team_2', type: 'team', name: 'Cody Tatum', category: 'Canvasser', allocated: 1500, actual: 1500, paid: false },
|
{ id: 'exp_team_2', type: 'team', name: 'Cody Tatum', category: 'Canvasser', costType: 'Hourly Wage', allocated: 1500, actual: 1500, paid: false },
|
||||||
{ id: 'exp_team_3', type: 'team', name: 'Sarah Calloway', category: 'Estimator', allocated: 1200, actual: 0, paid: false },
|
{ id: 'exp_team_3', type: 'team', name: 'Sarah Calloway', category: 'Estimator', costType: 'Salary', allocated: 1200, actual: 0, paid: false },
|
||||||
].slice(0, 2 + seed).map(row => ({
|
].slice(0, 2 + seed).map(row => ({
|
||||||
...row,
|
...row,
|
||||||
paymentRequests: generateMockPaymentRequests(row.id, row.actual, row.paid, row.allocated)
|
paymentRequests: generateMockPaymentRequests(row.id, row.actual, row.paid, row.allocated)
|
||||||
@@ -420,6 +431,7 @@ const OwnerProjectDetail = () => {
|
|||||||
type: type || data.type || 'other',
|
type: type || data.type || 'other',
|
||||||
name: data.name || '',
|
name: data.name || '',
|
||||||
category: data.category || '',
|
category: data.category || '',
|
||||||
|
costType: data.costType || '',
|
||||||
allocated: amt,
|
allocated: amt,
|
||||||
actual: amt,
|
actual: amt,
|
||||||
paid: false,
|
paid: false,
|
||||||
@@ -1171,7 +1183,7 @@ const OwnerProjectDetail = () => {
|
|||||||
<td className="px-5 py-4">
|
<td className="px-5 py-4">
|
||||||
<span className={`inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-[10px] font-bold uppercase tracking-widest border ${cfg.color} ${cfg.bg} ${cfg.border}`}>
|
<span className={`inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-[10px] font-bold uppercase tracking-widest border ${cfg.color} ${cfg.bg} ${cfg.border}`}>
|
||||||
<TypeIcon size={11} />
|
<TypeIcon size={11} />
|
||||||
{cfg.label}
|
{cfg.label}{row.type === 'team' && row.costType ? ` · ${COST_TYPE_ABBR[row.costType] || row.costType}` : ''}
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
<td className="px-5 py-4 font-bold text-sm text-zinc-900 dark:text-white">{row.name || '—'}</td>
|
<td className="px-5 py-4 font-bold text-sm text-zinc-900 dark:text-white">{row.name || '—'}</td>
|
||||||
@@ -2711,10 +2723,9 @@ const OwnerProjectDetail = () => {
|
|||||||
onClose={() => setAddTeamCostOpen(false)}
|
onClose={() => setAddTeamCostOpen(false)}
|
||||||
onSubmit={(data) => {
|
onSubmit={(data) => {
|
||||||
handleAddExpense(
|
handleAddExpense(
|
||||||
{ name: data.name, category: data.category, amount: data.amount },
|
{ name: data.name, category: data.category, costType: data.costType, amount: data.amount },
|
||||||
'team'
|
'team'
|
||||||
);
|
);
|
||||||
setAddTeamCostOpen(false);
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user