diff --git a/app/(app)/layout.tsx b/app/(app)/layout.tsx
index 22bad22..e14ad47 100644
--- a/app/(app)/layout.tsx
+++ b/app/(app)/layout.tsx
@@ -3,6 +3,7 @@ import { cookies } from 'next/headers'
import { getIronSession } from 'iron-session'
import { SessionData, sessionOptions } from '@/lib/session'
import { prisma } from '@/lib/prisma'
+import { productAccessFilter } from '@/lib/product-access'
import { NavBar } from '@/components/shared/nav-bar'
import { MinWidthBanner } from '@/components/shared/min-width-banner'
import { StatusBar } from '@/components/shared/status-bar'
@@ -18,7 +19,7 @@ export default async function AppLayout({ children }: { children: React.ReactNod
const [user, userRoles] = await Promise.all([
prisma.user.findUnique({
where: { id: session.userId },
- select: { username: true, email: true },
+ select: { username: true, email: true, active_product_id: true },
}),
prisma.userRole.findMany({
where: { user_id: session.userId },
@@ -31,6 +32,23 @@ export default async function AppLayout({ children }: { children: React.ReactNod
redirect('/login')
}
+ // Resolve active product — clear stale reference if archived or inaccessible
+ let activeProduct: { id: string; name: string } | null = null
+ if (user.active_product_id) {
+ const product = await prisma.product.findFirst({
+ where: { id: user.active_product_id, archived: false, ...productAccessFilter(session.userId) },
+ select: { id: true, name: true },
+ })
+ if (product) {
+ activeProduct = product
+ } else {
+ await prisma.user.update({
+ where: { id: session.userId },
+ data: { active_product_id: null },
+ })
+ }
+ }
+
return (
@@ -42,6 +60,7 @@ export default async function AppLayout({ children }: { children: React.ReactNod
userId={session.userId}
username={user.username}
email={user.email}
+ activeProduct={activeProduct}
/>
diff --git a/app/(app)/solo/page.tsx b/app/(app)/solo/page.tsx
index 7991495..72623ca 100644
--- a/app/(app)/solo/page.tsx
+++ b/app/(app)/solo/page.tsx
@@ -1,7 +1,6 @@
import { redirect } from 'next/navigation'
import { getSession } from '@/lib/auth'
-import { getLastProductCookie } from '@/lib/cookies'
-import { getAccessibleProduct, productAccessFilter } from '@/lib/product-access'
+import { productAccessFilter } from '@/lib/product-access'
import { prisma } from '@/lib/prisma'
import { ProductPicker } from '@/components/solo/product-picker'
@@ -9,11 +8,17 @@ export default async function SoloPage() {
const session = await getSession()
if (!session.userId) redirect('/login')
- const lastProductId = await getLastProductCookie()
+ const user = await prisma.user.findUnique({
+ where: { id: session.userId },
+ select: { active_product_id: true },
+ })
- if (lastProductId) {
- const product = await getAccessibleProduct(lastProductId, session.userId)
- if (product && !product.archived) redirect(`/products/${lastProductId}/solo`)
+ if (user?.active_product_id) {
+ const product = await prisma.product.findFirst({
+ where: { id: user.active_product_id, archived: false, ...productAccessFilter(session.userId) },
+ select: { id: true },
+ })
+ if (product) redirect(`/products/${user.active_product_id}/solo`)
}
const products = await prisma.product.findMany({
diff --git a/components/shared/nav-bar.tsx b/components/shared/nav-bar.tsx
index f52685a..f7cc8a8 100644
--- a/components/shared/nav-bar.tsx
+++ b/components/shared/nav-bar.tsx
@@ -15,9 +15,10 @@ interface NavBarProps {
userId: string
username: string
email: string | null
+ activeProduct: { id: string; name: string } | null
}
-export function NavBar({ isDemo, roles, userId, username, email }: NavBarProps) {
+export function NavBar({ isDemo, roles, userId, username, email, activeProduct: _activeProduct }: NavBarProps) {
const pathname = usePathname()
const currentProduct = useProductStore(s => s.currentProduct)
diff --git a/lib/cookies.ts b/lib/cookies.ts
deleted file mode 100644
index c63bdc1..0000000
--- a/lib/cookies.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-import { cookies } from 'next/headers'
-
-const LAST_PRODUCT_COOKIE = 'lastProductId'
-const THIRTY_DAYS_SECONDS = 60 * 60 * 24 * 30
-
-export async function setLastProductCookie(productId: string) {
- const store = await cookies()
- store.set(LAST_PRODUCT_COOKIE, productId, {
- httpOnly: true,
- sameSite: 'lax',
- maxAge: THIRTY_DAYS_SECONDS,
- path: '/',
- })
-}
-
-export async function getLastProductCookie(): Promise {
- const store = await cookies()
- return store.get(LAST_PRODUCT_COOKIE)?.value ?? null
-}
diff --git a/proxy.ts b/proxy.ts
index 5771204..0a4e228 100644
--- a/proxy.ts
+++ b/proxy.ts
@@ -5,9 +5,6 @@ import { sessionOptions } from '@/lib/session'
const protectedRoutes = ['/dashboard', '/products', '/todos', '/settings', '/solo']
const authRoutes = ['/login', '/register']
-const SOLO_ROUTE = /^\/products\/([^/]+)\/solo$/
-const THIRTY_DAYS_SECONDS = 60 * 60 * 24 * 30
-
export function proxy(request: NextRequest) {
const path = request.nextUrl.pathname
const isProtected = protectedRoutes.some(r => path.startsWith(r))
@@ -24,20 +21,7 @@ export function proxy(request: NextRequest) {
return NextResponse.redirect(new URL('/dashboard', request.url))
}
- const response = NextResponse.next()
-
- // Remember last visited product for /solo redirect
- const soloMatch = path.match(SOLO_ROUTE)
- if (soloMatch) {
- response.cookies.set('lastProductId', soloMatch[1], {
- httpOnly: true,
- sameSite: 'lax',
- maxAge: THIRTY_DAYS_SECONDS,
- path: '/',
- })
- }
-
- return response
+ return NextResponse.next()
}
export const config = {