Skip to content

Commit 043301f

Browse files
committed
Merge branch 'GUI'
2 parents 4941734 + bd414e5 commit 043301f

File tree

13 files changed

+374
-266
lines changed

13 files changed

+374
-266
lines changed
0 Bytes
Binary file not shown.
Lines changed: 77 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,108 @@
1+
// src/app/api/auth/[...nextauth]/route.js
2+
13
import NextAuth from 'next-auth';
2-
import GoogleProvider from 'next-auth/providers/google';
34
import CredentialsProvider from 'next-auth/providers/credentials';
5+
import GoogleProvider from 'next-auth/providers/google';
46

5-
const handler = NextAuth({
7+
/**
8+
* NextAuth configuration object
9+
* Handles authentication for both traditional login and Google OAuth
10+
*/
11+
const authOptions = {
612
providers: [
13+
// Google OAuth Provider - Using default profile handling
714
GoogleProvider({
815
name: 'google',
916
clientId: process.env.GOOGLE_CLIENT_ID,
1017
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
1118
}),
19+
20+
// Credentials Provider for traditional login
1221
CredentialsProvider({
1322
name: 'Credentials',
1423
credentials: {
15-
username: { label: 'Username', type: 'text' },
24+
email: { label: 'Email', type: 'text' },
1625
password: { label: 'Password', type: 'password' },
1726
},
1827
async authorize(credentials) {
19-
const user = await verifyUserCredentials(credentials.username, credentials.password);
20-
if (user) {
21-
return user;
28+
try {
29+
// Call your backend API to validate credentials
30+
const response = await fetch('https://your-api.com/auth/login', {
31+
method: 'POST',
32+
headers: { 'Content-Type': 'application/json' },
33+
body: JSON.stringify({
34+
email: credentials.email,
35+
password: credentials.password,
36+
}),
37+
});
38+
39+
const userData = await response.json();
40+
41+
if (response.ok && userData) {
42+
return userData;
43+
}
44+
return null;
45+
} catch (error) {
46+
console.error('Login failed:', error);
47+
return null;
2248
}
23-
return null;
24-
}
49+
},
2550
}),
2651
],
2752
session: {
2853
strategy: 'jwt',
29-
maxAge: 24 * 60 * 60,
54+
maxAge: 24 * 60 * 60, // 24 hours
3055
},
3156
callbacks: {
32-
async jwt({ token, user }) {
33-
if (user) {
34-
token.id = user.id;
35-
token.username = user.username;
57+
async jwt({ token, user, account }) {
58+
// Initial sign-in
59+
if (account && user) {
60+
// For Google sign in
61+
if (account.provider === 'google') {
62+
return {
63+
...token,
64+
id: user.id || user.sub, // Google provides 'sub' as user ID
65+
name: user.name,
66+
email: user.email,
67+
image: user.image || user.picture, // Google provides 'picture' for image
68+
provider: 'google'
69+
};
70+
}
71+
// For credentials sign in
72+
return {
73+
...token,
74+
id: user.id,
75+
name: user.name,
76+
email: user.email,
77+
image: user.image,
78+
token: user.token,
79+
provider: 'credentials'
80+
};
3681
}
3782
return token;
3883
},
3984
async session({ session, token }) {
40-
if (token) {
41-
session.id = token.id;
42-
session.username = token.username;
85+
// Add user data from token to session
86+
session.user = {
87+
...session.user,
88+
id: token.id,
89+
provider: token.provider
90+
};
91+
92+
// Only add token if it exists (for credentials login)
93+
if (token.token) {
94+
session.user.token = token.token;
4395
}
96+
4497
return session;
4598
},
4699
},
47-
});
100+
pages: {
101+
signIn: '/users/Login',
102+
error: '/auth/error',
103+
},
104+
};
48105

49-
export { handler as POST, handler as GET };
106+
// Create and export the NextAuth handler
107+
const handler = NextAuth(authOptions);
108+
export { handler as GET, handler as POST };

kommande-access-gui/src/app/api/getUser/route.jsx

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

kommande-access-gui/src/app/users/Dashboard/page.jsx

Lines changed: 128 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,151 @@
1+
'use client';
2+
3+
import { useEffect, useState } from 'react';
4+
import { useRouter } from 'next/navigation';
5+
import { signOut, useSession } from 'next-auth/react';
6+
import { Loader2 } from 'lucide-react';
7+
import { useUser } from '@/components/UserContext';
8+
19
/**
2-
* @file Dashboard/page.js
3-
* @brief User Dashboard Component with User Data Fetching.
4-
* @details This component displays a user's information after fetching data from the backend API.
5-
* The user data includes name, email, and phone number. The component uses `useEffect` to fetch the
6-
* user information on component mount and updates the state with the received data. Errors during
7-
* data fetching are handled and logged to the console.
8-
* @returns {JSX.Element} - A dashboard component displaying user details.
9-
*****************************************************************
10-
* @component Details
11-
* - Uses `useState` to store user data once it's fetched from the API.
12-
* - Uses `useEffect` to perform the fetch operation upon component mount.
13-
* - Displays user information such as name, email, and phone number, if available.
14-
* - Error handling is implemented to catch and log any issues during data fetching.
15-
*****************************************************************
10+
* Dashboard component that displays user information and handles session management
1611
*/
12+
export default function Dashboard() {
13+
const router = useRouter();
14+
const { data: session, status } = useSession();
15+
const { user, userLoggedOut } = useUser();
16+
const [loading, setLoading] = useState(true);
17+
const [userData, setUserData] = useState(null);
18+
const [error, setError] = useState('');
1719

20+
useEffect(() => {
21+
// Check authentication status
22+
if (status === 'unauthenticated') {
23+
router.push('/users/Login');
24+
return;
25+
}
1826

19-
'use client';
27+
// Fetch additional user data if needed
28+
const fetchUserData = async () => {
29+
if (!session?.user) return;
2030

21-
import { useUser } from '@/components/UserContext';
22-
import { signOut } from 'next-auth/react';
31+
try {
32+
const response = await fetch('https://your-api.com/user?name=${encodeURIComponent(session.user.name)}`', {
33+
method: 'GET',
34+
headers: {
35+
'Content-Type': 'application/json',
36+
//Authorization: `Bearer ${session.user.token}`, // Use token from session
37+
},
38+
});
2339

24-
export default function Dashboard() {
25-
const { user } = useUser();
40+
if (!response.ok) {
41+
throw new Error('Failed to fetch user data');
42+
}
43+
44+
const data = await response.json();
45+
setUserData(data);
46+
} catch (error) {
47+
console.error('Error fetching user data:', error);
48+
setError('Failed to load user information');
49+
} finally {
50+
setLoading(false);
51+
}
52+
};
53+
54+
// Only fetch additional data for credentials login
55+
// For Google login, use session data directly
56+
if (session?.user?.provider === 'credentials') {
57+
fetchUserData();
58+
} else {
59+
setUserData(session?.user);
60+
setLoading(false);
61+
}
62+
}, [session, status, router]);
63+
64+
// Handle sign out
65+
const handleSignOut = async () => {
66+
try {
67+
await signOut({
68+
redirect: false
69+
});
70+
userLoggedOut(); // Clear UserContext
71+
router.push('/users/Login');
72+
} catch (error) {
73+
console.error('Sign out error:', error);
74+
setError('Failed to sign out. Please try again.');
75+
}
76+
};
77+
78+
// Loading state
79+
if (loading || status === 'loading') {
80+
return (
81+
<div className="min-h-screen bg-base-200 flex items-center justify-center">
82+
<Loader2 className="w-12 h-12 text-primary animate-spin" />
83+
</div>
84+
);
85+
}
2686

87+
// Error state
88+
if (error) {
89+
return (
90+
<div className="min-h-screen bg-base-200 flex items-center justify-center">
91+
<div className="card w-full max-w-md shadow-xl bg-base-100">
92+
<div className="card-body items-center text-center">
93+
<div className="text-red-500 mb-4">{error}</div>
94+
<button
95+
className="btn btn-primary"
96+
onClick={() => router.push('/users/Login')}
97+
>
98+
Return to Login
99+
</button>
100+
</div>
101+
</div>
102+
</div>
103+
);
104+
}
105+
106+
// Render dashboard content
27107
return (
28108
<div className="min-h-screen bg-base-200 flex items-center justify-center">
29109
<div className="card w-full max-w-md shadow-xl bg-base-100">
30110
<div className="card-body items-center text-center">
31-
{/* 用户头像 */}
111+
{/* User Avatar */}
32112
<div className="avatar">
33113
<div className="w-24 rounded-full">
34-
<img src={user?.image || '/default-avatar.png'} alt="User Avatar" />
114+
<img
115+
src={userData?.image || '/default-avatar.png'}
116+
alt="User Avatar"
117+
/>
35118
</div>
36119
</div>
37-
{/* 欢迎信息 */}
120+
121+
{/* Welcome Message */}
38122
<h2 className="card-title text-2xl font-bold mt-4">
39-
Welcome, {user?.name || 'User'}!
123+
Welcome, {userData?.name || 'User'}!
40124
</h2>
41-
{/* 用户信息 */}
42-
<p className="text-base">
43-
Your E-mail: {user?.email || 'N/A'}
44-
</p>
45-
<p className="text-base">
46-
Your Phone Number: {user?.phone || 'N/A'}
47-
</p>
48-
{/* 操作按钮 */}
125+
126+
{/* User Information */}
127+
<div className="space-y-2 mt-4 w-full">
128+
<p className="text-base">
129+
<span className="font-semibold">Email:</span>{' '}
130+
{userData?.email || 'N/A'}
131+
</p>
132+
{userData?.phone && (
133+
<p className="text-base">
134+
<span className="font-semibold">Phone:</span>{' '}
135+
{userData.phone}
136+
</p>
137+
)}
138+
<p className="text-base">
139+
<span className="font-semibold">Login Provider:</span>{' '}
140+
{session?.user?.provider === 'google' ? 'Google' : 'Email'}
141+
</p>
142+
</div>
143+
144+
{/* Actions */}
49145
<div className="card-actions mt-6">
50146
<button
51147
className="btn btn-primary"
52-
onClick={() => {
53-
sessionStorage.removeItem('user');
54-
signOut({ callbackUrl: '/users/Login' });
55-
}}
148+
onClick={handleSignOut}
56149
>
57150
Sign Out
58151
</button>

0 commit comments

Comments
 (0)