Skip to content

Commit d577324

Browse files
committed
Day page improvements: Labor section, Net Outflow, Today nav rename, parseDate helper
1 parent 69e30bd commit d577324

10 files changed

Lines changed: 236 additions & 110 deletions

File tree

www/css/day.css

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,17 @@
1212
}
1313

1414
.stats-grid-2 {
15-
grid-template-columns: repeat(2, 1fr);
15+
grid-template-columns: repeat(2, minmax(0, 1fr));
1616
}
1717

1818
.stats-grid-3 {
19-
grid-template-columns: repeat(3, 1fr);
19+
grid-template-columns: repeat(3, minmax(0, 1fr));
2020
}
2121

2222
.stats-grid-3 .stat-value-sm {
2323
font-size: 15px;
24-
white-space: nowrap;
25-
overflow: hidden;
26-
text-overflow: ellipsis;
24+
word-wrap: break-word;
25+
overflow-wrap: break-word;
2726
}
2827

2928
.stats-grid-3 .stat-card-purple .stat-value-sm {
@@ -36,6 +35,8 @@
3635
border-radius: var(--radius-md);
3736
text-align: center;
3837
transition: all var(--transition);
38+
min-width: 0;
39+
overflow: hidden;
3940
}
4041

4142
.stat-card:hover {
@@ -47,21 +48,27 @@
4748
font-size: 13px;
4849
margin-bottom: 4px;
4950
font-weight: 500;
51+
word-wrap: break-word;
5052
}
5153

5254
.stat-value {
5355
font-size: 22px;
5456
font-weight: 700;
57+
word-wrap: break-word;
58+
overflow-wrap: break-word;
5559
}
5660

5761
.stat-value-sm {
5862
font-size: 18px;
5963
font-weight: 700;
64+
word-wrap: break-word;
65+
overflow-wrap: break-word;
6066
}
6167

6268
.stat-subtitle {
6369
font-size: 12px;
6470
margin-top: 4px;
71+
word-wrap: break-word;
6572
}
6673

6774
/* Stat Card Variants */
@@ -147,26 +154,29 @@
147154
/* Summary Grid */
148155
.summary-grid {
149156
display: grid;
150-
grid-template-columns: repeat(2, 1fr);
157+
grid-template-columns: repeat(2, minmax(0, 1fr));
151158
gap: 10px;
152159
font-size: 14px;
153160
}
154161

155162
.summary-item {
156163
display: flex;
157-
justify-content: space-between;
164+
flex-direction: column;
158165
padding: 10px 12px;
159166
border-radius: var(--radius);
160-
align-items: center;
167+
min-width: 0;
161168
}
162169

163170
.summary-item span {
164171
color: var(--text-secondary);
165172
font-weight: 500;
173+
font-size: 13px;
166174
}
167175

168176
.summary-item strong {
169177
font-weight: 700;
178+
font-size: 16px;
179+
margin-top: 4px;
170180
}
171181

