Создание карточки в коллекции + экран поиска коллекции

This commit is contained in:
2025-04-02 21:40:31 +03:00
parent fb7ff84087
commit 17dff72655
36 changed files with 2495 additions and 277 deletions

View File

@@ -43,6 +43,14 @@ InterceptorsWrapper get _error {
// String? token = await getIt<AuthService>().refresh();
}
if (error.response != null) {
try {
showErrorToast(error.response?.data['message']);
} catch (_) {
showErrorToast(error.response?.data);
}
}
handler.next(error);
},
);

View File

@@ -3,7 +3,7 @@ import 'package:drift/drift.dart';
import 'package:remever/common/functions.dart';
import 'package:remever/database/database.dart';
import 'package:remever/database/tables.dart';
import 'package:remever/models/collection_dto.dart';
import 'package:remever/models/crud_collection_dto.dart';
part 'collections_dao.g.dart';
@@ -16,9 +16,11 @@ class CollectionsDao extends DatabaseAccessor<AppDatabase>
CollectionsDao(super.attachedDatabase);
/// Получение коллекций из базы данных
Stream<List<Collection>> getCollections() {
Stream<List<Collection>> getCollections(String? search) {
try {
return db.managers.collections.watch();
return db.managers.collections
.filter((f) => f.title.contains(search ?? ''))
.watch();
} catch (e, st) {
logger.logError('Ошибка в методе getCollections', e, st);
@@ -27,7 +29,7 @@ class CollectionsDao extends DatabaseAccessor<AppDatabase>
}
/// Создание коллекции
Future<void> createCollection(CollectionDto dto) async {
Future<void> createCollection(CrudCollectionDto dto) async {
try {
await db.managers.collections.create(
(o) => o(
@@ -43,7 +45,7 @@ class CollectionsDao extends DatabaseAccessor<AppDatabase>
}
/// Обновление коллекции
Future<void> updateCollection(CollectionDto dto, String id) async {
Future<void> updateCollection(CrudCollectionDto dto, String id) async {
try {
await db.managers.collections
.filter((f) => f.id(id))

View File

@@ -0,0 +1,70 @@
// Package imports:
import 'package:drift/drift.dart';
import 'package:remever/common/functions.dart';
import 'package:remever/database/database.dart';
import 'package:remever/database/tables.dart';
import 'package:remever/models/create_ticket_dto.dart';
import 'package:remever/models/crud_collection_dto.dart';
part 'tickets_dao.g.dart';
@DriftAccessor(tables: <Type>[Tickets])
class TicketsDao extends DatabaseAccessor<AppDatabase> with _$TicketsDaoMixin {
///
/// Репозиторий для работы с билетами
///
TicketsDao(super.attachedDatabase);
/// Получение билетов из базы данных
Stream<List<Ticket>> getTickets(String collectionId) {
try {
return db.managers.tickets
.filter((f) => f.collectionId.id(collectionId))
.watch();
} catch (e, st) {
logger.logError('Ошибка в методе getTickets', e, st);
throw ('EXEPTION');
}
}
/// Удаление билета
Future<void> deleteTicket(String id) async {
try {
await db.managers.tickets.filter((f) => f.id(id)).delete();
} catch (e, st) {
logger.logError('Ошибка в методе deleteTicket', e, st);
}
}
/// Создание билета
Future<void> createTicket(CreateTicketDto dto) async {
try {
final TicketsCompanion companion = TicketsCompanion.insert(
question: dto.question!,
answer: dto.answer!,
collectionId: dto.collection!.id,
questionImage: Value<Uint8List?>(dto.questionImage),
answerImage: Value<Uint8List?>(dto.answerImage),
);
await db.managers.tickets.create((o) => companion);
if (dto.needRevert != null && dto.needRevert!) {
/// Создаем обратную карточку где ответ == вопрос и вопрос == ответ
final TicketsCompanion revertCompanion = TicketsCompanion.insert(
answer: dto.question!,
question: dto.answer!,
collectionId: dto.collection!.id,
answerImage: Value<Uint8List?>(dto.questionImage),
questionImage: Value<Uint8List?>(dto.answerImage),
);
await db.managers.tickets.create((o) => revertCompanion);
}
} catch (e, st) {
logger.logError('Ошибка в методе createTicket', e, st);
}
}
}

View File

@@ -0,0 +1,9 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'tickets_dao.dart';
// ignore_for_file: type=lint
mixin _$TicketsDaoMixin on DatabaseAccessor<AppDatabase> {
$CollectionsTable get collections => attachedDatabase.collections;
$TicketsTable get tickets => attachedDatabase.tickets;
}

View File

@@ -2,6 +2,7 @@ import 'package:drift/drift.dart';
import 'package:flutter/foundation.dart';
import 'package:injectable/injectable.dart';
import 'package:remever/database/dao/collections_dao.dart';
import 'package:remever/database/dao/tickets_dao.dart';
import 'package:remever/database/tables.dart';
import 'connection/connection.dart' as impl;
import 'package:uuid/uuid.dart';
@@ -10,8 +11,8 @@ part 'database.g.dart';
@DriftDatabase(
include: <String>{'sql.drift'},
daos: <Type>[CollectionsDao],
tables: <Type>[Collections],
daos: <Type>[CollectionsDao, TicketsDao],
tables: <Type>[Collections, Tickets],
)
@Singleton()
final class AppDatabase extends _$AppDatabase {

View File

@@ -745,6 +745,18 @@ class $TicketsTable extends Tickets with TableInfo<$TicketsTable, Ticket> {
type: DriftSqlType.string,
requiredDuringInsert: true,
);
static const VerificationMeta _questionImageMeta = const VerificationMeta(
'questionImage',
);
@override
late final GeneratedColumn<Uint8List> questionImage =
GeneratedColumn<Uint8List>(
'question_image',
aliasedName,
true,
type: DriftSqlType.blob,
requiredDuringInsert: false,
);
static const VerificationMeta _answerMeta = const VerificationMeta('answer');
@override
late final GeneratedColumn<String> answer = GeneratedColumn<String>(
@@ -754,15 +766,18 @@ class $TicketsTable extends Tickets with TableInfo<$TicketsTable, Ticket> {
type: DriftSqlType.string,
requiredDuringInsert: true,
);
static const VerificationMeta _imageMeta = const VerificationMeta('image');
@override
late final GeneratedColumn<Uint8List> image = GeneratedColumn<Uint8List>(
'image',
aliasedName,
true,
type: DriftSqlType.blob,
requiredDuringInsert: false,
static const VerificationMeta _answerImageMeta = const VerificationMeta(
'answerImage',
);
@override
late final GeneratedColumn<Uint8List> answerImage =
GeneratedColumn<Uint8List>(
'answer_image',
aliasedName,
true,
type: DriftSqlType.blob,
requiredDuringInsert: false,
);
static const VerificationMeta _collectionIdMeta = const VerificationMeta(
'collectionId',
);
@@ -795,8 +810,9 @@ class $TicketsTable extends Tickets with TableInfo<$TicketsTable, Ticket> {
createdAt,
updatedAt,
question,
questionImage,
answer,
image,
answerImage,
collectionId,
progress,
];
@@ -835,6 +851,15 @@ class $TicketsTable extends Tickets with TableInfo<$TicketsTable, Ticket> {
} else if (isInserting) {
context.missing(_questionMeta);
}
if (data.containsKey('question_image')) {
context.handle(
_questionImageMeta,
questionImage.isAcceptableOrUnknown(
data['question_image']!,
_questionImageMeta,
),
);
}
if (data.containsKey('answer')) {
context.handle(
_answerMeta,
@@ -843,10 +868,13 @@ class $TicketsTable extends Tickets with TableInfo<$TicketsTable, Ticket> {
} else if (isInserting) {
context.missing(_answerMeta);
}
if (data.containsKey('image')) {
if (data.containsKey('answer_image')) {
context.handle(
_imageMeta,
image.isAcceptableOrUnknown(data['image']!, _imageMeta),
_answerImageMeta,
answerImage.isAcceptableOrUnknown(
data['answer_image']!,
_answerImageMeta,
),
);
}
if (data.containsKey('collection_id')) {
@@ -895,14 +923,18 @@ class $TicketsTable extends Tickets with TableInfo<$TicketsTable, Ticket> {
DriftSqlType.string,
data['${effectivePrefix}question'],
)!,
questionImage: attachedDatabase.typeMapping.read(
DriftSqlType.blob,
data['${effectivePrefix}question_image'],
),
answer:
attachedDatabase.typeMapping.read(
DriftSqlType.string,
data['${effectivePrefix}answer'],
)!,
image: attachedDatabase.typeMapping.read(
answerImage: attachedDatabase.typeMapping.read(
DriftSqlType.blob,
data['${effectivePrefix}image'],
data['${effectivePrefix}answer_image'],
),
collectionId:
attachedDatabase.typeMapping.read(
@@ -933,8 +965,9 @@ class Ticket extends DataClass implements Insertable<Ticket> {
/// Дата последней модификации
final DateTime updatedAt;
final String question;
final Uint8List? questionImage;
final String answer;
final Uint8List? image;
final Uint8List? answerImage;
final String collectionId;
final double progress;
const Ticket({
@@ -942,8 +975,9 @@ class Ticket extends DataClass implements Insertable<Ticket> {
required this.createdAt,
required this.updatedAt,
required this.question,
this.questionImage,
required this.answer,
this.image,
this.answerImage,
required this.collectionId,
required this.progress,
});
@@ -954,9 +988,12 @@ class Ticket extends DataClass implements Insertable<Ticket> {
map['created_at'] = Variable<DateTime>(createdAt);
map['updated_at'] = Variable<DateTime>(updatedAt);
map['question'] = Variable<String>(question);
if (!nullToAbsent || questionImage != null) {
map['question_image'] = Variable<Uint8List>(questionImage);
}
map['answer'] = Variable<String>(answer);
if (!nullToAbsent || image != null) {
map['image'] = Variable<Uint8List>(image);
if (!nullToAbsent || answerImage != null) {
map['answer_image'] = Variable<Uint8List>(answerImage);
}
map['collection_id'] = Variable<String>(collectionId);
map['progress'] = Variable<double>(progress);
@@ -969,9 +1006,15 @@ class Ticket extends DataClass implements Insertable<Ticket> {
createdAt: Value(createdAt),
updatedAt: Value(updatedAt),
question: Value(question),
questionImage:
questionImage == null && nullToAbsent
? const Value.absent()
: Value(questionImage),
answer: Value(answer),
image:
image == null && nullToAbsent ? const Value.absent() : Value(image),
answerImage:
answerImage == null && nullToAbsent
? const Value.absent()
: Value(answerImage),
collectionId: Value(collectionId),
progress: Value(progress),
);
@@ -987,8 +1030,9 @@ class Ticket extends DataClass implements Insertable<Ticket> {
createdAt: serializer.fromJson<DateTime>(json['createdAt']),
updatedAt: serializer.fromJson<DateTime>(json['updatedAt']),
question: serializer.fromJson<String>(json['question']),
questionImage: serializer.fromJson<Uint8List?>(json['questionImage']),
answer: serializer.fromJson<String>(json['answer']),
image: serializer.fromJson<Uint8List?>(json['image']),
answerImage: serializer.fromJson<Uint8List?>(json['answerImage']),
collectionId: serializer.fromJson<String>(json['collectionId']),
progress: serializer.fromJson<double>(json['progress']),
);
@@ -1001,8 +1045,9 @@ class Ticket extends DataClass implements Insertable<Ticket> {
'createdAt': serializer.toJson<DateTime>(createdAt),
'updatedAt': serializer.toJson<DateTime>(updatedAt),
'question': serializer.toJson<String>(question),
'questionImage': serializer.toJson<Uint8List?>(questionImage),
'answer': serializer.toJson<String>(answer),
'image': serializer.toJson<Uint8List?>(image),
'answerImage': serializer.toJson<Uint8List?>(answerImage),
'collectionId': serializer.toJson<String>(collectionId),
'progress': serializer.toJson<double>(progress),
};
@@ -1013,8 +1058,9 @@ class Ticket extends DataClass implements Insertable<Ticket> {
DateTime? createdAt,
DateTime? updatedAt,
String? question,
Value<Uint8List?> questionImage = const Value.absent(),
String? answer,
Value<Uint8List?> image = const Value.absent(),
Value<Uint8List?> answerImage = const Value.absent(),
String? collectionId,
double? progress,
}) => Ticket(
@@ -1022,8 +1068,10 @@ class Ticket extends DataClass implements Insertable<Ticket> {
createdAt: createdAt ?? this.createdAt,
updatedAt: updatedAt ?? this.updatedAt,
question: question ?? this.question,
questionImage:
questionImage.present ? questionImage.value : this.questionImage,
answer: answer ?? this.answer,
image: image.present ? image.value : this.image,
answerImage: answerImage.present ? answerImage.value : this.answerImage,
collectionId: collectionId ?? this.collectionId,
progress: progress ?? this.progress,
);
@@ -1033,8 +1081,13 @@ class Ticket extends DataClass implements Insertable<Ticket> {
createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt,
updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt,
question: data.question.present ? data.question.value : this.question,
questionImage:
data.questionImage.present
? data.questionImage.value
: this.questionImage,
answer: data.answer.present ? data.answer.value : this.answer,
image: data.image.present ? data.image.value : this.image,
answerImage:
data.answerImage.present ? data.answerImage.value : this.answerImage,
collectionId:
data.collectionId.present
? data.collectionId.value
@@ -1050,8 +1103,9 @@ class Ticket extends DataClass implements Insertable<Ticket> {
..write('createdAt: $createdAt, ')
..write('updatedAt: $updatedAt, ')
..write('question: $question, ')
..write('questionImage: $questionImage, ')
..write('answer: $answer, ')
..write('image: $image, ')
..write('answerImage: $answerImage, ')
..write('collectionId: $collectionId, ')
..write('progress: $progress')
..write(')'))
@@ -1064,8 +1118,9 @@ class Ticket extends DataClass implements Insertable<Ticket> {
createdAt,
updatedAt,
question,
$driftBlobEquality.hash(questionImage),
answer,
$driftBlobEquality.hash(image),
$driftBlobEquality.hash(answerImage),
collectionId,
progress,
);
@@ -1077,8 +1132,9 @@ class Ticket extends DataClass implements Insertable<Ticket> {
other.createdAt == this.createdAt &&
other.updatedAt == this.updatedAt &&
other.question == this.question &&
$driftBlobEquality.equals(other.questionImage, this.questionImage) &&
other.answer == this.answer &&
$driftBlobEquality.equals(other.image, this.image) &&
$driftBlobEquality.equals(other.answerImage, this.answerImage) &&
other.collectionId == this.collectionId &&
other.progress == this.progress);
}
@@ -1088,8 +1144,9 @@ class TicketsCompanion extends UpdateCompanion<Ticket> {
final Value<DateTime> createdAt;
final Value<DateTime> updatedAt;
final Value<String> question;
final Value<Uint8List?> questionImage;
final Value<String> answer;
final Value<Uint8List?> image;
final Value<Uint8List?> answerImage;
final Value<String> collectionId;
final Value<double> progress;
final Value<int> rowid;
@@ -1098,8 +1155,9 @@ class TicketsCompanion extends UpdateCompanion<Ticket> {
this.createdAt = const Value.absent(),
this.updatedAt = const Value.absent(),
this.question = const Value.absent(),
this.questionImage = const Value.absent(),
this.answer = const Value.absent(),
this.image = const Value.absent(),
this.answerImage = const Value.absent(),
this.collectionId = const Value.absent(),
this.progress = const Value.absent(),
this.rowid = const Value.absent(),
@@ -1109,8 +1167,9 @@ class TicketsCompanion extends UpdateCompanion<Ticket> {
this.createdAt = const Value.absent(),
this.updatedAt = const Value.absent(),
required String question,
this.questionImage = const Value.absent(),
required String answer,
this.image = const Value.absent(),
this.answerImage = const Value.absent(),
required String collectionId,
this.progress = const Value.absent(),
this.rowid = const Value.absent(),
@@ -1122,8 +1181,9 @@ class TicketsCompanion extends UpdateCompanion<Ticket> {
Expression<DateTime>? createdAt,
Expression<DateTime>? updatedAt,
Expression<String>? question,
Expression<Uint8List>? questionImage,
Expression<String>? answer,
Expression<Uint8List>? image,
Expression<Uint8List>? answerImage,
Expression<String>? collectionId,
Expression<double>? progress,
Expression<int>? rowid,
@@ -1133,8 +1193,9 @@ class TicketsCompanion extends UpdateCompanion<Ticket> {
if (createdAt != null) 'created_at': createdAt,
if (updatedAt != null) 'updated_at': updatedAt,
if (question != null) 'question': question,
if (questionImage != null) 'question_image': questionImage,
if (answer != null) 'answer': answer,
if (image != null) 'image': image,
if (answerImage != null) 'answer_image': answerImage,
if (collectionId != null) 'collection_id': collectionId,
if (progress != null) 'progress': progress,
if (rowid != null) 'rowid': rowid,
@@ -1146,8 +1207,9 @@ class TicketsCompanion extends UpdateCompanion<Ticket> {
Value<DateTime>? createdAt,
Value<DateTime>? updatedAt,
Value<String>? question,
Value<Uint8List?>? questionImage,
Value<String>? answer,
Value<Uint8List?>? image,
Value<Uint8List?>? answerImage,
Value<String>? collectionId,
Value<double>? progress,
Value<int>? rowid,
@@ -1157,8 +1219,9 @@ class TicketsCompanion extends UpdateCompanion<Ticket> {
createdAt: createdAt ?? this.createdAt,
updatedAt: updatedAt ?? this.updatedAt,
question: question ?? this.question,
questionImage: questionImage ?? this.questionImage,
answer: answer ?? this.answer,
image: image ?? this.image,
answerImage: answerImage ?? this.answerImage,
collectionId: collectionId ?? this.collectionId,
progress: progress ?? this.progress,
rowid: rowid ?? this.rowid,
@@ -1180,11 +1243,14 @@ class TicketsCompanion extends UpdateCompanion<Ticket> {
if (question.present) {
map['question'] = Variable<String>(question.value);
}
if (questionImage.present) {
map['question_image'] = Variable<Uint8List>(questionImage.value);
}
if (answer.present) {
map['answer'] = Variable<String>(answer.value);
}
if (image.present) {
map['image'] = Variable<Uint8List>(image.value);
if (answerImage.present) {
map['answer_image'] = Variable<Uint8List>(answerImage.value);
}
if (collectionId.present) {
map['collection_id'] = Variable<String>(collectionId.value);
@@ -1205,8 +1271,9 @@ class TicketsCompanion extends UpdateCompanion<Ticket> {
..write('createdAt: $createdAt, ')
..write('updatedAt: $updatedAt, ')
..write('question: $question, ')
..write('questionImage: $questionImage, ')
..write('answer: $answer, ')
..write('image: $image, ')
..write('answerImage: $answerImage, ')
..write('collectionId: $collectionId, ')
..write('progress: $progress, ')
..write('rowid: $rowid')
@@ -1223,6 +1290,7 @@ abstract class _$AppDatabase extends GeneratedDatabase {
late final CollectionsDao collectionsDao = CollectionsDao(
this as AppDatabase,
);
late final TicketsDao ticketsDao = TicketsDao(this as AppDatabase);
@override
Iterable<TableInfo<Table, Object?>> get allTables =>
allSchemaEntities.whereType<TableInfo<Table, Object?>>();
@@ -1675,8 +1743,9 @@ typedef $$TicketsTableCreateCompanionBuilder =
Value<DateTime> createdAt,
Value<DateTime> updatedAt,
required String question,
Value<Uint8List?> questionImage,
required String answer,
Value<Uint8List?> image,
Value<Uint8List?> answerImage,
required String collectionId,
Value<double> progress,
Value<int> rowid,
@@ -1687,8 +1756,9 @@ typedef $$TicketsTableUpdateCompanionBuilder =
Value<DateTime> createdAt,
Value<DateTime> updatedAt,
Value<String> question,
Value<Uint8List?> questionImage,
Value<String> answer,
Value<Uint8List?> image,
Value<Uint8List?> answerImage,
Value<String> collectionId,
Value<double> progress,
Value<int> rowid,
@@ -1747,13 +1817,18 @@ class $$TicketsTableFilterComposer
builder: (column) => ColumnFilters(column),
);
ColumnFilters<Uint8List> get questionImage => $composableBuilder(
column: $table.questionImage,
builder: (column) => ColumnFilters(column),
);
ColumnFilters<String> get answer => $composableBuilder(
column: $table.answer,
builder: (column) => ColumnFilters(column),
);
ColumnFilters<Uint8List> get image => $composableBuilder(
column: $table.image,
ColumnFilters<Uint8List> get answerImage => $composableBuilder(
column: $table.answerImage,
builder: (column) => ColumnFilters(column),
);
@@ -1815,13 +1890,18 @@ class $$TicketsTableOrderingComposer
builder: (column) => ColumnOrderings(column),
);
ColumnOrderings<Uint8List> get questionImage => $composableBuilder(
column: $table.questionImage,
builder: (column) => ColumnOrderings(column),
);
ColumnOrderings<String> get answer => $composableBuilder(
column: $table.answer,
builder: (column) => ColumnOrderings(column),
);
ColumnOrderings<Uint8List> get image => $composableBuilder(
column: $table.image,
ColumnOrderings<Uint8List> get answerImage => $composableBuilder(
column: $table.answerImage,
builder: (column) => ColumnOrderings(column),
);
@@ -1875,11 +1955,18 @@ class $$TicketsTableAnnotationComposer
GeneratedColumn<String> get question =>
$composableBuilder(column: $table.question, builder: (column) => column);
GeneratedColumn<Uint8List> get questionImage => $composableBuilder(
column: $table.questionImage,
builder: (column) => column,
);
GeneratedColumn<String> get answer =>
$composableBuilder(column: $table.answer, builder: (column) => column);
GeneratedColumn<Uint8List> get image =>
$composableBuilder(column: $table.image, builder: (column) => column);
GeneratedColumn<Uint8List> get answerImage => $composableBuilder(
column: $table.answerImage,
builder: (column) => column,
);
GeneratedColumn<double> get progress =>
$composableBuilder(column: $table.progress, builder: (column) => column);
@@ -1940,8 +2027,9 @@ class $$TicketsTableTableManager
Value<DateTime> createdAt = const Value.absent(),
Value<DateTime> updatedAt = const Value.absent(),
Value<String> question = const Value.absent(),
Value<Uint8List?> questionImage = const Value.absent(),
Value<String> answer = const Value.absent(),
Value<Uint8List?> image = const Value.absent(),
Value<Uint8List?> answerImage = const Value.absent(),
Value<String> collectionId = const Value.absent(),
Value<double> progress = const Value.absent(),
Value<int> rowid = const Value.absent(),
@@ -1950,8 +2038,9 @@ class $$TicketsTableTableManager
createdAt: createdAt,
updatedAt: updatedAt,
question: question,
questionImage: questionImage,
answer: answer,
image: image,
answerImage: answerImage,
collectionId: collectionId,
progress: progress,
rowid: rowid,
@@ -1962,8 +2051,9 @@ class $$TicketsTableTableManager
Value<DateTime> createdAt = const Value.absent(),
Value<DateTime> updatedAt = const Value.absent(),
required String question,
Value<Uint8List?> questionImage = const Value.absent(),
required String answer,
Value<Uint8List?> image = const Value.absent(),
Value<Uint8List?> answerImage = const Value.absent(),
required String collectionId,
Value<double> progress = const Value.absent(),
Value<int> rowid = const Value.absent(),
@@ -1972,8 +2062,9 @@ class $$TicketsTableTableManager
createdAt: createdAt,
updatedAt: updatedAt,
question: question,
questionImage: questionImage,
answer: answer,
image: image,
answerImage: answerImage,
collectionId: collectionId,
progress: progress,
rowid: rowid,

View File

@@ -78,8 +78,9 @@ class Collections extends Table with _UuidPrimaryKey, _Timestampable {
@DataClassName('Ticket')
class Tickets extends Table with _UuidPrimaryKey, _Timestampable {
TextColumn get question => text()();
BlobColumn get questionImage => blob().named('question_image').nullable()();
TextColumn get answer => text()();
BlobColumn get image => blob().nullable()();
BlobColumn get answerImage => blob().named('answer_image').nullable()();
TextColumn get collectionId =>
text().references(Collections, #id, onDelete: KeyAction.cascade)();
RealColumn get progress => real().withDefault(Constant(0))();

View File

@@ -307,6 +307,14 @@ class $AssetsImagesGen {
AssetGenImage get propertyYA =>
const AssetGenImage('assets/images/Property YA.png');
/// File path: assets/images/app_icon.png
AssetGenImage get appIcon =>
const AssetGenImage('assets/images/app_icon.png');
/// File path: assets/images/app_icon_monochrome.png
AssetGenImage get appIconMonochrome =>
const AssetGenImage('assets/images/app_icon_monochrome.png');
/// File path: assets/images/img.png
AssetGenImage get img => const AssetGenImage('assets/images/img.png');
@@ -333,6 +341,8 @@ class $AssetsImagesGen {
propertyTG,
propertyVK,
propertyYA,
appIcon,
appIconMonochrome,
img,
imgCard,
logo,

View File

@@ -6,7 +6,7 @@
/// Locales: 2
/// Strings: 20 (10 per locale)
///
/// Built on 2025-04-01 at 19:29 UTC
/// Built on 2025-04-02 at 18:04 UTC
// coverage:ignore-file
// ignore_for_file: type=lint, unused_import

View File

@@ -1,42 +0,0 @@
// To parse this JSON data, do
//
// final collectionDto = collectionDtoFromJson(jsonString);
import 'dart:convert';
import 'dart:typed_data';
import 'package:freezed_annotation/freezed_annotation.dart';
part 'collection_dto.freezed.dart';
// part 'collection_dto.g.dart';
// CollectionDto collectionDtoFromJson(String str) =>
// CollectionDto.fromJson(json.decode(str));
// String collectionDtoToJson(CollectionDto data) => json.encode(data.toJson());
// class Uint8ListConverter implements JsonConverter<Uint8List?, List<int>?> {
// const Uint8ListConverter();
// @override
// Uint8List? fromJson(List<int>? json) {
// return json == null ? null : Uint8List.fromList(json);
// }
// @override
// List<int>? toJson(Uint8List? object) {
// return object?.toList();
// }
// }
@Freezed(copyWith: true, equal: true, fromJson: false, toJson: false)
abstract class CollectionDto with _$CollectionDto {
const factory CollectionDto({
required String desc,
required String title,
required bool isPublic,
Uint8List? avatar,
}) = _CollectionDto;
// factory CollectionDto.fromJson(Map<String, dynamic> json) =>
// _$CollectionDtoFromJson(json);
}

View File

@@ -0,0 +1,22 @@
// To parse this JSON data, do
//
// final collectionDto = collectionDtoFromJson(jsonString);
import 'dart:convert';
import 'dart:typed_data';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:remever/database/database.dart';
part 'create_ticket_dto.freezed.dart';
@Freezed(copyWith: true, equal: true, fromJson: false, toJson: false)
abstract class CreateTicketDto with _$CreateTicketDto {
const factory CreateTicketDto({
Collection? collection,
String? question,
Uint8List? questionImage,
String? answer,
Uint8List? answerImage,
bool? needRevert,
}) = _CreateTicketDto;
}

View File

@@ -0,0 +1,294 @@
// 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 'create_ticket_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 _$CreateTicketDto {
Collection? get collection => throw _privateConstructorUsedError;
String? get question => throw _privateConstructorUsedError;
Uint8List? get questionImage => throw _privateConstructorUsedError;
String? get answer => throw _privateConstructorUsedError;
Uint8List? get answerImage => throw _privateConstructorUsedError;
bool? get needRevert => throw _privateConstructorUsedError;
/// Create a copy of CreateTicketDto
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
$CreateTicketDtoCopyWith<CreateTicketDto> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $CreateTicketDtoCopyWith<$Res> {
factory $CreateTicketDtoCopyWith(
CreateTicketDto value,
$Res Function(CreateTicketDto) then,
) = _$CreateTicketDtoCopyWithImpl<$Res, CreateTicketDto>;
@useResult
$Res call({
Collection? collection,
String? question,
Uint8List? questionImage,
String? answer,
Uint8List? answerImage,
bool? needRevert,
});
}
/// @nodoc
class _$CreateTicketDtoCopyWithImpl<$Res, $Val extends CreateTicketDto>
implements $CreateTicketDtoCopyWith<$Res> {
_$CreateTicketDtoCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
/// Create a copy of CreateTicketDto
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? collection = freezed,
Object? question = freezed,
Object? questionImage = freezed,
Object? answer = freezed,
Object? answerImage = freezed,
Object? needRevert = freezed,
}) {
return _then(
_value.copyWith(
collection:
freezed == collection
? _value.collection
: collection // ignore: cast_nullable_to_non_nullable
as Collection?,
question:
freezed == question
? _value.question
: question // ignore: cast_nullable_to_non_nullable
as String?,
questionImage:
freezed == questionImage
? _value.questionImage
: questionImage // ignore: cast_nullable_to_non_nullable
as Uint8List?,
answer:
freezed == answer
? _value.answer
: answer // ignore: cast_nullable_to_non_nullable
as String?,
answerImage:
freezed == answerImage
? _value.answerImage
: answerImage // ignore: cast_nullable_to_non_nullable
as Uint8List?,
needRevert:
freezed == needRevert
? _value.needRevert
: needRevert // ignore: cast_nullable_to_non_nullable
as bool?,
)
as $Val,
);
}
}
/// @nodoc
abstract class _$$CreateTicketDtoImplCopyWith<$Res>
implements $CreateTicketDtoCopyWith<$Res> {
factory _$$CreateTicketDtoImplCopyWith(
_$CreateTicketDtoImpl value,
$Res Function(_$CreateTicketDtoImpl) then,
) = __$$CreateTicketDtoImplCopyWithImpl<$Res>;
@override
@useResult
$Res call({
Collection? collection,
String? question,
Uint8List? questionImage,
String? answer,
Uint8List? answerImage,
bool? needRevert,
});
}
/// @nodoc
class __$$CreateTicketDtoImplCopyWithImpl<$Res>
extends _$CreateTicketDtoCopyWithImpl<$Res, _$CreateTicketDtoImpl>
implements _$$CreateTicketDtoImplCopyWith<$Res> {
__$$CreateTicketDtoImplCopyWithImpl(
_$CreateTicketDtoImpl _value,
$Res Function(_$CreateTicketDtoImpl) _then,
) : super(_value, _then);
/// Create a copy of CreateTicketDto
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? collection = freezed,
Object? question = freezed,
Object? questionImage = freezed,
Object? answer = freezed,
Object? answerImage = freezed,
Object? needRevert = freezed,
}) {
return _then(
_$CreateTicketDtoImpl(
collection:
freezed == collection
? _value.collection
: collection // ignore: cast_nullable_to_non_nullable
as Collection?,
question:
freezed == question
? _value.question
: question // ignore: cast_nullable_to_non_nullable
as String?,
questionImage:
freezed == questionImage
? _value.questionImage
: questionImage // ignore: cast_nullable_to_non_nullable
as Uint8List?,
answer:
freezed == answer
? _value.answer
: answer // ignore: cast_nullable_to_non_nullable
as String?,
answerImage:
freezed == answerImage
? _value.answerImage
: answerImage // ignore: cast_nullable_to_non_nullable
as Uint8List?,
needRevert:
freezed == needRevert
? _value.needRevert
: needRevert // ignore: cast_nullable_to_non_nullable
as bool?,
),
);
}
}
/// @nodoc
class _$CreateTicketDtoImpl implements _CreateTicketDto {
const _$CreateTicketDtoImpl({
this.collection,
this.question,
this.questionImage,
this.answer,
this.answerImage,
this.needRevert,
});
@override
final Collection? collection;
@override
final String? question;
@override
final Uint8List? questionImage;
@override
final String? answer;
@override
final Uint8List? answerImage;
@override
final bool? needRevert;
@override
String toString() {
return 'CreateTicketDto(collection: $collection, question: $question, questionImage: $questionImage, answer: $answer, answerImage: $answerImage, needRevert: $needRevert)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$CreateTicketDtoImpl &&
const DeepCollectionEquality().equals(
other.collection,
collection,
) &&
(identical(other.question, question) ||
other.question == question) &&
const DeepCollectionEquality().equals(
other.questionImage,
questionImage,
) &&
(identical(other.answer, answer) || other.answer == answer) &&
const DeepCollectionEquality().equals(
other.answerImage,
answerImage,
) &&
(identical(other.needRevert, needRevert) ||
other.needRevert == needRevert));
}
@override
int get hashCode => Object.hash(
runtimeType,
const DeepCollectionEquality().hash(collection),
question,
const DeepCollectionEquality().hash(questionImage),
answer,
const DeepCollectionEquality().hash(answerImage),
needRevert,
);
/// Create a copy of CreateTicketDto
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@override
@pragma('vm:prefer-inline')
_$$CreateTicketDtoImplCopyWith<_$CreateTicketDtoImpl> get copyWith =>
__$$CreateTicketDtoImplCopyWithImpl<_$CreateTicketDtoImpl>(
this,
_$identity,
);
}
abstract class _CreateTicketDto implements CreateTicketDto {
const factory _CreateTicketDto({
final Collection? collection,
final String? question,
final Uint8List? questionImage,
final String? answer,
final Uint8List? answerImage,
final bool? needRevert,
}) = _$CreateTicketDtoImpl;
@override
Collection? get collection;
@override
String? get question;
@override
Uint8List? get questionImage;
@override
String? get answer;
@override
Uint8List? get answerImage;
@override
bool? get needRevert;
/// Create a copy of CreateTicketDto
/// with the given fields replaced by the non-null parameter values.
@override
@JsonKey(includeFromJson: false, includeToJson: false)
_$$CreateTicketDtoImplCopyWith<_$CreateTicketDtoImpl> get copyWith =>
throw _privateConstructorUsedError;
}

View File

@@ -0,0 +1,19 @@
// To parse this JSON data, do
//
// final collectionDto = collectionDtoFromJson(jsonString);
import 'dart:convert';
import 'dart:typed_data';
import 'package:freezed_annotation/freezed_annotation.dart';
part 'crud_collection_dto.freezed.dart';
@Freezed(copyWith: true, equal: true, fromJson: false, toJson: false)
abstract class CrudCollectionDto with _$CrudCollectionDto {
const factory CrudCollectionDto({
required String desc,
required String title,
required bool isPublic,
Uint8List? avatar,
}) = _CrudCollectionDto;
}

View File

@@ -3,7 +3,7 @@
// 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 'collection_dto.dart';
part of 'crud_collection_dto.dart';
// **************************************************************************
// FreezedGenerator
@@ -16,40 +16,40 @@ final _privateConstructorUsedError = UnsupportedError(
);
/// @nodoc
mixin _$CollectionDto {
mixin _$CrudCollectionDto {
String get desc => throw _privateConstructorUsedError;
String get title => throw _privateConstructorUsedError;
bool get isPublic => throw _privateConstructorUsedError;
Uint8List? get avatar => throw _privateConstructorUsedError;
/// Create a copy of CollectionDto
/// Create a copy of CrudCollectionDto
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
$CollectionDtoCopyWith<CollectionDto> get copyWith =>
$CrudCollectionDtoCopyWith<CrudCollectionDto> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $CollectionDtoCopyWith<$Res> {
factory $CollectionDtoCopyWith(
CollectionDto value,
$Res Function(CollectionDto) then,
) = _$CollectionDtoCopyWithImpl<$Res, CollectionDto>;
abstract class $CrudCollectionDtoCopyWith<$Res> {
factory $CrudCollectionDtoCopyWith(
CrudCollectionDto value,
$Res Function(CrudCollectionDto) then,
) = _$CrudCollectionDtoCopyWithImpl<$Res, CrudCollectionDto>;
@useResult
$Res call({String desc, String title, bool isPublic, Uint8List? avatar});
}
/// @nodoc
class _$CollectionDtoCopyWithImpl<$Res, $Val extends CollectionDto>
implements $CollectionDtoCopyWith<$Res> {
_$CollectionDtoCopyWithImpl(this._value, this._then);
class _$CrudCollectionDtoCopyWithImpl<$Res, $Val extends CrudCollectionDto>
implements $CrudCollectionDtoCopyWith<$Res> {
_$CrudCollectionDtoCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
/// Create a copy of CollectionDto
/// Create a copy of CrudCollectionDto
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
@@ -88,27 +88,27 @@ class _$CollectionDtoCopyWithImpl<$Res, $Val extends CollectionDto>
}
/// @nodoc
abstract class _$$CollectionDtoImplCopyWith<$Res>
implements $CollectionDtoCopyWith<$Res> {
factory _$$CollectionDtoImplCopyWith(
_$CollectionDtoImpl value,
$Res Function(_$CollectionDtoImpl) then,
) = __$$CollectionDtoImplCopyWithImpl<$Res>;
abstract class _$$CrudCollectionDtoImplCopyWith<$Res>
implements $CrudCollectionDtoCopyWith<$Res> {
factory _$$CrudCollectionDtoImplCopyWith(
_$CrudCollectionDtoImpl value,
$Res Function(_$CrudCollectionDtoImpl) then,
) = __$$CrudCollectionDtoImplCopyWithImpl<$Res>;
@override
@useResult
$Res call({String desc, String title, bool isPublic, Uint8List? avatar});
}
/// @nodoc
class __$$CollectionDtoImplCopyWithImpl<$Res>
extends _$CollectionDtoCopyWithImpl<$Res, _$CollectionDtoImpl>
implements _$$CollectionDtoImplCopyWith<$Res> {
__$$CollectionDtoImplCopyWithImpl(
_$CollectionDtoImpl _value,
$Res Function(_$CollectionDtoImpl) _then,
class __$$CrudCollectionDtoImplCopyWithImpl<$Res>
extends _$CrudCollectionDtoCopyWithImpl<$Res, _$CrudCollectionDtoImpl>
implements _$$CrudCollectionDtoImplCopyWith<$Res> {
__$$CrudCollectionDtoImplCopyWithImpl(
_$CrudCollectionDtoImpl _value,
$Res Function(_$CrudCollectionDtoImpl) _then,
) : super(_value, _then);
/// Create a copy of CollectionDto
/// Create a copy of CrudCollectionDto
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
@@ -119,7 +119,7 @@ class __$$CollectionDtoImplCopyWithImpl<$Res>
Object? avatar = freezed,
}) {
return _then(
_$CollectionDtoImpl(
_$CrudCollectionDtoImpl(
desc:
null == desc
? _value.desc
@@ -147,8 +147,8 @@ class __$$CollectionDtoImplCopyWithImpl<$Res>
/// @nodoc
class _$CollectionDtoImpl implements _CollectionDto {
const _$CollectionDtoImpl({
class _$CrudCollectionDtoImpl implements _CrudCollectionDto {
const _$CrudCollectionDtoImpl({
required this.desc,
required this.title,
required this.isPublic,
@@ -166,14 +166,14 @@ class _$CollectionDtoImpl implements _CollectionDto {
@override
String toString() {
return 'CollectionDto(desc: $desc, title: $title, isPublic: $isPublic, avatar: $avatar)';
return 'CrudCollectionDto(desc: $desc, title: $title, isPublic: $isPublic, avatar: $avatar)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$CollectionDtoImpl &&
other is _$CrudCollectionDtoImpl &&
(identical(other.desc, desc) || other.desc == desc) &&
(identical(other.title, title) || other.title == title) &&
(identical(other.isPublic, isPublic) ||
@@ -190,22 +190,25 @@ class _$CollectionDtoImpl implements _CollectionDto {
const DeepCollectionEquality().hash(avatar),
);
/// Create a copy of CollectionDto
/// Create a copy of CrudCollectionDto
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@override
@pragma('vm:prefer-inline')
_$$CollectionDtoImplCopyWith<_$CollectionDtoImpl> get copyWith =>
__$$CollectionDtoImplCopyWithImpl<_$CollectionDtoImpl>(this, _$identity);
_$$CrudCollectionDtoImplCopyWith<_$CrudCollectionDtoImpl> get copyWith =>
__$$CrudCollectionDtoImplCopyWithImpl<_$CrudCollectionDtoImpl>(
this,
_$identity,
);
}
abstract class _CollectionDto implements CollectionDto {
const factory _CollectionDto({
abstract class _CrudCollectionDto implements CrudCollectionDto {
const factory _CrudCollectionDto({
required final String desc,
required final String title,
required final bool isPublic,
final Uint8List? avatar,
}) = _$CollectionDtoImpl;
}) = _$CrudCollectionDtoImpl;
@override
String get desc;
@@ -216,10 +219,10 @@ abstract class _CollectionDto implements CollectionDto {
@override
Uint8List? get avatar;
/// Create a copy of CollectionDto
/// Create a copy of CrudCollectionDto
/// with the given fields replaced by the non-null parameter values.
@override
@JsonKey(includeFromJson: false, includeToJson: false)
_$$CollectionDtoImplCopyWith<_$CollectionDtoImpl> get copyWith =>
_$$CrudCollectionDtoImplCopyWith<_$CrudCollectionDtoImpl> get copyWith =>
throw _privateConstructorUsedError;
}

View File

@@ -23,6 +23,7 @@ class AppRouter extends RootStackRouter {
),
AutoRoute(path: '/crud_collection', page: CrudCollectionRoute.page),
AutoRoute(path: '/collection_search', page: CollectionSearchRoute.page),
AutoRoute(path: '/crudFullField', page: CrudCollectionFullscreenField.page),
AutoRoute(path: '/collection_details', page: CollectionDetailRoute.page),
// AutoRoute(path: '/addTags', page: AddTagsRoute.page),

View File

@@ -9,32 +9,34 @@
// coverage:ignore-file
// ignore_for_file: no_leading_underscores_for_library_prefixes
import 'package:auto_route/auto_route.dart' as _i12;
import 'package:flutter/cupertino.dart' as _i13;
import 'package:remever/database/database.dart' as _i14;
import 'package:auto_route/auto_route.dart' as _i13;
import 'package:flutter/cupertino.dart' as _i14;
import 'package:remever/database/database.dart' as _i15;
import 'package:remever/screens/auth/auth_screen.dart' as _i1;
import 'package:remever/screens/collections/collection_detail_screen.dart'
as _i2;
import 'package:remever/screens/collections/collection_search_screen.dart'
as _i4;
import 'package:remever/screens/collections/collections_screen.dart' as _i3;
import 'package:remever/screens/create_card/create_screen.dart' as _i4;
import 'package:remever/screens/crud_collection/crud_collection.dart' as _i6;
import 'package:remever/screens/create_card/create_screen.dart' as _i5;
import 'package:remever/screens/crud_collection/crud_collection.dart' as _i7;
import 'package:remever/screens/crud_collection/widgets/crud_collection_fullscreen_field.dart'
as _i5;
import 'package:remever/screens/home/home_screen.dart' as _i7;
import 'package:remever/screens/sandbox/sandbox_screen.dart' as _i8;
import 'package:remever/screens/settings/settings_screen.dart' as _i9;
import 'package:remever/screens/splash/splash_screen.dart' as _i10;
import 'package:remever/screens/statistick/statistick_screen.dart' as _i11;
as _i6;
import 'package:remever/screens/home/home_screen.dart' as _i8;
import 'package:remever/screens/sandbox/sandbox_screen.dart' as _i9;
import 'package:remever/screens/settings/settings_screen.dart' as _i10;
import 'package:remever/screens/splash/splash_screen.dart' as _i11;
import 'package:remever/screens/statistick/statistick_screen.dart' as _i12;
/// generated route for
/// [_i1.AuthScreen]
class AuthRoute extends _i12.PageRouteInfo<void> {
const AuthRoute({List<_i12.PageRouteInfo>? children})
class AuthRoute extends _i13.PageRouteInfo<void> {
const AuthRoute({List<_i13.PageRouteInfo>? children})
: super(AuthRoute.name, initialChildren: children);
static const String name = 'AuthRoute';
static _i12.PageInfo page = _i12.PageInfo(
static _i13.PageInfo page = _i13.PageInfo(
name,
builder: (data) {
return const _i1.AuthScreen();
@@ -45,11 +47,11 @@ class AuthRoute extends _i12.PageRouteInfo<void> {
/// generated route for
/// [_i2.CollectionDetailScreen]
class CollectionDetailRoute
extends _i12.PageRouteInfo<CollectionDetailRouteArgs> {
extends _i13.PageRouteInfo<CollectionDetailRouteArgs> {
CollectionDetailRoute({
_i13.Key? key,
required _i14.Collection collection,
List<_i12.PageRouteInfo>? children,
_i14.Key? key,
required _i15.Collection collection,
List<_i13.PageRouteInfo>? children,
}) : super(
CollectionDetailRoute.name,
args: CollectionDetailRouteArgs(key: key, collection: collection),
@@ -58,7 +60,7 @@ class CollectionDetailRoute
static const String name = 'CollectionDetailRoute';
static _i12.PageInfo page = _i12.PageInfo(
static _i13.PageInfo page = _i13.PageInfo(
name,
builder: (data) {
final args = data.argsAs<CollectionDetailRouteArgs>();
@@ -73,9 +75,9 @@ class CollectionDetailRoute
class CollectionDetailRouteArgs {
const CollectionDetailRouteArgs({this.key, required this.collection});
final _i13.Key? key;
final _i14.Key? key;
final _i14.Collection collection;
final _i15.Collection collection;
@override
String toString() {
@@ -85,13 +87,13 @@ class CollectionDetailRouteArgs {
/// generated route for
/// [_i3.CollectionScreen]
class CollectionRoute extends _i12.PageRouteInfo<void> {
const CollectionRoute({List<_i12.PageRouteInfo>? children})
class CollectionRoute extends _i13.PageRouteInfo<void> {
const CollectionRoute({List<_i13.PageRouteInfo>? children})
: super(CollectionRoute.name, initialChildren: children);
static const String name = 'CollectionRoute';
static _i12.PageInfo page = _i12.PageInfo(
static _i13.PageInfo page = _i13.PageInfo(
name,
builder: (data) {
return const _i3.CollectionScreen();
@@ -100,33 +102,77 @@ class CollectionRoute extends _i12.PageRouteInfo<void> {
}
/// generated route for
/// [_i4.CreateScreen]
class CreateRoute extends _i12.PageRouteInfo<void> {
const CreateRoute({List<_i12.PageRouteInfo>? children})
/// [_i4.CollectionSearchScreen]
class CollectionSearchRoute
extends _i13.PageRouteInfo<CollectionSearchRouteArgs> {
CollectionSearchRoute({
_i14.Key? key,
required void Function(_i15.Collection) onCollectionSelect,
List<_i13.PageRouteInfo>? children,
}) : super(
CollectionSearchRoute.name,
args: CollectionSearchRouteArgs(
key: key,
onCollectionSelect: onCollectionSelect,
),
initialChildren: children,
);
static const String name = 'CollectionSearchRoute';
static _i13.PageInfo page = _i13.PageInfo(
name,
builder: (data) {
final args = data.argsAs<CollectionSearchRouteArgs>();
return _i4.CollectionSearchScreen(
key: args.key,
onCollectionSelect: args.onCollectionSelect,
);
},
);
}
class CollectionSearchRouteArgs {
const CollectionSearchRouteArgs({this.key, required this.onCollectionSelect});
final _i14.Key? key;
final void Function(_i15.Collection) onCollectionSelect;
@override
String toString() {
return 'CollectionSearchRouteArgs{key: $key, onCollectionSelect: $onCollectionSelect}';
}
}
/// generated route for
/// [_i5.CreateScreen]
class CreateRoute extends _i13.PageRouteInfo<void> {
const CreateRoute({List<_i13.PageRouteInfo>? children})
: super(CreateRoute.name, initialChildren: children);
static const String name = 'CreateRoute';
static _i12.PageInfo page = _i12.PageInfo(
static _i13.PageInfo page = _i13.PageInfo(
name,
builder: (data) {
return const _i4.CreateScreen();
return const _i5.CreateScreen();
},
);
}
/// generated route for
/// [_i5.CrudCollectionFullscreenField]
/// [_i6.CrudCollectionFullscreenField]
class CrudCollectionFullscreenField
extends _i12.PageRouteInfo<CrudCollectionFullscreenFieldArgs> {
extends _i13.PageRouteInfo<CrudCollectionFullscreenFieldArgs> {
CrudCollectionFullscreenField({
_i13.Key? key,
_i14.Key? key,
String title = '',
String? hint,
String? content,
double height = 92,
required void Function(String?) onEditingComplete,
List<_i12.PageRouteInfo>? children,
List<_i13.PageRouteInfo>? children,
}) : super(
CrudCollectionFullscreenField.name,
args: CrudCollectionFullscreenFieldArgs(
@@ -142,11 +188,11 @@ class CrudCollectionFullscreenField
static const String name = 'CrudCollectionFullscreenField';
static _i12.PageInfo page = _i12.PageInfo(
static _i13.PageInfo page = _i13.PageInfo(
name,
builder: (data) {
final args = data.argsAs<CrudCollectionFullscreenFieldArgs>();
return _i5.CrudCollectionFullscreenField(
return _i6.CrudCollectionFullscreenField(
key: args.key,
title: args.title,
hint: args.hint,
@@ -168,7 +214,7 @@ class CrudCollectionFullscreenFieldArgs {
required this.onEditingComplete,
});
final _i13.Key? key;
final _i14.Key? key;
final String title;
@@ -187,12 +233,12 @@ class CrudCollectionFullscreenFieldArgs {
}
/// generated route for
/// [_i6.CrudCollectionScreen]
class CrudCollectionRoute extends _i12.PageRouteInfo<CrudCollectionRouteArgs> {
/// [_i7.CrudCollectionScreen]
class CrudCollectionRoute extends _i13.PageRouteInfo<CrudCollectionRouteArgs> {
CrudCollectionRoute({
_i13.Key? key,
_i14.Collection? editedCollection,
List<_i12.PageRouteInfo>? children,
_i14.Key? key,
_i15.Collection? editedCollection,
List<_i13.PageRouteInfo>? children,
}) : super(
CrudCollectionRoute.name,
args: CrudCollectionRouteArgs(
@@ -204,13 +250,13 @@ class CrudCollectionRoute extends _i12.PageRouteInfo<CrudCollectionRouteArgs> {
static const String name = 'CrudCollectionRoute';
static _i12.PageInfo page = _i12.PageInfo(
static _i13.PageInfo page = _i13.PageInfo(
name,
builder: (data) {
final args = data.argsAs<CrudCollectionRouteArgs>(
orElse: () => const CrudCollectionRouteArgs(),
);
return _i6.CrudCollectionScreen(
return _i7.CrudCollectionScreen(
key: args.key,
editedCollection: args.editedCollection,
);
@@ -221,9 +267,9 @@ class CrudCollectionRoute extends _i12.PageRouteInfo<CrudCollectionRouteArgs> {
class CrudCollectionRouteArgs {
const CrudCollectionRouteArgs({this.key, this.editedCollection});
final _i13.Key? key;
final _i14.Key? key;
final _i14.Collection? editedCollection;
final _i15.Collection? editedCollection;
@override
String toString() {
@@ -232,81 +278,81 @@ class CrudCollectionRouteArgs {
}
/// generated route for
/// [_i7.HomeScreen]
class HomeRoute extends _i12.PageRouteInfo<void> {
const HomeRoute({List<_i12.PageRouteInfo>? children})
/// [_i8.HomeScreen]
class HomeRoute extends _i13.PageRouteInfo<void> {
const HomeRoute({List<_i13.PageRouteInfo>? children})
: super(HomeRoute.name, initialChildren: children);
static const String name = 'HomeRoute';
static _i12.PageInfo page = _i12.PageInfo(
static _i13.PageInfo page = _i13.PageInfo(
name,
builder: (data) {
return const _i7.HomeScreen();
return const _i8.HomeScreen();
},
);
}
/// generated route for
/// [_i8.SandboxScreen]
class SandboxRoute extends _i12.PageRouteInfo<void> {
const SandboxRoute({List<_i12.PageRouteInfo>? children})
/// [_i9.SandboxScreen]
class SandboxRoute extends _i13.PageRouteInfo<void> {
const SandboxRoute({List<_i13.PageRouteInfo>? children})
: super(SandboxRoute.name, initialChildren: children);
static const String name = 'SandboxRoute';
static _i12.PageInfo page = _i12.PageInfo(
static _i13.PageInfo page = _i13.PageInfo(
name,
builder: (data) {
return const _i8.SandboxScreen();
return const _i9.SandboxScreen();
},
);
}
/// generated route for
/// [_i9.SettingsScreen]
class SettingsRoute extends _i12.PageRouteInfo<void> {
const SettingsRoute({List<_i12.PageRouteInfo>? children})
/// [_i10.SettingsScreen]
class SettingsRoute extends _i13.PageRouteInfo<void> {
const SettingsRoute({List<_i13.PageRouteInfo>? children})
: super(SettingsRoute.name, initialChildren: children);
static const String name = 'SettingsRoute';
static _i12.PageInfo page = _i12.PageInfo(
static _i13.PageInfo page = _i13.PageInfo(
name,
builder: (data) {
return const _i9.SettingsScreen();
return const _i10.SettingsScreen();
},
);
}
/// generated route for
/// [_i10.SplashScreen]
class SplashRoute extends _i12.PageRouteInfo<void> {
const SplashRoute({List<_i12.PageRouteInfo>? children})
/// [_i11.SplashScreen]
class SplashRoute extends _i13.PageRouteInfo<void> {
const SplashRoute({List<_i13.PageRouteInfo>? children})
: super(SplashRoute.name, initialChildren: children);
static const String name = 'SplashRoute';
static _i12.PageInfo page = _i12.PageInfo(
static _i13.PageInfo page = _i13.PageInfo(
name,
builder: (data) {
return const _i10.SplashScreen();
return const _i11.SplashScreen();
},
);
}
/// generated route for
/// [_i11.StatistickScreen]
class StatistickRoute extends _i12.PageRouteInfo<void> {
const StatistickRoute({List<_i12.PageRouteInfo>? children})
/// [_i12.StatistickScreen]
class StatistickRoute extends _i13.PageRouteInfo<void> {
const StatistickRoute({List<_i13.PageRouteInfo>? children})
: super(StatistickRoute.name, initialChildren: children);
static const String name = 'StatistickRoute';
static _i12.PageInfo page = _i12.PageInfo(
static _i13.PageInfo page = _i13.PageInfo(
name,
builder: (data) {
return const _i11.StatistickScreen();
return const _i12.StatistickScreen();
},
);
}

View File

@@ -13,7 +13,7 @@ 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/screens/collections/widgets/learning_card.dart';
import 'package:remever/screens/collections/widgets/ticket_card.dart';
import 'package:remever/screens/dialogs/info_dialog.dart';
import 'package:remever/services/tickets/tickets_interface.dart';
import 'package:remever/widgets/primary_button.dart';
@@ -104,8 +104,8 @@ class CollectionDetailScreen extends StatelessWidget {
color: AppColors.disabled,
),
const WSpace(2),
StreamBuilder<List<Collection>>(
stream: getIt<TicketsInterface>().watchTicketsList(),
StreamBuilder<List<Ticket>>(
stream: getIt<TicketsInterface>().watchTicketsList(collection.id),
builder: (context, snapshot) {
return _buildCount(snapshot.data?.length ?? 0);
},
@@ -210,7 +210,7 @@ class CollectionDetailScreen extends StatelessWidget {
physics: BouncingScrollPhysics(),
itemCount: 10,
itemBuilder:
(BuildContext context, int index) => LearningCard(index: index),
(BuildContext context, int index) => TicketCard(index: index),
);
}
}

View File

@@ -0,0 +1,273 @@
import 'package:auto_route/auto_route.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:remever/common/resources.dart';
import 'package:remever/common/utils.dart';
import 'package:remever/common/widgets/loose_focus.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/components/extensions/state.dart';
import 'package:remever/database/database.dart';
import 'package:remever/gen/assets.gen.dart';
import 'package:remever/inject.dart';
import 'package:remever/router.gr.dart';
import 'package:remever/screens/collections/collections_screen.dart';
import 'package:remever/screens/collections/widgets/collection_progress_bar.dart';
import 'package:remever/services/collection/collections_interface.dart';
@RoutePage()
class CollectionSearchScreen extends StatefulWidget {
const CollectionSearchScreen({super.key, required this.onCollectionSelect});
final void Function(Collection) onCollectionSelect;
@override
State<CollectionSearchScreen> createState() => _CollectionSearchScreenState();
}
class _CollectionSearchScreenState extends State<CollectionSearchScreen> {
final TextEditingController _searchController = TextEditingController();
String? _search;
@override
void initState() {
_searchController.addListener(() {
safeSetState(() {
_search = _searchController.text;
});
});
super.initState();
}
@override
void dispose() {
_searchController.dispose();
super.dispose();
}
void _onCreateTap() {
context.pushRoute(CrudCollectionRoute());
}
@override
Widget build(BuildContext context) {
return LooseFocus(
child: Scaffold(
backgroundColor: AppColors.bg,
appBar: _buildAppBar(context),
body: _buildBody(context),
),
);
}
AppBar _buildAppBar(BuildContext context) {
return AppBar(
toolbarHeight: 66.h,
backgroundColor: AppColors.white,
shadowColor: Colors.transparent,
title: SizedBox(
height: 48.h,
child: DecoratedBox(
decoration: BoxDecoration(
color: AppColors.white,
borderRadius: BorderRadius.circular(12).r,
border: Border.all(color: AppColors.bg),
),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 12).r,
child: Center(
child: TextField(
autofocus: true,
controller: _searchController,
textCapitalization: TextCapitalization.sentences,
maxLines: 1,
cursorColor: AppColors.danger,
decoration: const InputDecoration.collapsed(
hintText: 'Поиск',
hintStyle: TextStyle(color: AppColors.gray),
),
),
),
),
),
),
centerTitle: true,
leading: IconButton(
onPressed: () async {
context.back();
},
icon: const Icon(CupertinoIcons.left_chevron, color: Colors.black),
),
);
}
Widget _buildBody(BuildContext context) {
return Column(
children: [
_buildCreateButton(),
Expanded(
child: StreamBuilder<List<Collection>>(
stream: getIt<CollectionsInterface>().watchCollectionsList(
search: _search,
),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const LoadingList();
}
if (snapshot.hasError) {
return const ErrorList();
}
final collections = snapshot.data;
if (collections == null || collections.isEmpty) {
return const EmptyList();
}
return ListView.builder(
itemCount: collections.length,
padding: const EdgeInsets.symmetric(horizontal: 16).r,
itemBuilder:
(context, index) => Padding(
padding: const EdgeInsets.only(bottom: 8).r,
child: GestureDetector(
onTap: () {
widget.onCollectionSelect(collections[index]);
context.back();
},
child: _Collection(collection: collections[index]),
),
),
);
},
),
),
],
);
}
Padding _buildCreateButton() {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 28).r,
child: GestureDetector(
onTap: () => _onCreateTap(),
child: Row(
children: [
SizedBox.square(
dimension: 20.r,
child: DecoratedBox(
decoration: BoxDecoration(
color: AppColors.white,
shape: BoxShape.circle,
),
child: Center(
child: Icon(Icons.add, color: AppColors.disabled, size: 15.r),
),
),
),
WSpace(4),
AppTypography('Создать новую коллекцию', type: Regular16px()),
],
),
),
);
}
}
class _Collection extends StatelessWidget {
const _Collection({required this.collection});
final Collection collection;
@override
Widget build(BuildContext context) {
return Container(
constraints: BoxConstraints(minHeight: 66.h, maxHeight: 84.h),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12).r,
color: AppColors.white,
),
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8).r,
child: Row(
children: <Widget>[_buildAvatar(), const WSpace(5), _buildInfo()],
),
);
}
///
/// Построение основной информации
///
Widget _buildInfo() {
return SizedBox(
width: 230.w,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
_buildTitle(),
const HSpace(4),
Row(
children: <Widget>[
Assets.icons.typeCards.image(
height: 18.h,
width: 18.w,
color: AppColors.disabled,
),
const WSpace(2),
AppTypography(
'${collection.likesCount.toString()} ${Utils.declOfNum(collection.likesCount, ['карточек', 'карточки', 'карточек'])}',
type: Regular14px(),
color: AppColors.disabled,
),
],
),
const HSpace(6),
const CollectionProgressBar(),
],
),
);
}
///
/// Название коллекции
///
Widget _buildTitle() {
return AppTypography(
collection.title,
type: Medium16px(),
maxLines: 2,
softWrap: true,
);
}
///
/// Обложка коллекции
///
Widget _buildAvatar() {
return SizedBox.square(
dimension: 50.r,
child: DecoratedBox(
decoration: BoxDecoration(shape: BoxShape.circle, color: AppColors.bg),
child: Wif(
condition: collection.image != null,
builder:
(context) => ClipOval(
child: Image.memory(collection.image!, fit: BoxFit.cover),
),
fallback:
(context) => Center(
child: AppTypography(
collection.title.substring(0, 1),
type: Bold34px(),
),
),
),
),
);
}
}

View File

@@ -83,16 +83,16 @@ class _CollectionScreenState extends State<CollectionScreen> {
stream: getIt<CollectionsInterface>().watchCollectionsList(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const _LoadingList();
return const LoadingList();
}
if (snapshot.hasError) {
return const _ErrorList();
return const ErrorList();
}
final collections = snapshot.data;
if (collections == null || collections.isEmpty) {
return const _EmptyList();
return const EmptyList();
}
return ListView.builder(
@@ -113,8 +113,8 @@ class _CollectionScreenState extends State<CollectionScreen> {
}
}
class _LoadingList extends StatelessWidget {
const _LoadingList();
class LoadingList extends StatelessWidget {
const LoadingList({super.key});
@override
Widget build(BuildContext context) {
@@ -125,8 +125,8 @@ class _LoadingList extends StatelessWidget {
}
}
class _ErrorList extends StatelessWidget {
const _ErrorList();
class ErrorList extends StatelessWidget {
const ErrorList({super.key});
@override
Widget build(BuildContext context) {
@@ -139,8 +139,8 @@ class _ErrorList extends StatelessWidget {
}
}
class _EmptyList extends StatelessWidget {
const _EmptyList();
class EmptyList extends StatelessWidget {
const EmptyList({super.key});
@override
Widget build(BuildContext context) {

View File

@@ -14,8 +14,8 @@ import 'package:remever/screens/dialogs/replace_diaog.dart';
enum CardType { CREATE, SHOW }
class LearningCard extends StatelessWidget {
LearningCard({
class TicketCard extends StatelessWidget {
TicketCard({
required this.index,
super.key,
this.type = CardType.SHOW,

View File

@@ -1,22 +1,91 @@
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';
import 'package:flutter/material.dart';
import 'package:remever/common/functions.dart';
import 'package:remever/common/resources.dart';
import 'package:remever/common/utils.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/components/extensions/state.dart';
import 'package:remever/gen/assets.gen.dart';
import 'package:remever/inject.dart';
import 'package:remever/models/create_ticket_dto.dart';
import 'package:remever/router.gr.dart';
import 'package:remever/screens/collections/widgets/collection_progress_bar.dart';
import 'package:remever/screens/collections/widgets/learning_card.dart';
import 'package:remever/screens/create_card/widgets/crud_ticket.dart';
import 'package:remever/services/tickets/tickets_interface.dart';
import 'package:remever/widgets/debug/app_debug.dart';
import 'package:remever/widgets/primary_button.dart';
@RoutePage()
class CreateScreen extends StatelessWidget {
class CreateScreen extends StatefulWidget {
const CreateScreen({super.key});
@override
State<CreateScreen> createState() => _CreateScreenState();
}
class _CreateScreenState extends State<CreateScreen> {
CreateTicketDto _dto = CreateTicketDto();
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();
_dto =
isQuestion
? _dto.copyWith(questionImage: bytes)
: _dto.copyWith(answerImage: bytes);
safeSetState(() {});
}
void _onCollectionTap() {
{
context.pushRoute(
CollectionSearchRoute(
onCollectionSelect: (collection) {
safeSetState(() => _dto = _dto.copyWith(collection: collection));
},
),
);
}
}
void _onCreateTap() async {
if (_dto.collection == null ||
_dto.answer == null ||
_dto.question == null) {
showErrorToast('Необходимо заполнить все поля');
return;
}
await getIt<TicketsInterface>().createTicket(_dto);
context.pushRoute(CollectionRoute());
}
@override
Widget build(BuildContext context) {
return Scaffold(
@@ -59,42 +128,55 @@ class CreateScreen extends StatelessWidget {
const HSpace(16),
AppTypography('Вопрос', type: Medium16px()),
const HSpace(4),
LearningCard(
index: 0,
type: CardType.CREATE,
CrudTicket(
onTextTap: () {
context.pushRoute(
CrudCollectionFullscreenField(
title: 'Вопрос',
hint: '',
height: 313,
onEditingComplete: (p0) {},
content: _dto.question,
onEditingComplete: (res) {
safeSetState(() {
_dto = _dto.copyWith(question: res);
});
},
),
);
},
onImageTap: () => _pickImage(true),
isQuestion: true,
dto: _dto,
),
const HSpace(16),
AppTypography('Ответ', type: Medium16px()),
LearningCard(
index: 1,
type: CardType.CREATE,
const HSpace(4),
CrudTicket(
onTextTap: () {
context.pushRoute(
CrudCollectionFullscreenField(
title: 'Ответ',
hint: '',
height: 313,
onEditingComplete: (p0) {},
content: _dto.answer,
onEditingComplete: (res) {
safeSetState(() {
_dto = _dto.copyWith(answer: res);
});
},
),
);
},
onImageTap: () => _pickImage(false),
isQuestion: false,
dto: _dto,
),
revertCard(),
],
),
),
),
_createBtn(),
_buildCreateButton(),
const HSpace(31),
],
),
@@ -124,8 +206,12 @@ class CreateScreen extends StatelessWidget {
fit: BoxFit.contain,
child: CupertinoSwitch(
activeTrackColor: AppColors.primary,
value: false,
onChanged: (bool value) {},
value: _dto.needRevert ?? false,
onChanged: (bool value) {
safeSetState(() {
_dto = _dto.copyWith(needRevert: value);
});
},
),
),
),
@@ -134,17 +220,22 @@ class CreateScreen extends StatelessWidget {
);
}
Row _filters() {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
_buildFilterButton(AppColors.gray_bg, 'Запомнить', () {}),
_buildFilterButton(AppColors.white, 'Держать в фокусе', () {}),
],
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 _createBtn() {
Widget _buildCreateButton() {
return PrimaryButton(
color: AppColors.primary,
child: AppTypography(
@@ -152,7 +243,7 @@ class CreateScreen extends StatelessWidget {
type: Medium14px(),
color: AppColors.white,
),
onTap: () {},
onTap: () => _onCreateTap(),
);
}
@@ -176,7 +267,7 @@ class CreateScreen extends StatelessWidget {
Widget _buildCollection(BuildContext context) {
return GestureDetector(
onTap: () {},
onTap: () => _onCollectionTap(),
child: Container(
constraints: BoxConstraints(minHeight: 66.h, maxHeight: 84.h),
decoration: BoxDecoration(
@@ -184,8 +275,21 @@ class CreateScreen extends StatelessWidget {
color: AppColors.white,
),
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8).r,
child: Row(
children: <Widget>[_buildAvatar(), const WSpace(5), _buildInfo()],
child: Wif(
condition: _dto.collection != null,
builder: (context) {
return Row(
children: <Widget>[_buildAvatar(), const WSpace(5), _buildInfo()],
);
},
fallback: (context) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
AppTypography('Выберите коллекцию ', type: Bold14px()),
],
);
},
),
),
);
@@ -212,7 +316,7 @@ class CreateScreen extends StatelessWidget {
),
const WSpace(2),
AppTypography(
Random().nextInt(654).toString(),
'${_dto.collection!.likesCount.toString()} ${Utils.declOfNum(_dto.collection!.likesCount, ['карточек', 'карточки', 'карточек'])}',
type: Regular14px(),
color: AppColors.disabled,
),
@@ -230,7 +334,7 @@ class CreateScreen extends StatelessWidget {
///
Widget _buildTitle() {
return AppTypography(
'Астрономия',
_dto.collection!.title,
type: Medium16px(),
maxLines: 2,
softWrap: true,
@@ -244,9 +348,21 @@ class CreateScreen extends StatelessWidget {
return SizedBox.square(
dimension: 50.r,
child: DecoratedBox(
decoration: BoxDecoration(
shape: BoxShape.circle,
image: DecorationImage(image: Assets.images.img.provider()),
decoration: BoxDecoration(shape: BoxShape.circle, color: AppColors.bg),
child: Wif(
condition: _dto.collection?.image != null,
builder:
(context) => ClipOval(
child: Image.memory(_dto.collection!.image!, fit: BoxFit.cover),
),
fallback:
(context) => Center(
child: AppTypography(
_dto.collection!.title.substring(0, 1),
type: Bold34px(),
),
),
),
),
);

View File

@@ -0,0 +1,140 @@
import 'package:flutter/material.dart';
import 'package:readmore/readmore.dart';
import 'package:remever/common/resources.dart';
import 'package:remever/common/typography.dart';
import 'package:remever/common/widgets/w_if.dart';
import 'package:remever/components/extensions/context.dart';
import 'package:remever/gen/assets.gen.dart';
import 'package:remever/models/create_ticket_dto.dart';
class CrudTicket extends StatelessWidget {
CrudTicket({
super.key,
this.onTextTap,
this.onImageTap,
required this.isQuestion,
required this.dto,
});
void Function()? onTextTap;
void Function()? onImageTap;
final bool isQuestion;
final CreateTicketDto dto;
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: onTextTap,
child: Container(
width: double.infinity,
decoration: BoxDecoration(
borderRadius: const BorderRadius.all(Radius.circular(12)).r,
color: Colors.white,
),
constraints: BoxConstraints(minHeight: 50.h),
child: Stack(
children: <Widget>[
SizedBox(
height: 50.h,
width: double.infinity,
child: DecoratedBox(decoration: getDecoration()),
),
Padding(
padding: const EdgeInsets.all(12).r,
child: Column(
children: <Widget>[
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[_buildImage(), _buildText(context)],
),
],
),
),
],
),
),
);
}
Widget _buildText(BuildContext context) {
return SizedBox(
width: 228.w,
child: ReadMoreText(
isQuestion
? dto.question ?? 'Ввести текст вопроса'
: dto.answer ?? 'Ввести текст ответа',
isExpandable: true,
trimMode: TrimMode.Line,
trimLines: 3,
trimCollapsedText: '\nРазвернуть',
trimExpandedText: '\nСвернуть',
style: Regular16px().style,
moreStyle: Regular12px().style.copyWith(color: AppColors.primary_blue),
lessStyle: Regular12px().style.copyWith(color: AppColors.primary_blue),
),
);
}
/// Картинка
Widget _buildImage() {
return GestureDetector(
onTap: onImageTap,
child: Padding(
padding: const EdgeInsets.only(right: 8).r,
child: SizedBox.square(
dimension: 64.r,
child: DecoratedBox(
decoration: BoxDecoration(
borderRadius: const BorderRadius.all(Radius.circular(8)).r,
gradient: const LinearGradient(
colors: <Color>[Color(0xFFDBD7F4), Color(0xFFB6AAFE)],
begin: Alignment.topRight,
end: Alignment.bottomLeft,
),
),
child: Wif(
condition:
isQuestion
? dto.questionImage != null
: dto.answerImage != null,
builder: (context) {
return ClipRRect(
borderRadius: const BorderRadius.all(Radius.circular(8)).r,
child: Image.memory(
isQuestion ? dto.questionImage! : dto.answerImage!,
fit: BoxFit.cover,
),
);
},
fallback: (context) {
return Center(
child: Assets.icons.typePhoto.image(
height: 24.h,
width: 24.w,
color: AppColors.primary,
),
);
},
),
),
),
),
);
}
/// Декорирование контейнера
BoxDecoration getDecoration() {
return BoxDecoration(
borderRadius: const BorderRadius.all(Radius.circular(12)).r,
gradient: LinearGradient(
colors: <Color>[
isQuestion ? AppColors.question : AppColors.answer,
Colors.white,
],
begin: Alignment.topLeft,
end: const Alignment(-0.6, 1),
stops: const <double>[0.25, 0.25],
),
);
}
}

View File

@@ -15,7 +15,7 @@ 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/collection_dto.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';
@@ -39,7 +39,7 @@ class _CrudCollectionScreenState extends State<CrudCollectionScreen> {
/// Флаг публичности коллекции
bool _isPublic = false;
CollectionDto? _collection;
CrudCollectionDto? _collection;
/// Смена публичности
void _setPublic(bool public) {
@@ -49,7 +49,7 @@ class _CrudCollectionScreenState extends State<CrudCollectionScreen> {
@override
void initState() {
_collection = CollectionDto(
_collection = CrudCollectionDto(
desc: widget.editedCollection?.desc ?? '',
title: widget.editedCollection?.title ?? '',
isPublic: widget.editedCollection?.isPublic ?? false,

View File

@@ -1,16 +1,16 @@
import 'package:remever/database/database.dart';
import 'package:remever/models/collection_dto.dart';
import 'package:remever/models/crud_collection_dto.dart';
///
/// Интерфейс взаимодействия с коллекциями
///
abstract interface class CollectionsInterface {
/// Получение списка коллекций
Stream<List<Collection>> watchCollectionsList();
Stream<List<Collection>> watchCollectionsList({String? search});
/// Создание новой коллекции
Future<void> createCollection(CollectionDto dto);
Future<void> updateCollection(CollectionDto dto, String id);
Future<void> createCollection(CrudCollectionDto dto);
Future<void> updateCollection(CrudCollectionDto dto, String id);
Future<void> deleteCollection(String id);
/// Сделать коллекцию публичной

View File

@@ -1,7 +1,7 @@
import 'package:injectable/injectable.dart';
import 'package:remever/database/database.dart';
import 'package:remever/inject.dart';
import 'package:remever/models/collection_dto.dart';
import 'package:remever/models/crud_collection_dto.dart';
import 'package:remever/services/collection/collections_interface.dart';
///
@@ -11,17 +11,17 @@ import 'package:remever/services/collection/collections_interface.dart';
@Singleton(as: CollectionsInterface)
final class CollectionsService implements CollectionsInterface {
@override
Stream<List<Collection>> watchCollectionsList() {
return getIt<AppDatabase>().collectionsDao.getCollections();
Stream<List<Collection>> watchCollectionsList({String? search}) {
return getIt<AppDatabase>().collectionsDao.getCollections(search);
}
@override
Future<void> createCollection(CollectionDto dto) async {
Future<void> createCollection(CrudCollectionDto dto) async {
return await getIt<AppDatabase>().collectionsDao.createCollection(dto);
}
@override
Future<void> updateCollection(CollectionDto dto, String id) async {
Future<void> updateCollection(CrudCollectionDto dto, String id) async {
return await getIt<AppDatabase>().collectionsDao.updateCollection(dto, id);
}

View File

@@ -1,9 +1,13 @@
import 'package:remever/database/database.dart';
import 'package:remever/models/create_ticket_dto.dart';
///
/// Интерфейс взаимодействия с билетами в коллекция
///
abstract interface class TicketsInterface {
/// Получение списка билетов
Stream<List<Collection>> watchTicketsList();
Stream<List<Ticket>> watchTicketsList(String collectionId);
/// Создание нового билета
Future<void> createTicket(CreateTicketDto dto);
}

View File

@@ -1,5 +1,7 @@
import 'package:injectable/injectable.dart';
import 'package:remever/database/database.dart';
import 'package:remever/inject.dart';
import 'package:remever/models/create_ticket_dto.dart';
import 'package:remever/services/tickets/tickets_interface.dart';
///
@@ -9,7 +11,12 @@ import 'package:remever/services/tickets/tickets_interface.dart';
@Singleton(as: TicketsInterface)
final class TicketsService implements TicketsInterface {
@override
Stream<List<Collection>> watchTicketsList() {
return Stream.empty();
Stream<List<Ticket>> watchTicketsList(String collectionId) {
return getIt<AppDatabase>().ticketsDao.getTickets(collectionId);
}
@override
Future<void> createTicket(CreateTicketDto dto) async {
return await getIt<AppDatabase>().ticketsDao.createTicket(dto);
}
}