forked from eatvio/eatvio_app
feature(consultant): Невозможно поставить точку в адресе сайта
добавить лоти анимацию на модалку завершение
Убрать фокус на 4 шаге (соцсети)
добавить текст на первый экран
выход с последнего экрана
радиобаттон на 5 шаге в синий цвет
оптимизировать загрузку изображений
Добавить галерею
Лоадинг в кнопке при отправке
This commit is contained in:
1
assets/lottie_animations/success.json
Normal file
1
assets/lottie_animations/success.json
Normal file
File diff suppressed because one or more lines are too long
@@ -1,3 +1,5 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:dismissible_page/dismissible_page.dart';
|
||||
import 'package:eatvio_app/core/const.dart';
|
||||
@@ -11,11 +13,13 @@ import 'package:url_launcher/url_launcher.dart';
|
||||
class PhotoViewScreen extends StatefulWidget {
|
||||
final List<String> imageUrls;
|
||||
final int index;
|
||||
final bool isLocal;
|
||||
|
||||
const PhotoViewScreen({
|
||||
super.key,
|
||||
required this.imageUrls,
|
||||
required this.index,
|
||||
this.isLocal = false,
|
||||
});
|
||||
|
||||
@override
|
||||
@@ -47,9 +51,13 @@ class _PhotoViewScreenState extends State<PhotoViewScreen> {
|
||||
scrollPhysics: const BouncingScrollPhysics(),
|
||||
builder: (BuildContext context, int index) {
|
||||
return PhotoViewGalleryPageOptions(
|
||||
imageProvider: CachedNetworkImageProvider(
|
||||
widget.imageUrls[index],
|
||||
),
|
||||
imageProvider: widget.isLocal
|
||||
? FileImage(
|
||||
File(widget.imageUrls[index]),
|
||||
) as ImageProvider
|
||||
: CachedNetworkImageProvider(
|
||||
widget.imageUrls[index],
|
||||
),
|
||||
initialScale: PhotoViewComputedScale.contained,
|
||||
minScale: PhotoViewComputedScale.contained,
|
||||
heroAttributes: PhotoViewHeroAttributes(
|
||||
|
||||
@@ -24,7 +24,12 @@ class _BecomeConsultantScreenState extends State<BecomeConsultantScreen> {
|
||||
),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Text('Для регистрации потребуется следующий список документов, подготовьте их заранее'),
|
||||
child: Text(
|
||||
' Чтобы стать консультантом необходимо пройти короткую регистрацию. Подготовьте свои дипломы и/или сертификаты в формате jpg, они Вам пригодятся для проверки и подтверждения. Также необходимо будет указать ссылки на Ваши соц. сети и указать тип лица (физ. лицо или юр. лицо). На данный момент доступна регистрация в качестве физ. лица.\n\n Внутри Итвио разница между обычным пользователем и консультантом заключается в дополнительных возможностях последнего создавать публичные диеты, рецепты и планы питания; участвовать в ежемесячных рейтингах.',
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
),
|
||||
bottomSheet: _startRegistrationButton(),
|
||||
);
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:dismissible_page/dismissible_page.dart';
|
||||
import 'package:eatvio_app/features/chat/presentation/pages/photo_view_screen.dart';
|
||||
import 'package:eatvio_app/features/consultant/become_consultant/presentation/bloc/register_consultant_cubit/register_consultant_cubit.dart';
|
||||
import 'package:eatvio_app/theme/theme_helper.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@@ -75,51 +77,66 @@ class _PhotoOrScansScreenState extends State<PhotoOrScansScreen> {
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return InkWell(
|
||||
onTap: () {},
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
child: Stack(
|
||||
clipBehavior: Clip.none,
|
||||
children: [
|
||||
Ink(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.all(
|
||||
Radius.circular(20),
|
||||
return Hero(
|
||||
tag: imagesPaths[index],
|
||||
child: Material(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
context.pushTransparentRoute(
|
||||
rootNavigator: true,
|
||||
PhotoViewScreen(
|
||||
imageUrls: imagesPaths,
|
||||
isLocal: true,
|
||||
index: index,
|
||||
),
|
||||
image: DecorationImage(
|
||||
fit: BoxFit.fitHeight,
|
||||
image: FileImage(
|
||||
File(imagesPaths[index]),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
right: -12,
|
||||
top: -12,
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
setState(() {
|
||||
imagesPaths.removeAt(index);
|
||||
});
|
||||
_saveState();
|
||||
},
|
||||
customBorder: CircleBorder(),
|
||||
child: Ink(
|
||||
padding: EdgeInsets.all(4),
|
||||
);
|
||||
},
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
child: Stack(
|
||||
clipBehavior: Clip.none,
|
||||
children: [
|
||||
Ink(
|
||||
decoration: BoxDecoration(
|
||||
color: Color(0xFFF1F2F6),
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
child: Icon(
|
||||
size: 20,
|
||||
Icons.close,
|
||||
color: Colors.black,
|
||||
borderRadius: BorderRadius.all(
|
||||
Radius.circular(20),
|
||||
),
|
||||
image: DecorationImage(
|
||||
fit: BoxFit.fitHeight,
|
||||
image: FileImage(
|
||||
File(imagesPaths[index]),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
right: -12,
|
||||
top: -12,
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
setState(() {
|
||||
imagesPaths.removeAt(index);
|
||||
});
|
||||
_saveState();
|
||||
},
|
||||
customBorder: CircleBorder(),
|
||||
child: Ink(
|
||||
padding: EdgeInsets.all(4),
|
||||
decoration: BoxDecoration(
|
||||
color: Color(0xFFF1F2F6),
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
child: Icon(
|
||||
size: 20,
|
||||
Icons.close,
|
||||
color: Colors.black,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -133,9 +150,9 @@ class _PhotoOrScansScreenState extends State<PhotoOrScansScreen> {
|
||||
|
||||
_saveState() {
|
||||
context.read<RegisterConsultantCubit>().updateConsultantProfileModel(
|
||||
context.read<RegisterConsultantCubit>().state.consultant.copyWith(
|
||||
photos: imagesPaths,
|
||||
),
|
||||
);
|
||||
context.read<RegisterConsultantCubit>().state.consultant.copyWith(
|
||||
photos: imagesPaths,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import 'package:eatvio_app/theme/theme_helper.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class RegistrationAsScreen extends StatefulWidget {
|
||||
@@ -42,6 +43,7 @@ class _RegistrationAsScreenState extends State<RegistrationAsScreen> {
|
||||
height: 1,
|
||||
),
|
||||
),
|
||||
activeColor: appTheme.blueA400,
|
||||
onChanged: (value) {},
|
||||
contentPadding: EdgeInsets.symmetric(horizontal: 8),
|
||||
),
|
||||
|
||||
@@ -20,21 +20,21 @@ class _SocialNetworksScreenState extends State<SocialNetworksScreen> {
|
||||
var maskFormatter = new MaskTextInputFormatter(
|
||||
mask: 'https://########################################',
|
||||
filter: {
|
||||
'#': RegExp(r"(\w+)"),
|
||||
'#': RegExp(r"[a-zA-Z. ]+"),
|
||||
},
|
||||
type: MaskAutoCompletionType.lazy,
|
||||
);
|
||||
var maskTgFormatter = new MaskTextInputFormatter(
|
||||
mask: 'https://tg.me/########################################',
|
||||
filter: {
|
||||
'#': RegExp(r"(\w+)"),
|
||||
'#': RegExp(r"[a-zA-Z. ]+"),
|
||||
},
|
||||
type: MaskAutoCompletionType.lazy,
|
||||
);
|
||||
var maskVkFormatter = new MaskTextInputFormatter(
|
||||
mask: 'https://vk.com/########################################',
|
||||
filter: {
|
||||
'#': RegExp(r"(\w+)"),
|
||||
'#': RegExp(r"[a-zA-Z. ]+"),
|
||||
},
|
||||
type: MaskAutoCompletionType.lazy,
|
||||
);
|
||||
|
||||
@@ -12,6 +12,7 @@ import 'package:eatvio_app/widgets/app_bar/appbar_title_image.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:lottie/lottie.dart';
|
||||
|
||||
class StepperBecomeConsultantScreen extends StatefulWidget {
|
||||
const StepperBecomeConsultantScreen({super.key});
|
||||
@@ -25,6 +26,7 @@ class _StepperBecomeConsultantScreenState extends State<StepperBecomeConsultantS
|
||||
int step = 1;
|
||||
final pageController = PageController();
|
||||
final registrationConsultantCubit = sl<RegisterConsultantCubit>();
|
||||
bool isLoading = false;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -73,108 +75,130 @@ class _StepperBecomeConsultantScreenState extends State<StepperBecomeConsultantS
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
),
|
||||
backgroundColor: appTheme.blueA400,
|
||||
onPressed: () async {
|
||||
if (step == 6) {
|
||||
if (registrationConsultantCubit.state.acceptOffer) {
|
||||
await registrationConsultantCubit.registerConsultant();
|
||||
await showModalBottomSheet(
|
||||
useRootNavigator: true,
|
||||
showDragHandle: true,
|
||||
context: context,
|
||||
builder: (context) => Container(
|
||||
padding: EdgeInsets.all(16),
|
||||
width: MediaQuery.of(context).size.width,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
'Спасибо!\nВаши данные отправлены на модерацию',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
height: 1,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
color: appTheme.blueA400,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
child: Icon(
|
||||
size: 32,
|
||||
Icons.done,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
'В течении трех рабочих дней Вам придет уведомление о смене статуса',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
height: 1,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: Ink(
|
||||
width: MediaQuery.of(context).size.width - 32,
|
||||
height: 52,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
color: appTheme.blueA400,
|
||||
),
|
||||
child: Center(
|
||||
child: Text(
|
||||
'Закрыть',
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.w600,
|
||||
backgroundColor: isLoading ? Colors.grey : appTheme.blueA400,
|
||||
onPressed: isLoading
|
||||
? null
|
||||
: () async {
|
||||
if (step == 6) {
|
||||
if (registrationConsultantCubit.state.acceptOffer) {
|
||||
setState(() {
|
||||
isLoading = true;
|
||||
});
|
||||
try {
|
||||
await registrationConsultantCubit.registerConsultant();
|
||||
await showModalBottomSheet(
|
||||
useRootNavigator: true,
|
||||
showDragHandle: true,
|
||||
context: context,
|
||||
builder: (context) => Container(
|
||||
padding: EdgeInsets.all(16),
|
||||
width: MediaQuery.of(context).size.width,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
'Спасибо!\nВаши данные отправлены на модерацию',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
height: 1,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Lottie.asset(
|
||||
'assets/lottie_animations/success.json',
|
||||
width: 160,
|
||||
height: 160,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
'В течении трех рабочих дней Вам придет уведомление о смене статуса',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
height: 1,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
Navigator.of(context).pop();
|
||||
GoRouter.of(context).pop();
|
||||
},
|
||||
child: Ink(
|
||||
width: MediaQuery.of(context).size.width - 32,
|
||||
height: 52,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
color: appTheme.blueA400,
|
||||
),
|
||||
child: Center(
|
||||
child: Text(
|
||||
'Закрыть',
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
} catch (e) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
actionsPadding: const EdgeInsets.symmetric(horizontal: 4),
|
||||
content: Text(e.toString()),
|
||||
actions: [
|
||||
TextButton(
|
||||
child: const Text('Ок'),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
} finally {
|
||||
setState(() {
|
||||
isLoading = false;
|
||||
});
|
||||
}
|
||||
} else {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
actionsPadding: const EdgeInsets.symmetric(horizontal: 4),
|
||||
content: Text('Примите договор публичной офёрты'),
|
||||
actions: [
|
||||
TextButton(
|
||||
child: const Text('Ок'),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
actionsPadding: const EdgeInsets.symmetric(horizontal: 4),
|
||||
content: Text('Примите договор публичной офёрты'),
|
||||
actions: [
|
||||
TextButton(
|
||||
child: const Text('Ок'),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
setState(() {
|
||||
pageController.nextPage(
|
||||
duration: const Duration(milliseconds: 350),
|
||||
curve: Curves.easeInOut,
|
||||
);
|
||||
});
|
||||
}
|
||||
},
|
||||
label: Text(
|
||||
);
|
||||
}
|
||||
} else {
|
||||
FocusManager.instance.primaryFocus?.unfocus();
|
||||
setState(() {
|
||||
pageController.nextPage(
|
||||
duration: const Duration(milliseconds: 350),
|
||||
curve: Curves.easeInOut,
|
||||
);
|
||||
});
|
||||
}
|
||||
},
|
||||
label: isLoading ? CircularProgressIndicator() : Text(
|
||||
'Продолжить',
|
||||
style: theme.textTheme.titleSmall!.copyWith(color: Colors.white),
|
||||
),
|
||||
|
||||
@@ -49,6 +49,7 @@ dependencies:
|
||||
intl: ^0.19.0
|
||||
rive: ^0.13.14
|
||||
mask_text_input_formatter: ^2.9.0
|
||||
lottie: ^3.1.3
|
||||
|
||||
dev_dependencies:
|
||||
build_runner: ^2.4.13
|
||||
@@ -67,6 +68,7 @@ flutter:
|
||||
- assets/audio/
|
||||
- assets/icons/
|
||||
- assets/rive_animations/
|
||||
- assets/lottie_animations/
|
||||
|
||||
flutter_intl:
|
||||
enabled: true
|
||||
|
||||
Reference in New Issue
Block a user