Skip to content

Commit 8d17dee

Browse files
feat(ui): refresh auth and analytics surfaces
1 parent a6f9ca9 commit 8d17dee

16 files changed

Lines changed: 1723 additions & 1203 deletions

website/dist/assets/index-B3hSXaF9.css

Lines changed: 0 additions & 1 deletion
This file was deleted.

website/dist/assets/index-CVLcvas3.js

Lines changed: 0 additions & 378 deletions
This file was deleted.

website/dist/assets/index-DOINHLoi.css

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

website/dist/assets/index-XX6ZIrnT.js

Lines changed: 388 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

website/dist/index.html

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,20 @@
77
<link rel="apple-touch-icon" href="favicon.svg" />
88
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
99
<title>Juspay Decision Engine Dashboard</title>
10-
<script type="module" crossorigin src="/decision-engine/assets/index-CVLcvas3.js"></script>
11-
<link rel="stylesheet" crossorigin href="/decision-engine/assets/index-B3hSXaF9.css">
10+
<script>
11+
(function () {
12+
try {
13+
var theme = localStorage.getItem('theme')
14+
if (theme !== 'light') {
15+
document.documentElement.classList.add('dark')
16+
}
17+
} catch (_) {
18+
document.documentElement.classList.add('dark')
19+
}
20+
})()
21+
</script>
22+
<script type="module" crossorigin src="/decision-engine/assets/index-XX6ZIrnT.js"></script>
23+
<link rel="stylesheet" crossorigin href="/decision-engine/assets/index-DOINHLoi.css">
1224
</head>
1325
<body>
1426
<div id="root"></div>

website/index.html

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,18 @@
77
<link rel="apple-touch-icon" href="favicon.svg" />
88
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
99
<title>Juspay Decision Engine Dashboard</title>
10+
<script>
11+
(function () {
12+
try {
13+
var theme = localStorage.getItem('theme')
14+
if (theme !== 'light') {
15+
document.documentElement.classList.add('dark')
16+
}
17+
} catch (_) {
18+
document.documentElement.classList.add('dark')
19+
}
20+
})()
21+
</script>
1022
</head>
1123
<body>
1224
<div id="root"></div>

website/src/components/layout/AppShell.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@ export function AppShell() {
1010
<Sidebar />
1111
<div className="flex-1 flex flex-col overflow-hidden relative z-10">
1212
<TopBar />
13-
<main className="relative flex-1 overflow-y-auto p-6 md:p-8">
14-
<Outlet />
13+
<main className="relative flex-1 overflow-y-auto px-4 py-5 sm:px-5 sm:py-6 lg:px-6 lg:py-7 xl:px-8">
14+
<div className="mx-auto w-full max-w-[1760px] px-1 sm:px-2 lg:px-3">
15+
<Outlet />
16+
</div>
1517
</main>
1618
</div>
1719
</div>
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,85 @@
1+
import { useEffect, useState } from 'react'
12
import { Navigate, Outlet } from 'react-router-dom'
3+
import { Loader2 } from 'lucide-react'
24
import { useAuthStore } from '../../store/authStore'
5+
import { useMerchantStore } from '../../store/merchantStore'
6+
import { apiFetch } from '../../lib/api'
7+
8+
interface MeResponse {
9+
user_id: string
10+
email: string
11+
merchant_id: string
12+
role: string
13+
email_verified: boolean
14+
merchants: Array<{
15+
merchant_id: string
16+
merchant_name: string
17+
role: string
18+
}>
19+
}
320

421
export function AuthGuard() {
522
const token = useAuthStore((s) => s.token)
23+
const setAuth = useAuthStore((s) => s.setAuth)
24+
const clearAuth = useAuthStore((s) => s.clearAuth)
25+
const setMerchantId = useMerchantStore((s) => s.setMerchantId)
26+
const [status, setStatus] = useState<'checking' | 'ready' | 'invalid'>(
27+
token ? 'checking' : 'invalid'
28+
)
29+
30+
useEffect(() => {
31+
let cancelled = false
32+
33+
if (!token) {
34+
setStatus('invalid')
35+
return
36+
}
37+
38+
setStatus('checking')
39+
40+
apiFetch<MeResponse>('/auth/me')
41+
.then((me) => {
42+
if (cancelled) return
43+
44+
const activeMerchantId =
45+
me.merchant_id || me.merchants[0]?.merchant_id || ''
46+
47+
setAuth(
48+
token,
49+
{
50+
userId: me.user_id,
51+
email: me.email,
52+
merchantId: activeMerchantId,
53+
role: me.role,
54+
},
55+
me.merchants
56+
)
57+
setMerchantId(activeMerchantId)
58+
setStatus('ready')
59+
})
60+
.catch(() => {
61+
if (cancelled) return
62+
clearAuth()
63+
setMerchantId('')
64+
setStatus('invalid')
65+
})
66+
67+
return () => {
68+
cancelled = true
69+
}
70+
}, [token, setAuth, clearAuth, setMerchantId])
71+
672
if (!token) return <Navigate to="/login" replace />
73+
if (status === 'checking') {
74+
return (
75+
<div className="dark flex min-h-screen items-center justify-center bg-[#030507] text-white">
76+
<div className="flex items-center gap-3 rounded-2xl border border-[#1d1d23] bg-[#111318] px-5 py-4 text-sm text-[#c7cfdb]">
77+
<Loader2 size={16} className="animate-spin text-[#7ea4ff]" />
78+
Validating session
79+
</div>
80+
</div>
81+
)
82+
}
83+
if (status === 'invalid') return <Navigate to="/login" replace />
784
return <Outlet />
885
}

website/src/components/layout/TopBar.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export function TopBar() {
1616
const navigate = useNavigate()
1717
const { user, merchants, clearAuth, updateMerchant } = useAuthStore()
1818
const { setMerchantId } = useMerchantStore()
19-
const [isDark, setIsDark] = useState(() => localStorage.getItem('theme') === 'dark')
19+
const [isDark, setIsDark] = useState(() => localStorage.getItem('theme') !== 'light')
2020
const [merchantOpen, setMerchantOpen] = useState(false)
2121
const [switching, setSwitching] = useState<string | null>(null)
2222
const dropdownRef = useRef<HTMLDivElement>(null)

0 commit comments

Comments
 (0)