Compare commits
11 Commits
feature/12
...
feature/88
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e2fe0c7d4d | ||
|
|
b72ab70e02 | ||
|
|
189daf76dd | ||
|
|
0f987f4c7a | ||
|
|
5dd8f31942 | ||
|
|
0394f5edf9 | ||
|
|
d8abad6fd8 | ||
|
|
7e6c309de0 | ||
|
|
3344575132 | ||
|
|
9b66e58dc0 | ||
|
|
56562b22bb |
35
.gitea/ISSUE_TEMPLATE/BUG_REPORT.md
Normal file
35
.gitea/ISSUE_TEMPLATE/BUG_REPORT.md
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
---
|
||||||
|
name: Bug report
|
||||||
|
about: Erstelle eine Meldung für etwas, das nicht Funktioniert, wie es soll.
|
||||||
|
title: ''
|
||||||
|
labels: 'Task/Bug'
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Bug Report
|
||||||
|
|
||||||
|
## Beschreibung
|
||||||
|
[Eine klare und prägnante Beschreibung des Bugs]
|
||||||
|
|
||||||
|
## Schritte zur Reproduktion
|
||||||
|
1. Schritt 1
|
||||||
|
2. Schritt 2
|
||||||
|
3. ...
|
||||||
|
|
||||||
|
## Erwartetes Verhalten
|
||||||
|
[Was hätte passieren sollen]
|
||||||
|
|
||||||
|
## Tatsächliches Verhalten
|
||||||
|
[Was tatsächlich passiert ist]
|
||||||
|
|
||||||
|
## Screenshots/Protokolle
|
||||||
|
[Falls zutreffend, füge Screenshots, Error Logs oder Stack Traces hinzu]
|
||||||
|
|
||||||
|
## Umgebung
|
||||||
|
- Plattform: Android, iOS, Web
|
||||||
|
- OS: [z. B. iOS 18.5, Android 14]
|
||||||
|
- Flutter Version: [z.B. 3.35.6]
|
||||||
|
|
||||||
|
## Verwandte Issues
|
||||||
|
[Verweisen Sie auf ähnliche Issues oder PRs]
|
||||||
22
.gitea/ISSUE_TEMPLATE/ENHANCEMENT.md
Normal file
22
.gitea/ISSUE_TEMPLATE/ENHANCEMENT.md
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
---
|
||||||
|
name: Enhancement
|
||||||
|
about: Enhancements for current features
|
||||||
|
title: ''
|
||||||
|
labels: 'Task\Enhancement'
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Enhancement
|
||||||
|
|
||||||
|
## Aktuelles Verhalten
|
||||||
|
[Beschreibe die bestehende Funktionalität]
|
||||||
|
|
||||||
|
## Einschränkungen/Probleme
|
||||||
|
[Was sind die aktuellen Mängel?]
|
||||||
|
|
||||||
|
## Vorgeschlagene Verbesserung
|
||||||
|
[Wie kann das Problem bzw. die Einschränkung verbessert werden?]
|
||||||
|
|
||||||
|
## Zugehörige Issues
|
||||||
|
[Links zu verwandten oder blockierenden Issues]
|
||||||
19
.gitea/ISSUE_TEMPLATE/FEATURE.md
Normal file
19
.gitea/ISSUE_TEMPLATE/FEATURE.md
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
---
|
||||||
|
name: Feature
|
||||||
|
about: Neues Feature für die App
|
||||||
|
title: ''
|
||||||
|
labels: 'Task\Feature'
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Feature
|
||||||
|
|
||||||
|
## Beschreibung
|
||||||
|
[Ausführliche Erläuterung der vorgeschlagenen Funktion]
|
||||||
|
|
||||||
|
## Vorgeschlagene Lösung
|
||||||
|
[Beschreibe, wie die Feature funktionieren soll]
|
||||||
|
|
||||||
|
## Zugehörige Issues
|
||||||
|
[Links zu verwandten oder blockierenden Issues]
|
||||||
16
.gitea/PULL_REQUEST_TEMPLATE.md
Normal file
16
.gitea/PULL_REQUEST_TEMPLATE.md
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
# [PR Titel]
|
||||||
|
|
||||||
|
**Zugehörige Issue(s):**
|
||||||
|
Closes `<issue-no>`
|
||||||
|
|
||||||
|
## Beschreibung
|
||||||
|
*Eine klare und prägnante Übersicht über die vorgenommenen Änderungen. Erläutere nicht nur das was gemacht wurde, sondern auch warum.*
|
||||||
|
|
||||||
|
## Änderungen
|
||||||
|
- [ ] Neue Funktion X hinzugefügt
|
||||||
|
- [ ] Bug in Komponente Y behoben
|
||||||
|
- [ ] Modul Z für bessere Leistung refactored
|
||||||
|
- [ ] Dependencies aktualisiert
|
||||||
|
|
||||||
|
## Zusätzliche Anmerkungen
|
||||||
|
*Gibt es zusätzlichen Kontext, Einschränkungen oder Informationen, die Reviewer wissen sollten?*
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
name: Bug Report
|
|
||||||
about: Erstelle eine Bug Report
|
|
||||||
labels: 'Task/Bug'
|
|
||||||
title: ''
|
|
||||||
body:
|
|
||||||
- type: textarea
|
|
||||||
id: description
|
|
||||||
attributes:
|
|
||||||
label: Beschreibung
|
|
||||||
description: Beschreibe klar und pregnant das Fehlerverhalten
|
|
||||||
placeholder: |
|
|
||||||
- Was genau ist das unerwünschte Verhalten?
|
|
||||||
- Welche Auswirkungen hat der Fehler?
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: reproduce
|
|
||||||
attributes:
|
|
||||||
label: Schritte zur Reproduktion
|
|
||||||
description: Beschreibe, wie der Fehler reproduziert werden kann
|
|
||||||
placeholder: |
|
|
||||||
- 1. Schritt 1
|
|
||||||
- 2. Schritt 2
|
|
||||||
- 3. ...
|
|
||||||
|
|
||||||
- type: dropdown
|
|
||||||
id: enviroment
|
|
||||||
attributes:
|
|
||||||
label: Umgebung
|
|
||||||
description: Gebe an, auf welchen Platformen dieser Fehler auftritt
|
|
||||||
list: false
|
|
||||||
multiple: true
|
|
||||||
options: ['Android', 'iOS']
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: bahaviour
|
|
||||||
attributes:
|
|
||||||
label: Unerwünschtes Verhalten
|
|
||||||
description: Beschreibe, was passiert ist, obwohl es nicht passieren sollte
|
|
||||||
placeholder: Bei Verhalten X tritt folgendes Verhalten auf ...
|
|
||||||
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
attributes:
|
|
||||||
label: Verwandte Issues
|
|
||||||
description: Verweise auf ähnliche Issues oder PRs
|
|
||||||
placeholder: |
|
|
||||||
- Knüpft an Issue #35 an
|
|
||||||
- Ersetzt Issue #12
|
|
||||||
- Brauch Implementierung von #43
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
name: Enhancement
|
|
||||||
about: Erstelle ein Enhancement-Ticket
|
|
||||||
labels: 'Task/Enhancement'
|
|
||||||
title: ''
|
|
||||||
body:
|
|
||||||
- type: textarea
|
|
||||||
id: description
|
|
||||||
attributes:
|
|
||||||
label: Aktuelles Verhalten
|
|
||||||
description: Beschreibe, wie die Funktionalität aktuell gestaltet ist
|
|
||||||
placeholder: |
|
|
||||||
- Aktuell macht Button X folgendes ...
|
|
||||||
- Das Problem ist, dass ...
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: solution
|
|
||||||
attributes:
|
|
||||||
label: Vorgeschlagene Verbesserung
|
|
||||||
description: Beschreibe, wie das Problem bzw. die Einschränkung verbessert werden kann
|
|
||||||
placeholder: |
|
|
||||||
- Button X ändern, sodass ...
|
|
||||||
- Funktion X so erweitern, dass ...
|
|
||||||
- Design anpassen, sodass ...
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
attributes:
|
|
||||||
label: Zugehörige Issues
|
|
||||||
description: Links zu verwandten oder blockierenden Issues
|
|
||||||
placeholder: |
|
|
||||||
- Knüpft an Issue #35 an
|
|
||||||
- Ersetzt Issue #12
|
|
||||||
- Brauch Implementierung von #43
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
name: Feature
|
|
||||||
about: Erstelle ein Feature-Ticket
|
|
||||||
labels: 'Task/Feature'
|
|
||||||
title: ''
|
|
||||||
body:
|
|
||||||
- type: textarea
|
|
||||||
id: description
|
|
||||||
attributes:
|
|
||||||
label: Beschreibung
|
|
||||||
description: Ausführliche Erläuterung der vorgeschlagenen Funktion
|
|
||||||
placeholder: |
|
|
||||||
- Welchen Zweck erfüllt das Feature?
|
|
||||||
- Welches Problem löst das Feature?
|
|
||||||
- Wer profitiert davon?
|
|
||||||
- Warum ist es wichtig?
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: solution
|
|
||||||
attributes:
|
|
||||||
label: Vorgeschlagene Lösung
|
|
||||||
description: Beschreibe, wie das Feature funktionieren soll
|
|
||||||
placeholder: |
|
|
||||||
- Neues Widget, das folgendermaßen aussieht ...
|
|
||||||
- Neue Ansicht, die folgende Inhalte hat
|
|
||||||
- Neue Funktionsweise von Komponente XY
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
attributes:
|
|
||||||
label: Zugehörige Issues
|
|
||||||
description: Links zu verwandten oder blockierenden Issues
|
|
||||||
placeholder: |
|
|
||||||
- Knüpft an Issue #35 an
|
|
||||||
- Ersetzt Issue #12
|
|
||||||
- Brauch Implementierung von #43
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
name: Pull Request
|
|
||||||
about: Vorlage für Pull Requests
|
|
||||||
title: "WIP: [Name des Issues]"
|
|
||||||
|
|
||||||
body:
|
|
||||||
- type: input
|
|
||||||
id: related_issue
|
|
||||||
attributes:
|
|
||||||
label: Zugehörige Issue(s)
|
|
||||||
description: Issues welche mit diesem Pull Request geschlossen werden sollen
|
|
||||||
placeholder: "Closes #123"
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: description
|
|
||||||
attributes:
|
|
||||||
label: Beschreibung
|
|
||||||
description: |
|
|
||||||
Eine klare und prägnante Zusammenfassung aller vorgenommenen Änderungen.
|
|
||||||
placeholder: |
|
|
||||||
Was wurde geändert?
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: changes
|
|
||||||
attributes:
|
|
||||||
label: Änderungen
|
|
||||||
description: Liste alle Änderungen detailiert auf, die in diesem Pull Request vorgenommen wurden.
|
|
||||||
placeholder: |
|
|
||||||
- Neue Funktion X hinzugefügt
|
|
||||||
- Bug in Komponente X behoben
|
|
||||||
- Modul X für bessere Leistung refactored
|
|
||||||
- Dependencies aktualisiert
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: additional_notes
|
|
||||||
attributes:
|
|
||||||
label: Zusätzliche Anmerkungen
|
|
||||||
description: |
|
|
||||||
Gibt es zusätzlichen Kontext, Einschränkungen oder Informationen,
|
|
||||||
die Reviewer wissen sollten?
|
|
||||||
placeholder: |
|
|
||||||
- Bekannte Einschränkungen
|
|
||||||
- Offene TODOs
|
|
||||||
- Hinweise für Reviewer
|
|
||||||
@@ -1,98 +0,0 @@
|
|||||||
import 'package:drift/drift.dart';
|
|
||||||
import 'package:game_tracker/data/db/database.dart';
|
|
||||||
import 'package:game_tracker/data/db/tables/group_match_table.dart';
|
|
||||||
import 'package:game_tracker/data/dto/group.dart';
|
|
||||||
|
|
||||||
part 'group_match_dao.g.dart';
|
|
||||||
|
|
||||||
@DriftAccessor(tables: [GroupMatchTable])
|
|
||||||
class GroupMatchDao extends DatabaseAccessor<AppDatabase>
|
|
||||||
with _$GroupMatchDaoMixin {
|
|
||||||
GroupMatchDao(super.db);
|
|
||||||
|
|
||||||
/// Associates a group with a match by inserting a record into the
|
|
||||||
/// [GroupMatchTable].
|
|
||||||
Future<void> addGroupToMatch({
|
|
||||||
required String matchId,
|
|
||||||
required String groupId,
|
|
||||||
}) async {
|
|
||||||
if (await matchHasGroup(matchId: matchId)) {
|
|
||||||
throw Exception('Match already has a group');
|
|
||||||
}
|
|
||||||
await into(groupMatchTable).insert(
|
|
||||||
GroupMatchTableCompanion.insert(groupId: groupId, matchId: matchId),
|
|
||||||
mode: InsertMode.insertOrIgnore,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Retrieves the [Group] associated with the given [matchId].
|
|
||||||
/// Returns `null` if no group is found.
|
|
||||||
Future<Group?> getGroupOfMatch({required String matchId}) async {
|
|
||||||
final result = await (select(
|
|
||||||
groupMatchTable,
|
|
||||||
)..where((g) => g.matchId.equals(matchId))).getSingleOrNull();
|
|
||||||
|
|
||||||
if (result == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
final group = await db.groupDao.getGroupById(groupId: result.groupId);
|
|
||||||
return group;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Checks if there is a group associated with the given [matchId].
|
|
||||||
/// Returns `true` if there is a group, otherwise `false`.
|
|
||||||
Future<bool> matchHasGroup({required String matchId}) async {
|
|
||||||
final count =
|
|
||||||
await (selectOnly(groupMatchTable)
|
|
||||||
..where(groupMatchTable.matchId.equals(matchId))
|
|
||||||
..addColumns([groupMatchTable.groupId.count()]))
|
|
||||||
.map((row) => row.read(groupMatchTable.groupId.count()))
|
|
||||||
.getSingle();
|
|
||||||
return (count ?? 0) > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Checks if a specific group is associated with a specific match.
|
|
||||||
/// Returns `true` if the group is in the match, otherwise `false`.
|
|
||||||
Future<bool> isGroupInMatch({
|
|
||||||
required String matchId,
|
|
||||||
required String groupId,
|
|
||||||
}) async {
|
|
||||||
final count =
|
|
||||||
await (selectOnly(groupMatchTable)
|
|
||||||
..where(
|
|
||||||
groupMatchTable.matchId.equals(matchId) &
|
|
||||||
groupMatchTable.groupId.equals(groupId),
|
|
||||||
)
|
|
||||||
..addColumns([groupMatchTable.groupId.count()]))
|
|
||||||
.map((row) => row.read(groupMatchTable.groupId.count()))
|
|
||||||
.getSingle();
|
|
||||||
return (count ?? 0) > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Removes the association of a group from a match based on [groupId] and
|
|
||||||
/// [matchId].
|
|
||||||
/// Returns `true` if more than 0 rows were affected, otherwise `false`.
|
|
||||||
Future<bool> removeGroupFromMatch({
|
|
||||||
required String matchId,
|
|
||||||
required String groupId,
|
|
||||||
}) async {
|
|
||||||
final query = delete(groupMatchTable)
|
|
||||||
..where((g) => g.matchId.equals(matchId) & g.groupId.equals(groupId));
|
|
||||||
final rowsAffected = await query.go();
|
|
||||||
return rowsAffected > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Updates the group associated with a match to [newGroupId] based on
|
|
||||||
/// [matchId].
|
|
||||||
/// Returns `true` if more than 0 rows were affected, otherwise `false`.
|
|
||||||
Future<bool> updateGroupOfMatch({
|
|
||||||
required String matchId,
|
|
||||||
required String newGroupId,
|
|
||||||
}) async {
|
|
||||||
final updatedRows =
|
|
||||||
await (update(groupMatchTable)..where((g) => g.matchId.equals(matchId)))
|
|
||||||
.write(GroupMatchTableCompanion(groupId: Value(newGroupId)));
|
|
||||||
return updatedRows > 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
|
||||||
|
|
||||||
part of 'group_match_dao.dart';
|
|
||||||
|
|
||||||
// ignore_for_file: type=lint
|
|
||||||
mixin _$GroupMatchDaoMixin on DatabaseAccessor<AppDatabase> {
|
|
||||||
$GroupTableTable get groupTable => attachedDatabase.groupTable;
|
|
||||||
$MatchTableTable get matchTable => attachedDatabase.matchTable;
|
|
||||||
$GroupMatchTableTable get groupMatchTable => attachedDatabase.groupMatchTable;
|
|
||||||
}
|
|
||||||
@@ -1,12 +1,10 @@
|
|||||||
import 'package:drift/drift.dart';
|
import 'package:drift/drift.dart';
|
||||||
import 'package:drift_flutter/drift_flutter.dart';
|
import 'package:drift_flutter/drift_flutter.dart';
|
||||||
import 'package:game_tracker/data/dao/group_dao.dart';
|
import 'package:game_tracker/data/dao/group_dao.dart';
|
||||||
import 'package:game_tracker/data/dao/group_match_dao.dart';
|
|
||||||
import 'package:game_tracker/data/dao/match_dao.dart';
|
import 'package:game_tracker/data/dao/match_dao.dart';
|
||||||
import 'package:game_tracker/data/dao/player_dao.dart';
|
import 'package:game_tracker/data/dao/player_dao.dart';
|
||||||
import 'package:game_tracker/data/dao/player_group_dao.dart';
|
import 'package:game_tracker/data/dao/player_group_dao.dart';
|
||||||
import 'package:game_tracker/data/dao/player_match_dao.dart';
|
import 'package:game_tracker/data/dao/player_match_dao.dart';
|
||||||
import 'package:game_tracker/data/db/tables/group_match_table.dart';
|
|
||||||
import 'package:game_tracker/data/db/tables/group_table.dart';
|
import 'package:game_tracker/data/db/tables/group_table.dart';
|
||||||
import 'package:game_tracker/data/db/tables/match_table.dart';
|
import 'package:game_tracker/data/db/tables/match_table.dart';
|
||||||
import 'package:game_tracker/data/db/tables/player_group_table.dart';
|
import 'package:game_tracker/data/db/tables/player_group_table.dart';
|
||||||
@@ -22,16 +20,14 @@ part 'database.g.dart';
|
|||||||
GroupTable,
|
GroupTable,
|
||||||
MatchTable,
|
MatchTable,
|
||||||
PlayerGroupTable,
|
PlayerGroupTable,
|
||||||
PlayerMatchTable,
|
PlayerMatchTable
|
||||||
GroupMatchTable,
|
|
||||||
],
|
],
|
||||||
daos: [
|
daos: [
|
||||||
PlayerDao,
|
PlayerDao,
|
||||||
GroupDao,
|
GroupDao,
|
||||||
MatchDao,
|
MatchDao,
|
||||||
PlayerGroupDao,
|
PlayerGroupDao,
|
||||||
PlayerMatchDao,
|
PlayerMatchDao
|
||||||
GroupMatchDao,
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
class AppDatabase extends _$AppDatabase {
|
class AppDatabase extends _$AppDatabase {
|
||||||
|
|||||||
14
lib/data/db/tables/game_table.dart
Normal file
14
lib/data/db/tables/game_table.dart
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import 'package:drift/drift.dart';
|
||||||
|
|
||||||
|
class GameTable extends Table {
|
||||||
|
TextColumn get id => text()();
|
||||||
|
TextColumn get name => text()();
|
||||||
|
TextColumn get ruleset => text()();
|
||||||
|
TextColumn get description => text().nullable()();
|
||||||
|
TextColumn get color => text().nullable()();
|
||||||
|
TextColumn get icon => text().nullable()();
|
||||||
|
DateTimeColumn get createdAt => dateTime()();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Set<Column<Object>> get primaryKey => {id};
|
||||||
|
}
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
import 'package:drift/drift.dart';
|
|
||||||
import 'package:game_tracker/data/db/tables/group_table.dart';
|
|
||||||
import 'package:game_tracker/data/db/tables/match_table.dart';
|
|
||||||
|
|
||||||
class GroupMatchTable extends Table {
|
|
||||||
TextColumn get groupId =>
|
|
||||||
text().references(GroupTable, #id, onDelete: KeyAction.cascade)();
|
|
||||||
TextColumn get matchId =>
|
|
||||||
text().references(MatchTable, #id, onDelete: KeyAction.cascade)();
|
|
||||||
|
|
||||||
@override
|
|
||||||
Set<Column<Object>> get primaryKey => {groupId, matchId};
|
|
||||||
}
|
|
||||||
@@ -3,6 +3,7 @@ import 'package:drift/drift.dart';
|
|||||||
class GroupTable extends Table {
|
class GroupTable extends Table {
|
||||||
TextColumn get id => text()();
|
TextColumn get id => text()();
|
||||||
TextColumn get name => text()();
|
TextColumn get name => text()();
|
||||||
|
TextColumn get description => text().nullable()();
|
||||||
DateTimeColumn get createdAt => dateTime()();
|
DateTimeColumn get createdAt => dateTime()();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@@ -1,9 +1,15 @@
|
|||||||
import 'package:drift/drift.dart';
|
import 'package:drift/drift.dart';
|
||||||
|
import 'package:game_tracker/data/db/tables/game_table.dart';
|
||||||
|
import 'package:game_tracker/data/db/tables/group_table.dart';
|
||||||
|
|
||||||
class MatchTable extends Table {
|
class MatchTable extends Table {
|
||||||
TextColumn get id => text()();
|
TextColumn get id => text()();
|
||||||
TextColumn get name => text()();
|
TextColumn get gameId =>
|
||||||
late final winnerId = text().nullable()();
|
text().references(GameTable, #id, onDelete: KeyAction.cascade)();
|
||||||
|
TextColumn get groupId =>
|
||||||
|
text().references(GroupTable, #id, onDelete: KeyAction.cascade).nullable()(); // Nullable if not part of a group
|
||||||
|
TextColumn get name => text().nullable()();
|
||||||
|
TextColumn get notes => text().nullable()();
|
||||||
DateTimeColumn get createdAt => dateTime()();
|
DateTimeColumn get createdAt => dateTime()();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@@ -1,12 +1,16 @@
|
|||||||
import 'package:drift/drift.dart';
|
import 'package:drift/drift.dart';
|
||||||
import 'package:game_tracker/data/db/tables/match_table.dart';
|
import 'package:game_tracker/data/db/tables/match_table.dart';
|
||||||
import 'package:game_tracker/data/db/tables/player_table.dart';
|
import 'package:game_tracker/data/db/tables/player_table.dart';
|
||||||
|
import 'package:game_tracker/data/db/tables/team_table.dart';
|
||||||
|
|
||||||
class PlayerMatchTable extends Table {
|
class PlayerMatchTable extends Table {
|
||||||
TextColumn get playerId =>
|
TextColumn get playerId =>
|
||||||
text().references(PlayerTable, #id, onDelete: KeyAction.cascade)();
|
text().references(PlayerTable, #id, onDelete: KeyAction.cascade)();
|
||||||
TextColumn get matchId =>
|
TextColumn get matchId =>
|
||||||
text().references(MatchTable, #id, onDelete: KeyAction.cascade)();
|
text().references(MatchTable, #id, onDelete: KeyAction.cascade)();
|
||||||
|
TextColumn get teamId =>
|
||||||
|
text().references(TeamTable, #id).nullable()();
|
||||||
|
IntColumn get score => integer()();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Set<Column<Object>> get primaryKey => {playerId, matchId};
|
Set<Column<Object>> get primaryKey => {playerId, matchId};
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import 'package:drift/drift.dart';
|
|||||||
class PlayerTable extends Table {
|
class PlayerTable extends Table {
|
||||||
TextColumn get id => text()();
|
TextColumn get id => text()();
|
||||||
TextColumn get name => text()();
|
TextColumn get name => text()();
|
||||||
|
TextColumn get description => text().nullable()();
|
||||||
DateTimeColumn get createdAt => dateTime()();
|
DateTimeColumn get createdAt => dateTime()();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
16
lib/data/db/tables/score_table.dart
Normal file
16
lib/data/db/tables/score_table.dart
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import 'package:drift/drift.dart';
|
||||||
|
import 'package:game_tracker/data/db/tables/match_table.dart';
|
||||||
|
import 'package:game_tracker/data/db/tables/player_table.dart';
|
||||||
|
|
||||||
|
class ScoreTable extends Table {
|
||||||
|
TextColumn get playerId =>
|
||||||
|
text().references(PlayerTable, #id, onDelete: KeyAction.cascade)();
|
||||||
|
TextColumn get matchId =>
|
||||||
|
text().references(MatchTable, #id, onDelete: KeyAction.cascade)();
|
||||||
|
IntColumn get roundNumber => integer()();
|
||||||
|
IntColumn get score => integer()();
|
||||||
|
IntColumn get change => integer()();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Set<Column<Object>> get primaryKey => {playerId, matchId, roundNumber};
|
||||||
|
}
|
||||||
9
lib/data/db/tables/team_table.dart
Normal file
9
lib/data/db/tables/team_table.dart
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import 'package:drift/drift.dart';
|
||||||
|
|
||||||
|
class TeamTable extends Table {
|
||||||
|
TextColumn get id => text()();
|
||||||
|
TextColumn get name => text()();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Set<Column<Object>> get primaryKey => {id};
|
||||||
|
}
|
||||||
@@ -5,7 +5,6 @@ import 'package:game_tracker/l10n/generated/app_localizations.dart';
|
|||||||
import 'package:game_tracker/presentation/widgets/tiles/settings_list_tile.dart';
|
import 'package:game_tracker/presentation/widgets/tiles/settings_list_tile.dart';
|
||||||
import 'package:game_tracker/services/data_transfer_service.dart';
|
import 'package:game_tracker/services/data_transfer_service.dart';
|
||||||
import 'package:package_info_plus/package_info_plus.dart';
|
import 'package:package_info_plus/package_info_plus.dart';
|
||||||
import 'package:game_tracker/presentation/widgets/custom_alert_dialog.dart';
|
|
||||||
|
|
||||||
class SettingsView extends StatefulWidget {
|
class SettingsView extends StatefulWidget {
|
||||||
const SettingsView({super.key});
|
const SettingsView({super.key});
|
||||||
@@ -93,17 +92,17 @@ class _SettingsViewState extends State<SettingsView> {
|
|||||||
onPressed: () {
|
onPressed: () {
|
||||||
showDialog<bool>(
|
showDialog<bool>(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => CustomAlertDialog(
|
builder: (context) => AlertDialog(
|
||||||
title: '${loc.delete_all_data}?',
|
title: Text('${loc.delete_all_data}?'),
|
||||||
content: loc.this_cannot_be_undone,
|
content: Text(loc.this_cannot_be_undone),
|
||||||
actions: [
|
actions: [
|
||||||
_PressableButton(
|
TextButton(
|
||||||
onPressed: () => Navigator.of(context).pop(false),
|
onPressed: () => Navigator.of(context).pop(false),
|
||||||
child: Text(loc.cancel, style: const TextStyle(color: CustomTheme.textColor)),
|
child: Text(loc.cancel),
|
||||||
),
|
),
|
||||||
_PressableButton(
|
TextButton(
|
||||||
onPressed: () => Navigator.of(context).pop(true),
|
onPressed: () => Navigator.of(context).pop(true),
|
||||||
child: Text(loc.delete, style: TextStyle(color: CustomTheme.secondaryColor)),
|
child: Text(loc.delete),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -218,59 +217,3 @@ class _SettingsViewState extends State<SettingsView> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _PressableButton extends StatefulWidget {
|
|
||||||
final VoidCallback onPressed;
|
|
||||||
final Widget child;
|
|
||||||
|
|
||||||
const _PressableButton({required this.onPressed, required this.child});
|
|
||||||
|
|
||||||
@override
|
|
||||||
State<_PressableButton> createState() => _PressableButtonState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _PressableButtonState extends State<_PressableButton> {
|
|
||||||
bool _isPressed = false;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return GestureDetector(
|
|
||||||
onTapDown: (_) => setState(() => _isPressed = true),
|
|
||||||
onTapUp: (_) => setState(() => _isPressed = false),
|
|
||||||
onTapCancel: () => setState(() => _isPressed = false),
|
|
||||||
onTap: widget.onPressed,
|
|
||||||
child: AnimatedScale(
|
|
||||||
scale: _isPressed ? 0.95 : 1.0,
|
|
||||||
duration: const Duration(milliseconds: 100),
|
|
||||||
child: AnimatedOpacity(
|
|
||||||
opacity: _isPressed ? 0.6 : 1.0,
|
|
||||||
duration: const Duration(milliseconds: 100),
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.all(8.0),
|
|
||||||
child: widget.child,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
TextButton(
|
|
||||||
style: TextButton.styleFrom(
|
|
||||||
splashFactory: NoSplash.splashFactory,
|
|
||||||
overlayColor: Colors.transparent,
|
|
||||||
),
|
|
||||||
onPressed: () => Navigator.of(context).pop(false),
|
|
||||||
child: Text(loc.cancel, style: const TextStyle(color: CustomTheme.textColor),),
|
|
||||||
),
|
|
||||||
TextButton(
|
|
||||||
style: TextButton.styleFrom(
|
|
||||||
splashFactory: NoSplash.splashFactory,
|
|
||||||
overlayColor: Colors.transparent,
|
|
||||||
),
|
|
||||||
onPressed: () => Navigator.of(context).pop(true),
|
|
||||||
child: Text(loc.delete, style: TextStyle(color: CustomTheme.secondaryColor),),
|
|
||||||
),
|
|
||||||
*/
|
|
||||||
|
|||||||
@@ -1,30 +0,0 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:game_tracker/core/custom_theme.dart';
|
|
||||||
|
|
||||||
class CustomAlertDialog extends StatelessWidget {
|
|
||||||
final String title;
|
|
||||||
final String content;
|
|
||||||
final List<Widget> actions;
|
|
||||||
|
|
||||||
const CustomAlertDialog({
|
|
||||||
super.key,
|
|
||||||
required this.title,
|
|
||||||
required this.content,
|
|
||||||
required this.actions,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return AlertDialog(
|
|
||||||
title: Text(title, style: const TextStyle(color: CustomTheme.textColor,),),
|
|
||||||
content: Text(content, style: const TextStyle(color: CustomTheme.textColor),),
|
|
||||||
actions: actions,
|
|
||||||
backgroundColor: CustomTheme.boxColor,
|
|
||||||
actionsAlignment: MainAxisAlignment.spaceAround,
|
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius: CustomTheme.standardBorderRadiusAll,
|
|
||||||
side: BorderSide(color: CustomTheme.boxBorder),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user