Доработка создания карточки в коллекции

This commit is contained in:
2025-04-02 21:52:44 +03:00
parent 17dff72655
commit a3ef313e7c

View File

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