172182
.summary-item-success {

www/js/auth/authentication.js

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,6 @@ const AuthManager = {
365365
const restrictedTabs = {
366366
'financeTab': isOwnerOrManager,
367367
'analyticsTab': isOwnerOrManager,
368-
'stockTab': !isStaff,
369368
'salesTab': !isStaff
370369
};
371370

@@ -406,15 +405,21 @@ const AuthManager = {
406405
item.style.display = 'block';
407406
}
408407

409-
if (tabId === 'stock' && isStaff) {
408+
if (tabId === 'sales' && isStaff) {
410409
item.style.display = 'none';
411-
} else if (tabId === 'stock' && !isStaff) {
410+
} else if (tabId === 'sales' && !isStaff) {
412411
item.style.display = 'block';
413412
}
414413

415-
if (tabId === 'sales' && isStaff) {
414+
if (tabId === 'wholesale-sales' && isStaff) {
416415
item.style.display = 'none';
417-
} else if (tabId === 'sales' && !isStaff) {
416+
} else if (tabId === 'wholesale-sales' && !isStaff) {
417+
item.style.display = 'block';
418+
}
419+
420+
if (tabId === 'reports' && isStaff) {
421+
item.style.display = 'none';
422+
} else if (tabId === 'reports' && !isStaff) {
418423
item.style.display = 'block';
419424
}
420425
}

www/js/modules/day.js

Lines changed: 37 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -76,26 +76,26 @@ export const DayManager = {
7676

7777
// Filter today's purchases
7878
const todayPurchases = (AppState.purchaseHistory || []).filter(p => {
79-
const date = p.date?.toDate ? p.date.toDate() : new Date(p.date);
80-
return date >= today && date < tomorrow;
79+
const date = Helpers.parseDate(p.date);
80+
return date && date >= today && date < tomorrow;
8181
});
8282

8383
// Filter today's wholesale sales
8484
const todayWholesaleSales = (AppState.salesHistory || []).filter(s => {
85-
const date = s.date?.toDate ? s.date.toDate() : new Date(s.date);
86-
return date >= today && date < tomorrow;
85+
const date = Helpers.parseDate(s.date);
86+
return date && date >= today && date < tomorrow;
8787
});
8888

8989
// Filter today's retail sales
9090
const todayRetailSales = (AppState.retailSalesHistory || []).filter(s => {
91-
const date = s.date?.toDate ? s.date.toDate() : new Date(s.date);
92-
return date >= today && date < tomorrow;
91+
const date = Helpers.parseDate(s.date);
92+
return date && date >= today && date < tomorrow;
9393
});
9494

9595
// Filter today's expenses
9696
const todayExpenses = (AppState.expensesHistory || []).filter(e => {
97-
const date = e.date?.toDate ? e.date.toDate() : new Date(e.date);
98-
return date >= today && date < tomorrow;
97+
const date = Helpers.parseDate(e.date);
98+
return date && date >= today && date < tomorrow;
9999
});
100100

101101
// Calculate totals
@@ -113,11 +113,18 @@ export const DayManager = {
113113
return sum + amount;
114114
}, 0);
115115
const totalSales = totalWholesaleSales + totalRetailSales;
116-
// Expenses use 'amount' property
117-
const totalExpenses = todayExpenses.reduce((sum, e) => {
118-
const amount = Number(e.amount) || Number(e.total) || 0;
119-
return sum + amount;
116+
117+
// Expenses split by category
118+
const businessExpenses = todayExpenses.filter(e => e.category === 'business');
119+
const personalExpenses = todayExpenses.filter(e => e.category === 'personal');
120+
121+
const totalBusinessExpenses = businessExpenses.reduce((sum, e) => {
122+
return sum + (Number(e.amount) || Number(e.total) || 0);
120123
}, 0);
124+
const totalPersonalExpenses = personalExpenses.reduce((sum, e) => {
125+
return sum + (Number(e.amount) || Number(e.total) || 0);
126+
}, 0);
127+
const totalExpenses = totalBusinessExpenses + totalPersonalExpenses;
121128

122129
// Calculate labor cost from purchases
123130
const totalLaborCost = todayPurchases.reduce((sum, p) => sum + (p.laborCharges || p.labour || 0), 0);
@@ -158,8 +165,8 @@ export const DayManager = {
158165
// Calculate due paid and due received from cash management transactions
159166
let duePaid = 0, dueReceived = 0;
160167
const todayCashTransactions = (AppState.cashManagement || []).filter(t => {
161-
const date = t.date?.toDate ? t.date.toDate() : new Date(t.date);
162-
return date >= today && date < tomorrow;
168+
const date = Helpers.parseDate(t.date);
169+
return date && date >= today && date < tomorrow;
163170
});
164171

165172
todayCashTransactions.forEach(t => {
@@ -175,32 +182,40 @@ export const DayManager = {
175182
const totalCashOut = cashPaid + onlinePaid + totalExpenses + duePaid;
176183
const totalCashFlow = totalCashIn - totalCashOut;
177184

178-
// Net cash flow (simpler view)
179-
const netCashFlow = (cashReceived + onlineReceived) - (cashPaid + onlinePaid + totalExpenses);
185+
// Net outflow (Out - In): positive means money went out, negative means money came in
186+
const netOutflow = (cashPaid + onlinePaid + totalExpenses) - (cashReceived + onlineReceived);
180187

181188
// Update UI - Main Stats
182189
this.updateElement('todayTotalPurchases', formatCurrency(totalPurchases));
183190
this.updateElement('todayPurchaseCount', `${todayPurchases.length} bills`);
184191
this.updateElement('todayTotalSales', formatCurrency(totalSales));
185192
this.updateElement('todaySaleCount', `${todayWholesaleSales.length + todayRetailSales.length} bills`);
186-
this.updateElement('todayTotalExpenses', formatCurrency(totalExpenses));
187-
this.updateElement('todayExpenseCount', `${todayExpenses.length} entries`);
188193
this.updateElement('todayLaborCost', formatCurrency(totalLaborCost));
189194

195+
// Expenses breakdown
196+
this.updateElement('todayBusinessExpenses', formatCurrency(totalBusinessExpenses));
197+
this.updateElement('todayBusinessExpenseCount', `${businessExpenses.length} entries`);
198+
this.updateElement('todayPersonalExpenses', formatCurrency(totalPersonalExpenses));
199+
this.updateElement('todayPersonalExpenseCount', `${personalExpenses.length} entries`);
200+
190201
// Quantity metrics
191202
this.updateElement('todayQtyPurchased', `${qtyPurchased.toFixed(1)} kg`);
192203
this.updateElement('todayQtySold', `${qtySold.toFixed(1)} kg`);
193204

194-
// Net cash flow with color coding
205+
// Total In and Total Out for hero card
206+
this.updateElement('todayTotalIn', formatCurrency(cashReceived + onlineReceived));
207+
this.updateElement('todayTotalOut', formatCurrency(cashPaid + onlinePaid + totalExpenses));
208+
209+
// Net outflow with color coding
195210
const cashFlowLabel = document.getElementById('todayCashFlowLabel');
196211
if (cashFlowLabel) {
197-
cashFlowLabel.textContent = netCashFlow >= 0 ? 'Net Inflow' : 'Net Outflow';
212+
cashFlowLabel.textContent = netOutflow >= 0 ? 'Net Outflow:' : 'Net Inflow:';
198213
}
199214

200215
const netCashFlowEl = document.getElementById('todayNetCashFlow');
201216
if (netCashFlowEl) {
202-
netCashFlowEl.style.color = netCashFlow >= 0 ? '#16a34a' : '#dc2626';
203-
netCashFlowEl.textContent = (netCashFlow >= 0 ? '+' : '-') + formatCurrency(Math.abs(netCashFlow));
217+
netCashFlowEl.style.color = netOutflow >= 0 ? 'white' : '#a5f3fc';
218+
netCashFlowEl.textContent = formatCurrency(Math.abs(netOutflow));
204219
}
205220

206221
// Payment summary

www/js/modules/items.js

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,16 @@ const ItemsManager = {
551551
? item.saleRates.map(r => `${r}`).join(', ')
552552
: '-';
553553

554+
// Calculate average rate from stock for staff view
555+
let avgRate = '-';
556+
if (isStaff && AppState.stock) {
557+
// Try to find stock by item id or name
558+
const stockEntry = AppState.stock[item.id] || AppState.stock[item.name];
559+
if (stockEntry && stockEntry.rate) {
560+
avgRate = `₹${stockEntry.rate.toFixed(2)}`;
561+
}
562+
}
563+
554564
const itemFrequency = frequency[item.name] || 0;
555565

556566
const itemIndex = AppState.items.findIndex(i => i.id === item.id);
@@ -573,15 +583,29 @@ const ItemsManager = {
573583
};
574584
row.onclick = () => this.openEditModal(itemIndex);
575585
}
576-
row.innerHTML = `
577-
<td style="padding: 16px; font-weight: 600; color: #1f2937; font-size: 15px; border-right: 1px solid #f3f4f6;">
578-
${displayName || item.name || '-'}
579-
${itemFrequency > 0 ? `<span style="margin-left: 8px; padding: 3px 10px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; border-radius: 12px; font-size: 11px; font-weight: 600; box-shadow: 0 2px 4px rgba(102, 126, 234, 0.3);">${itemFrequency}</span>` : ''}
580-
</td>
581-
<td style="padding: 16px; color: #007bff; font-size: 14px; font-weight: 600; border-right: 1px solid #f3f4f6;">${purchaseRates}</td>
582-
<td style="padding: 16px; color: #28a745; font-size: 14px; font-weight: 600; border-right: 1px solid #f3f4f6;">${saleRates}</td>
583-
<td class="wholesale-column" style="padding: 16px; color: #9333ea; font-size: 14px; font-weight: 600; display: ${isStaff ? 'none' : 'table-cell'};">${wholesaleRates}</td>
584-
`;
586+
587+
// Staff view: show item name, sale rates, and avg rate
588+
// Non-staff view: show item name, purchase rates, sale rates, wholesale rates
589+
if (isStaff) {
590+
row.innerHTML = `
591+
<td style="padding: 16px; font-weight: 600; color: #1f2937; font-size: 15px; border-right: 1px solid #f3f4f6;">
592+
${displayName || item.name || '-'}
593+
${itemFrequency > 0 ? `<span style="margin-left: 8px; padding: 3px 10px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; border-radius: 12px; font-size: 11px; font-weight: 600; box-shadow: 0 2px 4px rgba(102, 126, 234, 0.3);">${itemFrequency}</span>` : ''}
594+
</td>
595+
<td style="padding: 16px; color: #28a745; font-size: 14px; font-weight: 600; border-right: 1px solid #f3f4f6;">${saleRates}</td>
596+
<td style="padding: 16px; color: #6366f1; font-size: 14px; font-weight: 600;">${avgRate}</td>
597+
`;
598+
} else {
599+
row.innerHTML = `
600+
<td style="padding: 16px; font-weight: 600; color: #1f2937; font-size: 15px; border-right: 1px solid #f3f4f6;">
601+
${displayName || item.name || '-'}
602+
${itemFrequency > 0 ? `<span style="margin-left: 8px; padding: 3px 10px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; border-radius: 12px; font-size: 11px; font-weight: 600; box-shadow: 0 2px 4px rgba(102, 126, 234, 0.3);">${itemFrequency}</span>` : ''}
603+
</td>
604+
<td style="padding: 16px; color: #007bff; font-size: 14px; font-weight: 600; border-right: 1px solid #f3f4f6;">${purchaseRates}</td>
605+
<td style="padding: 16px; color: #28a745; font-size: 14px; font-weight: 600; border-right: 1px solid #f3f4f6;">${saleRates}</td>
606+
<td class="wholesale-column" style="padding: 16px; color: #9333ea; font-size: 14px; font-weight: 600;">${wholesaleRates}</td>
607+
`;
608+
}
585609
tbody.appendChild(row);
586610
});
587611

www/js/modules/miscellaneous.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,9 @@ export class ExpensesManager {
195195
*/
196196
static renderBusinessExpenseHistory() {
197197
const container = document.getElementById('businessExpenseHistoryList');
198-
const businessExpenses = AppState.expensesHistory.filter(p => p.category === 'business' && p.id);
198+
const businessExpenses = AppState.expensesHistory
199+
.filter(p => p.category === 'business' && p.id)
200+
.sort((a, b) => new Date(b.date) - new Date(a.date));
199201

200202
if (businessExpenses.length === 0) {
201203
container.innerHTML = '<p style="text-align: center; color: #888; margin-top: 40px;">No business expenses recorded yet</p>';
@@ -224,7 +226,9 @@ export class ExpensesManager {
224226

225227
static renderPersonalExpenseHistory() {
226228
const container = document.getElementById('personalExpenseHistoryList');
227-
const personalExpenses = AppState.expensesHistory.filter(p => p.category === 'personal' && p.id);
229+
const personalExpenses = AppState.expensesHistory
230+
.filter(p => p.category === 'personal' && p.id)
231+
.sort((a, b) => new Date(b.date) - new Date(a.date));
228232

229233
if (personalExpenses.length === 0) {
230234
container.innerHTML = '<p style="text-align: center; color: #888; margin-top: 40px;">No personal expenses recorded yet</p>';

www/js/modules/stock.js

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -97,11 +97,20 @@ export class StockManager {
9797
return;
9898
}
9999

100+
// Check if user is staff (show limited quantity info for items > 100kg)
101+
const isStaff = AppState.userRole === 'staff';
102+
100103
stockWithDetails.forEach(item => {
101104
const displayName = (AppState.settings.showHindi && item.hindiName) ? item.hindiName : item.name;
102105
const div = document.createElement("div");
103106
div.className = "stock-item";
104107

108+
// For staff: show "Available" if quantity > 100, otherwise show actual quantity
109+
// Rate is always shown, value is hidden when showing "Available"
110+
const showLimitedQty = isStaff && item.quantity > 100;
111+
const quantityDisplay = showLimitedQty ? 'Available' : `${item.quantity.toFixed(1)} kg`;
112+
const valueDisplay = showLimitedQty ? '' : `<div style="color: #666; font-size: 12px; margin-top: 4px;">≈ ₹${Math.round(item.quantity * (item.rate || 0))}</div>`;
113+
105114
div.innerHTML = `
106115
<div style="display: flex; justify-content: space-between; align-items: center;">
107116
<div>
@@ -112,11 +121,9 @@ export class StockManager {
112121
</div>
113122
<div style="text-align: right;">
114123
<div style="font-size: 18px; font-weight: 700; color: #28a745;">
115-
${item.quantity.toFixed(1)} kg
116-
</div>
117-
<div style="color: #666; font-size: 12px; margin-top: 4px;">
118-
≈ ₹${Math.round(item.quantity * (item.rate || 0))}
124+
${quantityDisplay}
119125
</div>
126+
${valueDisplay}
120127
</div>
121128
</div>
122129
`;

0 commit comments

Comments
 (0)