@wopr-network/platform-ui-core 1.22.3 → 1.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/components/sidebar.tsx +65 -23
- package/src/lib/trpc.tsx +7 -1
package/package.json
CHANGED
|
@@ -1,6 +1,22 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
CreditCard,
|
|
5
|
+
GitBranch,
|
|
6
|
+
LayoutDashboard,
|
|
7
|
+
LayoutGrid,
|
|
8
|
+
LogOutIcon,
|
|
9
|
+
MessageCircle,
|
|
10
|
+
MessageSquare,
|
|
11
|
+
Network,
|
|
12
|
+
Puzzle,
|
|
13
|
+
Server,
|
|
14
|
+
SettingsIcon,
|
|
15
|
+
Shield,
|
|
16
|
+
Store,
|
|
17
|
+
UserIcon,
|
|
18
|
+
Wallet,
|
|
19
|
+
} from "lucide-react";
|
|
4
20
|
import Image from "next/image";
|
|
5
21
|
import Link from "next/link";
|
|
6
22
|
import { usePathname, useRouter } from "next/navigation";
|
|
@@ -53,6 +69,23 @@ function getInitials(name: string): string {
|
|
|
53
69
|
.toUpperCase();
|
|
54
70
|
}
|
|
55
71
|
|
|
72
|
+
function getNavIcon(href: string) {
|
|
73
|
+
if (href === "/dashboard") return LayoutDashboard;
|
|
74
|
+
if (href === "/chat") return MessageCircle;
|
|
75
|
+
if (href === "/marketplace") return Store;
|
|
76
|
+
if (href.startsWith("/channels")) return MessageSquare;
|
|
77
|
+
if (href.startsWith("/plugins")) return Puzzle;
|
|
78
|
+
if (href.startsWith("/instances")) return LayoutGrid;
|
|
79
|
+
if (href.startsWith("/changesets")) return GitBranch;
|
|
80
|
+
if (href.startsWith("/fleet")) return Server;
|
|
81
|
+
if (href.startsWith("/network")) return Network;
|
|
82
|
+
if (href.startsWith("/billing/credits")) return Wallet;
|
|
83
|
+
if (href.startsWith("/billing")) return CreditCard;
|
|
84
|
+
if (href.startsWith("/settings")) return SettingsIcon;
|
|
85
|
+
if (href.startsWith("/admin")) return Shield;
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
|
|
56
89
|
export function SidebarContent({ onNavigate }: { onNavigate?: () => void }) {
|
|
57
90
|
const pathname = usePathname();
|
|
58
91
|
const router = useRouter();
|
|
@@ -86,7 +119,10 @@ export function SidebarContent({ onNavigate }: { onNavigate?: () => void }) {
|
|
|
86
119
|
return (
|
|
87
120
|
<div className="flex h-full flex-col">
|
|
88
121
|
<div className="flex h-14 items-center border-b border-sidebar-border px-6">
|
|
89
|
-
<span
|
|
122
|
+
<span
|
|
123
|
+
className="text-lg font-semibold tracking-tight text-terminal"
|
|
124
|
+
style={{ textShadow: "0 0 12px var(--terminal-glow, rgba(0, 255, 65, 0.4))" }}
|
|
125
|
+
>
|
|
90
126
|
{productName()}
|
|
91
127
|
</span>
|
|
92
128
|
</div>
|
|
@@ -98,27 +134,33 @@ export function SidebarContent({ onNavigate }: { onNavigate?: () => void }) {
|
|
|
98
134
|
!item.href.startsWith("/admin") ||
|
|
99
135
|
(user as { role?: string } | undefined)?.role === "platform_admin",
|
|
100
136
|
)
|
|
101
|
-
.map((item) =>
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
<span className=
|
|
117
|
-
{
|
|
137
|
+
.map((item) => {
|
|
138
|
+
const NavIcon = getNavIcon(item.href);
|
|
139
|
+
return (
|
|
140
|
+
<Link
|
|
141
|
+
key={item.href}
|
|
142
|
+
href={item.href}
|
|
143
|
+
prefetch={false}
|
|
144
|
+
onClick={onNavigate}
|
|
145
|
+
className={cn(
|
|
146
|
+
"flex items-center justify-between rounded-md px-3 py-2 text-sm font-medium transition-colors hover:bg-sidebar-accent hover:text-foreground",
|
|
147
|
+
isNavActive(item.href, pathname)
|
|
148
|
+
? "bg-terminal/5 border-l-2 border-terminal text-terminal"
|
|
149
|
+
: "text-muted-foreground",
|
|
150
|
+
)}
|
|
151
|
+
>
|
|
152
|
+
<span className="flex items-center gap-2.5">
|
|
153
|
+
{NavIcon && <NavIcon className="size-4 shrink-0 opacity-70" />}
|
|
154
|
+
{item.label}
|
|
118
155
|
</span>
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
156
|
+
{item.label === "Credits" && creditBalance !== null && (
|
|
157
|
+
<span className={cn("text-xs font-mono", balanceColorClass(creditBalance))}>
|
|
158
|
+
{formatCreditStandard(creditBalance)}
|
|
159
|
+
</span>
|
|
160
|
+
)}
|
|
161
|
+
</Link>
|
|
162
|
+
);
|
|
163
|
+
})}
|
|
122
164
|
</nav>
|
|
123
165
|
<div className="border-t border-sidebar-border px-3 py-3">
|
|
124
166
|
{isPending ? (
|
|
@@ -138,7 +180,7 @@ export function SidebarContent({ onNavigate }: { onNavigate?: () => void }) {
|
|
|
138
180
|
className="size-8 rounded-full object-cover"
|
|
139
181
|
/>
|
|
140
182
|
) : (
|
|
141
|
-
<span className="flex size-8 items-center justify-center rounded-full bg-sidebar-accent text-xs font-semibold">
|
|
183
|
+
<span className="flex size-8 items-center justify-center rounded-full bg-sidebar-accent text-xs font-semibold ring-1 ring-terminal/20">
|
|
142
184
|
{user.name?.trim() ? getInitials(user.name) : <UserIcon className="size-4" />}
|
|
143
185
|
</span>
|
|
144
186
|
)}
|
package/src/lib/trpc.tsx
CHANGED
|
@@ -14,7 +14,13 @@ export const trpc = createTRPCReact<AppRouter>();
|
|
|
14
14
|
async function trpcFetchWithAuth(url: RequestInfo | URL, options?: RequestInit) {
|
|
15
15
|
const res = await fetch(url, { ...options, credentials: "include" });
|
|
16
16
|
if (res.status === 401) {
|
|
17
|
-
|
|
17
|
+
// On login page, don't throw — let the batch continue so public queries
|
|
18
|
+
// (like enabledSocialProviders) resolve alongside failing auth queries.
|
|
19
|
+
const onLoginPage =
|
|
20
|
+
typeof window !== "undefined" && window.location.pathname.startsWith("/login");
|
|
21
|
+
if (!onLoginPage) {
|
|
22
|
+
handleUnauthorized();
|
|
23
|
+
}
|
|
18
24
|
}
|
|
19
25
|
return res;
|
|
20
26
|
}
|