You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
decky/lib/screens/deck_create_screen.dart

216 lines
6.1 KiB

import 'package:flutter/material.dart';
import 'package:practice_engine/practice_engine.dart';
import '../services/deck_storage.dart';
import 'deck_edit_screen.dart';
class DeckCreateScreen extends StatefulWidget {
const DeckCreateScreen({super.key});
@override
State<DeckCreateScreen> createState() => _DeckCreateScreenState();
}
class _DeckCreateScreenState extends State<DeckCreateScreen> {
late TextEditingController _titleController;
late TextEditingController _descriptionController;
final List<QuestionEditor> _questionEditors = [];
final DeckStorage _deckStorage = DeckStorage();
@override
void initState() {
super.initState();
_titleController = TextEditingController();
_descriptionController = TextEditingController();
// Start with one empty question
_questionEditors.add(QuestionEditor.empty());
}
@override
void dispose() {
_titleController.dispose();
_descriptionController.dispose();
for (final editor in _questionEditors) {
editor.dispose();
}
super.dispose();
}
void _addQuestion() {
setState(() {
_questionEditors.add(QuestionEditor.empty());
});
}
void _removeQuestion(int index) {
setState(() {
_questionEditors.removeAt(index);
});
}
void _save() {
final title = _titleController.text.trim();
if (title.isEmpty) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Deck title cannot be empty'),
backgroundColor: Colors.red,
),
);
return;
}
// Validate all questions
final questions = <Question>[];
for (int i = 0; i < _questionEditors.length; i++) {
final editor = _questionEditors[i];
if (!editor.isValid) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Question ${i + 1} is invalid. Please fill in all fields.'),
backgroundColor: Colors.red,
),
);
return;
}
questions.add(editor.toQuestion());
}
if (questions.isEmpty) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Deck must have at least one question'),
backgroundColor: Colors.red,
),
);
return;
}
// Create new deck
final newDeck = Deck(
id: DateTime.now().millisecondsSinceEpoch.toString(),
title: title,
description: _descriptionController.text.trim(),
questions: questions,
config: const DeckConfig(),
currentAttemptIndex: 0,
attemptHistory: [],
);
_deckStorage.saveDeckSync(newDeck);
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Deck created successfully'),
backgroundColor: Colors.green,
duration: Duration(seconds: 1),
),
);
Navigator.pop(context, newDeck);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Create New Deck'),
actions: [
IconButton(
icon: const Icon(Icons.save),
onPressed: _save,
tooltip: 'Save Deck',
),
],
),
body: SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
// Deck Title
TextField(
controller: _titleController,
decoration: const InputDecoration(
labelText: 'Deck Title',
border: OutlineInputBorder(),
),
),
const SizedBox(height: 16),
// Deck Description
TextField(
controller: _descriptionController,
decoration: const InputDecoration(
labelText: 'Description (optional)',
border: OutlineInputBorder(),
),
maxLines: 3,
),
const SizedBox(height: 24),
// Questions Section
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'Questions',
style: Theme.of(context).textTheme.titleLarge,
),
FilledButton.icon(
onPressed: _addQuestion,
icon: const Icon(Icons.add),
label: const Text('Add Question'),
),
],
),
const SizedBox(height: 16),
// Questions List
...List.generate(_questionEditors.length, (index) {
return QuestionEditorCard(
key: ValueKey('question_$index'),
editor: _questionEditors[index],
questionNumber: index + 1,
onDelete: () => _removeQuestion(index),
onChanged: () => setState(() {}),
);
}),
if (_questionEditors.isEmpty)
Card(
child: Padding(
padding: const EdgeInsets.all(32),
child: Center(
child: Column(
children: [
Icon(
Icons.quiz_outlined,
size: 48,
color: Theme.of(context).colorScheme.onSurface.withValues(alpha: 0.3),
),
const SizedBox(height: 16),
Text(
'No questions yet',
style: Theme.of(context).textTheme.bodyLarge,
),
const SizedBox(height: 8),
Text(
'Tap "Add Question" to get started',
style: Theme.of(context).textTheme.bodySmall?.copyWith(
color: Theme.of(context).colorScheme.onSurface.withValues(alpha: 0.6),
),
),
],
),
),
),
),
],
),
),
);
}
}

Powered by TurnKey Linux.