Files
Kalana B. Thilakarathna f3f2b71bd4
CI/CD - ERP Distribution / Build & Deploy Backend (pull_request) Failing after 12m43s
CI/CD - ERP Distribution / Build & Deploy Frontend (pull_request) Failing after 16m30s
fix: update login function to handle profile data correctly
2026-10-19 10:25:29 +05:30

123 lines
3.3 KiB
TypeScript

'use client'
import { createContext, useContext, useState, useEffect, useCallback, type ReactNode } from 'react'
import { useRouter } from 'next/navigation'
import { api, registerUnauthorizedHandler } from '@/lib/api'
export interface User {
userId: string
username: string
roleId: string
roleCode: string
roleLevel: number
}
interface AuthContextValue {
user: User | null
permissions: Set<string>
loading: boolean
login: (identifier: string, password: string) => Promise<void>
logout: () => Promise<void>
hasPermission: (code: string) => boolean
}
const PERMISSIONS_KEY = 'app:permissions'
const USER_STORAGE_KEYS = [PERMISSIONS_KEY, 'distribution-dashboard-widgets-v3']
function savePermissions(perms: string[]): void {
try {
localStorage.setItem(PERMISSIONS_KEY, JSON.stringify(perms))
} catch {}
}
function readPermissions(): Set<string> {
try {
const raw = localStorage.getItem(PERMISSIONS_KEY)
if (raw) return new Set(JSON.parse(raw) as string[])
} catch {}
return new Set()
}
function clearUserStorage(): void {
try {
USER_STORAGE_KEYS.forEach(k => localStorage.removeItem(k))
} catch {}
}
const AuthContext = createContext<AuthContextValue | null>(null)
export function AuthProvider({ children }: { children: ReactNode }) {
const router = useRouter()
const [user, setUser] = useState<User | null>(null)
const [permissions, setPermissions] = useState<Set<string>>(new Set())
const [loading, setLoading] = useState(true)
const loadSession = useCallback(async () => {
setLoading(true)
try {
const { data } = await api.get<User>('/auth/me')
setUser(data)
setPermissions(readPermissions())
} catch {
setUser(null)
setPermissions(new Set())
} finally {
setLoading(false)
}
}, [])
useEffect(() => {
loadSession()
}, [loadSession])
useEffect(() => {
return registerUnauthorizedHandler(() => {
clearUserStorage()
setUser(null)
setPermissions(new Set())
router.push('/login')
})
}, [router])
async function login(identifier: string, password: string) {
const { data: res } = await api.post<{ statusCode: number; success: boolean; message: string; data: unknown | null; profile: User | null }>('/auth/login', { identifier, password, deviceName: 'Web' })
if (!res.profile) throw new Error(res.message ?? 'Invalid credentials')
setUser(res.profile)
try {
const { data: permData } = await api.get<{ permissions: string[] }>('/authorization/my-permissions')
savePermissions(permData.permissions)
setPermissions(new Set(permData.permissions))
} catch {
// permissions unavailable — user is still authenticated
}
router.push('/')
}
async function logout() {
try {
await api.post('/auth/logout')
} finally {
clearUserStorage()
setUser(null)
setPermissions(new Set())
router.push('/login')
}
}
function hasPermission(code: string): boolean {
return permissions.has(code)
}
return (
<AuthContext.Provider value={{ user, permissions, loading, login, logout, hasPermission }}>
{children}
</AuthContext.Provider>
)
}
export function useAuth(): AuthContextValue {
const ctx = useContext(AuthContext)
if (!ctx) throw new Error('useAuth must be used inside AuthProvider')
return ctx
}