fix: resolve frontend lint errors and cleanup types
This commit is contained in:
@@ -12,7 +12,7 @@ export default function ProtectedLayout({
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
const { data } = useSession();
|
||||
const isAdmin = (data?.user as any)?.isAdmin;
|
||||
const isAdmin = data?.user?.isAdmin;
|
||||
|
||||
return (
|
||||
<AuthGuard>
|
||||
|
||||
@@ -7,7 +7,6 @@ import { Button } from '@/components/ui/button';
|
||||
import { Progress } from '@/components/ui/progress';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { useSession } from 'next-auth/react';
|
||||
|
||||
export default function ShiftDetailPage({ params }: { params: Promise<{ id: string }> }) {
|
||||
const resolvedParams = use(params);
|
||||
@@ -15,7 +14,6 @@ export default function ShiftDetailPage({ params }: { params: Promise<{ id: stri
|
||||
const signUpMutation = useSignUpShift();
|
||||
const cancelMutation = useCancelSignUp();
|
||||
const router = useRouter();
|
||||
const { data: session } = useSession();
|
||||
|
||||
if (isLoading) return <div>Loading shift...</div>;
|
||||
if (!shift) return <div>Shift not found</div>;
|
||||
|
||||
@@ -47,14 +47,14 @@ export const { handlers, signIn, signOut, auth } = NextAuth({
|
||||
async jwt({ token, account }) {
|
||||
if (account && account.access_token) {
|
||||
// Add clubs claim from Keycloak access token
|
||||
token.clubs = (account as any).clubs as Record<string, string> || {}
|
||||
token.accessToken = account.access_token as string
|
||||
token.clubs = (account as { clubs?: Record<string, string> }).clubs || {}
|
||||
token.accessToken = account.access_token
|
||||
|
||||
try {
|
||||
const payload = JSON.parse(Buffer.from((token.accessToken as string).split('.')[1], 'base64').toString());
|
||||
const roles = payload.realm_access?.roles || [];
|
||||
const roles = (payload.realm_access?.roles as string[]) || [];
|
||||
token.isAdmin = roles.includes('admin');
|
||||
} catch (e) {
|
||||
} catch {
|
||||
token.isAdmin = false;
|
||||
}
|
||||
}
|
||||
@@ -63,10 +63,10 @@ export const { handlers, signIn, signOut, auth } = NextAuth({
|
||||
async session({ session, token }) {
|
||||
// Expose clubs to client
|
||||
if (session.user) {
|
||||
session.user.clubs = (token as any).clubs as Record<string, string> | undefined
|
||||
session.user.isAdmin = (token as any).isAdmin as boolean | undefined
|
||||
session.user.clubs = token.clubs as Record<string, string> | undefined
|
||||
session.user.isAdmin = token.isAdmin as boolean | undefined
|
||||
}
|
||||
session.accessToken = (token as any).accessToken as string | undefined
|
||||
session.accessToken = token.accessToken as string | undefined
|
||||
return session
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,10 +17,11 @@ export function ClubManagement() {
|
||||
const [isCreating, setIsCreating] = useState(false);
|
||||
const [newClub, setNewClub] = useState({ name: '', sportType: 'Tennis', description: '' });
|
||||
|
||||
const fetchClubs = async () => {
|
||||
useEffect(() => {
|
||||
const fetchClubsLocally = async () => {
|
||||
try {
|
||||
const res = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/api/admin/clubs`, {
|
||||
headers: { Authorization: `Bearer ${(session as any)?.accessToken}` },
|
||||
headers: { Authorization: `Bearer ${session?.accessToken}` },
|
||||
});
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
@@ -33,10 +34,25 @@ export function ClubManagement() {
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (session) fetchClubs();
|
||||
if (session) fetchClubsLocally();
|
||||
}, [session]);
|
||||
|
||||
const fetchClubs = async () => {
|
||||
try {
|
||||
const res = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/api/admin/clubs`, {
|
||||
headers: { Authorization: `Bearer ${session?.accessToken}` },
|
||||
});
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
setClubs(data);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch clubs', error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleCreate = async (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
try {
|
||||
@@ -44,7 +60,7 @@ export function ClubManagement() {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${(session as any)?.accessToken}`,
|
||||
Authorization: `Bearer ${session?.accessToken}`,
|
||||
},
|
||||
body: JSON.stringify({
|
||||
name: newClub.name,
|
||||
@@ -67,7 +83,7 @@ export function ClubManagement() {
|
||||
try {
|
||||
const res = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/api/admin/clubs/${id}`, {
|
||||
method: 'DELETE',
|
||||
headers: { Authorization: `Bearer ${(session as any)?.accessToken}` },
|
||||
headers: { Authorization: `Bearer ${session?.accessToken}` },
|
||||
});
|
||||
if (res.ok) {
|
||||
fetchClubs();
|
||||
|
||||
@@ -18,7 +18,7 @@ export function AuthGuard({ children }: { children: ReactNode }) {
|
||||
|
||||
useEffect(() => {
|
||||
if (status === 'authenticated') {
|
||||
const isAdmin = (data?.user as any)?.isAdmin;
|
||||
const isAdmin = data?.user?.isAdmin;
|
||||
|
||||
// Admin routing
|
||||
if (isAdmin) {
|
||||
@@ -59,7 +59,7 @@ export function AuthGuard({ children }: { children: ReactNode }) {
|
||||
);
|
||||
}
|
||||
|
||||
const isAdmin = (data?.user as any)?.isAdmin;
|
||||
const isAdmin = data?.user?.isAdmin;
|
||||
if (clubs.length === 0 && status === 'authenticated' && !isAdmin) {
|
||||
const handleSwitchAccount = () => {
|
||||
const keycloakLogoutUrl = `${process.env.NEXT_PUBLIC_KEYCLOAK_ISSUER || 'http://localhost:8080/realms/workclub'}/protocol/openid-connect/logout?redirect_uri=${encodeURIComponent(window.location.origin + '/login')}`;
|
||||
|
||||
Reference in New Issue
Block a user