Доработка создания карточки в коллекции
This commit is contained in:
@@ -1,6 +1,4 @@
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'dart:math';
|
|
||||||
|
|
||||||
import 'package:auto_route/auto_route.dart';
|
import 'package:auto_route/auto_route.dart';
|
||||||
import 'package:file_picker/file_picker.dart';
|
import 'package:file_picker/file_picker.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
@@ -34,68 +32,82 @@ class CreateScreen extends StatefulWidget {
|
|||||||
class _CreateScreenState extends State<CreateScreen> {
|
class _CreateScreenState extends State<CreateScreen> {
|
||||||
CreateTicketDto _dto = CreateTicketDto();
|
CreateTicketDto _dto = CreateTicketDto();
|
||||||
|
|
||||||
void _pickImage(bool isQuestion) async {
|
// Constants for spacing and dimensions
|
||||||
final result = await FilePicker.platform.pickFiles();
|
static const double _horizontalPadding = 16;
|
||||||
|
static const double _verticalSpacing = 16;
|
||||||
|
|
||||||
|
Future<void> _pickImage(bool isQuestion) async {
|
||||||
|
final result = await FilePicker.platform.pickFiles();
|
||||||
if (result == null || result.files.isEmpty) {
|
if (result == null || result.files.isEmpty) {
|
||||||
showErrorToast('Файл не выбран');
|
showErrorToast('Файл не выбран');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final filePath = result.files.single.path;
|
final filePath = result.files.single.path;
|
||||||
|
|
||||||
if (filePath == null) {
|
if (filePath == null) {
|
||||||
showErrorToast('Не удалось получить путь к файлу');
|
showErrorToast('Не удалось получить путь к файлу');
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final file = File(filePath);
|
final file = File(filePath);
|
||||||
final bytes = await file.readAsBytes();
|
final bytes = await file.readAsBytes();
|
||||||
|
safeSetState(() {
|
||||||
_dto =
|
_dto =
|
||||||
isQuestion
|
isQuestion
|
||||||
? _dto.copyWith(questionImage: bytes)
|
? _dto.copyWith(questionImage: bytes)
|
||||||
: _dto.copyWith(answerImage: bytes);
|
: _dto.copyWith(answerImage: bytes);
|
||||||
|
});
|
||||||
safeSetState(() {});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onCollectionTap() {
|
void _onCollectionTap() {
|
||||||
{
|
context.pushRoute(
|
||||||
context.pushRoute(
|
CollectionSearchRoute(
|
||||||
CollectionSearchRoute(
|
onCollectionSelect: (collection) {
|
||||||
onCollectionSelect: (collection) {
|
safeSetState(() => _dto = _dto.copyWith(collection: collection));
|
||||||
safeSetState(() => _dto = _dto.copyWith(collection: collection));
|
},
|
||||||
},
|
),
|
||||||
),
|
);
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onCreateTap() async {
|
Future<void> _onCreateTap() async {
|
||||||
if (_dto.collection == null ||
|
if (_dto.collection == null ||
|
||||||
_dto.answer == null ||
|
_dto.answer == null ||
|
||||||
_dto.question == null) {
|
_dto.question == null) {
|
||||||
showErrorToast('Необходимо заполнить все поля');
|
showErrorToast('Необходимо заполнить все поля');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await getIt<TicketsInterface>().createTicket(_dto);
|
await getIt<TicketsInterface>().createTicket(_dto);
|
||||||
|
|
||||||
context.pushRoute(CollectionRoute());
|
safeSetState(() => _dto = CreateTicketDto());
|
||||||
|
|
||||||
|
final tabsRouter = context.tabsRouter;
|
||||||
|
tabsRouter.setActiveIndex(3);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
void _openFullScreenField({
|
||||||
Widget build(BuildContext context) {
|
required String title,
|
||||||
return Scaffold(
|
required String? content,
|
||||||
backgroundColor: AppColors.gray_bg,
|
required void Function(String?) onEditingComplete,
|
||||||
appBar: _buildAppBar(),
|
}) {
|
||||||
body: _buildMain(context),
|
context.pushRoute(
|
||||||
|
CrudCollectionFullscreenField(
|
||||||
|
title: title,
|
||||||
|
hint: '',
|
||||||
|
height: 313,
|
||||||
|
content: content,
|
||||||
|
onEditingComplete: onEditingComplete,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
AppBar _buildAppBar() {
|
void _updateDto(String value, bool isQuestion) {
|
||||||
|
safeSetState(() {
|
||||||
|
_dto =
|
||||||
|
isQuestion
|
||||||
|
? _dto.copyWith(question: value)
|
||||||
|
: _dto.copyWith(answer: value);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
PreferredSizeWidget _buildAppBar() {
|
||||||
return AppBar(
|
return AppBar(
|
||||||
toolbarHeight: 66.h,
|
toolbarHeight: 66.h,
|
||||||
backgroundColor: AppColors.white,
|
backgroundColor: AppColors.white,
|
||||||
@@ -111,65 +123,47 @@ class _CreateScreenState extends State<CreateScreen> {
|
|||||||
|
|
||||||
Widget _buildMain(BuildContext context) {
|
Widget _buildMain(BuildContext context) {
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16).r,
|
padding: EdgeInsets.symmetric(horizontal: _horizontalPadding).r,
|
||||||
child: Column(
|
child: Column(
|
||||||
children: <Widget>[
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: <Widget>[
|
children: [
|
||||||
const HSpace(16),
|
const HSpace(_verticalSpacing),
|
||||||
_filters(),
|
_filters(),
|
||||||
const HSpace(16),
|
const HSpace(_verticalSpacing),
|
||||||
AppTypography('Коллекция', type: Medium16px()),
|
_buildSection('Коллекция', _buildCollection(context)),
|
||||||
const HSpace(4),
|
const HSpace(_verticalSpacing),
|
||||||
_buildCollection(context),
|
_buildSection(
|
||||||
const HSpace(16),
|
'Вопрос',
|
||||||
AppTypography('Вопрос', type: Medium16px()),
|
CrudTicket(
|
||||||
const HSpace(4),
|
onTextTap:
|
||||||
CrudTicket(
|
() => _openFullScreenField(
|
||||||
onTextTap: () {
|
title: 'Вопрос',
|
||||||
context.pushRoute(
|
content: _dto.question,
|
||||||
CrudCollectionFullscreenField(
|
onEditingComplete: (res) => _updateDto(res!, true),
|
||||||
title: 'Вопрос',
|
),
|
||||||
hint: '',
|
onImageTap: () => _pickImage(true),
|
||||||
height: 313,
|
isQuestion: true,
|
||||||
content: _dto.question,
|
dto: _dto,
|
||||||
onEditingComplete: (res) {
|
),
|
||||||
safeSetState(() {
|
|
||||||
_dto = _dto.copyWith(question: res);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
onImageTap: () => _pickImage(true),
|
|
||||||
isQuestion: true,
|
|
||||||
dto: _dto,
|
|
||||||
),
|
),
|
||||||
const HSpace(16),
|
const HSpace(_verticalSpacing),
|
||||||
AppTypography('Ответ', type: Medium16px()),
|
_buildSection(
|
||||||
const HSpace(4),
|
'Ответ',
|
||||||
CrudTicket(
|
CrudTicket(
|
||||||
onTextTap: () {
|
onTextTap:
|
||||||
context.pushRoute(
|
() => _openFullScreenField(
|
||||||
CrudCollectionFullscreenField(
|
title: 'Ответ',
|
||||||
title: 'Ответ',
|
content: _dto.answer,
|
||||||
hint: '',
|
onEditingComplete: (res) => _updateDto(res!, false),
|
||||||
height: 313,
|
),
|
||||||
content: _dto.answer,
|
onImageTap: () => _pickImage(false),
|
||||||
onEditingComplete: (res) {
|
isQuestion: false,
|
||||||
safeSetState(() {
|
dto: _dto,
|
||||||
_dto = _dto.copyWith(answer: res);
|
),
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
onImageTap: () => _pickImage(false),
|
|
||||||
isQuestion: false,
|
|
||||||
dto: _dto,
|
|
||||||
),
|
),
|
||||||
revertCard(),
|
revertCard(),
|
||||||
],
|
],
|
||||||
@@ -183,91 +177,20 @@ class _CreateScreenState extends State<CreateScreen> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget revertCard() {
|
Widget _buildSection(String title, Widget child) {
|
||||||
return SizedBox(
|
return Column(
|
||||||
height: 52.h,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
child: Row(
|
children: [
|
||||||
children: <Widget>[
|
AppTypography(title, type: Medium16px()),
|
||||||
Center(
|
const HSpace(4),
|
||||||
child: Assets.icons.typeFlip2.image(height: 20.h, width: 20.w),
|
child,
|
||||||
),
|
],
|
||||||
const WSpace(2),
|
|
||||||
Flexible(
|
|
||||||
fit: FlexFit.tight,
|
|
||||||
child: AppTypography(
|
|
||||||
'Создать карточку-наоборот',
|
|
||||||
type: Medium16px(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(
|
|
||||||
height: 20.h,
|
|
||||||
width: 36.w,
|
|
||||||
child: FittedBox(
|
|
||||||
fit: BoxFit.contain,
|
|
||||||
child: CupertinoSwitch(
|
|
||||||
activeTrackColor: AppColors.primary,
|
|
||||||
value: _dto.needRevert ?? false,
|
|
||||||
onChanged: (bool value) {
|
|
||||||
safeSetState(() {
|
|
||||||
_dto = _dto.copyWith(needRevert: value);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _filters() {
|
|
||||||
return AppDebug(
|
|
||||||
builder: (context, isDebug) {
|
|
||||||
if (!isDebug) return SizedBox();
|
|
||||||
return Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
children: <Widget>[
|
|
||||||
_buildFilterButton(AppColors.gray_bg, 'Запомнить', () {}),
|
|
||||||
_buildFilterButton(AppColors.white, 'Держать в фокусе', () {}),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _buildCreateButton() {
|
|
||||||
return PrimaryButton(
|
|
||||||
color: AppColors.primary,
|
|
||||||
child: AppTypography(
|
|
||||||
'Создать карточку',
|
|
||||||
type: Medium14px(),
|
|
||||||
color: AppColors.white,
|
|
||||||
),
|
|
||||||
onTap: () => _onCreateTap(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Построение кнопки фильтра
|
|
||||||
///
|
|
||||||
Widget _buildFilterButton(Color color, String title, void Function()? onTap) {
|
|
||||||
return GestureDetector(
|
|
||||||
onTap: onTap,
|
|
||||||
child: Container(
|
|
||||||
width: 158.h,
|
|
||||||
height: 36.h,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
borderRadius: const BorderRadius.all(Radius.circular(16)).r,
|
|
||||||
color: color,
|
|
||||||
),
|
|
||||||
child: Center(child: AppTypography(title, type: SemiBold14px())),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildCollection(BuildContext context) {
|
Widget _buildCollection(BuildContext context) {
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
onTap: () => _onCollectionTap(),
|
onTap: _onCollectionTap,
|
||||||
child: Container(
|
child: Container(
|
||||||
constraints: BoxConstraints(minHeight: 66.h, maxHeight: 84.h),
|
constraints: BoxConstraints(minHeight: 66.h, maxHeight: 84.h),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
@@ -277,38 +200,33 @@ class _CreateScreenState extends State<CreateScreen> {
|
|||||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8).r,
|
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8).r,
|
||||||
child: Wif(
|
child: Wif(
|
||||||
condition: _dto.collection != null,
|
condition: _dto.collection != null,
|
||||||
builder: (context) {
|
builder:
|
||||||
return Row(
|
(context) => Row(
|
||||||
children: <Widget>[_buildAvatar(), const WSpace(5), _buildInfo()],
|
children: [_buildAvatar(), const WSpace(5), _buildInfo()],
|
||||||
);
|
),
|
||||||
},
|
fallback:
|
||||||
fallback: (context) {
|
(context) => Row(
|
||||||
return Row(
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
children: [
|
||||||
children: [
|
AppTypography('Выберите коллекцию', type: Bold14px()),
|
||||||
AppTypography('Выберите коллекцию ', type: Bold14px()),
|
],
|
||||||
],
|
),
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
|
||||||
/// Построение основной информации
|
|
||||||
///
|
|
||||||
Widget _buildInfo() {
|
Widget _buildInfo() {
|
||||||
return SizedBox(
|
return SizedBox(
|
||||||
width: 230.w,
|
width: 230.w,
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: <Widget>[
|
children: [
|
||||||
_buildTitle(),
|
_buildTitle(),
|
||||||
const HSpace(4),
|
const HSpace(4),
|
||||||
Row(
|
Row(
|
||||||
children: <Widget>[
|
children: [
|
||||||
Assets.icons.typeCards.image(
|
Assets.icons.typeCards.image(
|
||||||
height: 18.h,
|
height: 18.h,
|
||||||
width: 18.w,
|
width: 18.w,
|
||||||
@@ -329,9 +247,6 @@ class _CreateScreenState extends State<CreateScreen> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
|
||||||
/// Название коллекции
|
|
||||||
///
|
|
||||||
Widget _buildTitle() {
|
Widget _buildTitle() {
|
||||||
return AppTypography(
|
return AppTypography(
|
||||||
_dto.collection!.title,
|
_dto.collection!.title,
|
||||||
@@ -341,15 +256,11 @@ class _CreateScreenState extends State<CreateScreen> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
|
||||||
/// Обложка коллекции
|
|
||||||
///
|
|
||||||
Widget _buildAvatar() {
|
Widget _buildAvatar() {
|
||||||
return SizedBox.square(
|
return SizedBox.square(
|
||||||
dimension: 50.r,
|
dimension: 50.r,
|
||||||
child: DecoratedBox(
|
child: DecoratedBox(
|
||||||
decoration: BoxDecoration(shape: BoxShape.circle, color: AppColors.bg),
|
decoration: BoxDecoration(shape: BoxShape.circle, color: AppColors.bg),
|
||||||
|
|
||||||
child: Wif(
|
child: Wif(
|
||||||
condition: _dto.collection?.image != null,
|
condition: _dto.collection?.image != null,
|
||||||
builder:
|
builder:
|
||||||
@@ -367,4 +278,92 @@ class _CreateScreenState extends State<CreateScreen> {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget revertCard() {
|
||||||
|
return SizedBox(
|
||||||
|
height: 52.h,
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Center(
|
||||||
|
child: Assets.icons.typeFlip2.image(height: 20.h, width: 20.w),
|
||||||
|
),
|
||||||
|
const WSpace(2),
|
||||||
|
Flexible(
|
||||||
|
fit: FlexFit.tight,
|
||||||
|
child: AppTypography(
|
||||||
|
'Создать карточку-наоборот',
|
||||||
|
type: Medium16px(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: 20.h,
|
||||||
|
width: 36.w,
|
||||||
|
child: FittedBox(
|
||||||
|
fit: BoxFit.contain,
|
||||||
|
child: CupertinoSwitch(
|
||||||
|
activeTrackColor: AppColors.primary,
|
||||||
|
value: _dto.needRevert ?? false,
|
||||||
|
onChanged:
|
||||||
|
(value) => safeSetState(
|
||||||
|
() => _dto = _dto.copyWith(needRevert: value),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildCreateButton() {
|
||||||
|
return PrimaryButton(
|
||||||
|
color: AppColors.primary,
|
||||||
|
onTap: _onCreateTap,
|
||||||
|
child: AppTypography(
|
||||||
|
'Создать карточку',
|
||||||
|
type: Medium14px(),
|
||||||
|
color: AppColors.white,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _filters() {
|
||||||
|
return AppDebug(
|
||||||
|
builder: (context, isDebug) {
|
||||||
|
if (!isDebug) return const SizedBox();
|
||||||
|
return Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
_buildFilterButton(AppColors.gray_bg, 'Запомнить', () {}),
|
||||||
|
const WSpace(10),
|
||||||
|
_buildFilterButton(AppColors.white, 'Держать в фокусе', () {}),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildFilterButton(Color color, String title, VoidCallback onTap) {
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: onTap,
|
||||||
|
child: Container(
|
||||||
|
width: 158.h,
|
||||||
|
height: 36.h,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(16).r,
|
||||||
|
color: color,
|
||||||
|
),
|
||||||
|
child: Center(child: AppTypography(title, type: SemiBold14px())),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
backgroundColor: AppColors.gray_bg,
|
||||||
|
appBar: _buildAppBar(),
|
||||||
|
body: _buildMain(context),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user