Skip to content

Commit 6cd291e

Browse files
jiajunagentclaude
andcommitted
feat: login/register 页面重新设计——左侧品牌渐变面板 + 右侧表单
使用 MetaboFlow NPG 品牌色(#3C5488 → #4DBBD5 → #00A087 渐变), 左侧展示产品卖点,右侧干净的表单。移动端适配。 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent cb53a1d commit 6cd291e

2 files changed

Lines changed: 249 additions & 123 deletions

File tree

packages/frontend/src/app/login/page.tsx

Lines changed: 118 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,6 @@
33
import { useState } from 'react';
44
import { useRouter } from 'next/navigation';
55
import { Button } from '@/components/ui/button';
6-
import {
7-
Card,
8-
CardContent,
9-
CardDescription,
10-
CardHeader,
11-
CardTitle,
12-
} from '@/components/ui/card';
136
import { Input } from '@/components/ui/input';
147
import { login } from '@/lib/auth';
158

@@ -26,7 +19,7 @@ export default function LoginPage() {
2619
setLoading(true);
2720
try {
2821
await login({ email, password });
29-
router.push('/analyses');
22+
router.push('/projects');
3023
} catch (err: unknown) {
3124
setError(err instanceof Error ? err.message : 'Login failed');
3225
} finally {
@@ -35,55 +28,126 @@ export default function LoginPage() {
3528
}
3629

3730
return (
38-
<div className="flex min-h-[calc(100vh-8rem)] items-center justify-center px-4">
39-
<Card className="w-full max-w-sm">
40-
<CardHeader>
41-
<CardTitle>Sign in</CardTitle>
42-
<CardDescription>Enter your email and password to continue.</CardDescription>
43-
</CardHeader>
44-
<CardContent>
45-
<form onSubmit={handleSubmit} className="space-y-4">
46-
<div className="space-y-1">
47-
<label htmlFor="email" className="text-sm font-medium">
48-
Email
49-
</label>
50-
<Input
51-
id="email"
52-
type="email"
53-
autoComplete="email"
54-
required
55-
value={email}
56-
onChange={(e) => setEmail(e.target.value)}
57-
/>
31+
<div className="flex min-h-screen">
32+
{/* Left brand panel */}
33+
<div className="hidden lg:flex lg:w-1/2 bg-gradient-to-br from-[#3C5488] via-[#4DBBD5] to-[#00A087] items-center justify-center p-12">
34+
<div className="max-w-md text-white">
35+
<div className="flex items-center gap-3 mb-8">
36+
<div className="w-12 h-12 rounded-xl bg-white/20 backdrop-blur flex items-center justify-center text-2xl font-bold">
37+
M
5838
</div>
59-
<div className="space-y-1">
60-
<label htmlFor="password" className="text-sm font-medium">
61-
Password
62-
</label>
63-
<Input
64-
id="password"
65-
type="password"
66-
autoComplete="current-password"
67-
required
68-
value={password}
69-
onChange={(e) => setPassword(e.target.value)}
70-
/>
39+
<span className="text-3xl font-bold tracking-tight">MetaboFlow</span>
40+
</div>
41+
<h2 className="text-2xl font-semibold mb-4">
42+
Multi-Engine Metabolomics Analysis Platform
43+
</h2>
44+
<p className="text-white/80 text-lg leading-relaxed mb-8">
45+
From raw mzML to publication-ready figures in one workflow.
46+
50 chart templates, automated reports, and multi-engine comparison.
47+
</p>
48+
<div className="space-y-3 text-white/70">
49+
<div className="flex items-center gap-3">
50+
<svg className="w-5 h-5 text-white/90" fill="none" stroke="currentColor" viewBox="0 0 24 24">
51+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
52+
</svg>
53+
<span>XCMS + MZmine + MS-DIAL engine support</span>
54+
</div>
55+
<div className="flex items-center gap-3">
56+
<svg className="w-5 h-5 text-white/90" fill="none" stroke="currentColor" viewBox="0 0 24 24">
57+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
58+
</svg>
59+
<span>Nature-grade figures with one click</span>
60+
</div>
61+
<div className="flex items-center gap-3">
62+
<svg className="w-5 h-5 text-white/90" fill="none" stroke="currentColor" viewBox="0 0 24 24">
63+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
64+
</svg>
65+
<span>MFSL spectral library: 960K compounds</span>
66+
</div>
67+
<div className="flex items-center gap-3">
68+
<svg className="w-5 h-5 text-white/90" fill="none" stroke="currentColor" viewBox="0 0 24 24">
69+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
70+
</svg>
71+
<span>PDF &amp; Word reports with auto Methods</span>
72+
</div>
73+
</div>
74+
</div>
75+
</div>
76+
77+
{/* Right form panel */}
78+
<div className="flex w-full lg:w-1/2 items-center justify-center p-8 bg-gray-50">
79+
<div className="w-full max-w-md">
80+
{/* Mobile logo */}
81+
<div className="lg:hidden flex items-center gap-2 mb-8 justify-center">
82+
<div className="w-10 h-10 rounded-lg bg-[#3C5488] flex items-center justify-center text-white text-xl font-bold">
83+
M
7184
</div>
72-
{error && (
73-
<p className="text-sm text-destructive">{error}</p>
74-
)}
75-
<Button type="submit" className="w-full" disabled={loading}>
76-
{loading ? 'Signing in…' : 'Sign in'}
77-
</Button>
78-
</form>
79-
<p className="mt-4 text-center text-sm text-muted-foreground">
80-
Don&apos;t have an account?{' '}
81-
<a href="/register" className="underline underline-offset-4 hover:text-foreground">
82-
Register
83-
</a>
85+
<span className="text-2xl font-bold text-gray-900">MetaboFlow</span>
86+
</div>
87+
88+
<div className="bg-white rounded-2xl shadow-sm border border-gray-100 p-8">
89+
<h1 className="text-2xl font-bold text-gray-900 mb-1">Welcome back</h1>
90+
<p className="text-gray-500 mb-6">Sign in to your account to continue.</p>
91+
92+
<form onSubmit={handleSubmit} className="space-y-5">
93+
<div className="space-y-1.5">
94+
<label htmlFor="email" className="text-sm font-medium text-gray-700">
95+
Email
96+
</label>
97+
<Input
98+
id="email"
99+
type="email"
100+
autoComplete="email"
101+
required
102+
placeholder="you@lab.edu"
103+
className="h-11 bg-gray-50 border-gray-200 focus:bg-white"
104+
value={email}
105+
onChange={(e) => setEmail(e.target.value)}
106+
/>
107+
</div>
108+
<div className="space-y-1.5">
109+
<label htmlFor="password" className="text-sm font-medium text-gray-700">
110+
Password
111+
</label>
112+
<Input
113+
id="password"
114+
type="password"
115+
autoComplete="current-password"
116+
required
117+
className="h-11 bg-gray-50 border-gray-200 focus:bg-white"
118+
value={password}
119+
onChange={(e) => setPassword(e.target.value)}
120+
/>
121+
</div>
122+
{error && (
123+
<div className="bg-red-50 text-red-700 text-sm px-4 py-2.5 rounded-lg border border-red-100">
124+
{error}
125+
</div>
126+
)}
127+
<Button
128+
type="submit"
129+
className="w-full h-11 bg-[#3C5488] hover:bg-[#2d3f66] text-white font-medium"
130+
disabled={loading}
131+
>
132+
{loading ? 'Signing in...' : 'Sign in'}
133+
</Button>
134+
</form>
135+
136+
<div className="mt-6 text-center">
137+
<p className="text-sm text-gray-500">
138+
Don&apos;t have an account?{' '}
139+
<a href="/register" className="text-[#3C5488] font-medium hover:underline">
140+
Request access
141+
</a>
142+
</p>
143+
</div>
144+
</div>
145+
146+
<p className="mt-6 text-center text-xs text-gray-400">
147+
MetaboFlow v0.1.0 Beta — Invite-only access
84148
</p>
85-
</CardContent>
86-
</Card>
149+
</div>
150+
</div>
87151
</div>
88152
);
89153
}

0 commit comments

Comments
 (0)