fix: crash bugs in TeamInvoices + faster load

Bug fixes:
- TeamInvoices: add useAuth import/currentUser (invoice-create crash)
- TeamInvoices: setChartYear -> setExportYear (year-dropdown crash)
- TeamDashboard: drop redundant setState-in-effect (cascading renders)
- Companies: delete dead _UnusedClientCompanies (illegal hook calls)
- annotate intentional empty PDF-fallback catches

Load speed:
- preconnect/dns-prefetch to Supabase origin
- lazy-load heic-to in Converters: page chunk 2737KB -> 9KB
- split recharts into its own 'charts' vendor chunk

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Krao Hasanee
2026-06-08 12:59:11 -04:00
parent 85625f4d95
commit 04e0911e9f
101 changed files with 11786 additions and 7445 deletions
+21 -14
View File
@@ -1,13 +1,14 @@
import { useState, useEffect } from 'react';
import { useParams, Link, useNavigate } from 'react-router-dom';
import Layout from '../components/Layout';
import PageLoader from '../components/PageLoader';
import StatusBadge from '../components/StatusBadge';
import { supabase } from '../lib/supabase';
import { useAuth } from '../context/AuthContext';
import { serviceTypes } from '../data/mockData';
import { cleanupTaskStorage, deleteCompanyData } from '../lib/deleteHelpers';
import { logActivity } from '../lib/activityLog';
import { createProjectFolder } from '../lib/filebrowserFolders';
import { ensureProjectFolder, renameCompanyFolder } from '../lib/folderSync';
export default function CompanyDetail() {
const { id } = useParams();
@@ -78,8 +79,14 @@ export default function CompanyDetail() {
if (!nameVal.trim()) return;
setSavingName(true);
const oldName = company.name;
await supabase.from('companies').update({ name: nameVal.trim() }).eq('id', id);
setCompany(c => ({ ...c, name: nameVal.trim() }));
const newName = nameVal.trim();
await supabase.from('companies').update({ name: newName }).eq('id', id);
try {
await renameCompanyFolder({ companyId: id, oldName, newName });
} catch (folderError) {
console.error('Company folder rename failed:', folderError);
}
setCompany(c => ({ ...c, name: newName }));
setEditingName(false);
setSavingName(false);
};
@@ -179,8 +186,12 @@ export default function CompanyDetail() {
status: 'active',
}).select().single();
if (data) {
try {
await ensureProjectFolder({ projectId: data.id });
} catch (folderError) {
console.error('Project folder sync failed:', folderError);
}
logActivity({ actorId: currentUser.id, actorName: currentUser.name, action: 'project_created', projectId: data.id, projectName: data.name });
createProjectFolder(company.name, data.name).catch(() => {});
setProjects(prev => [data, ...prev]);
setNewProjectName('');
setShowNewProject(false);
@@ -248,7 +259,7 @@ export default function CompanyDetail() {
setSavingSignFamilyPrice(null);
};
if (loading) return <Layout><p style={{ padding: 24, color: 'var(--text-muted)' }}>Loading...</p></Layout>;
if (loading) return <Layout><PageLoader /></Layout>;
if (!company) return <Layout><p>Company not found.</p></Layout>;
const activeTasks = tasks.filter(t => t.status !== 'client_approved');
@@ -318,15 +329,14 @@ export default function CompanyDetail() {
</div>
{/* Tabs */}
<div style={{ display: 'flex', gap: 4, marginBottom: 24, flexWrap: 'wrap' }}>
<div style={{ display: 'flex', gap: 4, marginBottom: 10, flexWrap: 'wrap', minHeight: 'var(--btn-height)' }}>
{(isTeam ? ['users', 'projects', 'pricing'] : ['users', 'projects']).map(t => (
<button
key={t}
onClick={() => setTab(t)}
className={`tab-btn${tab === t ? ' active' : ''}`}
style={{ textTransform: 'capitalize' }}
className={`section-tab-btn${tab === t ? ' is-active' : ''}`}
>
{t}
{t.charAt(0).toUpperCase() + t.slice(1)}
{t === 'users' && availableUsers.length > 0 && (
<span style={{ marginLeft: 6, fontSize: 10, background: tab === t ? 'rgba(0,0,0,0.3)' : 'var(--danger)', color: 'white', padding: '1px 5px', borderRadius: 4, fontWeight: 400 }}>
{availableUsers.length}
@@ -342,7 +352,7 @@ export default function CompanyDetail() {
<div className="card">
<div className="card-title">Assigned Users</div>
{users.length === 0 ? (
<p style={{ fontSize: 13, color: 'var(--text-muted)' }}>No users assigned to this company yet.</p>
<div className="card-empty-center">No users</div>
) : (
<div style={{ display: 'flex', flexDirection: 'column', gap: 0 }}>
{users.map((user, i) => (
@@ -494,10 +504,7 @@ export default function CompanyDetail() {
)}
{projects.length === 0 ? (
<div className="empty-state">
<h3>No projects yet</h3>
<p>Create a project to start adding jobs.</p>
</div>
<div className="card card-empty-center">No projects</div>
) : (
<div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
{projects.map(project => {