mirror of
https://github.com/jakobkordez/s5_practice.git
synced 2025-05-30 07:30:29 +00:00
Change responsive design
This commit is contained in:
parent
8b0180f091
commit
3fe0f46c75
@ -1,29 +1,7 @@
|
||||
# This file configures the analyzer, which statically analyzes Dart code to
|
||||
# check for errors, warnings, and lints.
|
||||
#
|
||||
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
|
||||
# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
|
||||
# invoked from the command line by running `flutter analyze`.
|
||||
|
||||
# The following line activates a set of recommended lints for Flutter apps,
|
||||
# packages, and plugins designed to encourage good coding practices.
|
||||
include: package:flutter_lints/flutter.yaml
|
||||
|
||||
linter:
|
||||
# The lint rules applied to this project can be customized in the
|
||||
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
|
||||
# included above or to enable additional rules. A list of all available lints
|
||||
# and their documentation is published at
|
||||
# https://dart-lang.github.io/linter/lints/index.html.
|
||||
#
|
||||
# Instead of disabling a lint rule for the entire project in the
|
||||
# section below, it can also be suppressed for a single line of code
|
||||
# or a specific dart file by using the `// ignore: name_of_lint` and
|
||||
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
|
||||
# producing the lint.
|
||||
rules:
|
||||
avoid_print: false # Uncomment to disable the `avoid_print` rule
|
||||
prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
|
||||
|
||||
# Additional information about this file can be found at
|
||||
# https://dart.dev/guides/language/analysis-options
|
||||
avoid_print: false
|
||||
prefer_single_quotes: true
|
||||
prefer_relative_imports: true
|
||||
|
@ -1,228 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
import '../cubit/questions_cubit.dart';
|
||||
import '../models/category.dart';
|
||||
import '../quiz/cubit/quiz_cubit.dart';
|
||||
import 'cubit/generator_cubit.dart';
|
||||
|
||||
class PracticeTab extends StatelessWidget {
|
||||
const PracticeTab({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
'Vaja',
|
||||
style: Theme.of(context).textTheme.headlineSmall,
|
||||
),
|
||||
const SizedBox(height: 15),
|
||||
const Text(
|
||||
'Izberi pogročje in vpiši število vprašanj, ki jih želiš generirati. '
|
||||
'Če želiš generirati vprašanja iz vseh področij, pusti polje za področje prazno.'),
|
||||
const SizedBox(height: 20),
|
||||
LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
final mxW = constraints.maxWidth - 80;
|
||||
return Wrap(
|
||||
alignment: WrapAlignment.center,
|
||||
spacing: 10,
|
||||
crossAxisAlignment: WrapCrossAlignment.end,
|
||||
children: [
|
||||
Container(
|
||||
width: mxW * 2 / 3,
|
||||
constraints: const BoxConstraints(minWidth: 500),
|
||||
child: _CategoryInput(),
|
||||
),
|
||||
Container(
|
||||
width: mxW / 3,
|
||||
constraints: const BoxConstraints(minWidth: 100),
|
||||
child: _PracticeQuestionNumberInput(),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
Container(
|
||||
alignment: Alignment.bottomRight,
|
||||
child: ElevatedButton(
|
||||
onPressed: () {
|
||||
final generatorState = context.read<GeneratorCubit>().state;
|
||||
final questionsState =
|
||||
context.read<QuestionsCubit>().state as QuestionsLoaded;
|
||||
Navigator.pushNamed(context, '/quiz',
|
||||
arguments: QuizState(
|
||||
title: generatorState.category == null
|
||||
? 'Vaja - Vse kategorije'
|
||||
: 'Vaja - ${generatorState.category!.title}',
|
||||
questions:
|
||||
questionsState.getRandom(generatorState.category?.id),
|
||||
count: generatorState.practiceQuestionCount,
|
||||
revealInstantly: true,
|
||||
));
|
||||
},
|
||||
child: const Text('Začni'),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
class _CategoryInput extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) =>
|
||||
BlocBuilder<QuestionsCubit, QuestionsState>(
|
||||
builder: (context, qstate) =>
|
||||
BlocBuilder<GeneratorCubit, GeneratorState>(
|
||||
builder: (context, gstate) {
|
||||
qstate as QuestionsLoaded;
|
||||
|
||||
return DropdownButtonFormField<Category>(
|
||||
isExpanded: true,
|
||||
value: gstate.category,
|
||||
decoration: InputDecoration(
|
||||
isDense: true,
|
||||
enabled: gstate.singleCategory,
|
||||
labelText: 'Izberi področje',
|
||||
suffixIcon: gstate.category == null
|
||||
? null
|
||||
: IconButton(
|
||||
splashRadius: 18,
|
||||
icon: const Icon(Icons.clear),
|
||||
onPressed: () => context
|
||||
.read<GeneratorCubit>()
|
||||
.setSingleCategory(false),
|
||||
),
|
||||
),
|
||||
items: qstate.categories
|
||||
.map((e) => DropdownMenuItem(
|
||||
value: e,
|
||||
child: Text(
|
||||
e.title,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
))
|
||||
.toList(),
|
||||
onChanged: (value) {
|
||||
if (value == null) return;
|
||||
context.read<GeneratorCubit>().setCategory(value);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
class _PracticeQuestionNumberInput extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) =>
|
||||
BlocBuilder<GeneratorCubit, GeneratorState>(
|
||||
buildWhen: (previous, current) =>
|
||||
previous.practiceQuestionCount != current.practiceQuestionCount,
|
||||
builder: (context, state) => TextFormField(
|
||||
initialValue: '${state.practiceQuestionCount}',
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'Število vprašanj',
|
||||
),
|
||||
inputFormatters: [FilteringTextInputFormatter.digitsOnly],
|
||||
keyboardType: TextInputType.number,
|
||||
onChanged: context.read<GeneratorCubit>().setPracticeQuestionCount,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
class _TestQuestionNumberInput extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) =>
|
||||
BlocBuilder<GeneratorCubit, GeneratorState>(
|
||||
buildWhen: (previous, current) =>
|
||||
previous.testQuestionCount != current.testQuestionCount,
|
||||
builder: (context, state) => TextFormField(
|
||||
initialValue: '${state.testQuestionCount}',
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'Število vprašanj',
|
||||
),
|
||||
inputFormatters: [FilteringTextInputFormatter.digitsOnly],
|
||||
keyboardType: TextInputType.number,
|
||||
onChanged: context.read<GeneratorCubit>().setTestQuestionCount,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
class TestTab extends StatelessWidget {
|
||||
const TestTab({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
'Preizkus uspeha',
|
||||
style: Theme.of(context).textTheme.headlineSmall,
|
||||
),
|
||||
const SizedBox(height: 15),
|
||||
const Text(
|
||||
'Kandidati za radioamaterja razreda A opravljajo izpit, ki je '
|
||||
'sestavljen iz 60 različnih vprašanj. Vsako vprašanje ima 3 možne odgovore, od katerih je '
|
||||
'samo en pravilen. Kandidat ima na voljo 90 minut za reševanje izpitne pole. Kandidat mora '
|
||||
'pravilno odgovoriti vsaj na 36 vprašanj (60%).'),
|
||||
const SizedBox(height: 20),
|
||||
const Text(
|
||||
'Preizkus uspeha NE bo vseboval vprašanj s področja "Risanje"!'),
|
||||
const SizedBox(height: 20),
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
Expanded(child: _TestQuestionNumberInput()),
|
||||
const SizedBox(width: 10),
|
||||
Expanded(child: _DurationInput()),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
Container(
|
||||
alignment: Alignment.bottomRight,
|
||||
child: ElevatedButton(
|
||||
onPressed: () {
|
||||
final generatorState = context.read<GeneratorCubit>().state;
|
||||
final questionsState =
|
||||
context.read<QuestionsCubit>().state as QuestionsLoaded;
|
||||
Navigator.pushNamed(context, '/quiz',
|
||||
arguments: QuizState(
|
||||
title: 'Preizkus uspeha',
|
||||
questions: questionsState
|
||||
.getRandom(null, true)
|
||||
.take(generatorState.testQuestionCount)
|
||||
.toList(),
|
||||
count: generatorState.testQuestionCount,
|
||||
duration: generatorState.timerDuration,
|
||||
revealInstantly: false,
|
||||
));
|
||||
},
|
||||
child: const Text('Naprej'),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
class _DurationInput extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) =>
|
||||
BlocBuilder<GeneratorCubit, GeneratorState>(
|
||||
buildWhen: (previous, current) =>
|
||||
previous.timerDuration != current.timerDuration,
|
||||
builder: (context, state) => TextFormField(
|
||||
initialValue: '${state.timerDuration.inMinutes}',
|
||||
decoration: const InputDecoration(
|
||||
suffixText: 'min',
|
||||
labelText: 'Čas za reševanje',
|
||||
),
|
||||
inputFormatters: [FilteringTextInputFormatter.digitsOnly],
|
||||
keyboardType: TextInputType.number,
|
||||
onChanged: context.read<GeneratorCubit>().setDuration,
|
||||
),
|
||||
);
|
||||
}
|
141
lib/src/generator/practice_tab.dart
Normal file
141
lib/src/generator/practice_tab.dart
Normal file
@ -0,0 +1,141 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
import '../cubit/questions_cubit.dart';
|
||||
import '../models/category.dart';
|
||||
import '../quiz/cubit/quiz_cubit.dart';
|
||||
import 'cubit/generator_cubit.dart';
|
||||
|
||||
class PracticeTab extends StatelessWidget {
|
||||
const PracticeTab({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
'Vaja',
|
||||
style: Theme.of(context).textTheme.headlineSmall,
|
||||
),
|
||||
const SizedBox(height: 15),
|
||||
const Text(
|
||||
'Izberi pogročje in vpiši število vprašanj, ki jih želiš generirati. '
|
||||
'Če želiš generirati vprašanja iz vseh področij, pusti polje za področje prazno.'),
|
||||
const SizedBox(height: 20),
|
||||
LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
if (constraints.maxWidth > 600) {
|
||||
return Row(
|
||||
children: [
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: _CategoryInput(),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: _QuestionNumberInput(),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
_CategoryInput(),
|
||||
const SizedBox(height: 15),
|
||||
_QuestionNumberInput(),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
Container(
|
||||
alignment: Alignment.bottomRight,
|
||||
child: ElevatedButton(
|
||||
onPressed: () {
|
||||
final generatorState = context.read<GeneratorCubit>().state;
|
||||
final questionsState =
|
||||
context.read<QuestionsCubit>().state as QuestionsLoaded;
|
||||
Navigator.pushNamed(context, '/quiz',
|
||||
arguments: QuizState(
|
||||
title: generatorState.category == null
|
||||
? 'Vaja - Vse kategorije'
|
||||
: 'Vaja - ${generatorState.category!.title}',
|
||||
questions:
|
||||
questionsState.getRandom(generatorState.category?.id),
|
||||
count: generatorState.practiceQuestionCount,
|
||||
revealInstantly: true,
|
||||
));
|
||||
},
|
||||
child: const Text('Začni'),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
class _CategoryInput extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) =>
|
||||
BlocBuilder<QuestionsCubit, QuestionsState>(
|
||||
builder: (context, qstate) =>
|
||||
BlocBuilder<GeneratorCubit, GeneratorState>(
|
||||
builder: (context, gstate) {
|
||||
qstate as QuestionsLoaded;
|
||||
|
||||
return DropdownButtonFormField<Category>(
|
||||
isExpanded: true,
|
||||
value: gstate.category,
|
||||
decoration: InputDecoration(
|
||||
isDense: true,
|
||||
enabled: gstate.singleCategory,
|
||||
labelText: 'Izberi področje',
|
||||
suffixIcon: gstate.category == null
|
||||
? null
|
||||
: IconButton(
|
||||
splashRadius: 18,
|
||||
icon: const Icon(Icons.clear),
|
||||
onPressed: () => context
|
||||
.read<GeneratorCubit>()
|
||||
.setSingleCategory(false),
|
||||
),
|
||||
),
|
||||
items: qstate.categories
|
||||
.map((e) => DropdownMenuItem(
|
||||
value: e,
|
||||
child: Text(
|
||||
e.title,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
))
|
||||
.toList(),
|
||||
onChanged: (value) {
|
||||
if (value == null) return;
|
||||
context.read<GeneratorCubit>().setCategory(value);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
class _QuestionNumberInput extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) =>
|
||||
BlocBuilder<GeneratorCubit, GeneratorState>(
|
||||
buildWhen: (previous, current) =>
|
||||
previous.practiceQuestionCount != current.practiceQuestionCount,
|
||||
builder: (context, state) => TextFormField(
|
||||
initialValue: '${state.practiceQuestionCount}',
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'Število vprašanj',
|
||||
),
|
||||
inputFormatters: [FilteringTextInputFormatter.digitsOnly],
|
||||
keyboardType: TextInputType.number,
|
||||
onChanged: context.read<GeneratorCubit>().setPracticeQuestionCount,
|
||||
),
|
||||
);
|
||||
}
|
100
lib/src/generator/test_tab.dart
Normal file
100
lib/src/generator/test_tab.dart
Normal file
@ -0,0 +1,100 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
import '../cubit/questions_cubit.dart';
|
||||
import '../quiz/cubit/quiz_cubit.dart';
|
||||
import 'cubit/generator_cubit.dart';
|
||||
|
||||
class TestTab extends StatelessWidget {
|
||||
const TestTab({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
'Preizkus uspeha',
|
||||
style: Theme.of(context).textTheme.headlineSmall,
|
||||
),
|
||||
const SizedBox(height: 15),
|
||||
const Text(
|
||||
'Kandidati za radioamaterja razreda A opravljajo izpit, ki je '
|
||||
'sestavljen iz 60 različnih vprašanj. Vsako vprašanje ima 3 možne odgovore, od katerih je '
|
||||
'samo en pravilen. Kandidat ima na voljo 90 minut za reševanje izpitne pole. Kandidat mora '
|
||||
'pravilno odgovoriti vsaj na 36 vprašanj (60%).'),
|
||||
const SizedBox(height: 20),
|
||||
const Text(
|
||||
'Preizkus uspeha NE bo vseboval vprašanj s področja "Risanje"!'),
|
||||
const SizedBox(height: 20),
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
Expanded(child: _TestQuestionNumberInput()),
|
||||
const SizedBox(width: 10),
|
||||
Expanded(child: _DurationInput()),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
Container(
|
||||
alignment: Alignment.bottomRight,
|
||||
child: ElevatedButton(
|
||||
onPressed: () {
|
||||
final generatorState = context.read<GeneratorCubit>().state;
|
||||
final questionsState =
|
||||
context.read<QuestionsCubit>().state as QuestionsLoaded;
|
||||
Navigator.pushNamed(context, '/quiz',
|
||||
arguments: QuizState(
|
||||
title: 'Preizkus uspeha',
|
||||
questions: questionsState
|
||||
.getRandom(null, true)
|
||||
.take(generatorState.testQuestionCount)
|
||||
.toList(),
|
||||
count: generatorState.testQuestionCount,
|
||||
duration: generatorState.timerDuration,
|
||||
revealInstantly: false,
|
||||
));
|
||||
},
|
||||
child: const Text('Naprej'),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
class _TestQuestionNumberInput extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) =>
|
||||
BlocBuilder<GeneratorCubit, GeneratorState>(
|
||||
buildWhen: (previous, current) =>
|
||||
previous.testQuestionCount != current.testQuestionCount,
|
||||
builder: (context, state) => TextFormField(
|
||||
initialValue: '${state.testQuestionCount}',
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'Število vprašanj',
|
||||
),
|
||||
inputFormatters: [FilteringTextInputFormatter.digitsOnly],
|
||||
keyboardType: TextInputType.number,
|
||||
onChanged: context.read<GeneratorCubit>().setTestQuestionCount,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
class _DurationInput extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) =>
|
||||
BlocBuilder<GeneratorCubit, GeneratorState>(
|
||||
buildWhen: (previous, current) =>
|
||||
previous.timerDuration != current.timerDuration,
|
||||
builder: (context, state) => TextFormField(
|
||||
initialValue: '${state.timerDuration.inMinutes}',
|
||||
decoration: const InputDecoration(
|
||||
suffixText: 'min',
|
||||
labelText: 'Čas za reševanje',
|
||||
),
|
||||
inputFormatters: [FilteringTextInputFormatter.digitsOnly],
|
||||
keyboardType: TextInputType.number,
|
||||
onChanged: context.read<GeneratorCubit>().setDuration,
|
||||
),
|
||||
);
|
||||
}
|
@ -1,10 +1,11 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:s5_practice/src/cubit/questions_cubit.dart';
|
||||
import 'package:s5_practice/src/generator/generator_form.dart';
|
||||
|
||||
import 'components/sized_card.dart';
|
||||
import 'cubit/questions_cubit.dart';
|
||||
import 'generator/cubit/generator_cubit.dart';
|
||||
import 'generator/practice_tab.dart';
|
||||
import 'generator/test_tab.dart';
|
||||
|
||||
class HomeScreen extends StatelessWidget {
|
||||
static const _tabs = [
|
||||
|
@ -2,7 +2,8 @@ import 'dart:math';
|
||||
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:s5_practice/src/models/question.dart';
|
||||
|
||||
import '../../models/question.dart';
|
||||
|
||||
part 'quiz_state.dart';
|
||||
|
||||
|
@ -2,10 +2,10 @@ import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:s5_practice/src/components/sized_card.dart';
|
||||
import 'package:s5_practice/src/quiz/cubit/quiz_cubit.dart';
|
||||
import 'package:timer_builder/timer_builder.dart';
|
||||
|
||||
import '../components/sized_card.dart';
|
||||
import 'cubit/quiz_cubit.dart';
|
||||
import 'question_card.dart';
|
||||
|
||||
class QuizScreen extends StatefulWidget {
|
||||
|
Loading…
x
Reference in New Issue
Block a user