import 'dart:convert'; import 'dart:io'; import 'package:auto_route/auto_route.dart'; import 'package:file_picker/file_picker.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:remever/common/functions.dart'; import 'package:remever/common/resources.dart'; import 'package:remever/common/widgets/bottom_safe_space.dart'; import 'package:remever/common/widgets/typography.dart'; import 'package:remever/common/widgets/w_if.dart'; import 'package:remever/common/widgets/wspace.dart'; import 'package:remever/components/extensions/context.dart'; import 'package:remever/database/database.dart'; import 'package:remever/gen/assets.gen.dart'; import 'package:remever/inject.dart'; import 'package:remever/models/crud_collection_dto.dart'; import 'package:remever/router.gr.dart'; import 'package:remever/screens/crud_collection/widgets/crud_collection_field.dart'; import 'package:remever/screens/dialogs/alert_dialog.dart'; import 'package:remever/screens/dialogs/tags_dialog.dart'; import 'package:remever/services/collection/collections_interface.dart'; import 'package:remever/widgets/primary_button.dart'; import '../../../components/extensions/state.dart'; @RoutePage() class CrudCollectionScreen extends StatefulWidget { const CrudCollectionScreen({super.key, this.editedCollection}); final Collection? editedCollection; @override State createState() => _CrudCollectionScreenState(); } class _CrudCollectionScreenState extends State { /// Флаг публичности коллекции bool _isPublic = false; CrudCollectionDto? _collection; /// Смена публичности void _setPublic(bool public) { _collection = _collection?.copyWith(isPublic: public); safeSetState(() => _isPublic = public); } @override void initState() { _collection = CrudCollectionDto( desc: widget.editedCollection?.desc ?? '', title: widget.editedCollection?.title ?? '', isPublic: widget.editedCollection?.isPublic ?? false, avatar: widget.editedCollection?.image, ); super.initState(); } void _pickImage() 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(); // final base64String = base64Encode(bytes); _collection = _collection?.copyWith(avatar: bytes); safeSetState(() {}); } @override Widget build(BuildContext context) { logger.logBuild('build create screen'); return Scaffold( backgroundColor: AppColors.gray_bg, appBar: _buildAppBar(context), body: _buildMainBody(context), ); } /// Основное тело экрана Widget _buildMainBody(BuildContext context) { return Padding( padding: const EdgeInsets.symmetric(horizontal: 16).r, child: SingleChildScrollView( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const HSpace(16), _buildPhotoAndTitle(context), const HSpace(16), ..._buildDescription(context), const HSpace(16), // _buildPublickSwitch(), const HSpace(16), AnimatedOpacity( // opacity: _isPublic ? 1 : 0, opacity: 0, duration: const Duration(seconds: 1), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ ..._buildTagButton(), const HSpace(16), _buildTagsList(), const HSpace(47), ], ), ), _buildCreateBtn(context), const BottomSafeSpace(), ], ), ), ); } ///Кнопка создания Widget _buildCreateBtn(BuildContext context) { return PrimaryButton( height: 52, onTap: () async { if (_collection!.desc.isEmpty && _collection!.title.isEmpty) { showErrorToast( 'Для создания публичной коллекции добавьте описание и тэги', ); return; } widget.editedCollection != null ? await getIt().updateCollection( _collection!, widget.editedCollection!.id, ) : await getIt().createCollection( _collection!, ); context.back(); }, color: AppColors.primary, child: AppTypography( widget.editedCollection == null ? 'Создать коллекцию' : 'Сохранить изменения', type: Regular14px(), color: Colors.white, ), ); } /// Построение списка тегов Widget _buildTagsList() { return SizedBox( height: 68.h, child: Row( children: [ Expanded( child: Wrap( runSpacing: 8.r, spacing: 8.r, children: List.generate(6, (int index) { return GestureDetector( onTap: () {}, child: Container( height: 30, decoration: BoxDecoration( borderRadius: const BorderRadius.all(Radius.circular(6)).r, color: const Color(0xFFFFE4E6), ), child: Padding( padding: const EdgeInsets.all(8.0), child: Row( crossAxisAlignment: CrossAxisAlignment.center, mainAxisSize: MainAxisSize.min, children: [ AppTypography( 'tag $index', type: Regular14px(), height: 0.95, color: AppColors.danger, ), const WSpace(8), Center( child: Icon( Icons.close, size: 14.r, color: AppColors.danger, ), ), ], ), ), ), ); }), ), ), const WSpace(9), GestureDetector( onTap: () { showCuperModalBottomSheet( context: context, height: 270.h, builder: (BuildContext context) => const TagsDialog(), ); }, child: AppTypography( '+13', type: Medium16px(), color: AppColors.primary, ), ), ], ), ); } /// Построение кнопки добавления тега List _buildTagButton() { return [ AppTypography('Тэги', type: SemiBold14px()), const HSpace(4), CrudCollectionField( height: 42, width: 348, hint: 'Добавить тэг', // onTap: () => context.pushRoute(const AddTagsRoute()), ), ]; } /// Построение свитчера на публичность коллекции Widget _buildPublickSwitch() { return GestureDetector( onTap: () => _setPublic(!_isPublic), child: Row( children: [ SizedBox.square( dimension: 20.r, child: Assets.icons.typePublic.image(color: AppColors.primary), ), const WSpace(2), Flexible( fit: FlexFit.tight, child: AppTypography( 'Публичная коллекция', type: Medium16px(), color: AppColors.primary, ), ), const WSpace(2), SizedBox( height: 20.h, width: 36.w, child: FittedBox( fit: BoxFit.contain, child: CupertinoSwitch( activeTrackColor: AppColors.primary, value: _isPublic, onChanged: _setPublic, ), ), ), ], ), ); } /// Построение блока с описанием List _buildDescription(BuildContext context) { return [ AppTypography('Описание', type: SemiBold14px()), const HSpace(4), CrudCollectionField( height: 110, width: 348, hint: 'Добавить описание', content: _collection?.desc, onTap: () { context.pushRoute( CrudCollectionFullscreenField( title: 'Описание', height: 333, content: _collection?.desc, onEditingComplete: (res) { safeSetState( () => _collection = _collection?.copyWith(desc: res ?? ''), ); }, ), ); }, ), ]; } /// Построение блока фото и заголовка Widget _buildPhotoAndTitle(BuildContext context) { return Row( children: [_buildPhoto(), const WSpace(8), _buildTitle(context)], ); } /// Построение поля для ввода заголовка Widget _buildTitle(BuildContext context) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ AppTypography('Название', type: SemiBold14px()), const HSpace(4), CrudCollectionField( height: 91, width: 225, hint: 'Добавить название', content: _collection?.title, onTap: () { context.pushRoute( CrudCollectionFullscreenField( title: 'Название', hint: 'Максимальное количество символов - 250', content: _collection?.title, onEditingComplete: (res) { safeSetState( () => _collection = _collection?.copyWith(title: res ?? ''), ); }, ), ); }, ), ], ); } /// Построение обложки Widget _buildPhoto() { return GestureDetector( onTap: () => _pickImage(), child: SizedBox.square( dimension: 115.r, child: DecoratedBox( decoration: const BoxDecoration( shape: BoxShape.circle, gradient: LinearGradient( colors: [Color(0xFFB6AAFE), Color(0xFFDBD7F4)], begin: Alignment.bottomLeft, end: Alignment.topRight, ), ), child: Wif( condition: _collection!.avatar != null, builder: (context) => ClipOval( child: Image.memory(_collection!.avatar!, fit: BoxFit.cover), ), fallback: (context) => SizedBox.square( dimension: 32.r, child: Center( child: Assets.icons.typePhoto.image( height: 32.h, width: 32.w, color: AppColors.primary, ), ), ), ), ), ), ); } /// Построение шапки AppBar _buildAppBar(BuildContext context) { return AppBar( toolbarHeight: 56.h, backgroundColor: AppColors.white, shadowColor: Colors.transparent, leading: IconButton( onPressed: () async { if (widget.editedCollection != null) { final bool? res = await showCuperModalBottomSheet( context: context, height: 262.h, builder: (BuildContext context) => const AlertInfoDialog( title: 'Вы хотите сбросить все внесенные изменения?', acceptTitle: 'Да, сбросить', declineTitle: 'Нет, оставить', ), ); if (res != null && res) context.back(); } else { context.back(); } }, icon: const Icon(CupertinoIcons.left_chevron, color: Colors.black), ), centerTitle: true, title: GestureDetector( onLongPress: () => context.pushRoute(const SandboxRoute()), child: AppTypography( widget.editedCollection == null ? 'Создать коллекцию' : 'Редактировать', type: SemiBold20px(), color: AppColors.body_text, ), ), actions: [ Wif( condition: widget.editedCollection != null, builder: (BuildContext context) { return Padding( padding: const EdgeInsets.only(right: 16).r, child: GestureDetector( onTap: () { showCuperModalBottomSheet( context: context, height: 262.h, builder: (BuildContext context) => const AlertInfoDialog( title: 'Вы хотите сбросить все внесенные изменения?', acceptTitle: 'Да, сбросить', declineTitle: 'Нет, оставить', ), ); }, child: Assets.icons.typeTrash.image( height: 24.h, width: 24.w, color: AppColors.primary, ), ), ); }, ), ], ); } }