// Author: fruit.com.cn import 'package:flutter/material.dart'; import '../home/home_view.dart'; /// 登录页:Google / 手机号 / 邮箱 三种登录入口 + 游客浏览。 /// 当前为 UI 占位实现,真实登录逻辑在接入后端 /app/auth/** 后补充。 class LoginPage extends StatefulWidget { const LoginPage({super.key}); @override State createState() => _LoginPageState(); } class _LoginPageState extends State { static const _orange = Color(0xFFFF5B3D); static const _purple = Color(0xFF9278EA); void _enterHome() { Navigator.of(context).pushReplacement( MaterialPageRoute(builder: (_) => const HomePage()), ); } @override Widget build(BuildContext context) { return Scaffold( body: SafeArea( child: Column( children: [ // 顶部:关闭 + 游客浏览 Padding( padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 8), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ _IconButton(icon: Icons.close, onTap: () {}), TextButton( onPressed: _enterHome, style: TextButton.styleFrom( foregroundColor: Colors.white54, backgroundColor: Colors.white.withValues(alpha: 0.05), padding: const EdgeInsets.symmetric( horizontal: 14, vertical: 8, ), shape: const StadiumBorder(), ), child: const Text('Guest Explore'), ), ], ), ), // 中央内容 Expanded( child: Center( child: Padding( padding: const EdgeInsets.symmetric(horizontal: 28), child: Column( mainAxisSize: MainAxisSize.min, children: [ const _BrandLogo(), const SizedBox(height: 20), const Text( 'DramaPulse', style: TextStyle( fontSize: 30, fontWeight: FontWeight.w800, color: Colors.white, ), ), const SizedBox(height: 8), const Text( 'Sign in to sync your progress and coins', textAlign: TextAlign.center, style: TextStyle( fontSize: 14, color: Colors.white54, ), ), const SizedBox(height: 36), _GoogleButton(onTap: _enterHome), const SizedBox(height: 14), _DarkButton( icon: Icons.phone_iphone, iconColor: _orange, label: 'Continue with Phone Number', onTap: _enterHome, ), const SizedBox(height: 14), _DarkButton( icon: Icons.email_outlined, iconColor: _purple, label: 'Continue with Email', onTap: _enterHome, ), const SizedBox(height: 32), const _BonusPill(), ], ), ), ), ), // 底部协议 const Padding( padding: EdgeInsets.only(bottom: 24), child: Text( 'By continuing, you agree to DramaPulse\'s\n' 'Terms of Service · Privacy Policy · Content Policy', textAlign: TextAlign.center, style: TextStyle(fontSize: 11, color: Colors.white38), ), ), ], ), ), ); } } class _IconButton extends StatelessWidget { const _IconButton({required this.icon, required this.onTap}); final IconData icon; final VoidCallback onTap; @override Widget build(BuildContext context) { return InkWell( onTap: onTap, borderRadius: BorderRadius.circular(24), child: Container( width: 40, height: 40, decoration: BoxDecoration( color: Colors.white.withValues(alpha: 0.05), border: Border.all(color: Colors.white12), shape: BoxShape.circle, ), child: Icon(icon, color: Colors.white54, size: 20), ), ); } } class _BrandLogo extends StatelessWidget { const _BrandLogo(); @override Widget build(BuildContext context) { return Container( width: 80, height: 80, decoration: BoxDecoration( gradient: const LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [Color(0xFFFF5B3D), Color(0xFFD8536C), Color(0xFF9278EA)], ), borderRadius: BorderRadius.circular(20), border: Border.all(color: Colors.white24), ), child: const Icon(Icons.play_arrow_rounded, color: Colors.white, size: 40), ); } } class _GoogleButton extends StatelessWidget { const _GoogleButton({required this.onTap}); final VoidCallback onTap; @override Widget build(BuildContext context) { return _AuthButton( onTap: onTap, background: Colors.white, child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ const _GoogleG(), const SizedBox(width: 12), Text( 'Continue with Google', style: TextStyle( fontSize: 14, fontWeight: FontWeight.w600, color: Colors.grey.shade900, ), ), ], ), ); } } /// 简化版 Google「G」logo。 class _GoogleG extends StatelessWidget { const _GoogleG(); @override Widget build(BuildContext context) { return Container( width: 20, height: 20, decoration: const BoxDecoration( shape: BoxShape.circle, color: Color(0xFF4285F4), ), child: const Center( child: Text( 'G', style: TextStyle( color: Colors.white, fontSize: 13, fontWeight: FontWeight.w700, ), ), ), ); } } class _DarkButton extends StatelessWidget { const _DarkButton({ required this.icon, required this.iconColor, required this.label, required this.onTap, }); final IconData icon; final Color iconColor; final String label; final VoidCallback onTap; @override Widget build(BuildContext context) { return _AuthButton( onTap: onTap, background: const Color(0xFF161822), border: const Color(0xFF232634), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(icon, color: iconColor, size: 20), const SizedBox(width: 12), Text( label, style: const TextStyle( fontSize: 14, fontWeight: FontWeight.w500, color: Colors.white, ), ), ], ), ); } } class _AuthButton extends StatelessWidget { const _AuthButton({ required this.onTap, required this.background, required this.child, this.border, }); final VoidCallback onTap; final Color background; final Color? border; final Widget child; @override Widget build(BuildContext context) { return SizedBox( width: double.infinity, height: 52, child: Material( color: background, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16), side: border == null ? BorderSide.none : BorderSide(color: border!), ), child: InkWell( onTap: onTap, borderRadius: BorderRadius.circular(16), child: child, ), ), ); } } class _BonusPill extends StatelessWidget { const _BonusPill(); @override Widget build(BuildContext context) { return Container( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), decoration: BoxDecoration( color: Colors.white.withValues(alpha: 0.04), border: Border.all(color: Colors.white12), borderRadius: BorderRadius.circular(999), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ Container( width: 6, height: 6, decoration: const BoxDecoration( color: Color(0xFF34D399), shape: BoxShape.circle, ), ), const SizedBox(width: 8), const Text( 'Get ', style: TextStyle(fontSize: 11, color: Colors.white54), ), const Text( '100 Free Bonus Coins', style: TextStyle( fontSize: 11, fontWeight: FontWeight.w600, color: Colors.white, ), ), const Text( ' upon first sign-in', style: TextStyle(fontSize: 11, color: Colors.white54), ), ], ), ); } }