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
@@ -0,0 +1,200 @@
create or replace function public.get_my_role()
returns text as $$
select role from public.profiles where id = auth.uid();
$$ language sql security definer stable
set search_path = public;
create or replace function public.is_external()
returns boolean as $$
select get_my_role() = 'external';
$$ language sql security definer stable
set search_path = public;
create or replace function public.get_my_company_id()
returns uuid as $$
select company_id from public.profiles where id = auth.uid();
$$ language sql security definer stable
set search_path = public;
create or replace function public.has_company_access(company uuid)
returns boolean as $$
select exists (
select 1
from public.profiles p
where p.id = auth.uid()
and (
p.company_id = company
or exists (
select 1
from public.company_members cm
where cm.profile_id = auth.uid()
and cm.company_id = company
)
)
);
$$ language sql security definer stable
set search_path = public;
create or replace function public.guard_task_update()
returns trigger as $$
declare
caller_role text;
begin
select role into caller_role from public.profiles where id = auth.uid();
if caller_role = 'client' then
new.project_id := old.project_id;
new.invoiced := old.invoiced;
if not (
new.status = 'not_started'
and coalesce(new.current_version, 0) > coalesce(old.current_version, 0)
and new.assigned_to is null
and new.assigned_name is null
) then
new.assigned_to := old.assigned_to;
new.assigned_name := old.assigned_name;
end if;
elsif caller_role = 'external' then
new.project_id := old.project_id;
new.invoiced := old.invoiced;
end if;
return new;
end;
$$ language plpgsql security definer
set search_path = public;
create or replace function public.handle_new_user()
returns trigger as $$
begin
insert into public.profiles (id, name, email, role)
values (
new.id,
coalesce(new.raw_user_meta_data->>'name', ''),
new.email,
coalesce(new.raw_user_meta_data->>'role', 'client')
);
return new;
end;
$$ language plpgsql security definer
set search_path = public;
create or replace function public.prevent_duplicate_active_subcontractor_po_task()
returns trigger as $$
declare
current_po_status text;
duplicate_po_number text;
begin
if new.task_id is null then
return new;
end if;
select status into current_po_status
from public.subcontractor_payments
where id = new.po_id;
if current_po_status = 'cancelled' then
return new;
end if;
select sp.po_number into duplicate_po_number
from public.subcontractor_po_items item
join public.subcontractor_payments sp on sp.id = item.po_id
where item.task_id = new.task_id
and item.id <> coalesce(new.id, '00000000-0000-0000-0000-000000000000'::uuid)
and sp.status <> 'cancelled'
limit 1;
if duplicate_po_number is not null then
raise exception 'Task is already attached to active subcontractor PO %', duplicate_po_number
using errcode = '23505';
end if;
return new;
end;
$$ language plpgsql security definer
set search_path = public;
create or replace function public.prevent_duplicate_on_subcontractor_po_reactivation()
returns trigger as $$
declare
duplicate_task_title text;
begin
if old.status = new.status or new.status = 'cancelled' then
return new;
end if;
select t.title into duplicate_task_title
from public.subcontractor_po_items current_item
join public.subcontractor_po_items other_item
on other_item.task_id = current_item.task_id
and other_item.po_id <> current_item.po_id
join public.subcontractor_payments other_po
on other_po.id = other_item.po_id
and other_po.status <> 'cancelled'
left join public.tasks t on t.id = current_item.task_id
where current_item.po_id = new.id
and current_item.task_id is not null
limit 1;
if duplicate_task_title is not null then
raise exception 'Cannot reactivate PO because task "%" is already attached to another active subcontractor PO', duplicate_task_title
using errcode = '23505';
end if;
return new;
end;
$$ language plpgsql security definer
set search_path = public;
create or replace function public.sync_subcontractor_project_member()
returns trigger as $$
begin
if new.profile_id is not null and new.project_id is not null then
insert into public.project_members (project_id, profile_id)
values (new.project_id, new.profile_id)
on conflict (project_id, profile_id) do nothing;
end if;
return new;
end;
$$ language plpgsql security definer
set search_path = public;
create or replace function public.sync_project_member_on_task_assign()
returns trigger as $$
begin
if new.assigned_to is not null and new.project_id is not null then
insert into public.project_members (project_id, profile_id)
values (new.project_id, new.assigned_to)
on conflict (project_id, profile_id) do nothing;
end if;
return new;
end;
$$ language plpgsql security definer
set search_path = public;
do $$
declare
fn record;
begin
for fn in
select n.nspname as schema_name, p.proname as function_name, pg_get_function_identity_arguments(p.oid) as identity_args
from pg_proc p
join pg_namespace n on n.oid = p.pronamespace
where n.nspname = 'public'
and p.proname in (
'notify_company_folder_sync',
'notify_profile_folder_sync',
'sync_project_status'
)
loop
execute format(
'drop function if exists %I.%I(%s) cascade;',
fn.schema_name,
fn.function_name,
fn.identity_args
);
end loop;
end
$$;