Files
moonwell-launcher/lib/app/design_system/mw_authentication.dart
T

219 lines
6.7 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import 'package:flutter/material.dart';
import 'package:moonwell_launcher/app/design_system/mw_shells.dart';
import 'package:moonwell_launcher/app/theme/moonwell_design_system.dart';
class MwAuthenticationForm extends StatefulWidget {
const MwAuthenticationForm({
super.key,
required this.usernameController,
required this.passwordController,
required this.onSubmit,
this.loading = false,
this.error,
});
final TextEditingController usernameController;
final TextEditingController passwordController;
final VoidCallback onSubmit;
final bool loading;
final String? error;
@override
State<MwAuthenticationForm> createState() => _MwAuthenticationFormState();
}
class _MwAuthenticationFormState extends State<MwAuthenticationForm> {
bool _remember = true;
@override
Widget build(BuildContext context) {
final accent = MoonWellDesignTokens.of(context).accent;
return AutofillGroup(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const MwBrandMark(width: 210, compact: true),
const SizedBox(height: 28),
Text(
'ВХОД',
style: TextStyle(color: accent, fontSize: 10, letterSpacing: 2.4),
),
const SizedBox(height: 10),
const Text(
'С возвращением',
style: TextStyle(
fontFamily: 'Cinzel',
color: Color(0xFFECE4D0),
fontSize: 30,
letterSpacing: 1,
),
),
const SizedBox(height: 7),
const Text(
'Войди в свой аккаунт, чтобы продолжить путь.',
style: TextStyle(
fontFamily: 'Cormorant Garamond',
fontStyle: FontStyle.italic,
color: Color(0x80ECE4D0),
fontSize: 15,
),
),
const SizedBox(height: 22),
Row(
children: [
_Tab(label: 'ВХОД', selected: true, accent: accent),
_Tab(label: 'РЕГИСТРАЦИЯ', accent: accent),
],
),
const SizedBox(height: 18),
_FieldLabel(text: 'ЛОГИН ИЛИ EMAIL'),
const SizedBox(height: 7),
TextField(
controller: widget.usernameController,
enabled: !widget.loading,
textInputAction: TextInputAction.next,
autofillHints: const [AutofillHints.username],
decoration: const InputDecoration(hintText: 'Aranthel'),
),
const SizedBox(height: 14),
_FieldLabel(text: 'ПАРОЛЬ'),
const SizedBox(height: 7),
TextField(
controller: widget.passwordController,
enabled: !widget.loading,
obscureText: true,
textInputAction: TextInputAction.done,
autofillHints: const [AutofillHints.password],
onSubmitted: (_) => widget.onSubmit(),
),
if (widget.error != null) ...[
const SizedBox(height: 10),
Text(
widget.error!,
style: const TextStyle(color: Color(0xFFD76A78), fontSize: 12),
),
],
const SizedBox(height: 8),
Row(
children: [
SizedBox(
width: 24,
child: Checkbox(
value: _remember,
onChanged: widget.loading
? null
: (value) => setState(() => _remember = value ?? false),
),
),
const SizedBox(width: 8),
const Text(
'Запомнить меня',
style: TextStyle(color: Color(0x9AECE4D0), fontSize: 11),
),
const Spacer(),
Text(
'Забыли пароль?',
style: TextStyle(color: accent, fontSize: 11),
),
],
),
const SizedBox(height: 18),
SizedBox(
height: 54,
child: ElevatedButton(
onPressed: widget.loading ? null : widget.onSubmit,
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFF6D499E),
foregroundColor: const Color(0xFFECE4D0),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(6),
),
),
child: widget.loading
? const SizedBox.square(
dimension: 18,
child: CircularProgressIndicator(strokeWidth: 2),
)
: const Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'ВОЙТИ',
style: TextStyle(
fontFamily: 'Cinzel',
letterSpacing: 2.5,
),
),
SizedBox(width: 14),
Icon(Icons.arrow_forward, size: 18),
],
),
),
),
const SizedBox(height: 28),
const Center(
child: Text(
'MOONWELL · V 1.0.0 · LOGIN.MOONWELL.GG',
style: TextStyle(
fontFamily: 'JetBrains Mono',
color: Color(0x52ECE4D0),
fontSize: 8,
letterSpacing: 1.2,
),
),
),
],
),
);
}
}
class _FieldLabel extends StatelessWidget {
const _FieldLabel({required this.text});
final String text;
@override
Widget build(BuildContext context) => Text(
text,
style: const TextStyle(
fontFamily: 'JetBrains Mono',
color: Color(0x80ECE4D0),
fontSize: 9,
letterSpacing: 1.5,
),
);
}
class _Tab extends StatelessWidget {
const _Tab({
required this.label,
required this.accent,
this.selected = false,
});
final String label;
final Color accent;
final bool selected;
@override
Widget build(BuildContext context) => Expanded(
child: Container(
height: 38,
alignment: Alignment.center,
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
color: selected ? accent : const Color(0x247FB8D4),
),
),
),
child: Text(
label,
style: TextStyle(
fontFamily: 'Cinzel',
color: selected ? const Color(0xFFECE4D0) : const Color(0x80ECE4D0),
fontSize: 9,
letterSpacing: 1.5,
),
),
),
);
}