diff --git a/src/app/(app)/timeline/page.tsx b/src/app/(app)/timeline/page.tsx index b0a81e1..efbda33 100644 --- a/src/app/(app)/timeline/page.tsx +++ b/src/app/(app)/timeline/page.tsx @@ -41,7 +41,9 @@ const ZOOM_LABELS: Record = { export default function TimelinePage() { const [zoom, setZoom] = useState("day"); - const [statusFilter, setStatusFilter] = useState("ACTIVE"); + // Default to "all" — previously ACTIVE, which hid every PIPELINE project + // (i.e. everything freshly imported) and left the timeline empty. + const [statusFilter, setStatusFilter] = useState("all"); const [priorityFilter, setPriorityFilter] = useState("all"); const { data: projects, isLoading } = useTimeline({ @@ -205,9 +207,11 @@ export default function TimelinePage() { All Statuses + Pipeline Active On Hold Completed + Canceled Archived diff --git a/src/app/api/timeline/route.ts b/src/app/api/timeline/route.ts index e7ea749..daf6648 100644 --- a/src/app/api/timeline/route.ts +++ b/src/app/api/timeline/route.ts @@ -1,6 +1,7 @@ import { NextRequest, NextResponse } from "next/server"; import { serverError } from "@/lib/api-utils"; -import { requireAuth } from "@/lib/rbac/require-auth"; +import { requireAuth, visibilityContextFromSession } from "@/lib/rbac/require-auth"; +import { visibleProjectsWhere } from "@/lib/rbac/visibility"; import { prisma } from "@/lib/prisma"; // GET /api/timeline?status=ACTIVE&priority=&projectIds= @@ -16,13 +17,19 @@ export async function GET(request: NextRequest) { const projectIds = projectIdsParam ? projectIdsParam.split(",") : undefined; const organizationId = session.user.organizationId; + const ctx = visibilityContextFromSession(session); - // Build project filter - const projectWhere: any = { organizationId }; - if (statusFilter) projectWhere.status = statusFilter; + // Build project filter — AND-in the team visibility scope so non-ADMIN + // users only see projects on the ClientTeams they belong to (previously + // the timeline leaked cross-team data). + const baseFilter: any = { organizationId }; + if (statusFilter) baseFilter.status = statusFilter; if (projectIds && projectIds.length > 0) { - projectWhere.id = { in: projectIds }; + baseFilter.id = { in: projectIds }; } + const projectWhere: any = { + AND: [baseFilter, await visibleProjectsWhere(ctx)], + }; const delivWhere: any = {}; if (priorityFilter) delivWhere.priority = priorityFilter;