diff --git a/database/migrations/run_all.sql b/database/migrations/run_all.sql
index 40460d1..da761a6 100644
--- a/database/migrations/run_all.sql
+++ b/database/migrations/run_all.sql
@@ -85,5 +85,8 @@ BEGIN;
\echo '=== Running 022_custom_fields.sql (Custom Fields + Workflows) ==='
\i 022_custom_fields.sql
+\echo '=== Running 023_client_portal.sql (Client Portal) ==='
+\i ../../src/app/client-portal/database/020_client_portal.sql
+
\echo '=== Migration Complete ==='
COMMIT;
diff --git a/package-lock.json b/package-lock.json
index e662964..f32239e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -248,7 +248,6 @@
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/@dnd-kit/core/-/core-6.3.1.tgz",
"integrity": "sha512-xkGBRQQab4RLwgXxoqETICr6S5JlogafbhNsidmrkVv2YRs5MLwpjoF2qpiGjQt8S9AoxtIV603s0GIUpY5eYQ==",
- "license": "MIT",
"dependencies": {
"@dnd-kit/accessibility": "^3.1.1",
"@dnd-kit/utilities": "^3.2.2",
@@ -263,7 +262,6 @@
"version": "10.0.0",
"resolved": "https://registry.npmjs.org/@dnd-kit/sortable/-/sortable-10.0.0.tgz",
"integrity": "sha512-+xqhmIIzvAYMGfBYYnbKuNicfSsk4RksY2XdmJhT+HAC01nix6fHCztU68jooFiMUB01Ky3F0FyOvhG/BZrWkg==",
- "license": "MIT",
"dependencies": {
"@dnd-kit/utilities": "^3.2.2",
"tslib": "^2.0.0"
@@ -277,7 +275,6 @@
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/@dnd-kit/utilities/-/utilities-3.2.2.tgz",
"integrity": "sha512-+MKAJEOfaBe5SmV6t34p80MMKhjvUz0vRrvVJbPT0WElzaOJ/1xs+D+KDv+tD/NE5ujfrChEcshd4fLn0wpiqg==",
- "license": "MIT",
"dependencies": {
"tslib": "^2.0.0"
},
diff --git a/src/app/(dashboard)/projects/page.tsx b/src/app/(dashboard)/projects/page.tsx
index a6a9be1..50fe795 100644
--- a/src/app/(dashboard)/projects/page.tsx
+++ b/src/app/(dashboard)/projects/page.tsx
@@ -62,7 +62,8 @@ export default function ProjectsPage() {
if (search) params.set("search", search)
if (statusFilter !== "all") params.set("status", statusFilter)
const res = await fetch(`/api/projects?${params}`)
- setProjects(await res.json())
+ const data = await res.json()
+ setProjects(Array.isArray(data) ? data : [])
} catch (e) {
console.error("Failed to load projects", e)
} finally {
@@ -73,7 +74,7 @@ export default function ProjectsPage() {
useEffect(() => { fetchProjects() }, [search, statusFilter])
useEffect(() => {
- fetch("/api/project-statuses").then(r => r.json()).then(setStatuses).catch(() => {})
+ fetch("/api/project-statuses").then(r => r.json()).then((d) => setStatuses(Array.isArray(d) ? d : [])).catch(() => {})
}, [])
const formatDate = (d: string) => d ? new Date(d).toLocaleDateString() : "—"
@@ -166,8 +167,8 @@ function NewProjectDialog({ statuses, onCreated }: { statuses: ProjectStatus[];
useEffect(() => {
if (!open) return
- fetch("/api/customers?limit=100").then(r => r.json()).then(setCustomers).catch(() => {})
- fetch("/api/users").then(r => r.json()).then(setUsers).catch(() => {})
+ fetch("/api/customers?limit=100").then(r => r.json()).then((d) => setCustomers(Array.isArray(d) ? d : (d.customers || d.rows || []))).catch(() => {})
+ fetch("/api/users").then(r => r.json()).then((d) => setUsers(Array.isArray(d) ? d : (d.users || d.rows || []))).catch(() => {})
}, [open])
const handleSubmit = async () => {
diff --git a/src/app/(dashboard)/time-tracking/page.tsx b/src/app/(dashboard)/time-tracking/page.tsx
index 7a286a4..bee6f7e 100644
--- a/src/app/(dashboard)/time-tracking/page.tsx
+++ b/src/app/(dashboard)/time-tracking/page.tsx
@@ -52,9 +52,12 @@ export default function TimeTrackingPage() {
fetch("/api/time-entries/summary"),
fetch("/api/projects"),
])
- setEntries(await eRes.json())
- setSummary(await sRes.json())
- setProjects(await pRes.json())
+ const eData = await eRes.json()
+ const sData = await sRes.json()
+ const pData = await pRes.json()
+ setEntries(Array.isArray(eData) ? eData : [])
+ setSummary(sData?.totals ? sData : null)
+ setProjects(Array.isArray(pData) ? pData : [])
} catch (e) {
console.error("Failed to load time data", e)
} finally {
diff --git a/src/app/client-portal/activity/page.tsx b/src/app/client-portal/activity/page.tsx
index 403991e..a39326a 100644
--- a/src/app/client-portal/activity/page.tsx
+++ b/src/app/client-portal/activity/page.tsx
@@ -71,7 +71,7 @@ export default function ClientActivity() {
- {events.map((e, i) => (
+ {(events || []).map((e, i) => (