Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions app/api/auth/[...nextauth]/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import { handlers } from "@/app/auth" // Referring to the auth.ts we just created
export const { GET, POST } = handlers
7 changes: 7 additions & 0 deletions app/auth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

import NextAuth from "next-auth"
import GitHub from "next-auth/providers/github"

export const { handlers, signIn, signOut, auth } = NextAuth({
providers: [GitHub],
})
1 change: 1 addition & 0 deletions app/middleware.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { auth as middleware } from "@/app/auth"
9 changes: 7 additions & 2 deletions app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import Link from 'next/link';
// import VulnerabilityList from '@/components/CveList';
import { message } from 'antd';
import Image from 'next/image';
import SignIn from '@/components/sign-in';
import { SessionProvider } from "next-auth/react"


const HomePage: React.FC = () => {
const [searchQuery, setSearchQuery] = useState('');
Expand Down Expand Up @@ -49,13 +52,15 @@ const HomePage: React.FC = () => {
</div>
</Link>

<nav>
<nav className="flex items-center gap-6">
<ul className="flex space-x-5">

<li><a href="#" className="hover:underline">About</a></li>
<li><a href="#" className="hover:underline">Documentation</a></li>
<li><a href="#" className="hover:underline">Blog</a></li>
</ul>
<SessionProvider>
<SignIn />
</SessionProvider>
</nav>
</header>
{/* 搜索部分 */}
Expand Down
18 changes: 18 additions & 0 deletions app/profile/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import '@/app/ui/global.css';
import { SessionProvider } from "next-auth/react"

export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="cn">
<body>
<SessionProvider>
{children}
</SessionProvider>
</body>
</html>
)
}
217 changes: 217 additions & 0 deletions app/profile/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
'use client';

import { useSession } from 'next-auth/react';
import Image from 'next/image';
import Link from 'next/link';
import { Tabs } from 'antd';
import { useState } from 'react';

export default function ProfilePage() {
const { data: session } = useSession();
const [activeTab, setActiveTab] = useState('1');

if (!session) {
return (
<div className="min-h-screen bg-gray-100 flex items-center justify-center">
<div className="text-center">
<h1 className="text-2xl font-bold text-gray-800">Please login first</h1>
</div>
</div>
);
}

return (
<div className="min-h-screen bg-gray-100">
{/* Top bar: Return Home button on the left, Profile Info on the right */}
<header className="bg-white border-b">
<div className="max-w-6xl mx-auto flex justify-between items-center px-4 py-6">
{/* Left: Return Home Button */}
<div>
<Link href="/">
<button className="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600 transition duration-200">
Return Home
</button>
</Link>
</div>
{/* Right: Profile Info */}
<div className="flex items-center space-x-6">
<div className="relative">
<Image
src={session.user?.image || '/default-avatar.png'}
alt="Profile"
width={100}
height={100}
className="rounded-full"
/>
</div>
<div>
<h1 className="text-2xl font-bold mb-1">{session.user?.name}</h1>
<p className="text-gray-600 mb-2">{session.user?.email}</p>
<button className="px-4 py-2 bg-gray-100 rounded-md hover:bg-gray-200">
Edit Profile
</button>
</div>
</div>
</div>
</header>

{/* Main Content Area (Tabs) */}
<div className="max-w-6xl mx-auto px-4 py-6">
<Tabs
activeKey={activeTab}
onChange={setActiveTab}
items={[
{
key: '1',
label: 'Overview',
children: <OverviewTab />,
},
{
key: '2',
label: 'My Favorites',
children: <FavoritesTab />,
},
{
key: '3',
label: 'Uploads',
children: <UploadsTab />,
},
{
key: '4',
label: 'Analysis History',
children: <AnalysisHistoryTab />,
},
]}
/>
</div>
</div>
);
}

// Overview Tab component
function OverviewTab() {
return (
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
{/* Activity Stats */}
<div className="bg-white p-6 rounded-lg shadow">
<h3 className="text-lg font-semibold mb-4">Activity Stats</h3>
<div className="space-y-4">
<div className="flex justify-between">
<span>Analysis Count</span>
<span className="font-semibold">123</span>
</div>
<div className="flex justify-between">
<span>Favorites Count</span>
<span className="font-semibold">45</span>
</div>
<div className="flex justify-between">
<span>Crate Uploads</span>
<span className="font-semibold">12</span>
</div>
</div>
</div>

{/* Recent Activity */}
<div className="bg-white p-6 rounded-lg shadow">
<h3 className="text-lg font-semibold mb-4">Recent Activity</h3>
<div className="space-y-4">
<div className="flex items-center space-x-3">
<div className="flex-1">
<p className="text-sm">Analyzed tokio crate</p>
<p className="text-xs text-gray-500">2 hours ago</p>
</div>
</div>
<div className="flex items-center space-x-3">
<div className="flex-1">
<p className="text-sm">Favorited serde crate</p>
<p className="text-xs text-gray-500">1 day ago</p>
</div>
</div>
</div>
</div>
</div>
);
}

