feature(consultant): Невозможно поставить точку в адресе сайта

добавить лоти анимацию на модалку завершение
                     Убрать фокус на 4 шаге (соцсети)
                     добавить текст на первый экран
                     выход с последнего экрана
                     радиобаттон на 5 шаге в синий цвет
                     оптимизировать загрузку изображений
                     Добавить галерею
                     Лоадинг в кнопке при отправке
This commit is contained in:
mso7nueh
2024-10-14 16:23:43 +03:00
parent 78be72372c
commit df290fa89b
8 changed files with 208 additions and 149 deletions

File diff suppressed because one or more lines are too long

View File

@@ -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(

View File

@@ -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(),
);

View File

@@ -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,
),
);
}
}

View File

@@ -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),
),

View File

@@ -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,
);

View File

@@ -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),
),

View File

@@ -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