fix: add brand picker to sidebar, use getActiveBrandId in stops page
Deploy to route.crispygoat.com / deploy (push) Successful in 4m11s

- AdminSidebar now renders BrandSelector when brands are available
- Stops page uses getActiveBrandId() instead of adminUser.brand_id
  directly, so platform admins see all stops and brand selection
  via the sidebar picker works correctly
- BrandSelector already existed and was wired up in the layout,
  just never rendered in the sidebar
This commit is contained in:
Tyler
2026-06-10 14:32:50 -06:00
parent f0a703794a
commit 001840ab05
2 changed files with 32 additions and 13 deletions
+15 -7
View File
@@ -1,5 +1,6 @@
import { pool } from "@/lib/db";
import { getAdminUser } from "@/lib/admin-permissions";
import { getActiveBrandId } from "@/lib/brand-scope";
import AdminAccessDenied from "@/components/admin/AdminAccessDenied";
import { PageHeader } from "@/components/admin/design-system";
import { redirect } from "next/navigation";
@@ -26,11 +27,18 @@ export default async function AdminStopsPage({ searchParams }: PageProps) {
let error: string | null = null;
let totalCount = 0;
// Resolve active brand from cookie/URL (respects platform_admin "All brands" = null)
let activeBrandId: string | null = null;
try {
// Platform admin sees all stops, brand admin sees their brand's stops
const brandCondition = adminUser.brand_id
? `brand_id = '${adminUser.brand_id}'`
: "1=1";
activeBrandId = await getActiveBrandId(adminUser);
// If brand-scoped (not platform_admin) and no active brand, restrict query
const brandCondition =
activeBrandId
? `brand_id = '${activeBrandId}'`
: adminUser.role === "platform_admin"
? "1=1"
: `brand_id IN ('${(adminUser.brand_ids ?? []).join("','")}')`;
const countResult = await pool.query<{ count: string }>(
`SELECT count(*) as count FROM stops WHERE ${brandCondition}`
@@ -104,9 +112,9 @@ export default async function AdminStopsPage({ searchParams }: PageProps) {
</div>
<h3 className="font-display text-2xl font-medium text-stone-950">No stops found</h3>
<p className="mt-2 text-stone-500">
{adminUser.brand_id
? "No stops for your brand yet. Upload a schedule or add stops manually."
: "No stops in the database. Import the Tuxedo Tour schedule."}
{activeBrandId
? "No stops for the selected brand. Upload a schedule or add stops manually."
: "No stops in the database."}
</p>
<div className="mt-6 flex justify-center gap-3">
<a
+17 -6
View File
@@ -5,6 +5,7 @@ import Link from "next/link";
import { usePathname } from "next/navigation";
import { useRouter } from "next/navigation";
import { signOutAction } from "@/actions/auth-actions";
import BrandSelector from "@/components/admin/BrandSelector";
// Elegant warm sidebar design
// Colors: parchment 100 bg, soft linen text, powder petal accent
@@ -470,15 +471,25 @@ export default function AdminSidebar({
</ul>
</nav>
{/* Bottom: role + sign out */}
<div
className="px-4 py-5 border-t flex-shrink-0"
{/* Bottom: brand picker + role + sign out */}
<div
className="px-4 py-5 border-t flex-shrink-0 space-y-3"
style={{ borderColor: "rgba(208, 203, 180, 0.2)" }}
>
{/* Brand selector — only show when admin has access to brands */}
{brands && brands.length > 0 && (
<BrandSelector
brands={brands}
activeBrandId={activeBrandId ?? null}
showAllBrandsOption={userRole === "platform_admin"}
isMultiBrandAdmin={(brandIds?.length ?? 0) > 1}
/>
)}
{roleLabel && (
<div
className="px-3 py-2.5 mb-3 rounded-xl border"
style={{
<div
className="px-3 py-2.5 rounded-xl border"
style={{
backgroundColor: "rgba(208, 203, 180, 0.1)",
borderColor: "rgba(208, 203, 180, 0.2)"
}}