fix: add brand picker to sidebar, use getActiveBrandId in stops page
Deploy to route.crispygoat.com / deploy (push) Successful in 4m11s
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:
@@ -1,5 +1,6 @@
|
|||||||
import { pool } from "@/lib/db";
|
import { pool } from "@/lib/db";
|
||||||
import { getAdminUser } from "@/lib/admin-permissions";
|
import { getAdminUser } from "@/lib/admin-permissions";
|
||||||
|
import { getActiveBrandId } from "@/lib/brand-scope";
|
||||||
import AdminAccessDenied from "@/components/admin/AdminAccessDenied";
|
import AdminAccessDenied from "@/components/admin/AdminAccessDenied";
|
||||||
import { PageHeader } from "@/components/admin/design-system";
|
import { PageHeader } from "@/components/admin/design-system";
|
||||||
import { redirect } from "next/navigation";
|
import { redirect } from "next/navigation";
|
||||||
@@ -26,11 +27,18 @@ export default async function AdminStopsPage({ searchParams }: PageProps) {
|
|||||||
let error: string | null = null;
|
let error: string | null = null;
|
||||||
let totalCount = 0;
|
let totalCount = 0;
|
||||||
|
|
||||||
|
// Resolve active brand from cookie/URL (respects platform_admin "All brands" = null)
|
||||||
|
let activeBrandId: string | null = null;
|
||||||
try {
|
try {
|
||||||
// Platform admin sees all stops, brand admin sees their brand's stops
|
activeBrandId = await getActiveBrandId(adminUser);
|
||||||
const brandCondition = adminUser.brand_id
|
|
||||||
? `brand_id = '${adminUser.brand_id}'`
|
// If brand-scoped (not platform_admin) and no active brand, restrict query
|
||||||
: "1=1";
|
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 }>(
|
const countResult = await pool.query<{ count: string }>(
|
||||||
`SELECT count(*) as count FROM stops WHERE ${brandCondition}`
|
`SELECT count(*) as count FROM stops WHERE ${brandCondition}`
|
||||||
@@ -104,9 +112,9 @@ export default async function AdminStopsPage({ searchParams }: PageProps) {
|
|||||||
</div>
|
</div>
|
||||||
<h3 className="font-display text-2xl font-medium text-stone-950">No stops found</h3>
|
<h3 className="font-display text-2xl font-medium text-stone-950">No stops found</h3>
|
||||||
<p className="mt-2 text-stone-500">
|
<p className="mt-2 text-stone-500">
|
||||||
{adminUser.brand_id
|
{activeBrandId
|
||||||
? "No stops for your brand yet. Upload a schedule or add stops manually."
|
? "No stops for the selected brand. Upload a schedule or add stops manually."
|
||||||
: "No stops in the database. Import the Tuxedo Tour schedule."}
|
: "No stops in the database."}
|
||||||
</p>
|
</p>
|
||||||
<div className="mt-6 flex justify-center gap-3">
|
<div className="mt-6 flex justify-center gap-3">
|
||||||
<a
|
<a
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import Link from "next/link";
|
|||||||
import { usePathname } from "next/navigation";
|
import { usePathname } from "next/navigation";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { signOutAction } from "@/actions/auth-actions";
|
import { signOutAction } from "@/actions/auth-actions";
|
||||||
|
import BrandSelector from "@/components/admin/BrandSelector";
|
||||||
|
|
||||||
// Elegant warm sidebar design
|
// Elegant warm sidebar design
|
||||||
// Colors: parchment 100 bg, soft linen text, powder petal accent
|
// Colors: parchment 100 bg, soft linen text, powder petal accent
|
||||||
@@ -470,15 +471,25 @@ export default function AdminSidebar({
|
|||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
{/* Bottom: role + sign out */}
|
{/* Bottom: brand picker + role + sign out */}
|
||||||
<div
|
<div
|
||||||
className="px-4 py-5 border-t flex-shrink-0"
|
className="px-4 py-5 border-t flex-shrink-0 space-y-3"
|
||||||
style={{ borderColor: "rgba(208, 203, 180, 0.2)" }}
|
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 && (
|
{roleLabel && (
|
||||||
<div
|
<div
|
||||||
className="px-3 py-2.5 mb-3 rounded-xl border"
|
className="px-3 py-2.5 rounded-xl border"
|
||||||
style={{
|
style={{
|
||||||
backgroundColor: "rgba(208, 203, 180, 0.1)",
|
backgroundColor: "rgba(208, 203, 180, 0.1)",
|
||||||
borderColor: "rgba(208, 203, 180, 0.2)"
|
borderColor: "rgba(208, 203, 180, 0.2)"
|
||||||
}}
|
}}
|
||||||
|
|||||||
Reference in New Issue
Block a user