Compare commits
3 Commits
ff9f3263ae
...
0f7d938ad7
Author | SHA1 | Date | |
---|---|---|---|
0f7d938ad7 | |||
b1c7fc8882 | |||
7c71f5fa3e |
|
@ -1,30 +1,5 @@
|
||||||
# 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
|
include: package:flutter_lints/flutter.yaml
|
||||||
|
|
||||||
linter:
|
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:
|
rules:
|
||||||
curly_braces_in_flow_control_structures: false
|
curly_braces_in_flow_control_structures: false
|
||||||
# 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
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ import 'dart:io';
|
||||||
|
|
||||||
import 'package:fmassive/gym_set.dart';
|
import 'package:fmassive/gym_set.dart';
|
||||||
import 'package:fmassive/main.dart';
|
import 'package:fmassive/main.dart';
|
||||||
|
import 'package:fmassive/plans.dart';
|
||||||
import 'package:moor/ffi.dart';
|
import 'package:moor/ffi.dart';
|
||||||
import 'package:moor/moor.dart';
|
import 'package:moor/moor.dart';
|
||||||
import 'package:path/path.dart';
|
import 'package:path/path.dart';
|
||||||
|
@ -11,7 +12,7 @@ import 'settings.dart';
|
||||||
|
|
||||||
part 'database.g.dart';
|
part 'database.g.dart';
|
||||||
|
|
||||||
@UseMoor(tables: [Settings, GymSets])
|
@UseMoor(tables: [Settings, GymSets, Plans])
|
||||||
class MyDatabase extends _$MyDatabase {
|
class MyDatabase extends _$MyDatabase {
|
||||||
MyDatabase() : super(_openConnection());
|
MyDatabase() : super(_openConnection());
|
||||||
|
|
||||||
|
@ -35,7 +36,6 @@ LazyDatabase _openConnection() {
|
||||||
return LazyDatabase(() async {
|
return LazyDatabase(() async {
|
||||||
final dbFolder = await getDatabasesPath();
|
final dbFolder = await getDatabasesPath();
|
||||||
final file = File(join(dbFolder, 'massive.db'));
|
final file = File(join(dbFolder, 'massive.db'));
|
||||||
print('file.path=${file.path}');
|
|
||||||
return VmDatabase(file, logStatements: true);
|
return VmDatabase(file, logStatements: true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1239,12 +1239,220 @@ class $GymSetsTable extends GymSets with TableInfo<$GymSetsTable, GymSet> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Plan extends DataClass implements Insertable<Plan> {
|
||||||
|
final int id;
|
||||||
|
final String days;
|
||||||
|
final String workouts;
|
||||||
|
Plan({required this.id, required this.days, required this.workouts});
|
||||||
|
factory Plan.fromData(Map<String, dynamic> data, GeneratedDatabase db,
|
||||||
|
{String? prefix}) {
|
||||||
|
final effectivePrefix = prefix ?? '';
|
||||||
|
return Plan(
|
||||||
|
id: const IntType()
|
||||||
|
.mapFromDatabaseResponse(data['${effectivePrefix}id'])!,
|
||||||
|
days: const StringType()
|
||||||
|
.mapFromDatabaseResponse(data['${effectivePrefix}days'])!,
|
||||||
|
workouts: const StringType()
|
||||||
|
.mapFromDatabaseResponse(data['${effectivePrefix}workouts'])!,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@override
|
||||||
|
Map<String, Expression> toColumns(bool nullToAbsent) {
|
||||||
|
final map = <String, Expression>{};
|
||||||
|
map['id'] = Variable<int>(id);
|
||||||
|
map['days'] = Variable<String>(days);
|
||||||
|
map['workouts'] = Variable<String>(workouts);
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
PlansCompanion toCompanion(bool nullToAbsent) {
|
||||||
|
return PlansCompanion(
|
||||||
|
id: Value(id),
|
||||||
|
days: Value(days),
|
||||||
|
workouts: Value(workouts),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
factory Plan.fromJson(Map<String, dynamic> json,
|
||||||
|
{ValueSerializer? serializer}) {
|
||||||
|
serializer ??= moorRuntimeOptions.defaultSerializer;
|
||||||
|
return Plan(
|
||||||
|
id: serializer.fromJson<int>(json['id']),
|
||||||
|
days: serializer.fromJson<String>(json['days']),
|
||||||
|
workouts: serializer.fromJson<String>(json['workouts']),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@override
|
||||||
|
Map<String, dynamic> toJson({ValueSerializer? serializer}) {
|
||||||
|
serializer ??= moorRuntimeOptions.defaultSerializer;
|
||||||
|
return <String, dynamic>{
|
||||||
|
'id': serializer.toJson<int>(id),
|
||||||
|
'days': serializer.toJson<String>(days),
|
||||||
|
'workouts': serializer.toJson<String>(workouts),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Plan copyWith({int? id, String? days, String? workouts}) => Plan(
|
||||||
|
id: id ?? this.id,
|
||||||
|
days: days ?? this.days,
|
||||||
|
workouts: workouts ?? this.workouts,
|
||||||
|
);
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return (StringBuffer('Plan(')
|
||||||
|
..write('id: $id, ')
|
||||||
|
..write('days: $days, ')
|
||||||
|
..write('workouts: $workouts')
|
||||||
|
..write(')'))
|
||||||
|
.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(id, days, workouts);
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) =>
|
||||||
|
identical(this, other) ||
|
||||||
|
(other is Plan &&
|
||||||
|
other.id == this.id &&
|
||||||
|
other.days == this.days &&
|
||||||
|
other.workouts == this.workouts);
|
||||||
|
}
|
||||||
|
|
||||||
|
class PlansCompanion extends UpdateCompanion<Plan> {
|
||||||
|
final Value<int> id;
|
||||||
|
final Value<String> days;
|
||||||
|
final Value<String> workouts;
|
||||||
|
const PlansCompanion({
|
||||||
|
this.id = const Value.absent(),
|
||||||
|
this.days = const Value.absent(),
|
||||||
|
this.workouts = const Value.absent(),
|
||||||
|
});
|
||||||
|
PlansCompanion.insert({
|
||||||
|
this.id = const Value.absent(),
|
||||||
|
required String days,
|
||||||
|
required String workouts,
|
||||||
|
}) : days = Value(days),
|
||||||
|
workouts = Value(workouts);
|
||||||
|
static Insertable<Plan> custom({
|
||||||
|
Expression<int>? id,
|
||||||
|
Expression<String>? days,
|
||||||
|
Expression<String>? workouts,
|
||||||
|
}) {
|
||||||
|
return RawValuesInsertable({
|
||||||
|
if (id != null) 'id': id,
|
||||||
|
if (days != null) 'days': days,
|
||||||
|
if (workouts != null) 'workouts': workouts,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
PlansCompanion copyWith(
|
||||||
|
{Value<int>? id, Value<String>? days, Value<String>? workouts}) {
|
||||||
|
return PlansCompanion(
|
||||||
|
id: id ?? this.id,
|
||||||
|
days: days ?? this.days,
|
||||||
|
workouts: workouts ?? this.workouts,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map<String, Expression> toColumns(bool nullToAbsent) {
|
||||||
|
final map = <String, Expression>{};
|
||||||
|
if (id.present) {
|
||||||
|
map['id'] = Variable<int>(id.value);
|
||||||
|
}
|
||||||
|
if (days.present) {
|
||||||
|
map['days'] = Variable<String>(days.value);
|
||||||
|
}
|
||||||
|
if (workouts.present) {
|
||||||
|
map['workouts'] = Variable<String>(workouts.value);
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return (StringBuffer('PlansCompanion(')
|
||||||
|
..write('id: $id, ')
|
||||||
|
..write('days: $days, ')
|
||||||
|
..write('workouts: $workouts')
|
||||||
|
..write(')'))
|
||||||
|
.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class $PlansTable extends Plans with TableInfo<$PlansTable, Plan> {
|
||||||
|
@override
|
||||||
|
final GeneratedDatabase attachedDatabase;
|
||||||
|
final String? _alias;
|
||||||
|
$PlansTable(this.attachedDatabase, [this._alias]);
|
||||||
|
final VerificationMeta _idMeta = const VerificationMeta('id');
|
||||||
|
@override
|
||||||
|
late final GeneratedColumn<int?> id = GeneratedColumn<int?>(
|
||||||
|
'id', aliasedName, false,
|
||||||
|
type: const IntType(),
|
||||||
|
requiredDuringInsert: false,
|
||||||
|
defaultConstraints: 'PRIMARY KEY AUTOINCREMENT');
|
||||||
|
final VerificationMeta _daysMeta = const VerificationMeta('days');
|
||||||
|
@override
|
||||||
|
late final GeneratedColumn<String?> days = GeneratedColumn<String?>(
|
||||||
|
'days', aliasedName, false,
|
||||||
|
type: const StringType(), requiredDuringInsert: true);
|
||||||
|
final VerificationMeta _workoutsMeta = const VerificationMeta('workouts');
|
||||||
|
@override
|
||||||
|
late final GeneratedColumn<String?> workouts = GeneratedColumn<String?>(
|
||||||
|
'workouts', aliasedName, false,
|
||||||
|
type: const StringType(), requiredDuringInsert: true);
|
||||||
|
@override
|
||||||
|
List<GeneratedColumn> get $columns => [id, days, workouts];
|
||||||
|
@override
|
||||||
|
String get aliasedName => _alias ?? 'plans';
|
||||||
|
@override
|
||||||
|
String get actualTableName => 'plans';
|
||||||
|
@override
|
||||||
|
VerificationContext validateIntegrity(Insertable<Plan> instance,
|
||||||
|
{bool isInserting = false}) {
|
||||||
|
final context = VerificationContext();
|
||||||
|
final data = instance.toColumns(true);
|
||||||
|
if (data.containsKey('id')) {
|
||||||
|
context.handle(_idMeta, id.isAcceptableOrUnknown(data['id']!, _idMeta));
|
||||||
|
}
|
||||||
|
if (data.containsKey('days')) {
|
||||||
|
context.handle(
|
||||||
|
_daysMeta, days.isAcceptableOrUnknown(data['days']!, _daysMeta));
|
||||||
|
} else if (isInserting) {
|
||||||
|
context.missing(_daysMeta);
|
||||||
|
}
|
||||||
|
if (data.containsKey('workouts')) {
|
||||||
|
context.handle(_workoutsMeta,
|
||||||
|
workouts.isAcceptableOrUnknown(data['workouts']!, _workoutsMeta));
|
||||||
|
} else if (isInserting) {
|
||||||
|
context.missing(_workoutsMeta);
|
||||||
|
}
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Set<GeneratedColumn> get $primaryKey => {id};
|
||||||
|
@override
|
||||||
|
Plan map(Map<String, dynamic> data, {String? tablePrefix}) {
|
||||||
|
return Plan.fromData(data, attachedDatabase,
|
||||||
|
prefix: tablePrefix != null ? '$tablePrefix.' : null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
$PlansTable createAlias(String alias) {
|
||||||
|
return $PlansTable(attachedDatabase, alias);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
abstract class _$MyDatabase extends GeneratedDatabase {
|
abstract class _$MyDatabase extends GeneratedDatabase {
|
||||||
_$MyDatabase(QueryExecutor e) : super(SqlTypeSystem.defaultInstance, e);
|
_$MyDatabase(QueryExecutor e) : super(SqlTypeSystem.defaultInstance, e);
|
||||||
late final $SettingsTable settings = $SettingsTable(this);
|
late final $SettingsTable settings = $SettingsTable(this);
|
||||||
late final $GymSetsTable gymSets = $GymSetsTable(this);
|
late final $GymSetsTable gymSets = $GymSetsTable(this);
|
||||||
|
late final $PlansTable plans = $PlansTable(this);
|
||||||
@override
|
@override
|
||||||
Iterable<TableInfo> get allTables => allSchemaEntities.whereType<TableInfo>();
|
Iterable<TableInfo> get allTables => allSchemaEntities.whereType<TableInfo>();
|
||||||
@override
|
@override
|
||||||
List<DatabaseSchemaEntity> get allSchemaEntities => [settings, gymSets];
|
List<DatabaseSchemaEntity> get allSchemaEntities =>
|
||||||
|
[settings, gymSets, plans];
|
||||||
}
|
}
|
||||||
|
|
113
lib/edit_plan.dart
Normal file
113
lib/edit_plan.dart
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/material.dart' as material;
|
||||||
|
import 'package:fmassive/database.dart';
|
||||||
|
import 'package:fmassive/main.dart';
|
||||||
|
import 'package:moor_flutter/moor_flutter.dart';
|
||||||
|
|
||||||
|
class EditPlanPage extends StatefulWidget {
|
||||||
|
final PlansCompanion plan;
|
||||||
|
|
||||||
|
const EditPlanPage({required this.plan, super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
createState() => _EditPlanPageState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _EditPlanPageState extends State<EditPlanPage> {
|
||||||
|
final TextEditingController _daysController = TextEditingController();
|
||||||
|
final TextEditingController _workoutsController = TextEditingController();
|
||||||
|
late PlansCompanion plan;
|
||||||
|
final daysNode = FocusNode();
|
||||||
|
final workoutsNode = FocusNode();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
plan = widget.plan;
|
||||||
|
_daysController.text = plan.days.value;
|
||||||
|
_workoutsController.text = plan.workouts.value;
|
||||||
|
if (plan.id.present)
|
||||||
|
workoutsNode.requestFocus();
|
||||||
|
else
|
||||||
|
daysNode.requestFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
dispose() {
|
||||||
|
daysNode.dispose();
|
||||||
|
workoutsNode.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
List<Widget> actions = [];
|
||||||
|
if (widget.plan.id.present)
|
||||||
|
actions.add(IconButton(
|
||||||
|
onPressed: () async {
|
||||||
|
await db.plans.deleteOne(widget.plan);
|
||||||
|
if (!mounted) return;
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
icon: const Icon(Icons.delete)));
|
||||||
|
|
||||||
|
return SafeArea(
|
||||||
|
child: Scaffold(
|
||||||
|
appBar: AppBar(title: const Text('Edit Plan'), actions: actions),
|
||||||
|
body: Padding(
|
||||||
|
padding: const EdgeInsets.all(16.0),
|
||||||
|
child: material.Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
TextFormField(
|
||||||
|
controller: _daysController,
|
||||||
|
focusNode: daysNode,
|
||||||
|
decoration: const InputDecoration(labelText: 'Days'),
|
||||||
|
onTap: () {
|
||||||
|
_daysController.selection = TextSelection(
|
||||||
|
baseOffset: 0, extentOffset: _daysController.text.length);
|
||||||
|
},
|
||||||
|
onChanged: (value) {
|
||||||
|
setState(() {
|
||||||
|
plan = plan.copyWith(days: Value(value));
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
TextFormField(
|
||||||
|
controller: _workoutsController,
|
||||||
|
focusNode: workoutsNode,
|
||||||
|
onTap: () {
|
||||||
|
_workoutsController.selection = TextSelection(
|
||||||
|
baseOffset: 0,
|
||||||
|
extentOffset: _workoutsController.text.length);
|
||||||
|
},
|
||||||
|
decoration: const InputDecoration(labelText: 'Workouts'),
|
||||||
|
onChanged: (value) {
|
||||||
|
setState(() {
|
||||||
|
plan = plan.copyWith(workouts: Value(value));
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
floatingActionButton: FloatingActionButton(
|
||||||
|
onPressed: () async {
|
||||||
|
if (_daysController.text.isEmpty) {
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
const SnackBar(content: Text('Please enter days')));
|
||||||
|
daysNode.requestFocus();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (plan.id.present)
|
||||||
|
await db.update(db.plans).write(plan);
|
||||||
|
else
|
||||||
|
await db.into(db.plans).insert(plan);
|
||||||
|
if (!mounted) return;
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
child: const Icon(Icons.check),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
|
@ -54,7 +54,8 @@ class _EditGymSetPageState extends State<EditGymSetPage> {
|
||||||
},
|
},
|
||||||
icon: const Icon(Icons.delete)));
|
icon: const Icon(Icons.delete)));
|
||||||
|
|
||||||
return Scaffold(
|
return SafeArea(
|
||||||
|
child: Scaffold(
|
||||||
appBar: AppBar(title: const Text('Edit Gym Set'), actions: actions),
|
appBar: AppBar(title: const Text('Edit Gym Set'), actions: actions),
|
||||||
body: Padding(
|
body: Padding(
|
||||||
padding: const EdgeInsets.all(16.0),
|
padding: const EdgeInsets.all(16.0),
|
||||||
|
@ -111,6 +112,12 @@ class _EditGymSetPageState extends State<EditGymSetPage> {
|
||||||
),
|
),
|
||||||
floatingActionButton: FloatingActionButton(
|
floatingActionButton: FloatingActionButton(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
|
if (_nameController.text.isEmpty) {
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
const SnackBar(content: Text('Please enter a name')));
|
||||||
|
nameNode.requestFocus();
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (gymSet.id.present)
|
if (gymSet.id.present)
|
||||||
await db.update(db.gymSets).write(gymSet);
|
await db.update(db.gymSets).write(gymSet);
|
||||||
else {
|
else {
|
||||||
|
@ -123,6 +130,6 @@ class _EditGymSetPageState extends State<EditGymSetPage> {
|
||||||
},
|
},
|
||||||
child: const Icon(Icons.check),
|
child: const Icon(Icons.check),
|
||||||
),
|
),
|
||||||
);
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,7 +51,7 @@ class RootPage extends State<HomePage> {
|
||||||
case 'Best':
|
case 'Best':
|
||||||
return const BestPage();
|
return const BestPage();
|
||||||
case 'Plans':
|
case 'Plans':
|
||||||
return const PlansPage();
|
return PlansPage(search: search);
|
||||||
default:
|
default:
|
||||||
return _HomePageWidget(search: search);
|
return _HomePageWidget(search: search);
|
||||||
}
|
}
|
||||||
|
@ -59,7 +59,8 @@ class RootPage extends State<HomePage> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return SafeArea(
|
||||||
|
child: Scaffold(
|
||||||
drawer: Drawer(
|
drawer: Drawer(
|
||||||
child: ListView.builder(
|
child: ListView.builder(
|
||||||
itemCount: routes.length,
|
itemCount: routes.length,
|
||||||
|
@ -103,7 +104,7 @@ class RootPage extends State<HomePage> {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
body: getBody(),
|
body: getBody(),
|
||||||
);
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
7
lib/plans.dart
Normal file
7
lib/plans.dart
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
import 'package:moor/moor.dart';
|
||||||
|
|
||||||
|
class Plans extends Table {
|
||||||
|
IntColumn get id => integer().autoIncrement()();
|
||||||
|
TextColumn get days => text()();
|
||||||
|
TextColumn get workouts => text()();
|
||||||
|
}
|
|
@ -1,163 +1,102 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/material.dart' as material;
|
|
||||||
import 'package:fmassive/database.dart';
|
import 'package:fmassive/database.dart';
|
||||||
|
import 'package:fmassive/edit_plan.dart';
|
||||||
import 'package:fmassive/main.dart';
|
import 'package:fmassive/main.dart';
|
||||||
import 'package:fmassive/settings.dart';
|
|
||||||
import 'package:moor/moor.dart';
|
import 'package:moor/moor.dart';
|
||||||
|
|
||||||
class PlansPage extends StatelessWidget {
|
class PlansPage extends StatelessWidget {
|
||||||
const PlansPage({super.key});
|
const PlansPage({super.key, required this.search});
|
||||||
|
|
||||||
|
final String search;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return const Scaffold(
|
return Scaffold(
|
||||||
body: Center(
|
body: Center(
|
||||||
child: _PlansPage(),
|
child: _PlansPage(search: search),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _PlansPage extends StatefulWidget {
|
class _PlansPage extends StatefulWidget {
|
||||||
const _PlansPage({Key? key}) : super(key: key);
|
const _PlansPage({Key? key, required this.search}) : super(key: key);
|
||||||
|
|
||||||
|
final String search;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
createState() => _PlansPageState();
|
createState() => _PlansPageState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _PlansPageState extends State<_PlansPage> {
|
class _PlansPageState extends State<_PlansPage> {
|
||||||
late Stream<Setting> stream;
|
bool showSearch = false;
|
||||||
|
late Stream<List<Plan>> stream;
|
||||||
|
|
||||||
final TextEditingController searchController = TextEditingController();
|
@override
|
||||||
|
initState() {
|
||||||
|
super.initState();
|
||||||
|
setStream();
|
||||||
|
}
|
||||||
|
|
||||||
void reset() async {
|
void setStream() {
|
||||||
var data = await db.select(db.settings).get();
|
stream = (db.select(db.plans)
|
||||||
if (data.isEmpty) await db.into(db.settings).insert(defaultSettings);
|
..where((gymSet) => gymSet.days.contains(widget.search))
|
||||||
setState(() {
|
..limit(10, offset: 0))
|
||||||
if (data.isEmpty) return;
|
.watch();
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
didUpdateWidget(covariant _PlansPage oldWidget) {
|
||||||
super.initState();
|
super.didUpdateWidget(oldWidget);
|
||||||
stream = db.select(db.settings).watchSingle();
|
setStream();
|
||||||
|
}
|
||||||
|
|
||||||
|
void toggleSearch() {
|
||||||
|
setState(() {
|
||||||
|
showSearch = !showSearch;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
body: StreamBuilder<Setting>(
|
body: StreamBuilder<List<Plan>>(
|
||||||
stream: stream,
|
stream: stream,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
final settings = snapshot.data;
|
final plans = snapshot.data;
|
||||||
|
|
||||||
if (settings == null)
|
if (plans == null)
|
||||||
return const Center(child: CircularProgressIndicator());
|
return const Center(child: CircularProgressIndicator());
|
||||||
|
|
||||||
return SingleChildScrollView(
|
return ListView.builder(
|
||||||
padding: const EdgeInsets.all(8.0),
|
itemCount: plans.length,
|
||||||
child: material.Column(
|
itemBuilder: (context, index) {
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
return ListTile(
|
||||||
children: [
|
title: Text(plans[index].days),
|
||||||
SwitchListTile(
|
subtitle: Text(plans[index].workouts),
|
||||||
title: const Text('Alarm'),
|
onTap: () async {
|
||||||
value: settings.alarm,
|
await Navigator.push(
|
||||||
onChanged: (value) {
|
context,
|
||||||
db
|
MaterialPageRoute(
|
||||||
.update(db.settings)
|
builder: (context) => EditPlanPage(
|
||||||
.write(SettingsCompanion(alarm: Value(value)));
|
plan: plans[index].toCompanion(false)),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
},
|
},
|
||||||
),
|
|
||||||
SwitchListTile(
|
|
||||||
title: const Text('Vibrate'),
|
|
||||||
value: settings.vibrate,
|
|
||||||
onChanged: (value) {
|
|
||||||
db
|
|
||||||
.update(db.settings)
|
|
||||||
.write(SettingsCompanion(vibrate: Value(value)));
|
|
||||||
},
|
|
||||||
),
|
|
||||||
SwitchListTile(
|
|
||||||
title: const Text('Notify'),
|
|
||||||
value: settings.notify,
|
|
||||||
onChanged: (value) {
|
|
||||||
db
|
|
||||||
.update(db.settings)
|
|
||||||
.write(SettingsCompanion(notify: Value(value)));
|
|
||||||
},
|
|
||||||
),
|
|
||||||
SwitchListTile(
|
|
||||||
title: const Text('Images'),
|
|
||||||
value: settings.images,
|
|
||||||
onChanged: (value) {
|
|
||||||
db
|
|
||||||
.update(db.settings)
|
|
||||||
.write(SettingsCompanion(images: Value(value)));
|
|
||||||
},
|
|
||||||
),
|
|
||||||
SwitchListTile(
|
|
||||||
title: const Text('Show Unit'),
|
|
||||||
value: settings.showUnit,
|
|
||||||
onChanged: (value) {
|
|
||||||
db
|
|
||||||
.update(db.settings)
|
|
||||||
.write(SettingsCompanion(showUnit: Value(value)));
|
|
||||||
},
|
|
||||||
),
|
|
||||||
SwitchListTile(
|
|
||||||
title: const Text('Steps'),
|
|
||||||
value: settings.steps,
|
|
||||||
onChanged: (value) {
|
|
||||||
db
|
|
||||||
.update(db.settings)
|
|
||||||
.write(SettingsCompanion(steps: Value(value)));
|
|
||||||
},
|
|
||||||
),
|
|
||||||
TextField(
|
|
||||||
decoration: const InputDecoration(
|
|
||||||
labelText: 'Sound',
|
|
||||||
),
|
|
||||||
onChanged: (value) {
|
|
||||||
db
|
|
||||||
.update(db.settings)
|
|
||||||
.write(SettingsCompanion(sound: Value(value)));
|
|
||||||
},
|
|
||||||
),
|
|
||||||
TextField(
|
|
||||||
decoration: const InputDecoration(
|
|
||||||
labelText: 'Light Color',
|
|
||||||
),
|
|
||||||
onChanged: (value) {
|
|
||||||
db
|
|
||||||
.update(db.settings)
|
|
||||||
.write(SettingsCompanion(lightColor: Value(value)));
|
|
||||||
},
|
|
||||||
),
|
|
||||||
TextField(
|
|
||||||
decoration: const InputDecoration(
|
|
||||||
labelText: 'Dark Color',
|
|
||||||
),
|
|
||||||
onChanged: (value) {
|
|
||||||
db
|
|
||||||
.update(db.settings)
|
|
||||||
.write(SettingsCompanion(darkColor: Value(value)));
|
|
||||||
},
|
|
||||||
),
|
|
||||||
TextField(
|
|
||||||
decoration: const InputDecoration(
|
|
||||||
labelText: 'Date',
|
|
||||||
),
|
|
||||||
onChanged: (value) {
|
|
||||||
db
|
|
||||||
.update(db.settings)
|
|
||||||
.write(SettingsCompanion(date: Value(value)));
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
|
floatingActionButton: FloatingActionButton(
|
||||||
|
onPressed: () async {
|
||||||
|
await Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) => const EditPlanPage(
|
||||||
|
plan:
|
||||||
|
PlansCompanion(days: Value(''), workouts: Value(''))),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
},
|
||||||
|
child: const Icon(Icons.add)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user