feature(training): отбражение данных для тренировки
This commit is contained in:
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -28,6 +28,18 @@ class CollectionsDao extends DatabaseAccessor<AppDatabase>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<Collection?> getCollectionById(String? id) {
|
||||||
|
try {
|
||||||
|
return db.managers.collections
|
||||||
|
.filter((f) => f.id.equals(id))
|
||||||
|
.getSingleOrNull();
|
||||||
|
} catch (e, st) {
|
||||||
|
logger.logError('Ошибка в методе getCollectionById', e, st);
|
||||||
|
|
||||||
|
throw ('EXEPTION');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Создание коллекции
|
/// Создание коллекции
|
||||||
Future<void> createCollection(CrudCollectionDto dto) async {
|
Future<void> createCollection(CrudCollectionDto dto) async {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
/// Locales: 2
|
/// Locales: 2
|
||||||
/// Strings: 20 (10 per locale)
|
/// Strings: 20 (10 per locale)
|
||||||
///
|
///
|
||||||
/// Built on 2025-09-08 at 14:50 UTC
|
/// Built on 2025-09-08 at 19:38 UTC
|
||||||
|
|
||||||
// coverage:ignore-file
|
// coverage:ignore-file
|
||||||
// ignore_for_file: type=lint, unused_import
|
// ignore_for_file: type=lint, unused_import
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ import 'services/core/theme_service.dart' as _i84;
|
|||||||
import 'services/logs/logs_service.dart' as _i393;
|
import 'services/logs/logs_service.dart' as _i393;
|
||||||
import 'services/tickets/tickets_interface.dart' as _i147;
|
import 'services/tickets/tickets_interface.dart' as _i147;
|
||||||
import 'services/tickets/tickets_service.dart' as _i548;
|
import 'services/tickets/tickets_service.dart' as _i548;
|
||||||
|
import 'services/training/training_interface.dart' as _i813;
|
||||||
|
import 'services/training/training_service.dart' as _i162;
|
||||||
import 'services/warmup_service.dart' as _i564;
|
import 'services/warmup_service.dart' as _i564;
|
||||||
|
|
||||||
extension GetItInjectableX on _i174.GetIt {
|
extension GetItInjectableX on _i174.GetIt {
|
||||||
@@ -37,6 +39,7 @@ extension GetItInjectableX on _i174.GetIt {
|
|||||||
gh.factory<_i84.ThemeService>(() => _i84.ThemeService());
|
gh.factory<_i84.ThemeService>(() => _i84.ThemeService());
|
||||||
gh.singleton<_i565.AppDatabase>(() => _i565.AppDatabase());
|
gh.singleton<_i565.AppDatabase>(() => _i565.AppDatabase());
|
||||||
gh.singleton<_i393.LogsService>(() => _i393.LogsService());
|
gh.singleton<_i393.LogsService>(() => _i393.LogsService());
|
||||||
|
gh.singleton<_i813.TrainingInterface>(() => _i162.TrainingService());
|
||||||
gh.singleton<_i147.TicketsInterface>(() => _i548.TicketsService());
|
gh.singleton<_i147.TicketsInterface>(() => _i548.TicketsService());
|
||||||
gh.singleton<_i764.CollectionsInterface>(() => _i1001.CollectionsService());
|
gh.singleton<_i764.CollectionsInterface>(() => _i1001.CollectionsService());
|
||||||
gh.singleton<_i580.AuthInterface>(() => _i975.AuthService());
|
gh.singleton<_i580.AuthInterface>(() => _i975.AuthService());
|
||||||
|
|||||||
14
lib/models/training_dto.dart
Normal file
14
lib/models/training_dto.dart
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
// To parse this JSON data, do
|
||||||
|
//
|
||||||
|
// final collectionDto = collectionDtoFromJson(jsonString);
|
||||||
|
|
||||||
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
import 'package:remever/database/database.dart';
|
||||||
|
|
||||||
|
part 'training_dto.freezed.dart';
|
||||||
|
|
||||||
|
@Freezed(copyWith: true, equal: true, fromJson: false, toJson: false)
|
||||||
|
abstract class TrainingDto with _$TrainingDto {
|
||||||
|
const factory TrainingDto({Collection? collection, required Ticket ticket}) =
|
||||||
|
_TrainingDto;
|
||||||
|
}
|
||||||
176
lib/models/training_dto.freezed.dart
Normal file
176
lib/models/training_dto.freezed.dart
Normal file
@@ -0,0 +1,176 @@
|
|||||||
|
// coverage:ignore-file
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||||
|
|
||||||
|
part of 'training_dto.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// FreezedGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
T _$identity<T>(T value) => value;
|
||||||
|
|
||||||
|
final _privateConstructorUsedError = UnsupportedError(
|
||||||
|
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models',
|
||||||
|
);
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$TrainingDto {
|
||||||
|
Collection? get collection => throw _privateConstructorUsedError;
|
||||||
|
Ticket get ticket => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
|
/// Create a copy of TrainingDto
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
$TrainingDtoCopyWith<TrainingDto> get copyWith =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class $TrainingDtoCopyWith<$Res> {
|
||||||
|
factory $TrainingDtoCopyWith(
|
||||||
|
TrainingDto value,
|
||||||
|
$Res Function(TrainingDto) then,
|
||||||
|
) = _$TrainingDtoCopyWithImpl<$Res, TrainingDto>;
|
||||||
|
@useResult
|
||||||
|
$Res call({Collection? collection, Ticket ticket});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class _$TrainingDtoCopyWithImpl<$Res, $Val extends TrainingDto>
|
||||||
|
implements $TrainingDtoCopyWith<$Res> {
|
||||||
|
_$TrainingDtoCopyWithImpl(this._value, this._then);
|
||||||
|
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Val _value;
|
||||||
|
// ignore: unused_field
|
||||||
|
final $Res Function($Val) _then;
|
||||||
|
|
||||||
|
/// Create a copy of TrainingDto
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({Object? collection = freezed, Object? ticket = freezed}) {
|
||||||
|
return _then(
|
||||||
|
_value.copyWith(
|
||||||
|
collection:
|
||||||
|
freezed == collection
|
||||||
|
? _value.collection
|
||||||
|
: collection // ignore: cast_nullable_to_non_nullable
|
||||||
|
as Collection?,
|
||||||
|
ticket:
|
||||||
|
freezed == ticket
|
||||||
|
? _value.ticket
|
||||||
|
: ticket // ignore: cast_nullable_to_non_nullable
|
||||||
|
as Ticket,
|
||||||
|
)
|
||||||
|
as $Val,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract class _$$TrainingDtoImplCopyWith<$Res>
|
||||||
|
implements $TrainingDtoCopyWith<$Res> {
|
||||||
|
factory _$$TrainingDtoImplCopyWith(
|
||||||
|
_$TrainingDtoImpl value,
|
||||||
|
$Res Function(_$TrainingDtoImpl) then,
|
||||||
|
) = __$$TrainingDtoImplCopyWithImpl<$Res>;
|
||||||
|
@override
|
||||||
|
@useResult
|
||||||
|
$Res call({Collection? collection, Ticket ticket});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
class __$$TrainingDtoImplCopyWithImpl<$Res>
|
||||||
|
extends _$TrainingDtoCopyWithImpl<$Res, _$TrainingDtoImpl>
|
||||||
|
implements _$$TrainingDtoImplCopyWith<$Res> {
|
||||||
|
__$$TrainingDtoImplCopyWithImpl(
|
||||||
|
_$TrainingDtoImpl _value,
|
||||||
|
$Res Function(_$TrainingDtoImpl) _then,
|
||||||
|
) : super(_value, _then);
|
||||||
|
|
||||||
|
/// Create a copy of TrainingDto
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({Object? collection = freezed, Object? ticket = freezed}) {
|
||||||
|
return _then(
|
||||||
|
_$TrainingDtoImpl(
|
||||||
|
collection:
|
||||||
|
freezed == collection
|
||||||
|
? _value.collection
|
||||||
|
: collection // ignore: cast_nullable_to_non_nullable
|
||||||
|
as Collection?,
|
||||||
|
ticket:
|
||||||
|
freezed == ticket
|
||||||
|
? _value.ticket
|
||||||
|
: ticket // ignore: cast_nullable_to_non_nullable
|
||||||
|
as Ticket,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
|
||||||
|
class _$TrainingDtoImpl implements _TrainingDto {
|
||||||
|
const _$TrainingDtoImpl({this.collection, required this.ticket});
|
||||||
|
|
||||||
|
@override
|
||||||
|
final Collection? collection;
|
||||||
|
@override
|
||||||
|
final Ticket ticket;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'TrainingDto(collection: $collection, ticket: $ticket)';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) ||
|
||||||
|
(other.runtimeType == runtimeType &&
|
||||||
|
other is _$TrainingDtoImpl &&
|
||||||
|
const DeepCollectionEquality().equals(
|
||||||
|
other.collection,
|
||||||
|
collection,
|
||||||
|
) &&
|
||||||
|
const DeepCollectionEquality().equals(other.ticket, ticket));
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(
|
||||||
|
runtimeType,
|
||||||
|
const DeepCollectionEquality().hash(collection),
|
||||||
|
const DeepCollectionEquality().hash(ticket),
|
||||||
|
);
|
||||||
|
|
||||||
|
/// Create a copy of TrainingDto
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$$TrainingDtoImplCopyWith<_$TrainingDtoImpl> get copyWith =>
|
||||||
|
__$$TrainingDtoImplCopyWithImpl<_$TrainingDtoImpl>(this, _$identity);
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class _TrainingDto implements TrainingDto {
|
||||||
|
const factory _TrainingDto({
|
||||||
|
final Collection? collection,
|
||||||
|
required final Ticket ticket,
|
||||||
|
}) = _$TrainingDtoImpl;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Collection? get collection;
|
||||||
|
@override
|
||||||
|
Ticket get ticket;
|
||||||
|
|
||||||
|
/// Create a copy of TrainingDto
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
_$$TrainingDtoImplCopyWith<_$TrainingDtoImpl> get copyWith =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
|
}
|
||||||
@@ -1,11 +1,17 @@
|
|||||||
import 'package:bloc/bloc.dart';
|
import 'package:bloc/bloc.dart';
|
||||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
import 'package:remever/database/database.dart';
|
||||||
|
import 'package:remever/inject.dart';
|
||||||
|
import 'package:remever/models/training_dto.dart';
|
||||||
|
import 'package:remever/services/training/training_interface.dart';
|
||||||
|
|
||||||
part 'training_state.dart';
|
part 'training_state.dart';
|
||||||
part 'training_cubit.freezed.dart';
|
part 'training_cubit.freezed.dart';
|
||||||
|
|
||||||
class TrainingCubit extends Cubit<TrainingState> {
|
class TrainingCubit extends Cubit<TrainingState> {
|
||||||
TrainingCubit() : super(TrainingState.data());
|
TrainingCubit() : super(TrainingState.loading()) {
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> toLoading() async {
|
Future<void> toLoading() async {
|
||||||
emit(TrainingState.loading());
|
emit(TrainingState.loading());
|
||||||
@@ -16,10 +22,34 @@ class TrainingCubit extends Cubit<TrainingState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> toDataState() async {
|
Future<void> toDataState() async {
|
||||||
emit(TrainingState.data());
|
emit(TrainingState.data([]));
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> toResultState() async {
|
Future<void> toResultState() async {
|
||||||
emit(TrainingState.result());
|
emit(TrainingState.result());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> init() async {
|
||||||
|
final List<Ticket> data = await getIt<TrainingInterface>().getTraining();
|
||||||
|
|
||||||
|
if (data.isEmpty) {
|
||||||
|
emit(TrainingState.empty());
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<TrainingDto> dto = [];
|
||||||
|
|
||||||
|
for (final ticket in data) {
|
||||||
|
dto.add(
|
||||||
|
TrainingDto(
|
||||||
|
ticket: ticket,
|
||||||
|
collection: await getIt<AppDatabase>().collectionsDao
|
||||||
|
.getCollectionById(ticket.collectionId),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
emit(TrainingState.data(dto));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,21 +21,21 @@ mixin _$TrainingState {
|
|||||||
TResult when<TResult extends Object?>({
|
TResult when<TResult extends Object?>({
|
||||||
required TResult Function() loading,
|
required TResult Function() loading,
|
||||||
required TResult Function() empty,
|
required TResult Function() empty,
|
||||||
required TResult Function() data,
|
required TResult Function(List<TrainingDto> data) data,
|
||||||
required TResult Function() result,
|
required TResult Function() result,
|
||||||
}) => throw _privateConstructorUsedError;
|
}) => throw _privateConstructorUsedError;
|
||||||
@optionalTypeArgs
|
@optionalTypeArgs
|
||||||
TResult? whenOrNull<TResult extends Object?>({
|
TResult? whenOrNull<TResult extends Object?>({
|
||||||
TResult? Function()? loading,
|
TResult? Function()? loading,
|
||||||
TResult? Function()? empty,
|
TResult? Function()? empty,
|
||||||
TResult? Function()? data,
|
TResult? Function(List<TrainingDto> data)? data,
|
||||||
TResult? Function()? result,
|
TResult? Function()? result,
|
||||||
}) => throw _privateConstructorUsedError;
|
}) => throw _privateConstructorUsedError;
|
||||||
@optionalTypeArgs
|
@optionalTypeArgs
|
||||||
TResult maybeWhen<TResult extends Object?>({
|
TResult maybeWhen<TResult extends Object?>({
|
||||||
TResult Function()? loading,
|
TResult Function()? loading,
|
||||||
TResult Function()? empty,
|
TResult Function()? empty,
|
||||||
TResult Function()? data,
|
TResult Function(List<TrainingDto> data)? data,
|
||||||
TResult Function()? result,
|
TResult Function()? result,
|
||||||
required TResult orElse(),
|
required TResult orElse(),
|
||||||
}) => throw _privateConstructorUsedError;
|
}) => throw _privateConstructorUsedError;
|
||||||
@@ -130,7 +130,7 @@ class _$LoadingImpl implements _Loading {
|
|||||||
TResult when<TResult extends Object?>({
|
TResult when<TResult extends Object?>({
|
||||||
required TResult Function() loading,
|
required TResult Function() loading,
|
||||||
required TResult Function() empty,
|
required TResult Function() empty,
|
||||||
required TResult Function() data,
|
required TResult Function(List<TrainingDto> data) data,
|
||||||
required TResult Function() result,
|
required TResult Function() result,
|
||||||
}) {
|
}) {
|
||||||
return loading();
|
return loading();
|
||||||
@@ -141,7 +141,7 @@ class _$LoadingImpl implements _Loading {
|
|||||||
TResult? whenOrNull<TResult extends Object?>({
|
TResult? whenOrNull<TResult extends Object?>({
|
||||||
TResult? Function()? loading,
|
TResult? Function()? loading,
|
||||||
TResult? Function()? empty,
|
TResult? Function()? empty,
|
||||||
TResult? Function()? data,
|
TResult? Function(List<TrainingDto> data)? data,
|
||||||
TResult? Function()? result,
|
TResult? Function()? result,
|
||||||
}) {
|
}) {
|
||||||
return loading?.call();
|
return loading?.call();
|
||||||
@@ -152,7 +152,7 @@ class _$LoadingImpl implements _Loading {
|
|||||||
TResult maybeWhen<TResult extends Object?>({
|
TResult maybeWhen<TResult extends Object?>({
|
||||||
TResult Function()? loading,
|
TResult Function()? loading,
|
||||||
TResult Function()? empty,
|
TResult Function()? empty,
|
||||||
TResult Function()? data,
|
TResult Function(List<TrainingDto> data)? data,
|
||||||
TResult Function()? result,
|
TResult Function()? result,
|
||||||
required TResult orElse(),
|
required TResult orElse(),
|
||||||
}) {
|
}) {
|
||||||
@@ -249,7 +249,7 @@ class _$EmptyImpl implements _Empty {
|
|||||||
TResult when<TResult extends Object?>({
|
TResult when<TResult extends Object?>({
|
||||||
required TResult Function() loading,
|
required TResult Function() loading,
|
||||||
required TResult Function() empty,
|
required TResult Function() empty,
|
||||||
required TResult Function() data,
|
required TResult Function(List<TrainingDto> data) data,
|
||||||
required TResult Function() result,
|
required TResult Function() result,
|
||||||
}) {
|
}) {
|
||||||
return empty();
|
return empty();
|
||||||
@@ -260,7 +260,7 @@ class _$EmptyImpl implements _Empty {
|
|||||||
TResult? whenOrNull<TResult extends Object?>({
|
TResult? whenOrNull<TResult extends Object?>({
|
||||||
TResult? Function()? loading,
|
TResult? Function()? loading,
|
||||||
TResult? Function()? empty,
|
TResult? Function()? empty,
|
||||||
TResult? Function()? data,
|
TResult? Function(List<TrainingDto> data)? data,
|
||||||
TResult? Function()? result,
|
TResult? Function()? result,
|
||||||
}) {
|
}) {
|
||||||
return empty?.call();
|
return empty?.call();
|
||||||
@@ -271,7 +271,7 @@ class _$EmptyImpl implements _Empty {
|
|||||||
TResult maybeWhen<TResult extends Object?>({
|
TResult maybeWhen<TResult extends Object?>({
|
||||||
TResult Function()? loading,
|
TResult Function()? loading,
|
||||||
TResult Function()? empty,
|
TResult Function()? empty,
|
||||||
TResult Function()? data,
|
TResult Function(List<TrainingDto> data)? data,
|
||||||
TResult Function()? result,
|
TResult Function()? result,
|
||||||
required TResult orElse(),
|
required TResult orElse(),
|
||||||
}) {
|
}) {
|
||||||
@@ -329,6 +329,8 @@ abstract class _$$DataImplCopyWith<$Res> {
|
|||||||
_$DataImpl value,
|
_$DataImpl value,
|
||||||
$Res Function(_$DataImpl) then,
|
$Res Function(_$DataImpl) then,
|
||||||
) = __$$DataImplCopyWithImpl<$Res>;
|
) = __$$DataImplCopyWithImpl<$Res>;
|
||||||
|
@useResult
|
||||||
|
$Res call({List<TrainingDto> data});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@@ -340,36 +342,67 @@ class __$$DataImplCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of TrainingState
|
/// Create a copy of TrainingState
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
@override
|
||||||
|
$Res call({Object? data = null}) {
|
||||||
|
return _then(
|
||||||
|
_$DataImpl(
|
||||||
|
null == data
|
||||||
|
? _value._data
|
||||||
|
: data // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<TrainingDto>,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
|
|
||||||
class _$DataImpl implements _Data {
|
class _$DataImpl implements _Data {
|
||||||
const _$DataImpl();
|
const _$DataImpl(final List<TrainingDto> data) : _data = data;
|
||||||
|
|
||||||
|
final List<TrainingDto> _data;
|
||||||
|
@override
|
||||||
|
List<TrainingDto> get data {
|
||||||
|
if (_data is EqualUnmodifiableListView) return _data;
|
||||||
|
// ignore: implicit_dynamic_type
|
||||||
|
return EqualUnmodifiableListView(_data);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'TrainingState.data()';
|
return 'TrainingState.data(data: $data)';
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) ||
|
return identical(this, other) ||
|
||||||
(other.runtimeType == runtimeType && other is _$DataImpl);
|
(other.runtimeType == runtimeType &&
|
||||||
|
other is _$DataImpl &&
|
||||||
|
const DeepCollectionEquality().equals(other._data, _data));
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int get hashCode => runtimeType.hashCode;
|
int get hashCode =>
|
||||||
|
Object.hash(runtimeType, const DeepCollectionEquality().hash(_data));
|
||||||
|
|
||||||
|
/// Create a copy of TrainingState
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$$DataImplCopyWith<_$DataImpl> get copyWith =>
|
||||||
|
__$$DataImplCopyWithImpl<_$DataImpl>(this, _$identity);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@optionalTypeArgs
|
@optionalTypeArgs
|
||||||
TResult when<TResult extends Object?>({
|
TResult when<TResult extends Object?>({
|
||||||
required TResult Function() loading,
|
required TResult Function() loading,
|
||||||
required TResult Function() empty,
|
required TResult Function() empty,
|
||||||
required TResult Function() data,
|
required TResult Function(List<TrainingDto> data) data,
|
||||||
required TResult Function() result,
|
required TResult Function() result,
|
||||||
}) {
|
}) {
|
||||||
return data();
|
return data(this.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -377,10 +410,10 @@ class _$DataImpl implements _Data {
|
|||||||
TResult? whenOrNull<TResult extends Object?>({
|
TResult? whenOrNull<TResult extends Object?>({
|
||||||
TResult? Function()? loading,
|
TResult? Function()? loading,
|
||||||
TResult? Function()? empty,
|
TResult? Function()? empty,
|
||||||
TResult? Function()? data,
|
TResult? Function(List<TrainingDto> data)? data,
|
||||||
TResult? Function()? result,
|
TResult? Function()? result,
|
||||||
}) {
|
}) {
|
||||||
return data?.call();
|
return data?.call(this.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -388,12 +421,12 @@ class _$DataImpl implements _Data {
|
|||||||
TResult maybeWhen<TResult extends Object?>({
|
TResult maybeWhen<TResult extends Object?>({
|
||||||
TResult Function()? loading,
|
TResult Function()? loading,
|
||||||
TResult Function()? empty,
|
TResult Function()? empty,
|
||||||
TResult Function()? data,
|
TResult Function(List<TrainingDto> data)? data,
|
||||||
TResult Function()? result,
|
TResult Function()? result,
|
||||||
required TResult orElse(),
|
required TResult orElse(),
|
||||||
}) {
|
}) {
|
||||||
if (data != null) {
|
if (data != null) {
|
||||||
return data();
|
return data(this.data);
|
||||||
}
|
}
|
||||||
return orElse();
|
return orElse();
|
||||||
}
|
}
|
||||||
@@ -437,7 +470,15 @@ class _$DataImpl implements _Data {
|
|||||||
}
|
}
|
||||||
|
|
||||||
abstract class _Data implements TrainingState {
|
abstract class _Data implements TrainingState {
|
||||||
const factory _Data() = _$DataImpl;
|
const factory _Data(final List<TrainingDto> data) = _$DataImpl;
|
||||||
|
|
||||||
|
List<TrainingDto> get data;
|
||||||
|
|
||||||
|
/// Create a copy of TrainingState
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
_$$DataImplCopyWith<_$DataImpl> get copyWith =>
|
||||||
|
throw _privateConstructorUsedError;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@@ -485,7 +526,7 @@ class _$ResultImpl implements _Result {
|
|||||||
TResult when<TResult extends Object?>({
|
TResult when<TResult extends Object?>({
|
||||||
required TResult Function() loading,
|
required TResult Function() loading,
|
||||||
required TResult Function() empty,
|
required TResult Function() empty,
|
||||||
required TResult Function() data,
|
required TResult Function(List<TrainingDto> data) data,
|
||||||
required TResult Function() result,
|
required TResult Function() result,
|
||||||
}) {
|
}) {
|
||||||
return result();
|
return result();
|
||||||
@@ -496,7 +537,7 @@ class _$ResultImpl implements _Result {
|
|||||||
TResult? whenOrNull<TResult extends Object?>({
|
TResult? whenOrNull<TResult extends Object?>({
|
||||||
TResult? Function()? loading,
|
TResult? Function()? loading,
|
||||||
TResult? Function()? empty,
|
TResult? Function()? empty,
|
||||||
TResult? Function()? data,
|
TResult? Function(List<TrainingDto> data)? data,
|
||||||
TResult? Function()? result,
|
TResult? Function()? result,
|
||||||
}) {
|
}) {
|
||||||
return result?.call();
|
return result?.call();
|
||||||
@@ -507,7 +548,7 @@ class _$ResultImpl implements _Result {
|
|||||||
TResult maybeWhen<TResult extends Object?>({
|
TResult maybeWhen<TResult extends Object?>({
|
||||||
TResult Function()? loading,
|
TResult Function()? loading,
|
||||||
TResult Function()? empty,
|
TResult Function()? empty,
|
||||||
TResult Function()? data,
|
TResult Function(List<TrainingDto> data)? data,
|
||||||
TResult Function()? result,
|
TResult Function()? result,
|
||||||
required TResult orElse(),
|
required TResult orElse(),
|
||||||
}) {
|
}) {
|
||||||
|
|||||||
@@ -4,6 +4,6 @@ part of 'training_cubit.dart';
|
|||||||
class TrainingState with _$TrainingState {
|
class TrainingState with _$TrainingState {
|
||||||
const factory TrainingState.loading() = _Loading;
|
const factory TrainingState.loading() = _Loading;
|
||||||
const factory TrainingState.empty() = _Empty;
|
const factory TrainingState.empty() = _Empty;
|
||||||
const factory TrainingState.data() = _Data;
|
const factory TrainingState.data(List<TrainingDto> data) = _Data;
|
||||||
const factory TrainingState.result() = _Result;
|
const factory TrainingState.result() = _Result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,13 @@
|
|||||||
import 'package:auto_route/auto_route.dart';
|
import 'package:auto_route/auto_route.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:remever/common/resources.dart';
|
import 'package:remever/common/resources.dart';
|
||||||
import 'package:remever/common/typography.dart';
|
|
||||||
import 'package:remever/common/widgets/typography.dart';
|
import 'package:remever/common/widgets/typography.dart';
|
||||||
import 'package:remever/common/widgets/w_if.dart';
|
import 'package:remever/common/widgets/w_if.dart';
|
||||||
import 'package:remever/common/widgets/wspace.dart';
|
import 'package:remever/common/widgets/wspace.dart';
|
||||||
import 'package:remever/components/extensions/context.dart';
|
import 'package:remever/components/extensions/context.dart';
|
||||||
import 'package:remever/components/extensions/state.dart';
|
import 'package:remever/components/extensions/state.dart';
|
||||||
import 'package:remever/gen/assets.gen.dart';
|
import 'package:remever/models/training_dto.dart';
|
||||||
import 'package:remever/router.gr.dart';
|
|
||||||
import 'package:remever/screens/training/cubit/training_cubit.dart';
|
import 'package:remever/screens/training/cubit/training_cubit.dart';
|
||||||
import 'package:remever/screens/training/states/empty.dart';
|
import 'package:remever/screens/training/states/empty.dart';
|
||||||
import 'package:remever/screens/training/states/loading.dart';
|
import 'package:remever/screens/training/states/loading.dart';
|
||||||
@@ -40,7 +37,7 @@ class TrainingScreen extends StatelessWidget {
|
|||||||
return state.when(
|
return state.when(
|
||||||
loading: () => TrainingLoading(),
|
loading: () => TrainingLoading(),
|
||||||
empty: () => TrainingEmpty(),
|
empty: () => TrainingEmpty(),
|
||||||
data: () => TrainingData(),
|
data: (data) => TrainingData(data: data),
|
||||||
result: () => Placeholder(),
|
result: () => Placeholder(),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@@ -50,8 +47,9 @@ class TrainingScreen extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class TrainingData extends StatefulWidget {
|
class TrainingData extends StatefulWidget {
|
||||||
const TrainingData({super.key});
|
const TrainingData({super.key, required this.data});
|
||||||
|
|
||||||
|
final List<TrainingDto> data;
|
||||||
@override
|
@override
|
||||||
State<TrainingData> createState() => _TrainingDataState();
|
State<TrainingData> createState() => _TrainingDataState();
|
||||||
}
|
}
|
||||||
@@ -59,6 +57,8 @@ class TrainingData extends StatefulWidget {
|
|||||||
class _TrainingDataState extends State<TrainingData> {
|
class _TrainingDataState extends State<TrainingData> {
|
||||||
bool _showAnswer = false;
|
bool _showAnswer = false;
|
||||||
|
|
||||||
|
int _currentTicketIndex = 0;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
@@ -97,7 +97,12 @@ class _TrainingDataState extends State<TrainingData> {
|
|||||||
),
|
),
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(3).r,
|
padding: const EdgeInsets.all(3).r,
|
||||||
child: Center(child: AppTypography('1 из 9', type: Regular14px())),
|
child: Center(
|
||||||
|
child: AppTypography(
|
||||||
|
'${_currentTicketIndex + 1} из ${widget.data.length}',
|
||||||
|
type: Regular14px(),
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -117,7 +122,13 @@ class _TrainingDataState extends State<TrainingData> {
|
|||||||
children: [
|
children: [
|
||||||
Flexible(
|
Flexible(
|
||||||
child: PrimaryButton(
|
child: PrimaryButton(
|
||||||
onTap: () {},
|
onTap: () {
|
||||||
|
if (widget.data.length == _currentTicketIndex + 1) {
|
||||||
|
context.read<TrainingCubit>().toResultState();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
safeSetState(() => _currentTicketIndex++);
|
||||||
|
},
|
||||||
color: AppColors.danger,
|
color: AppColors.danger,
|
||||||
child: AppTypography(
|
child: AppTypography(
|
||||||
'Не помню',
|
'Не помню',
|
||||||
@@ -133,7 +144,13 @@ class _TrainingDataState extends State<TrainingData> {
|
|||||||
type: Medium14px(),
|
type: Medium14px(),
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
),
|
),
|
||||||
onTap: () {},
|
onTap: () {
|
||||||
|
if (widget.data.length == _currentTicketIndex + 1) {
|
||||||
|
context.read<TrainingCubit>().toResultState();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
safeSetState(() => _currentTicketIndex++);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -171,10 +188,14 @@ class _TrainingDataState extends State<TrainingData> {
|
|||||||
child: Column(
|
child: Column(
|
||||||
spacing: 8.r,
|
spacing: 8.r,
|
||||||
children: [
|
children: [
|
||||||
TrainingTicket(),
|
TrainingTicket(trainingDto: widget.data[_currentTicketIndex]),
|
||||||
Wif(
|
Wif(
|
||||||
condition: _showAnswer,
|
condition: _showAnswer,
|
||||||
builder: (context) => TrainingTicket(isAnswer: true),
|
builder:
|
||||||
|
(context) => TrainingTicket(
|
||||||
|
trainingDto: widget.data[_currentTicketIndex],
|
||||||
|
isAnswer: true,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -1,13 +1,22 @@
|
|||||||
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:remever/common/resources.dart';
|
import 'package:remever/common/resources.dart';
|
||||||
import 'package:remever/common/widgets/typography.dart';
|
import 'package:remever/common/widgets/typography.dart';
|
||||||
import 'package:remever/common/widgets/w_if.dart';
|
import 'package:remever/common/widgets/w_if.dart';
|
||||||
import 'package:remever/common/widgets/wspace.dart';
|
import 'package:remever/common/widgets/wspace.dart';
|
||||||
import 'package:remever/components/extensions/context.dart';
|
import 'package:remever/components/extensions/context.dart';
|
||||||
|
import 'package:remever/database/database.dart';
|
||||||
|
import 'package:remever/models/training_dto.dart';
|
||||||
|
|
||||||
class TrainingTicket extends StatelessWidget {
|
class TrainingTicket extends StatelessWidget {
|
||||||
const TrainingTicket({super.key, this.isAnswer = false});
|
const TrainingTicket({
|
||||||
|
super.key,
|
||||||
|
this.isAnswer = false,
|
||||||
|
required this.trainingDto,
|
||||||
|
});
|
||||||
|
|
||||||
|
final TrainingDto trainingDto;
|
||||||
final bool isAnswer;
|
final bool isAnswer;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -43,8 +52,10 @@ class TrainingTicket extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildCollectionInfo() {
|
Widget _buildCollectionInfo() {
|
||||||
|
final collection = trainingDto.collection;
|
||||||
|
|
||||||
return Wif(
|
return Wif(
|
||||||
condition: !isAnswer,
|
condition: !isAnswer && collection != null,
|
||||||
builder: (context) {
|
builder: (context) {
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.only(bottom: 8).r,
|
padding: const EdgeInsets.only(bottom: 8).r,
|
||||||
@@ -53,16 +64,28 @@ class TrainingTicket extends StatelessWidget {
|
|||||||
SizedBox(
|
SizedBox(
|
||||||
height: 24.h,
|
height: 24.h,
|
||||||
width: 24.w,
|
width: 24.w,
|
||||||
child: ClipOval(
|
child: Wif(
|
||||||
child: Image.network(
|
condition: collection!.image != null,
|
||||||
'https://avatars.mds.yandex.net/i?id=56429b65e9098a58fcd538387d43bcbb_l-5384017-images-thumbs&n=13',
|
builder:
|
||||||
fit: BoxFit.cover,
|
(context) => ClipOval(
|
||||||
),
|
child: Image.file(
|
||||||
|
File(collection.image!),
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
fallback:
|
||||||
|
(context) => Center(
|
||||||
|
child: AppTypography(
|
||||||
|
collection.title.substring(0, 1),
|
||||||
|
type: Bold34px(),
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
WSpace(4),
|
WSpace(4),
|
||||||
AppTypography(
|
AppTypography(
|
||||||
'Астрология и астрофизика',
|
collection.title,
|
||||||
type: Regular14px(),
|
type: Regular14px(),
|
||||||
color: AppColors.disabled,
|
color: AppColors.disabled,
|
||||||
),
|
),
|
||||||
@@ -70,6 +93,7 @@ class TrainingTicket extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
fallback: (context) => Row(children: []),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,20 +114,21 @@ class TrainingTicket extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildText(BuildContext context) {
|
Widget _buildText(BuildContext context) {
|
||||||
|
final ticket = trainingDto.ticket;
|
||||||
return AppTypography(
|
return AppTypography(
|
||||||
'Родился 19 февраля 1473 года в Торуне в семье купца. После смерти отца воспитывался у дяди, епископа Вармийской епархии. Коперник изложил свои идеи в сочинении «Commentariolus» («Малый комментарий»), в котором сформулировал основные положения гелиоцентрической системы мира в виде 6 аксиом. Их смысл состоит в том, что Земля, как и другие планеты,'
|
isAnswer ? ticket.answer : ticket.question,
|
||||||
'Родился 19 февраля 1473 года в Торуне в семье купца. После смерти отца воспитывался у дяди, епископа Вармийской епархии. Коперник изложил свои идеи в сочинении «Commentariolus» («Малый комментарий»), в котором сформулировал основные положения гелиоцентрической системы мира в виде 6 аксиом. Их смысл состоит в том, что Земля, как и другие планеты,',
|
|
||||||
maxLines: 99,
|
maxLines: 99,
|
||||||
type: Regular14px(),
|
type: Regular14px(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildImage() {
|
Widget _buildImage() {
|
||||||
// final imageBytes =
|
final ticket = trainingDto.ticket;
|
||||||
// isAnswer ? ticket.answerImage : ticket.questionImage;
|
final String? imagePath =
|
||||||
|
isAnswer ? ticket.answerImage : ticket.questionImage;
|
||||||
|
|
||||||
return Wif(
|
return Wif(
|
||||||
condition: true, // imageBytes != null,
|
condition: imagePath != null,
|
||||||
builder:
|
builder:
|
||||||
(context) => Padding(
|
(context) => Padding(
|
||||||
padding: const EdgeInsets.only(right: 8).r,
|
padding: const EdgeInsets.only(right: 8).r,
|
||||||
@@ -111,11 +136,7 @@ class TrainingTicket extends StatelessWidget {
|
|||||||
dimension: 100.r,
|
dimension: 100.r,
|
||||||
child: ClipRRect(
|
child: ClipRRect(
|
||||||
borderRadius: BorderRadius.circular(8).r,
|
borderRadius: BorderRadius.circular(8).r,
|
||||||
// child: Image.memory(imageBytes!, fit: BoxFit.cover),
|
child: Image.file(File(imagePath!), fit: BoxFit.cover),
|
||||||
child: Image.network(
|
|
||||||
'https://avatars.mds.yandex.net/i?id=56429b65e9098a58fcd538387d43bcbb_l-5384017-images-thumbs&n=13',
|
|
||||||
fit: BoxFit.cover,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
10
lib/services/training/training_interface.dart
Normal file
10
lib/services/training/training_interface.dart
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import 'package:remever/database/database.dart';
|
||||||
|
import 'package:remever/models/crud_collection_dto.dart';
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Интерфейс взаимодействия с тренировкой
|
||||||
|
///
|
||||||
|
abstract interface class TrainingInterface {
|
||||||
|
/// Получение списка тикетов для тренировки
|
||||||
|
Future<List<Ticket>> getTraining();
|
||||||
|
}
|
||||||
49
lib/services/training/training_service.dart
Normal file
49
lib/services/training/training_service.dart
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
import 'dart:math';
|
||||||
|
|
||||||
|
import 'package:injectable/injectable.dart';
|
||||||
|
import 'package:remever/database/database.dart';
|
||||||
|
import 'package:remever/inject.dart';
|
||||||
|
import 'package:remever/services/training/training_interface.dart';
|
||||||
|
|
||||||
|
@Singleton(as: TrainingInterface)
|
||||||
|
final class TrainingService implements TrainingInterface {
|
||||||
|
// @override
|
||||||
|
// Future<void> removeTicket(String ticketId) async {
|
||||||
|
// return await getIt<AppDatabase>().ticketsDao.removeTicket(ticketId);
|
||||||
|
// }
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<List<Ticket>> getTraining() async {
|
||||||
|
try {
|
||||||
|
final db = getIt<AppDatabase>();
|
||||||
|
|
||||||
|
final rows =
|
||||||
|
await db
|
||||||
|
.customSelect('SELECT * FROM tickets ORDER BY RANDOM() LIMIT 10')
|
||||||
|
.get();
|
||||||
|
|
||||||
|
return rows.map((row) {
|
||||||
|
final data = row.data;
|
||||||
|
print("ALARMA $data");
|
||||||
|
|
||||||
|
// Преобразуем snake_case ключи в camelCase для Moor сериализатора
|
||||||
|
final camelCaseData = {
|
||||||
|
'id': data['id'],
|
||||||
|
'createdAt': data['created_at'],
|
||||||
|
'updatedAt': data['updated_at'],
|
||||||
|
'question': data['question'],
|
||||||
|
'questionImage': data['question_image'],
|
||||||
|
'answer': data['answer'],
|
||||||
|
'answerImage': data['answer_image'],
|
||||||
|
'collectionId': data['collection_id'],
|
||||||
|
'progress': data['progress'],
|
||||||
|
};
|
||||||
|
|
||||||
|
return Ticket.fromJson(camelCaseData);
|
||||||
|
}).toList();
|
||||||
|
} catch (e) {
|
||||||
|
print('Error in training $e');
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user