1 Commits

Author SHA1 Message Date
gelbeinhalb
8bd53a69c3 add soft delete parameter 2026-04-19 12:39:14 +02:00
14 changed files with 78 additions and 122 deletions

View File

@@ -8,6 +8,7 @@ class GameTable extends Table {
TextColumn get color => text()(); TextColumn get color => text()();
TextColumn get icon => text()(); TextColumn get icon => text()();
DateTimeColumn get createdAt => dateTime()(); DateTimeColumn get createdAt => dateTime()();
BoolColumn get deleted => boolean().withDefault(const Constant(false))();
@override @override
Set<Column<Object>> get primaryKey => {id}; Set<Column<Object>> get primaryKey => {id};

View File

@@ -5,6 +5,7 @@ class GroupTable extends Table {
TextColumn get name => text()(); TextColumn get name => text()();
TextColumn get description => text()(); TextColumn get description => text()();
DateTimeColumn get createdAt => dateTime()(); DateTimeColumn get createdAt => dateTime()();
BoolColumn get deleted => boolean().withDefault(const Constant(false))();
@override @override
Set<Column<Object>> get primaryKey => {id}; Set<Column<Object>> get primaryKey => {id};

View File

@@ -15,6 +15,7 @@ class MatchTable extends Table {
TextColumn get notes => text().nullable()(); TextColumn get notes => text().nullable()();
DateTimeColumn get createdAt => dateTime()(); DateTimeColumn get createdAt => dateTime()();
DateTimeColumn get endedAt => dateTime().nullable()(); DateTimeColumn get endedAt => dateTime().nullable()();
BoolColumn get deleted => boolean().withDefault(const Constant(false))();
@override @override
Set<Column<Object>> get primaryKey => {id}; Set<Column<Object>> get primaryKey => {id};

View File

@@ -7,6 +7,7 @@ class PlayerGroupTable extends Table {
text().references(PlayerTable, #id, onDelete: KeyAction.cascade)(); text().references(PlayerTable, #id, onDelete: KeyAction.cascade)();
TextColumn get groupId => TextColumn get groupId =>
text().references(GroupTable, #id, onDelete: KeyAction.cascade)(); text().references(GroupTable, #id, onDelete: KeyAction.cascade)();
BoolColumn get deleted => boolean().withDefault(const Constant(false))();
@override @override
Set<Column<Object>> get primaryKey => {playerId, groupId}; Set<Column<Object>> get primaryKey => {playerId, groupId};

View File

@@ -9,6 +9,7 @@ class PlayerMatchTable extends Table {
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()(); TextColumn get teamId => text().references(TeamTable, #id).nullable()();
BoolColumn get deleted => boolean().withDefault(const Constant(false))();
@override @override
Set<Column<Object>> get primaryKey => {playerId, matchId}; Set<Column<Object>> get primaryKey => {playerId, matchId};

View File

@@ -5,6 +5,7 @@ class PlayerTable extends Table {
TextColumn get name => text()(); TextColumn get name => text()();
TextColumn get description => text()(); TextColumn get description => text()();
DateTimeColumn get createdAt => dateTime()(); DateTimeColumn get createdAt => dateTime()();
BoolColumn get deleted => boolean().withDefault(const Constant(false))();
@override @override
Set<Column<Object>> get primaryKey => {id}; Set<Column<Object>> get primaryKey => {id};

View File

@@ -10,6 +10,7 @@ class ScoreEntryTable extends Table {
IntColumn get roundNumber => integer()(); IntColumn get roundNumber => integer()();
IntColumn get score => integer()(); IntColumn get score => integer()();
IntColumn get change => integer()(); IntColumn get change => integer()();
BoolColumn get deleted => boolean().withDefault(const Constant(false))();
@override @override
Set<Column<Object>> get primaryKey => {playerId, matchId, roundNumber}; Set<Column<Object>> get primaryKey => {playerId, matchId, roundNumber};

View File

@@ -4,6 +4,7 @@ class TeamTable extends Table {
TextColumn get id => text()(); TextColumn get id => text()();
TextColumn get name => text()(); TextColumn get name => text()();
DateTimeColumn get createdAt => dateTime()(); DateTimeColumn get createdAt => dateTime()();
BoolColumn get deleted => boolean().withDefault(const Constant(false))();
@override @override
Set<Column<Object>> get primaryKey => {id}; Set<Column<Object>> get primaryKey => {id};

View File

@@ -3,7 +3,6 @@ import 'package:intl/intl.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:tallee/core/adaptive_page_route.dart'; import 'package:tallee/core/adaptive_page_route.dart';
import 'package:tallee/core/custom_theme.dart'; import 'package:tallee/core/custom_theme.dart';
import 'package:tallee/core/enums.dart';
import 'package:tallee/data/db/database.dart'; import 'package:tallee/data/db/database.dart';
import 'package:tallee/data/models/group.dart'; import 'package:tallee/data/models/group.dart';
import 'package:tallee/data/models/match.dart'; import 'package:tallee/data/models/match.dart';
@@ -11,10 +10,10 @@ import 'package:tallee/data/models/player.dart';
import 'package:tallee/l10n/generated/app_localizations.dart'; import 'package:tallee/l10n/generated/app_localizations.dart';
import 'package:tallee/presentation/views/main_menu/group_view/create_group_view.dart'; import 'package:tallee/presentation/views/main_menu/group_view/create_group_view.dart';
import 'package:tallee/presentation/widgets/app_skeleton.dart'; import 'package:tallee/presentation/widgets/app_skeleton.dart';
import 'package:tallee/presentation/widgets/buttons/animated_dialog_button.dart';
import 'package:tallee/presentation/widgets/buttons/main_menu_button.dart'; import 'package:tallee/presentation/widgets/buttons/main_menu_button.dart';
import 'package:tallee/presentation/widgets/colored_icon_container.dart'; import 'package:tallee/presentation/widgets/colored_icon_container.dart';
import 'package:tallee/presentation/widgets/dialog/custom_alert_dialog.dart'; import 'package:tallee/presentation/widgets/custom_alert_dialog.dart';
import 'package:tallee/presentation/widgets/dialog/custom_dialog_action.dart';
import 'package:tallee/presentation/widgets/tiles/info_tile.dart'; import 'package:tallee/presentation/widgets/tiles/info_tile.dart';
import 'package:tallee/presentation/widgets/tiles/text_icon_tile.dart'; import 'package:tallee/presentation/widgets/tiles/text_icon_tile.dart';
@@ -71,16 +70,23 @@ class _GroupDetailViewState extends State<GroupDetailView> {
context: context, context: context,
builder: (context) => CustomAlertDialog( builder: (context) => CustomAlertDialog(
title: '${loc.delete_group}?', title: '${loc.delete_group}?',
content: Text(loc.this_cannot_be_undone), content: loc.this_cannot_be_undone,
actions: [ actions: [
CustomDialogAction( AnimatedDialogButton(
onPressed: () => Navigator.of(context).pop(true),
text: loc.delete,
),
CustomDialogAction(
onPressed: () => Navigator.of(context).pop(false), onPressed: () => Navigator.of(context).pop(false),
buttonType: ButtonType.secondary, child: Text(
text: loc.cancel, loc.cancel,
style: const TextStyle(color: CustomTheme.textColor),
),
),
AnimatedDialogButton(
onPressed: () => Navigator.of(context).pop(true),
child: Text(
loc.delete,
style: const TextStyle(
color: CustomTheme.secondaryColor,
),
),
), ),
], ],
), ),

View File

@@ -4,16 +4,15 @@ import 'package:provider/provider.dart';
import 'package:tallee/core/adaptive_page_route.dart'; import 'package:tallee/core/adaptive_page_route.dart';
import 'package:tallee/core/common.dart'; import 'package:tallee/core/common.dart';
import 'package:tallee/core/custom_theme.dart'; import 'package:tallee/core/custom_theme.dart';
import 'package:tallee/core/enums.dart';
import 'package:tallee/data/db/database.dart'; import 'package:tallee/data/db/database.dart';
import 'package:tallee/data/models/match.dart'; import 'package:tallee/data/models/match.dart';
import 'package:tallee/l10n/generated/app_localizations.dart'; import 'package:tallee/l10n/generated/app_localizations.dart';
import 'package:tallee/presentation/views/main_menu/match_view/create_match/create_match_view.dart'; import 'package:tallee/presentation/views/main_menu/match_view/create_match/create_match_view.dart';
import 'package:tallee/presentation/views/main_menu/match_view/match_result_view.dart'; import 'package:tallee/presentation/views/main_menu/match_view/match_result_view.dart';
import 'package:tallee/presentation/widgets/buttons/animated_dialog_button.dart';
import 'package:tallee/presentation/widgets/buttons/main_menu_button.dart'; import 'package:tallee/presentation/widgets/buttons/main_menu_button.dart';
import 'package:tallee/presentation/widgets/colored_icon_container.dart'; import 'package:tallee/presentation/widgets/colored_icon_container.dart';
import 'package:tallee/presentation/widgets/dialog/custom_alert_dialog.dart'; import 'package:tallee/presentation/widgets/custom_alert_dialog.dart';
import 'package:tallee/presentation/widgets/dialog/custom_dialog_action.dart';
import 'package:tallee/presentation/widgets/tiles/info_tile.dart'; import 'package:tallee/presentation/widgets/tiles/info_tile.dart';
import 'package:tallee/presentation/widgets/tiles/text_icon_tile.dart'; import 'package:tallee/presentation/widgets/tiles/text_icon_tile.dart';
@@ -65,16 +64,23 @@ class _MatchDetailViewState extends State<MatchDetailView> {
context: context, context: context,
builder: (context) => CustomAlertDialog( builder: (context) => CustomAlertDialog(
title: '${loc.delete_match}?', title: '${loc.delete_match}?',
content: Text(loc.this_cannot_be_undone), content: loc.this_cannot_be_undone,
actions: [ actions: [
CustomDialogAction( AnimatedDialogButton(
onPressed: () => Navigator.of(context).pop(true),
text: loc.delete,
),
CustomDialogAction(
onPressed: () => Navigator.of(context).pop(false), onPressed: () => Navigator.of(context).pop(false),
buttonType: ButtonType.secondary, child: Text(
text: loc.cancel, loc.cancel,
style: const TextStyle(color: CustomTheme.textColor),
),
),
AnimatedDialogButton(
onPressed: () => Navigator.of(context).pop(true),
child: Text(
loc.delete,
style: const TextStyle(
color: CustomTheme.secondaryColor,
),
),
), ),
], ],
), ),

View File

@@ -9,8 +9,8 @@ import 'package:tallee/core/custom_theme.dart';
import 'package:tallee/core/enums.dart'; import 'package:tallee/core/enums.dart';
import 'package:tallee/l10n/generated/app_localizations.dart'; import 'package:tallee/l10n/generated/app_localizations.dart';
import 'package:tallee/presentation/views/main_menu/settings_view/licenses_view.dart'; import 'package:tallee/presentation/views/main_menu/settings_view/licenses_view.dart';
import 'package:tallee/presentation/widgets/dialog/custom_alert_dialog.dart'; import 'package:tallee/presentation/widgets/buttons/animated_dialog_button.dart';
import 'package:tallee/presentation/widgets/dialog/custom_dialog_action.dart'; import 'package:tallee/presentation/widgets/custom_alert_dialog.dart';
import 'package:tallee/presentation/widgets/tiles/settings_list_tile.dart'; import 'package:tallee/presentation/widgets/tiles/settings_list_tile.dart';
import 'package:tallee/services/data_transfer_service.dart'; import 'package:tallee/services/data_transfer_service.dart';
import 'package:url_launcher/url_launcher.dart'; import 'package:url_launcher/url_launcher.dart';
@@ -122,16 +122,25 @@ class _SettingsViewState extends State<SettingsView> {
context: context, context: context,
builder: (context) => CustomAlertDialog( builder: (context) => CustomAlertDialog(
title: '${loc.delete_all_data}?', title: '${loc.delete_all_data}?',
content: Text(loc.this_cannot_be_undone), content: loc.this_cannot_be_undone,
actions: [ actions: [
CustomDialogAction( AnimatedDialogButton(
onPressed: () => Navigator.of(context).pop(true),
text: loc.delete,
),
CustomDialogAction(
onPressed: () => Navigator.of(context).pop(false), onPressed: () => Navigator.of(context).pop(false),
buttonType: ButtonType.secondary, child: Text(
text: loc.cancel, loc.cancel,
style: const TextStyle(
color: CustomTheme.textColor,
),
),
),
AnimatedDialogButton(
onPressed: () => Navigator.of(context).pop(true),
child: Text(
loc.delete,
style: const TextStyle(
color: CustomTheme.secondaryColor,
),
),
), ),
], ],
), ),

View File

@@ -1,28 +1,22 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:tallee/core/enums.dart'; import 'package:tallee/core/custom_theme.dart';
class AnimatedDialogButton extends StatefulWidget { class AnimatedDialogButton extends StatefulWidget {
/// A custom animated button widget that provides a scaling and opacity effect /// A custom animated button widget that provides a scaling and opacity effect
/// when pressed. /// when pressed.
/// - [onPressed]: Callback function that is triggered when the button is pressed. /// - [onPressed]: Callback function that is triggered when the button is pressed.
/// - [buttonText]: The text to be displayed on the button. /// - [child]: The child widget to be displayed inside the button, typically a text or icon.
/// - [buttonType]: The type of the button, which determines its styling.
/// - [buttonConstraints]: Optional constraints to control the button's size.
const AnimatedDialogButton({ const AnimatedDialogButton({
super.key, super.key,
required this.buttonText,
required this.onPressed, required this.onPressed,
this.buttonConstraints, required this.child,
this.buttonType = ButtonType.primary,
}); });
final String buttonText; /// Callback function that is triggered when the button is pressed.
final VoidCallback onPressed; final VoidCallback onPressed;
final BoxConstraints? buttonConstraints; /// The child widget to be displayed inside the button, typically a text or icon.
final Widget child;
final ButtonType buttonType;
@override @override
State<AnimatedDialogButton> createState() => _AnimatedDialogButtonState(); State<AnimatedDialogButton> createState() => _AnimatedDialogButtonState();
@@ -33,29 +27,6 @@ class _AnimatedDialogButtonState extends State<AnimatedDialogButton> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final textStyling = TextStyle(
color: widget.buttonType == ButtonType.primary
? Colors.black
: Colors.white,
fontSize: 16,
fontWeight: FontWeight.bold,
);
final buttonDecoration = widget.buttonType == ButtonType.primary
// Primary
? BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
)
: widget.buttonType == ButtonType.secondary
// Secondary
? BoxDecoration(
border: BoxBorder.all(color: Colors.white, width: 2),
borderRadius: BorderRadius.circular(12),
)
// Tertiary
: const BoxDecoration();
return GestureDetector( return GestureDetector(
onTapDown: (_) => setState(() => _isPressed = true), onTapDown: (_) => setState(() => _isPressed = true),
onTapUp: (_) => setState(() => _isPressed = false), onTapUp: (_) => setState(() => _isPressed = false),
@@ -67,18 +38,10 @@ class _AnimatedDialogButtonState extends State<AnimatedDialogButton> {
child: AnimatedOpacity( child: AnimatedOpacity(
opacity: _isPressed ? 0.6 : 1.0, opacity: _isPressed ? 0.6 : 1.0,
duration: const Duration(milliseconds: 100), duration: const Duration(milliseconds: 100),
child: Center( child: Container(
child: Container( decoration: CustomTheme.standardBoxDecoration,
constraints: widget.buttonConstraints, padding: const EdgeInsets.symmetric(horizontal: 26, vertical: 6),
decoration: buttonDecoration, child: widget.child,
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
margin: const EdgeInsets.symmetric(vertical: 8),
child: Text(
widget.buttonText,
style: textStyling,
textAlign: TextAlign.center,
),
),
), ),
), ),
), ),

View File

@@ -1,6 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:tallee/core/custom_theme.dart'; import 'package:tallee/core/custom_theme.dart';
import 'package:tallee/presentation/widgets/dialog/custom_dialog_action.dart';
class CustomAlertDialog extends StatelessWidget { class CustomAlertDialog extends StatelessWidget {
/// A custom alert dialog widget that provides a os unspecific AlertDialog, /// A custom alert dialog widget that provides a os unspecific AlertDialog,
@@ -17,23 +16,20 @@ class CustomAlertDialog extends StatelessWidget {
}); });
final String title; final String title;
final Widget content; final String content;
final List<CustomDialogAction> actions; final List<Widget> actions;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return AlertDialog( return AlertDialog(
title: Text( title: Text(title, style: const TextStyle(color: CustomTheme.textColor)),
title, content: Text(
style: const TextStyle( content,
fontWeight: FontWeight.bold, style: const TextStyle(color: CustomTheme.textColor),
color: CustomTheme.textColor,
),
), ),
content: content,
actions: actions, actions: actions,
backgroundColor: CustomTheme.boxColor, backgroundColor: CustomTheme.boxColor,
actionsAlignment: MainAxisAlignment.center, actionsAlignment: MainAxisAlignment.spaceAround,
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: CustomTheme.standardBorderRadiusAll, borderRadius: CustomTheme.standardBorderRadiusAll,
side: const BorderSide(color: CustomTheme.boxBorderColor), side: const BorderSide(color: CustomTheme.boxBorderColor),

View File

@@ -1,32 +0,0 @@
import 'package:flutter/cupertino.dart';
import 'package:tallee/core/enums.dart';
import 'package:tallee/presentation/widgets/buttons/animated_dialog_button.dart';
class CustomDialogAction extends StatelessWidget {
/// A custom dialog action widget that represents a button in a dialog.
/// - [text]: The text to be displayed on the button.
/// - [buttonType]: The type of the button, which determines its styling.
/// - [onPressed]: Callback function that is triggered when the button is pressed.
const CustomDialogAction({
super.key,
required this.onPressed,
required this.text,
this.buttonType = ButtonType.primary,
});
final String text;
final ButtonType buttonType;
final VoidCallback onPressed;
@override
Widget build(BuildContext context) {
return AnimatedDialogButton(
onPressed: onPressed,
buttonText: text,
buttonType: buttonType,
buttonConstraints: const BoxConstraints(minWidth: 300),
);
}
}