From da13caf9cbf0d03b74acbd91ae9755c588e634f1 Mon Sep 17 00:00:00 2001 From: lorentz Date: Sun, 10 May 2026 07:40:40 -0400 Subject: [PATCH] feat(09-04): page shell, drawer wiring, skeleton helper, channels placeholder - app/mobile/profile/page.tsx: server-component shell gated by requireAuth() + redirect('/auth/sign-in') - ProfileSectionSkeleton.tsx: generic 3-row pulsing skeleton Card - ProfileChannelsSectionPlaceholder.tsx: stub Channels card (Plan 05 swaps real component) - MoreDrawer.tsx Account section: identity row wrapped in Link, new Profile & preferences row above Sign-out --- app/mobile/profile/page.tsx | 30 +++++++++++++ components/mobile/MoreDrawer.tsx | 44 +++++++++++-------- .../ProfileChannelsSectionPlaceholder.tsx | 25 +++++++++++ .../mobile/profile/ProfileSectionSkeleton.tsx | 21 +++++++++ 4 files changed, 102 insertions(+), 18 deletions(-) create mode 100644 app/mobile/profile/page.tsx create mode 100644 components/mobile/profile/ProfileChannelsSectionPlaceholder.tsx create mode 100644 components/mobile/profile/ProfileSectionSkeleton.tsx diff --git a/app/mobile/profile/page.tsx b/app/mobile/profile/page.tsx new file mode 100644 index 0000000..f7cf71a --- /dev/null +++ b/app/mobile/profile/page.tsx @@ -0,0 +1,30 @@ +// /mobile/profile (PROF-01) — gated by requireAuth(), server-rendered shell +// hosts the four client sections. + +import { redirect } from 'next/navigation'; +import { requireAuth } from '@/lib/auth-utils'; +import { ProfileTimezoneSection } from '@/components/mobile/profile/ProfileTimezoneSection'; +import { ProfileThemeSection } from '@/components/mobile/profile/ProfileThemeSection'; +import { ProfileNotificationMatrix } from '@/components/mobile/profile/ProfileNotificationMatrix'; +import { ProfileChannelsSection } from '@/components/mobile/profile/ProfileChannelsSectionPlaceholder'; + +export default async function MobileProfilePage() { + const { session, error } = await requireAuth(); + // CRITICAL: requireAuth() returns NextResponse on miss — that shape is for + // API routes only. A Page route MUST call redirect() instead. Returning + // `error` from here would render a JSON 401 body as the page, which is wrong. + if (error || !session) { + redirect('/auth/sign-in'); + } + return ( +
+

Profile & Preferences

+
+ + + + +
+
+ ); +} diff --git a/components/mobile/MoreDrawer.tsx b/components/mobile/MoreDrawer.tsx index 5bf36b6..21c8674 100644 --- a/components/mobile/MoreDrawer.tsx +++ b/components/mobile/MoreDrawer.tsx @@ -125,31 +125,39 @@ export function MoreDrawer({ open, onOpenChange }: MoreDrawerProps) { - {/* Section 3: Account (DRAWER-05) */} + {/* Section 3: Account (DRAWER-05, PROF-04) */}

Account

{user && ( -
- - {initials} - -
- {user.name && ( -

- {user.name} -

- )} - {user.email && ( -

- {user.email} -

- )} -
-
+ + + + {initials} + +
+ {user.name && ( +

+ {user.name} +

+ )} + {user.email && ( +

+ {user.email} +

+ )} +
+ +
)} + + + + Profile & preferences + +