- Create ProfileChannelsSection.tsx with Teams + ntfy sub-sections - Teams: URL input, inline 400 error (teamsError), save/clear buttons, inline test result - ntfy: mint-on-first-save (State A → State B), QR code via QRCodeSVG, subscribe link - ntfy: advanced disclosure with custom topic input + inline 400 error (customTopicError) - ntfy: test-now and remove buttons - Install qrcode.react ^4.2.0 (node_modules + package.json + package-lock.json updated) - Delete ProfileChannelsSectionPlaceholder.tsx (replaced by real component) - Update app/mobile/profile/page.tsx import to ProfileChannelsSection (not Placeholder)
30 lines
1.3 KiB
TypeScript
30 lines
1.3 KiB
TypeScript
// /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/ProfileChannelsSection';
|
|
|
|
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 (
|
|
<main className="px-4 pb-safe">
|
|
<h1 className="text-xl font-semibold pt-4 pb-2">Profile & Preferences</h1>
|
|
<div className="space-y-4">
|
|
<ProfileTimezoneSection />
|
|
<ProfileThemeSection />
|
|
<ProfileNotificationMatrix />
|
|
<ProfileChannelsSection />
|
|
</div>
|
|
</main>
|
|
);
|
|
}
|