mnemo_cards/mnemo_cards_admin/old/add_card.dart
2025-12-03 02:17:15 +03:00

332 lines
15 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'dart:async';
import 'dart:convert';
import 'package:mnemo_cards/domain/router/dialogs.dart';
import 'package:universal_io/io.dart';
import 'package:flutter/material.dart';
import 'package:file_picker/file_picker.dart';
import 'package:mnemo_cards/admin/admin_api.dart';
import 'package:mnemo_cards_common/mnemo_cards_common.dart';
import 'package:mnemo_cards_frontend_common/mnemo_cards_frontend_common.dart';
import '../main.dart';
class EditCard {
GameCardDto gameCardDto;
AdminApi adminApi;
bool imageChanged = false;
EditCard(GameCardDto? cardDto, this.adminApi)
: gameCardDto =
cardDto ??
const GameCardDto(
id: -1,
image: null,
mnemo: null,
original: null,
translation: null,
transcription: null,
transcriptionMnemo: null,
imageBack: null,
back: null,
);
void _saveCard() async {
final dto = imageChanged ? gameCardDto : gameCardDto.copyWith.image(null);
final _progress = ValueNotifier<(int, int)>((0, 1));
final _dialogCompleter = Completer();
showInfoDialog(
'',
child: ValueListenableBuilder(
valueListenable: _progress,
builder: (c, v, _) => Text(
(v.$1 == v.$2 || v.$2 < 0)
? 'Waiting for response...'
: 'Uploading ${v.$1}/${v.$2}...',
),
),
completer: _dialogCompleter,
);
final result = await adminApi.addCard(
dto,
progressCallback: (a, b) => _progress.value = (a, b),
);
_dialogCompleter.complete();
if (!result) {
ScaffoldMessenger.of(
scaffoldKey.currentContext!,
).showSnackBar(SnackBar(content: Text('ERROR')));
} else {
ScaffoldMessenger.of(
scaffoldKey.currentContext!,
).showSnackBar(SnackBar(content: Text('Success!!!')));
appRouter.maybePop();
}
}
void _deleteCard() async {
final result = await adminApi.deleteCard(gameCardDto);
if (!result) {
ScaffoldMessenger.of(
scaffoldKey.currentContext!,
).showSnackBar(SnackBar(content: Text('ERROR')));
} else {
ScaffoldMessenger.of(
scaffoldKey.currentContext!,
).showSnackBar(SnackBar(content: Text('Success!!!')));
appRouter.maybePop();
}
}
void addCard(BuildContext context) {
final theme = Theme.of(context).textTheme;
final TextEditingController originalController = TextEditingController(
text: gameCardDto.original,
);
final TextEditingController translationController = TextEditingController(
text: gameCardDto.translation,
);
final TextEditingController transcriptionController = TextEditingController(
text: gameCardDto.transcription,
);
final TextEditingController transcriptionMnemoController =
TextEditingController(text: gameCardDto.transcriptionMnemo);
final TextEditingController mnemoController = TextEditingController(
text: gameCardDto.mnemo,
);
final TextEditingController backController = TextEditingController(
text: gameCardDto.back,
);
showDialog(
context: context,
builder: (c) {
return Center(
child: Scaffold(
body: Material(
child: ListView(
children: [
Header(
'${gameCardDto.id}',
hasPopButton: true,
trail: Row(
children: [
IconButton(
onPressed: _saveCard,
icon: Icon(Icons.save),
),
if (gameCardDto.id >= 0)
GestureDetector(
onLongPress: _deleteCard,
child: Icon(Icons.delete),
),
],
),
),
StatefulBuilder(
builder: (context, setState) {
return Stack(
alignment: Alignment.center,
children: [
Padding(
padding: EdgeInsets.all(8.0),
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Column(
children: [
TextField(
controller: originalController,
onChanged: (v) {
gameCardDto = gameCardDto.copyWith(
original: v,
);
},
decoration: InputDecoration(
hintText: 'Original (cerdo)',
),
maxLines: 1,
style: theme.displayMedium?.copyWith(
fontSize:
theme.displayMedium!.fontSize!,
),
),
TextField(
controller: translationController,
onChanged: (v) {
gameCardDto = gameCardDto.copyWith(
translation: v,
);
},
decoration: InputDecoration(
hintText: 'Translation (свинья)',
),
maxLines: 1,
style: theme.headlineSmall?.copyWith(
color: theme.headlineSmall!.color!
.withOpacity(0.5),
fontSize:
theme.headlineSmall!.fontSize!,
),
),
Row(
children: [
Flexible(
child: TextField(
controller: transcriptionController,
onChanged: (v) {
gameCardDto = gameCardDto
.copyWith(transcription: v);
},
decoration: InputDecoration(
hintText: 'Transcription',
),
maxLines: 1,
style: theme.headlineSmall
?.copyWith(
color: theme
.headlineSmall!
.color!,
fontSize: theme
.headlineSmall!
.fontSize!,
),
),
),
SizedBox(width: 4.0),
Flexible(
child: TextField(
controller:
transcriptionMnemoController,
onChanged: (v) {
gameCardDto = gameCardDto
.copyWith(
transcriptionMnemo: v,
);
},
decoration: InputDecoration(
hintText: 'Transcription mnemo',
),
maxLines: 1,
style: theme.headlineSmall
?.copyWith(
color: theme
.headlineSmall!
.color!,
fontSize: theme
.headlineSmall!
.fontSize!,
),
),
),
],
),
],
),
SizedBox(
width: MediaQuery.of(context).size.width - 20,
height:
MediaQuery.of(context).size.width - 20,
child: GestureDetector(
onTap: () async {
FilePickerResult? result =
await FilePicker.platform.pickFiles();
if (result != null &&
result.files.isNotEmpty) {
imageChanged = true;
final file = result.files.first;
final encoded = base64.normalize(
base64.encode(
File(file.path!).readAsBytesSync(),
),
);
gameCardDto = gameCardDto.copyWith(
image: encoded,
);
}
setState(() {});
},
child: gameCardDto.image == null
? Container(
alignment: Alignment.center,
color: Colors.white,
child: Icon(
Icons.image,
color: Colors.grey,
),
)
: Stack(
children: [
Image(
key: ValueKey(base64),
image: MemoryImage(
base64.decode(
gameCardDto.image!,
),
),
gaplessPlayback: true,
fit: BoxFit.contain,
),
Positioned(
top: 8.0,
right: 8.0,
child: IconButton(
onPressed: () {
gameCardDto = gameCardDto
.copyWith(image: null);
setState(() {});
},
icon: Icon(Icons.delete),
),
),
],
),
),
),
TextField(
controller: mnemoController,
onChanged: (v) {
gameCardDto = gameCardDto.copyWith(
mnemo: v,
);
},
decoration: InputDecoration(
hintText: 'Mnemo ([свинья] с сердечком)',
),
maxLines: 1,
style: theme.headlineSmall?.copyWith(
fontSize: theme.headlineSmall!.fontSize!,
),
),
TextField(
controller: backController,
onChanged: (v) {
gameCardDto = gameCardDto.copyWith(back: v);
},
decoration: InputDecoration(
hintText: 'Задняя сторона',
),
maxLines: 1,
style: theme.headlineSmall?.copyWith(
fontSize: theme.headlineSmall!.fontSize!,
),
),
],
),
),
],
);
},
),
],
),
),
),
);
},
);
}
}