Skip to content

Commit

Permalink
Merge pull request #110 from andreped/95-feat-configure-linting-for-d…
Browse files Browse the repository at this point in the history
…art-code

Configured linting and added linting CI
  • Loading branch information
andreped authored Aug 9, 2024
2 parents 8322587 + 18e0a85 commit f434955
Show file tree
Hide file tree
Showing 10 changed files with 344 additions and 80 deletions.
31 changes: 31 additions & 0 deletions .github/workflows/linting.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: Linting

on:
pull_request:
branches:
- "*"
workflow_dispatch:

jobs:
build:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3
- uses: subosito/flutter-action@v2
with:
flutter-version: '3.22.2'
channel: 'stable'
- run: flutter --version

- name: Install dependencies
run: dart pub get

- name: Verify formatting
run: dart format --output=none --set-exit-if-changed .

#- name: Analyze project source
# run: dart analyze --fatal-infos

#- name: Run tests
# run: flutter test
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
[![GitHub Downloads](https://img.shields.io/github/downloads/andreped/IronFlow/total?label=GitHub%20downloads&logo=github)](https://github.com/andreped/IronFlow/releases)
![CI](https://github.com/andreped/IronFlow/workflows/Build%20APK/badge.svg)
![CI](https://github.com/andreped/IronFlow/workflows/Build%20IPA/badge.svg)
![CI](https://github.com/andreped/IronFlow/workflows/Linting/badge.svg)
</h3>

**IronFlow** was developed to allow free, private, and seemless tracking of training progress and activities.
Expand Down Expand Up @@ -45,6 +46,7 @@ The app is compatible with both Android and iOS.
| **Build APK** | ![CI](https://github.com/andreped/IronFlow/workflows/Build%20APK/badge.svg) |
| **Build IPA** | ![CI](https://github.com/andreped/IronFlow/workflows/Build%20IPA/badge.svg) |
| **Create Release** | ![CI](https://github.com/andreped/IronFlow/workflows/Create%20Release/badge.svg) |
| **Linting** | ![CI](https://github.com/andreped/IronFlow/workflows/Linting/badge.svg) |

## [Getting Started](https://github.com/andreped/IronFlow#Getting-Started)

Expand Down
35 changes: 18 additions & 17 deletions lib/core/database.dart
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ class DatabaseHelper {
await _initializePredefinedExercises(db);
}

Future<void> _upgradeDatabase(Database db, int oldVersion, int newVersion) async {
Future<void> _upgradeDatabase(
Database db, int oldVersion, int newVersion) async {
// Placeholder for future upgrade logic
if (oldVersion < newVersion) {
// Example: if (oldVersion < 2) {
Expand Down Expand Up @@ -104,9 +105,8 @@ class DatabaseHelper {

Future<List<DateTime>> getExerciseDates() async {
final db = await database;
final List<Map<String, dynamic>> datesResult = await db.rawQuery(
'SELECT DISTINCT date(timestamp) as date FROM exercises'
);
final List<Map<String, dynamic>> datesResult = await db
.rawQuery('SELECT DISTINCT date(timestamp) as date FROM exercises');

return datesResult.map((row) {
return DateTime.parse(row['date']);
Expand Down Expand Up @@ -136,8 +136,8 @@ class DatabaseHelper {
);
}


Future<bool> isNewHighScore(String exerciseName, double newWeight, int newReps) async {
Future<bool> isNewHighScore(
String exerciseName, double newWeight, int newReps) async {
final db = await database;

// Query to get the current highest weight and corresponding reps for that weight
Expand All @@ -157,7 +157,8 @@ class DatabaseHelper {
final maxReps = row['reps'] as int;

// Check if both weight and reps are greater than the current record
if (newWeight > maxWeight || (newWeight == maxWeight && newReps > maxReps)) {
if (newWeight > maxWeight ||
(newWeight == maxWeight && newReps > maxReps)) {
return true; // New record found
}
}
Expand Down Expand Up @@ -234,7 +235,8 @@ class DatabaseHelper {

Future<List<String>> getPredefinedExercises() async {
final db = await database;
final List<Map<String, dynamic>> result = await db.query('predefined_exercises');
final List<Map<String, dynamic>> result =
await db.query('predefined_exercises');
return result.map((row) => row['name'] as String).toList();
}

Expand All @@ -243,16 +245,16 @@ class DatabaseHelper {
await db.insert(
'predefined_exercises',
{'name': exerciseName},
conflictAlgorithm: ConflictAlgorithm.ignore, // Handle if exercise already exists
conflictAlgorithm:
ConflictAlgorithm.ignore, // Handle if exercise already exists
);
}

Future<Map<String, Map<String, dynamic>>> getMaxWeightsForExercises() async {
final db = await database;

// Query to get the maximum weight and corresponding highest reps for each exercise
final List<Map<String, dynamic>> results = await db.rawQuery(
'''
final List<Map<String, dynamic>> results = await db.rawQuery('''
SELECT exercise, weight, reps
FROM exercises
WHERE (exercise, CAST(weight AS REAL)) IN (
Expand All @@ -261,8 +263,7 @@ class DatabaseHelper {
GROUP BY exercise
)
ORDER BY exercise, CAST(weight AS REAL) DESC, reps DESC
'''
);
''');

Map<String, Map<String, dynamic>> maxWeights = {};
for (var result in results) {
Expand Down Expand Up @@ -291,8 +292,8 @@ class DatabaseHelper {
return maxWeights;
}


Future<Map<String, dynamic>?> getLastLoggedExercise(String exerciseName) async {
Future<Map<String, dynamic>?> getLastLoggedExercise(
String exerciseName) async {
final db = await database;
final List<Map<String, dynamic>> result = await db.query(
'exercises',
Expand All @@ -306,12 +307,12 @@ class DatabaseHelper {
final row = result.first;
return {
'exercise': row['exercise'],
'weight': double.tryParse(row['weight']) ?? 0.0, // Convert weight to double
'weight':
double.tryParse(row['weight']) ?? 0.0, // Convert weight to double
'reps': row['reps'] as int,
'sets': row['sets'] as int,
};
}
return null;
}

}
89 changes: 48 additions & 41 deletions lib/tabs/home.dart
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ class ExerciseStoreHomePage extends StatefulWidget {
_ExerciseStoreHomePageState createState() => _ExerciseStoreHomePageState();
}

class _ExerciseStoreHomePageState extends State<ExerciseStoreHomePage> with SingleTickerProviderStateMixin {
class _ExerciseStoreHomePageState extends State<ExerciseStoreHomePage>
with SingleTickerProviderStateMixin {
final DatabaseHelper _dbHelper = DatabaseHelper();
DateTime _selectedDay = DateTime.now();
late TabController _tabController;
Expand Down Expand Up @@ -91,7 +92,8 @@ class _ExerciseStoreHomePageState extends State<ExerciseStoreHomePage> with Sing
builder: (BuildContext context) {
return AlertDialog(
title: const Text('⚠️ Confirm Deletion'),
content: const Text('🚨 Clicking this button deletes all the recorded exercise data. Are you sure you want to do this?'),
content: const Text(
'🚨 Clicking this button deletes all the recorded exercise data. Are you sure you want to do this?'),
actions: <Widget>[
TextButton(
child: const Text('No'),
Expand All @@ -112,7 +114,8 @@ class _ExerciseStoreHomePageState extends State<ExerciseStoreHomePage> with Sing
builder: (BuildContext context) {
return AlertDialog(
title: const Text('❗️ Are you really sure?'),
content: const Text('💥 Are you really sure you want to lose all your data? There is no going back!'),
content: const Text(
'💥 Are you really sure you want to lose all your data? There is no going back!'),
actions: <Widget>[
TextButton(
child: const Text('No'),
Expand Down Expand Up @@ -164,7 +167,9 @@ class _ExerciseStoreHomePageState extends State<ExerciseStoreHomePage> with Sing
tabs: const [
Tab(icon: Icon(Icons.add), text: 'Log\nExercise'),
Tab(icon: Icon(Icons.calendar_today), text: 'Summary'),
Tab(icon: Icon(Icons.celebration), text: 'Records'), // New Records tab
Tab(
icon: Icon(Icons.celebration),
text: 'Records'), // New Records tab
Tab(icon: Icon(Icons.show_chart), text: 'Visualize\nData'),
Tab(icon: Icon(Icons.table_chart), text: 'View\nTable'),
],
Expand All @@ -174,7 +179,8 @@ class _ExerciseStoreHomePageState extends State<ExerciseStoreHomePage> with Sing
bucket: bucket,
child: PageView(
controller: _pageController,
physics: const NeverScrollableScrollPhysics(), // Disable swipe gesture
physics:
const NeverScrollableScrollPhysics(), // Disable swipe gesture
onPageChanged: (index) {
_tabController.animateTo(index);
},
Expand Down Expand Up @@ -213,43 +219,44 @@ class _ExerciseStoreHomePageState extends State<ExerciseStoreHomePage> with Sing
}
final exercises = snapshot.data!;
return DataTable(
columns: const [
DataColumn(label: Text('ID')),
DataColumn(label: Text('Exercise')),
DataColumn(label: Text('Weight')),
DataColumn(label: Text('Reps')),
DataColumn(label: Text('Sets')),
DataColumn(label: Text('Timestamp')),
DataColumn(label: Text('Actions')),
],
rows: exercises.map((exercise) {
return DataRow(cells: [
DataCell(Text(exercise['id'].toString())),
DataCell(Text(exercise['exercise'])),
DataCell(Text(exercise['weight'])),
DataCell(Text(exercise['reps'].toString())),
DataCell(Text(exercise['sets'].toString())),
DataCell(Text(exercise['timestamp'])), // Display the timestamp
DataCell(
Row(
children: [
IconButton(
icon: const Icon(Icons.edit),
onPressed: () {
_showEditDialog(exercise);
},
),
IconButton(
icon: const Icon(Icons.delete),
onPressed: () async {
await _deleteExercise(exercise['id']);
},
),
],
),
columns: const [
DataColumn(label: Text('ID')),
DataColumn(label: Text('Exercise')),
DataColumn(label: Text('Weight')),
DataColumn(label: Text('Reps')),
DataColumn(label: Text('Sets')),
DataColumn(label: Text('Timestamp')),
DataColumn(label: Text('Actions')),
],
rows: exercises.map((exercise) {
return DataRow(cells: [
DataCell(Text(exercise['id'].toString())),
DataCell(Text(exercise['exercise'])),
DataCell(Text(exercise['weight'])),
DataCell(Text(exercise['reps'].toString())),
DataCell(Text(exercise['sets'].toString())),
DataCell(Text(
exercise['timestamp'])), // Display the timestamp
DataCell(
Row(
children: [
IconButton(
icon: const Icon(Icons.edit),
onPressed: () {
_showEditDialog(exercise);
},
),
IconButton(
icon: const Icon(Icons.delete),
onPressed: () async {
await _deleteExercise(exercise['id']);
},
),
],
),
]);
}).toList(),
),
]);
}).toList(),
);
},
),
Expand Down
27 changes: 19 additions & 8 deletions lib/tabs/inputs.dart
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ class _ExerciseSetterState extends State<ExerciseSetter> {
List<String> exercises = await _dbHelper.getPredefinedExercises();
setState(() {
_predefinedExercises = exercises;
_selectedExercise = _predefinedExercises.isNotEmpty ? _predefinedExercises.first : null;
_selectedExercise =
_predefinedExercises.isNotEmpty ? _predefinedExercises.first : null;
if (_selectedExercise != null) {
_loadLastLoggedExercise();
}
Expand All @@ -46,7 +47,8 @@ class _ExerciseSetterState extends State<ExerciseSetter> {

Future<void> _loadLastLoggedExercise() async {
if (_selectedExercise != null) {
final lastLogged = await _dbHelper.getLastLoggedExercise(_selectedExercise!);
final lastLogged =
await _dbHelper.getLastLoggedExercise(_selectedExercise!);
if (lastLogged != null) {
setState(() {
_lastExerciseName = lastLogged['exercise'];
Expand All @@ -71,7 +73,8 @@ class _ExerciseSetterState extends State<ExerciseSetter> {
final reps = int.parse(_repsController.text);
final sets = int.parse(_setsController.text);

final isNewHighScore = await _dbHelper.isNewHighScore(exerciseName, weight, reps);
final isNewHighScore =
await _dbHelper.isNewHighScore(exerciseName, weight, reps);

await _dbHelper.insertExercise(
exercise: exerciseName,
Expand Down Expand Up @@ -169,10 +172,16 @@ class _ExerciseSetterState extends State<ExerciseSetter> {
child: GestureDetector(
onTap: _openExerciseSelectionSheet,
child: InputDecorator(
decoration: const InputDecoration(labelText: 'Select Exercise'),
decoration:
const InputDecoration(labelText: 'Select Exercise'),
child: Text(
_isAddingNewExercise ? 'Add New Exercise' : _selectedExercise ?? 'Select Exercise',
style: TextStyle(color: _selectedExercise == null ? Colors.grey : Colors.black),
_isAddingNewExercise
? 'Add New Exercise'
: _selectedExercise ?? 'Select Exercise',
style: TextStyle(
color: _selectedExercise == null
? Colors.grey
: Colors.black),
),
),
),
Expand All @@ -184,9 +193,11 @@ class _ExerciseSetterState extends State<ExerciseSetter> {
padding: const EdgeInsets.only(top: 16.0),
child: TextFormField(
controller: _newExerciseController,
decoration: const InputDecoration(labelText: 'New Exercise Name'),
decoration:
const InputDecoration(labelText: 'New Exercise Name'),
validator: (value) {
if (_isAddingNewExercise && (value == null || value.isEmpty)) {
if (_isAddingNewExercise &&
(value == null || value.isEmpty)) {
return 'Please enter a new exercise name';
}
return null;
Expand Down
6 changes: 4 additions & 2 deletions lib/tabs/summary.dart
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ class _SummaryTabState extends State<SummaryTab> {
const Text('Select Day: '),
TextButton(
onPressed: () => _selectDate(context),
child: Text('${widget.selectedDay.year}-${widget.selectedDay.month}-${widget.selectedDay.day}'),
child: Text(
'${widget.selectedDay.year}-${widget.selectedDay.month}-${widget.selectedDay.day}'),
),
],
),
Expand All @@ -65,7 +66,8 @@ class _SummaryTabState extends State<SummaryTab> {
final totalSets = details['totalSets'];
final totalReps = details['totalReps'];
final avgWeight = details['avgWeight'];
final records = details['records'] as List<Map<String, dynamic>>;
final records =
details['records'] as List<Map<String, dynamic>>;

return Card(
child: ExpansionTile(
Expand Down
Loading

0 comments on commit f434955

Please sign in to comment.