first commit
This commit is contained in:
64
lib/screens/auth/widgets/auth_text_field.dart
Normal file
64
lib/screens/auth/widgets/auth_text_field.dart
Normal file
@@ -0,0 +1,64 @@
|
||||
// Flutter imports:
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:remever/common/resources.dart';
|
||||
import 'package:remever/common/typography.dart';
|
||||
import 'package:remever/components/extensions/context.dart';
|
||||
|
||||
class AuthTextField extends StatelessWidget {
|
||||
const AuthTextField({required this.email, super.key, this.autofocus = true});
|
||||
|
||||
final TextEditingController email;
|
||||
final bool autofocus;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final OutlineInputBorder border = OutlineInputBorder(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(8)).r,
|
||||
borderSide: BorderSide(color: AppColors.gray),
|
||||
);
|
||||
|
||||
return TextFormField(
|
||||
autofocus: autofocus,
|
||||
controller: email,
|
||||
validator: (String? value) {
|
||||
if (value == null || value == '') return 'Поле не может быть пустым';
|
||||
if (!value.contains('@') || !value.contains('.')) {
|
||||
return 'Неверный e-mail';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
cursorColor: AppColors.primary,
|
||||
|
||||
decoration: InputDecoration(
|
||||
filled: true,
|
||||
fillColor: AppColors.white,
|
||||
focusedBorder: border,
|
||||
enabledBorder: border,
|
||||
errorBorder: border,
|
||||
focusedErrorBorder: border,
|
||||
hintText: 'Введите e-mail',
|
||||
hintStyle: const TextStyle(fontWeight: FontWeight.w400, height: 1.2),
|
||||
errorStyle: SemiBold12px().style.copyWith(color: AppColors.red),
|
||||
suffixIconConstraints: const BoxConstraints(minWidth: 0, minHeight: 0),
|
||||
suffixIcon: Padding(
|
||||
padding: const EdgeInsets.only(right: 12).r,
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
email.clear();
|
||||
},
|
||||
child: SizedBox.square(
|
||||
dimension: 24.r,
|
||||
child: DecoratedBox(
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.bg,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
child: Icon(Icons.close, color: AppColors.disabled, size: 16.r),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
50
lib/screens/auth/widgets/pin_code.dart
Normal file
50
lib/screens/auth/widgets/pin_code.dart
Normal file
@@ -0,0 +1,50 @@
|
||||
// Flutter imports:
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:pin_code_fields/pin_code_fields.dart';
|
||||
import 'package:remever/common/resources.dart';
|
||||
import 'package:remever/components/extensions/context.dart';
|
||||
|
||||
class PinCode extends StatefulWidget {
|
||||
const PinCode({super.key, required this.pinController});
|
||||
|
||||
final TextEditingController pinController;
|
||||
|
||||
@override
|
||||
State<PinCode> createState() => _PinCodeState();
|
||||
}
|
||||
|
||||
class _PinCodeState extends State<PinCode> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return PinCodeTextField(
|
||||
controller: widget.pinController,
|
||||
appContext: context,
|
||||
length: 6,
|
||||
keyboardType: TextInputType.number,
|
||||
animationType: AnimationType.slide,
|
||||
hapticFeedbackTypes: HapticFeedbackTypes.medium,
|
||||
autoFocus: true,
|
||||
enableActiveFill: true,
|
||||
cursorColor: AppColors.primary,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) return 'Поле не может быть пустым';
|
||||
if (value.length < 5) return 'Слишком мало символов';
|
||||
return null;
|
||||
},
|
||||
pinTheme: PinTheme(
|
||||
fieldWidth: 48.w,
|
||||
fieldHeight: 62.h,
|
||||
borderRadius: BorderRadius.circular(8).r,
|
||||
activeFillColor: AppColors.white,
|
||||
selectedFillColor: AppColors.white,
|
||||
inactiveColor: AppColors.white,
|
||||
|
||||
selectedColor: AppColors.white,
|
||||
activeColor: AppColors.white,
|
||||
shape: PinCodeFieldShape.box,
|
||||
inactiveFillColor: AppColors.white,
|
||||
),
|
||||
onCompleted: (String value) async {},
|
||||
);
|
||||
}
|
||||
}
|
||||
95
lib/screens/auth/widgets/timer.dart
Normal file
95
lib/screens/auth/widgets/timer.dart
Normal file
@@ -0,0 +1,95 @@
|
||||
// Dart imports:
|
||||
import 'dart:async';
|
||||
|
||||
// Flutter imports:
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
// Package imports:
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:remever/common/resources.dart';
|
||||
import 'package:remever/common/widgets/typography.dart';
|
||||
import 'package:remever/common/widgets/w_if.dart';
|
||||
import 'package:remever/common/widgets/wspace.dart';
|
||||
import 'package:remever/components/extensions/context.dart';
|
||||
import 'package:remever/components/extensions/state.dart';
|
||||
|
||||
class ResendTimer extends StatefulWidget {
|
||||
const ResendTimer({required this.onTap, super.key});
|
||||
|
||||
final Function() onTap;
|
||||
|
||||
@override
|
||||
State<ResendTimer> createState() => _ResendTimerState();
|
||||
}
|
||||
|
||||
class _ResendTimerState extends State<ResendTimer> {
|
||||
Timer? _timer;
|
||||
int _start = 60;
|
||||
|
||||
void _startTimer() {
|
||||
const Duration oneSec = Duration(seconds: 1);
|
||||
_timer = Timer.periodic(oneSec, (Timer timer) {
|
||||
if (_start > 0) {
|
||||
safeSetState(() {
|
||||
_start--;
|
||||
});
|
||||
} else {
|
||||
_timer?.cancel();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_startTimer();
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_timer?.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Wif(
|
||||
condition: _start == 0,
|
||||
builder: (BuildContext context) => _buildResend(),
|
||||
fallback: (BuildContext context) => _buildTimer(),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildResend() {
|
||||
return InkWell(
|
||||
onTap: () async {
|
||||
await widget.onTap();
|
||||
safeSetState(() => _start = 60);
|
||||
_startTimer();
|
||||
},
|
||||
child: AppTypography(
|
||||
'Получить новый код на e-mail',
|
||||
type: Regular14px(),
|
||||
color: AppColors.primary,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildTimer() {
|
||||
return Row(
|
||||
children: <Widget>[
|
||||
AppTypography(
|
||||
'Получить новый код можно будет через: ',
|
||||
type: Regular14px(),
|
||||
color: AppColors.disabled,
|
||||
),
|
||||
AppTypography(
|
||||
'$_start сек',
|
||||
type: Regular14px(),
|
||||
color: AppColors.disabled,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user