// My Favorites Tab component
function FavoritesTab() {
return (
<div className="space-y-4">
<div className="bg-white p-6 rounded-lg shadow">
<h3 className="text-lg font-semibold mb-4">My Favorites</h3>
{/* Favorites list */}
<div className="space-y-4">
{/* Sample favorite item */}
<div className="border-b pb-4">
<div className="flex justify-between items-start">
<div>
<h4 className="text-lg font-medium">serde</h4>
<p className="text-sm text-gray-600">
A generic serialization/deserialization framework
</p>
</div>
<button className="text-red-500 hover:text-red-600">
Unfavorite
</button>
</div>
</div>
{/* More favorite items... */}
</div>
</div>
</div>
);
}

// Uploads Tab component
function UploadsTab() {
return (
<div className="space-y-4">
<div className="bg-white p-6 rounded-lg shadow">
<h3 className="text-lg font-semibold mb-4">Uploads</h3>
{/* Uploads list */}
<div className="space-y-4">
{/* Sample upload item */}
<div className="border-b pb-4">
<div className="flex justify-between items-start">
<div>
<h4 className="text-lg font-medium">my-crate</h4>
<p className="text-sm text-gray-600">Upload Time: 2024-03-20</p>
</div>
<button className="text-blue-500 hover:text-blue-600">
View Analysis
</button>
</div>
</div>
{/* More upload items... */}
</div>
</div>
</div>
);
}

// Analysis History Tab component
function AnalysisHistoryTab() {
return (
<div className="space-y-4">
<div className="bg-white p-6 rounded-lg shadow">
<h3 className="text-lg font-semibold mb-4">Analysis History</h3>
{/* Analysis history list */}
<div className="space-y-4">
{/* Sample analysis item */}
<div className="border-b pb-4">
<div className="flex justify-between items-start">
<div>
<h4 className="text-lg font-medium">tokio (v1.36.0)</h4>
<p className="text-sm text-gray-600">Analysis Time: 2024-03-21</p>
</div>
<button className="text-blue-500 hover:text-blue-600">
View Report
</button>
</div>
</div>
{/* More analysis items... */}
</div>
</div>
</div>
);
}
72 changes: 72 additions & 0 deletions components/sign-in.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
'use client';

import { signIn, signOut, useSession } from 'next-auth/react';
import Image from 'next/image';
import Link from 'next/link';
import { Dropdown } from 'antd';
import type { MenuProps } from 'antd';

export default function SignInButton() {
const { data: session, status } = useSession();

if (status === 'loading') {
return (
<button className="bg-gray-200 text-gray-400 px-4 py-2 rounded-md cursor-not-allowed">
Loading...
</button>
);
}

if (session) {
const items: MenuProps['items'] = [
{
key: '1',
label: <Link href="/profile">个人中心</Link>,
},
{
key: '2',
label: <span onClick={() => signOut()}>退出登录</span>,
},
];

return (
<Dropdown menu={{ items }} placement="bottomRight">
<div className="flex items-center gap-2 cursor-pointer">
<div className="flex items-center gap-2 px-2 py-1 rounded-full bg-gray-100 hover:bg-gray-200 transition-colors duration-200">
{session.user?.image && (
<Image
src={session.user.image}
alt={session.user.name || 'User avatar'}
width={32}
height={32}
className="rounded-full"
/>
)}
<span className="text-sm text-gray-700">{session.user?.name}</span>
</div>
</div>
</Dropdown>
);
}

return (
<button
onClick={() => signIn('github')}
className="flex items-center gap-2 px-4 py-2 bg-gray-800 hover:bg-gray-700 text-white rounded-md transition-colors duration-200"
>
<svg
className="w-5 h-5"
fill="currentColor"
viewBox="0 0 24 24"
aria-hidden="true"
>
<path
fillRule="evenodd"
d="M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z"
clipRule="evenodd"
/>
</svg>
登录
</button>
);
}
13 changes: 3 additions & 10 deletions next.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,7 @@
export default {
output: "standalone",
reactStrictMode: true,
// async redirects() {
// return [
// {
// source: '/',

// destination: '/hompage',
// permanent: false,
// },
// ];
// },
images: {
domains: ['avatars.githubusercontent.com'], // 允许 GitHub 头像
},
};
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"clsx": "^2.1.1",
"d3": "^7.9.0",
"next": "^15.1.0",
"next-auth": "4.24.11",
"next-auth": "^5.0.0-beta.25",
"postcss": "8.4.49",
"react": "18.3.1",
"react-dom": "18.3.1",
Expand All @@ -36,4 +36,4 @@
"engines": {
"node": ">=20.12.0"
}
}
}