import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import '../../../core/l10n/app_localizations.dart'; import '../../../core/theme/app_colors.dart'; import '../../../providers/auth_provider.dart'; // ── 输入方式 Tab(邮箱 / 手机号)──────────────────────────── class AuthInputMethodTab extends StatelessWidget { const AuthInputMethodTab({ super.key, required this.selected, required this.onSelect, }); final AuthInputMethod selected; final ValueChanged onSelect; @override Widget build(BuildContext context) { return Row( children: [ AuthTabItem( label: AppLocalizations.of(context)!.emailTab, active: selected == AuthInputMethod.email, onTap: () => onSelect(AuthInputMethod.email), ), const SizedBox(width: 24), AuthTabItem( label: AppLocalizations.of(context)!.phoneTab, active: selected == AuthInputMethod.phone, onTap: () => onSelect(AuthInputMethod.phone), ), ], ); } } // ── 登录模式 Tab(密码 / 验证码)──────────────────────────── class LoginModeTab extends StatelessWidget { const LoginModeTab({ super.key, required this.selected, required this.onSelect, }); final LoginMode selected; final ValueChanged onSelect; @override Widget build(BuildContext context) { return Row( children: [ AuthTabItem( label: AppLocalizations.of(context)!.passwordLoginTab, active: selected == LoginMode.password, onTap: () => onSelect(LoginMode.password), ), const SizedBox(width: 24), AuthTabItem( label: AppLocalizations.of(context)!.codeLoginTab, active: selected == LoginMode.code, onTap: () => onSelect(LoginMode.code), ), ], ); } } // ── 单个 Tab 项 ─────────────────────────────────────────────── class AuthTabItem extends StatelessWidget { const AuthTabItem({ super.key, required this.label, required this.active, required this.onTap, }); final String label; final bool active; final VoidCallback onTap; @override Widget build(BuildContext context) { final cs = Theme.of(context).colorScheme; return GestureDetector( onTap: onTap, child: Column( children: [ Text( label, style: TextStyle( color: active ? cs.onSurface : cs.onSurface.withAlpha(153), fontSize: 15, fontWeight: active ? FontWeight.w600 : FontWeight.w400, ), ), const SizedBox(height: 4), if (active) Container( height: 2, width: 24, decoration: BoxDecoration( color: AppColors.brand, borderRadius: BorderRadius.circular(1), ), ), ], ), ); } } // ── 通用输入框 ──────────────────────────────────────────────── class AuthField extends StatelessWidget { const AuthField({ super.key, required this.controller, required this.hint, this.obscure = false, this.suffixIcon, this.keyboardType, this.onChanged, this.maxLength, this.semanticsLabel, this.focusNode, this.errorText, this.inputFormatters, }); final TextEditingController controller; final String hint; final bool obscure; final Widget? suffixIcon; final TextInputType? keyboardType; final ValueChanged? onChanged; final int? maxLength; final String? semanticsLabel; final FocusNode? focusNode; final String? errorText; final List? inputFormatters; @override Widget build(BuildContext context) { final cs = Theme.of(context).colorScheme; final hasError = errorText != null && errorText!.isNotEmpty; final errorBorder = OutlineInputBorder( borderRadius: BorderRadius.circular(10), borderSide: BorderSide(color: cs.error, width: 1.5), ); return Semantics( label: semanticsLabel, textField: true, child: TextField( controller: controller, focusNode: focusNode, obscureText: obscure, keyboardType: keyboardType, onChanged: onChanged, maxLength: maxLength, inputFormatters: inputFormatters, buildCounter: maxLength != null ? (_, {required currentLength, required isFocused, required maxLength}) => null : null, style: TextStyle(color: cs.onSurface, fontSize: 15), decoration: InputDecoration( hintText: hint, hintStyle: TextStyle(color: cs.onSurface.withAlpha(80), fontSize: 15), contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 16), suffixIcon: suffixIcon, errorText: errorText, errorStyle: TextStyle(color: cs.error, fontSize: 12), // 聚焦态:品牌黄描边,覆盖全局主题的主文字色 focusedBorder: hasError ? errorBorder : OutlineInputBorder( borderRadius: BorderRadius.circular(10), borderSide: const BorderSide(color: AppColors.brand, width: 1.5), ), enabledBorder: hasError ? errorBorder : null, ), ), ); } } // ── 发送验证码按钮 ──────────────────────────────────────────── class SendCodeButton extends StatelessWidget { const SendCodeButton({ super.key, required this.countdown, required this.onTap, }); final int countdown; final VoidCallback? onTap; @override Widget build(BuildContext context) { return GestureDetector( onTap: onTap, child: Container( height: 50, padding: const EdgeInsets.symmetric(horizontal: 14), decoration: BoxDecoration( color: onTap != null ? AppColors.brand : AppColors.brand.withAlpha(60), borderRadius: BorderRadius.circular(10), ), child: Center( child: Text( countdown > 0 ? '${countdown}s' : AppLocalizations.of(context)!.sendCode, style: TextStyle( color: onTap != null ? Colors.black : Colors.black.withAlpha(100), fontSize: 13, fontWeight: FontWeight.w600, ), ), ), ), ); } }