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