diff --git a/bun.lockb b/bun.lockb index 5adc3b1..6213102 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/src/components/cases/import-unbilled-dialog.tsx b/src/components/cases/import-unbilled-dialog.tsx index 898230a..94656ff 100644 --- a/src/components/cases/import-unbilled-dialog.tsx +++ b/src/components/cases/import-unbilled-dialog.tsx @@ -55,8 +55,8 @@ export function ImportUnbilledDialog({ open, onOpenChange, kind, caseId, clientI return; } const select = kind === "time" - ? "id, work_date, description, hours, hourly_rate, case_id, user:profiles!time_entries_user_id_fkey(full_name, email)" - : "id, expense_date, description, amount, case_id, user:profiles!expenses_user_id_fkey(full_name, email)"; + ? "id, work_date, description, hours, hourly_rate, case_id, user_id" + : "id, expense_date, description, amount, case_id, user_id"; const { data, error } = await supabase .from(table) .select(select) @@ -66,7 +66,18 @@ export function ImportUnbilledDialog({ open, onOpenChange, kind, caseId, clientI .order(dateCol, { ascending: false }) .limit(1000); if (error) toast.error(error.message); - setRows((data ?? []).map((r: any) => ({ ...r, _case: caseMap[r.case_id] }))); + const baseRows = (data ?? []) as any[]; + // Fetch users separately (no FK relationship between these tables and profiles). + const userIds = Array.from(new Set(baseRows.map((r) => r.user_id).filter(Boolean))); + let userMap: Record = {}; + if (userIds.length) { + const { data: profs } = await supabase + .from("profiles") + .select("id, full_name, email") + .in("id", userIds); + userMap = Object.fromEntries((profs ?? []).map((p: any) => [p.id, p])); + } + setRows(baseRows.map((r) => ({ ...r, _case: caseMap[r.case_id], user: r.user_id ? userMap[r.user_id] : null }))); setLoading(false); })(); }, [open, clientId, caseId, kind]); diff --git a/src/routes/invoices.new.tsx b/src/routes/invoices.new.tsx index 9fc22b9..fd4f6e2 100644 --- a/src/routes/invoices.new.tsx +++ b/src/routes/invoices.new.tsx @@ -1,4 +1,4 @@ -import { createFileRoute, useNavigate } from "@tanstack/react-router"; +import { createFileRoute, useNavigate, Outlet, useMatches } from "@tanstack/react-router"; import { useEffect, useMemo, useState } from "react"; import { ProtectedLayout } from "@/components/protected-layout"; import { PageContainer, PageHeader } from "@/components/app-shell"; @@ -11,12 +11,20 @@ import { Search, ArrowLeft } from "lucide-react"; import { formatCurrency } from "@/lib/format"; export const Route = createFileRoute("/invoices/new")({ - component: () => ( + component: NewInvoiceLayout, +}); + +function NewInvoiceLayout() { + // If a child route (e.g. /invoices/new/$clientId) is matched, render only it. + const matches = useMatches(); + const hasChild = matches.some((m) => m.routeId !== "/invoices/new" && m.routeId.startsWith("/invoices/new/")); + if (hasChild) return ; + return ( - ), -}); + ); +} interface ClientLite { id: string;