From 7c126c999fef79643726c9aba7868430ad5b6e17 Mon Sep 17 00:00:00 2001 From: prudentbird Date: Wed, 26 Nov 2025 21:58:12 +0100 Subject: [PATCH] feat: Integrate Next.js auth session into providers for Mixpanel user identification and refine user types. --- frontend/src/app/(auth)/auth.ts | 5 +++-- frontend/src/app/layout.tsx | 11 ++++++++--- frontend/src/app/providers.tsx | 11 +++++++++-- frontend/src/lib/mixpanel.ts | 13 ++++++++++++- frontend/src/types/user.ts | 7 +++++-- 5 files changed, 37 insertions(+), 10 deletions(-) diff --git a/frontend/src/app/(auth)/auth.ts b/frontend/src/app/(auth)/auth.ts index 41d8961..d094796 100644 --- a/frontend/src/app/(auth)/auth.ts +++ b/frontend/src/app/(auth)/auth.ts @@ -2,7 +2,7 @@ import { env } from '~/env'; import { loginUser } from './actions'; import { authConfig } from './auth.config'; import { loginFormSchema } from './schema'; -import { UserInterface } from '~/types/user'; +import { UserInterface, UserBase } from '~/types/user'; import type { DefaultJWT } from 'next-auth/jwt'; import NextAuth, { type DefaultSession } from 'next-auth'; import Credentials from 'next-auth/providers/credentials'; @@ -12,7 +12,8 @@ declare module 'next-auth' { user: UserInterface & DefaultSession['user'] & { access_token: string }; } - interface User extends UserInterface { + interface User extends UserBase { + email: string; access_token: string; } } diff --git a/frontend/src/app/layout.tsx b/frontend/src/app/layout.tsx index 568fb15..e564325 100644 --- a/frontend/src/app/layout.tsx +++ b/frontend/src/app/layout.tsx @@ -1,7 +1,8 @@ import './globals.css'; -import { Suspense } from 'react'; import Providers from './providers'; import type { Metadata } from 'next'; +import { Suspense, cache } from 'react'; +import { auth } from '~/app/(auth)/auth'; import Loader from '~/components/loader'; import { Outfit } from 'next/font/google'; import { Toaster } from '~/components/ui/sonner'; @@ -17,11 +18,15 @@ export const metadata: Metadata = { description: 'Retailytics aka Retail Intelligence', }; -export default function RootLayout({ +const getSession = cache(() => auth()); + +export default async function RootLayout({ children, }: Readonly<{ children: React.ReactNode; }>) { + const session = await getSession(); + return ( @@ -32,7 +37,7 @@ export default function RootLayout({ /> - + }>{children} diff --git a/frontend/src/app/providers.tsx b/frontend/src/app/providers.tsx index 296f8d3..02e8c30 100644 --- a/frontend/src/app/providers.tsx +++ b/frontend/src/app/providers.tsx @@ -2,12 +2,19 @@ import * as React from 'react'; import { ThemeProvider } from './theme'; +import type { Session } from 'next-auth'; import { initMixpanel } from '~/lib/mixpanel'; import { ProgressProvider } from '@bprogress/next/app'; -const Providers = ({ children }: { children: React.ReactNode }) => { +const Providers = ({ + children, + session, +}: { + children: React.ReactNode; + session: Session | null; +}) => { React.useEffect(() => { - initMixpanel(); + initMixpanel(session); }, []); return ( diff --git a/frontend/src/lib/mixpanel.ts b/frontend/src/lib/mixpanel.ts index 8c4b616..e6392bb 100644 --- a/frontend/src/lib/mixpanel.ts +++ b/frontend/src/lib/mixpanel.ts @@ -1,7 +1,8 @@ import { env } from '~/env'; import mixpanel from 'mixpanel-browser'; +import type { Session } from 'next-auth'; -export const initMixpanel = () => { +export const initMixpanel = (session: Session | null) => { if (!env.NEXT_PUBLIC_MIXPANEL_TOKEN) { console.warn('Mixpanel token is missing! Check your .env file.'); return; @@ -11,4 +12,14 @@ export const initMixpanel = () => { autocapture: true, record_sessions_percent: 100, }); + + if (session?.user) { + mixpanel.identify(session.user.id); + mixpanel.people.set({ + $email: session.user.email, + role: session.user.role, + }); + } else { + mixpanel.identify('Guest'); + } }; diff --git a/frontend/src/types/user.ts b/frontend/src/types/user.ts index c9aa9df..d160dfc 100644 --- a/frontend/src/types/user.ts +++ b/frontend/src/types/user.ts @@ -16,8 +16,7 @@ export enum AuthProvider { GOOGLE = 'google', } -export interface UserInterface extends AbstractBaseInterface { - email: string; +export interface UserBase extends AbstractBaseInterface { password: string; role: UserRole; status: UserStatus; @@ -30,3 +29,7 @@ export interface UserInterface extends AbstractBaseInterface { assigned_phase_id?: string; assigned_district_id?: string; } + +export interface UserInterface extends UserBase { + email: string; +}