Flutter | バスケットボールスコア入力アプリに試合データ削除機能等を追加

今回のアップデートでは、バスケットボールスコア入力アプリにいくつかの新機能を追加しました。これにより、ユーザーは試合データの管理がより簡単になり、試合情報を柔軟に編集できるようになりました。以下に新機能の詳細と、対応するコードを紹介します。

新機能の概要

  • 試合データの削除機能: 保存された試合データを削除する機能を追加しました。
  • 試合会場の項目追加: 試合情報に会場名を追加しました。
  • 試合名と会場名の編集機能: 保存された試合データの試合名と会場名を編集できるようにしました。

試合データの削除機能

試合管理画面で、不要な試合データを簡単に削除できる機能を追加しました。削除アイコンをクリックすると、削除確認ダイアログが表示され、ユーザーが確認した場合にのみデータが削除されます。

// manage_games_screen.dartの一部
void _showDeleteConfirmationDialog(GameEntry game) {
  showDialog(
    context: context,
    builder: (BuildContext context) {
      return AlertDialog(
        title: Text("試合削除"),
        content: Text("本当にこの試合を削除しますか?"),
        actions: [
          TextButton(
            onPressed: () async {
              await _gameProvider.deleteGame(game.id!);
              _loadGames();
              Navigator.of(context).pop();
            },
            child: Text("はい"),
          ),
          TextButton(
            onPressed: () {
              Navigator.of(context).pop();
            },
            child: Text("いいえ"),
          ),
        ],
      );
    },
  );
}

試合会場の項目追加

新たに試合会場の情報を入力・編集できる項目を追加しました。試合名と同様に、会場名もアプリに保存されるようになりました。

// main.dartの一部
Future<void> _showGameNameDialog() async {
  String? gameName = await showDialog<String>(
    context: context,
    builder: (BuildContext context) {
      String name = '';
      String venue = '';
      return AlertDialog(
        title: Text('試合情報を入力'),
        content: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            TextField(
              decoration: InputDecoration(hintText: '試合名'),
              onChanged: (value) {
                name = value;
              },
            ),
            TextField(
              decoration: InputDecoration(hintText: '会場名'),
              onChanged: (value) {
                venue = value;
              },
            ),
          ],
        ),
        actions: [
          TextButton(
            onPressed: () {
              Navigator.of(context).pop(null);
            },
            child: Text('キャンセル'),
          ),
          TextButton(
            onPressed: () {
              if (name.isNotEmpty) {
                _currentGameName = name;
                _currentVenue = venue;
                Navigator.of(context).pop(name);
              }
            },
            child: Text('開始'),
          ),
        ],
      );
    },
  );

  if (gameName != null && gameName.isNotEmpty) {
    _saveNewGame(gameName);
  }
}

試合データの試合名・会場名の編集機能

試合管理画面で、保存済みの試合データの試合名や会場名を編集できるようになりました。編集ボタンを押すと、編集ダイアログが表示され、入力内容を保存できます。

// manage_games_screen.dartの一部
void _showEditGameDialog(GameEntry game) async {
  TextEditingController nameController =
      TextEditingController(text: game.name);
  TextEditingController venueController =
      TextEditingController(text: game.venue);
  showDialog(
    context: context,
    builder: (BuildContext context) {
      return AlertDialog(
        title: Text("試合情報を編集"),
        content: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            TextField(
              controller: nameController,
              decoration: InputDecoration(hintText: '試合名'),
            ),
            TextField(
              controller: venueController,
              decoration: InputDecoration(hintText: '会場名'),
            ),
          ],
        ),
        actions: [
          TextButton(
            onPressed: () => Navigator.of(context).pop(),
            child: Text('キャンセル'),
          ),
          TextButton(
            onPressed: () async {
              GameEntry updatedGame = GameEntry(
                  id: game.id,
                  name: nameController.text,
                  venue: venueController.text,
                  date: game.date);
              await _gameProvider.updateGame(updatedGame);
              _loadGames();
              Navigator.of(context).pop();
            },
            child: Text('保存'),
          ),
        ],
      );
    },
  );
}

完全版のコード

database_helper.dart

import 'package:sqflite/sqflite.dart';
import 'package:path/path.dart';

class DatabaseHelper {
  static final DatabaseHelper instance = DatabaseHelper._privateConstructor();
  static Database? _database;

  DatabaseHelper._privateConstructor();

  Future<Database> get database async => _database ??= await _initDatabase();

  Future<Database> _initDatabase() async {
    String path = join(await getDatabasesPath(), 'basketball_score.db');
    return await openDatabase(
      path,
      version: 1,
      onCreate: _onCreate,
      onUpgrade: _onUpgrade,
    );
  }

  Future _onCreate(Database db, int version) async {
    await db.execute('''
      CREATE TABLE games (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        name TEXT,
        venue TEXT,
        date TEXT
      )
    ''');

    await db.execute('''
      CREATE TABLE plays (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        team TEXT,
        points INTEGER,
        quarter INTEGER,
        playType TEXT,
        time TEXT,
        playerNumber TEXT,
        gameId INTEGER
      )
    ''');
  }

  Future _onUpgrade(Database db, int oldVersion, int newVersion) async {
    // Perform any database upgrade tasks here
  }
}

game_entry_provider.dart

import 'package:sqflite/sqflite.dart';
import 'database_helper.dart';

class GameEntry {
  final int? id;
  final String name;
  final String venue;
  final String date;

  GameEntry({this.id, required this.name, required this.venue, required this.date});

  Map<String, dynamic> toMap() {
    return {
      'id': id,
      'name': name,
      'venue': venue,
      'date': date,
    };
  }

  factory GameEntry.fromMap(Map<String, dynamic> map) {
    return GameEntry(
      id: map['id'],
      name: map['name'],
      venue: map['venue'],
      date: map['date'],
    );
  }
}

class GameEntryProvider {
  final DatabaseHelper _dbHelper = DatabaseHelper.instance;

  Future<int> insertGame(GameEntry game) async {
    Database db = await _dbHelper.database;
    return await db.insert('games', game.toMap(), conflictAlgorithm: ConflictAlgorithm.replace);
  }

  Future<List<GameEntry>> getAllGames() async {
    Database db = await _dbHelper.database;
    final List<Map<String, dynamic>> maps = await db.query('games');
    return List.generate(maps.length, (i) {
      return GameEntry.fromMap(maps[i]);
    });
  }

  Future<int> updateGame(GameEntry game) async {
    Database db = await _dbHelper.database;
    return await db.update(
      'games',
      game.toMap(),
      where: 'id = ?',
      whereArgs: [game.id],
    );
  }

  Future<int> deleteGame(int id) async {
    Database db = await _dbHelper.database;
    return await db.delete(
      'games',
      where: 'id = ?',
      whereArgs: [id],
    );
  }
}

main.dart

import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'database_helper.dart';
import 'game_entry_provider.dart';
import 'play_entry_provider.dart';
import 'manage_games_screen.dart';

void main() {
  runApp(BasketballScoreApp());
}

class BasketballScoreApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'バスケットボール スコア入力アプリ',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: ScoreHomePage(),
      debugShowCheckedModeBanner: false,
    );
  }
}

class ScoreHomePage extends StatefulWidget {
  @override
  _ScoreHomePageState createState() => _ScoreHomePageState();
}

class _ScoreHomePageState extends State<ScoreHomePage>
    with SingleTickerProviderStateMixin {
  final PlayEntryProvider _playProvider = PlayEntryProvider();
  final GameEntryProvider _gameProvider = GameEntryProvider();
  List<PlayEntry> _plays = [];
  String? _selectedTeam;
  int _selectedQuarter = 1;
  String? _selectedPlayer;
  int? _currentGameId;
  String _currentGameName = '';
  String _currentVenue = '';
  late AnimationController _animationController;

  @override
  void initState() {
    super.initState();
    _animationController = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 300),
    );
    WidgetsBinding.instance.addPostFrameCallback((_) {
      _showGameNameDialog();
    });
  }

  @override
  void dispose() {
    _animationController.dispose();
    super.dispose();
  }

  Future<void> _showGameNameDialog() async {
    String? gameName = await showDialog<String>(
      context: context,
      builder: (BuildContext context) {
        String name = '';
        String venue = '';
        return AlertDialog(
          title: Text('試合情報を入力'),
          content: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              TextField(
                decoration: InputDecoration(hintText: '試合名'),
                onChanged: (value) {
                  name = value;
                },
              ),
              TextField(
                decoration: InputDecoration(hintText: '会場名'),
                onChanged: (value) {
                  venue = value;
                },
              ),
            ],
          ),
          actions: [
            TextButton(
              onPressed: () {
                Navigator.of(context).pop(null);
              },
              child: Text('キャンセル'),
            ),
            TextButton(
              onPressed: () {
                if (name.isNotEmpty) {
                  _currentGameName = name;
                  _currentVenue = venue;
                  Navigator.of(context).pop(name);
                }
              },
              child: Text('開始'),
            ),
          ],
        );
      },
    );

    if (gameName != null && gameName.isNotEmpty) {
      _saveNewGame(gameName);
    }
  }

  Future<void> _saveNewGame(String gameName) async {
    final newGame = GameEntry(
        name: gameName, venue: _currentVenue, date: DateTime.now().toString());
    _currentGameId = await _gameProvider.insertGame(newGame);
    _plays = [];
    _selectedTeam = null;
    _selectedPlayer = null;
    setState(() {});
  }

  Future<void> _addPlay(String team, int points, String playType) async {
    if (_currentGameId == null) return;

    String formattedTime = DateFormat('H:mm:ss').format(DateTime.now());
    PlayEntry newPlay = PlayEntry(
      team: team,
      points: points,
      quarter: _selectedQuarter,
      playType: playType,
      time: formattedTime,
      playerNumber: _selectedPlayer ?? 'TEAM',
      gameId: _currentGameId!,
    );

    await _playProvider.insertPlay(newPlay);
    _loadPlaysForCurrentGame();
    _selectedPlayer = null;
    _selectedTeam = null;
  }

  Future<void> _loadPlaysForCurrentGame() async {
    if (_currentGameId == null) return;

    List<PlayEntry> plays =
        await _playProvider.getPlaysByGameId(_currentGameId!);

    plays.sort((a, b) {
      int quarterComparison = b.quarter.compareTo(a.quarter);
      if (quarterComparison == 0) {
        return b.time.compareTo(a.time);
      }
      return quarterComparison;
    });

    setState(() {
      _plays = plays;
    });
  }

  Future<void> _showQuarterDialog(int quarter) async {
    bool shouldSwitch = await showDialog<bool>(
          context: context,
          builder: (BuildContext context) {
            return AlertDialog(
              title: Text("クォーター切り替え"),
              content: Text("本当にクォーターを $quarter に切り替えますか?"),
              actions: [
                TextButton(
                  onPressed: () {
                    Navigator.of(context).pop(true);
                  },


                  child: Text("はい"),
                ),
                TextButton(
                  onPressed: () {
                    Navigator.of(context).pop(false);
                  },
                  child: Text("いいえ"),
                ),
              ],
            );
          },
        ) ??
        false;

    if (shouldSwitch) {
      setState(() {
        _selectedQuarter = quarter;
      });
      _loadPlaysForCurrentGame();
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('バスケットボール スコア入力アプリ'),
        actions: [
          IconButton(
            icon: Icon(Icons.list),
            onPressed: () {
              Navigator.push(
                context,
                MaterialPageRoute(
                  builder: (context) => ManageGamesScreen(
                    onGameSelected: (game) {
                      setState(() {
                        _currentGameId = game.id;
                        _currentGameName = game.name;
                        _currentVenue = game.venue;
                      });
                      _loadPlaysForCurrentGame();
                      Navigator.pop(context); // メインスクリーンに戻る
                    },
                    currentGameId: _currentGameId, // 現在の試合IDを渡す
                  ),
                ),
              );
            },
          ),
        ],
      ),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          Padding(
            padding: const EdgeInsets.symmetric(vertical: 8.0),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Text(
                  'チームA',
                  style: TextStyle(fontSize: 24),
                ),
                SizedBox(width: 10),
                Text(
                  '${_getTotalScore('A')}',
                  style: TextStyle(fontSize: 24),
                ),
                SizedBox(width: 10),
                Text(
                  '-',
                  style: TextStyle(fontSize: 24),
                ),
                SizedBox(width: 10),
                Text(
                  '${_getTotalScore('B')}',
                  style: TextStyle(fontSize: 24),
                ),
                SizedBox(width: 10),
                Text(
                  'チームB',
                  style: TextStyle(fontSize: 24),
                ),
              ],
            ),
          ),
          SizedBox(height: 20),
          Text(
            'クォーターを選択してください:',
            style: TextStyle(fontSize: 20),
          ),
          Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              ElevatedButton(
                onPressed: () => _showQuarterDialog(1),
                child: Text('1Q'),
                style: ElevatedButton.styleFrom(
                  backgroundColor:
                      _selectedQuarter == 1 ? Colors.blue : Colors.grey,
                ),
              ),
              SizedBox(width: 10),
              ElevatedButton(
                onPressed: () => _showQuarterDialog(2),
                child: Text('2Q'),
                style: ElevatedButton.styleFrom(
                  backgroundColor:
                      _selectedQuarter == 2 ? Colors.blue : Colors.grey,
                ),
              ),
              SizedBox(width: 10),
              ElevatedButton(
                onPressed: () => _showQuarterDialog(3),
                child: Text('3Q'),
                style: ElevatedButton.styleFrom(
                  backgroundColor:
                      _selectedQuarter == 3 ? Colors.blue : Colors.grey,
                ),
              ),
              SizedBox(width: 10),
              ElevatedButton(
                onPressed: () => _showQuarterDialog(4),
                child: Text('4Q'),
                style: ElevatedButton.styleFrom(
                  backgroundColor:
                      _selectedQuarter == 4 ? Colors.blue : Colors.grey,
                ),
              ),
            ],
          ),
          SizedBox(height: 20),
          Text(
            'チームを選択してください:',
            style: TextStyle(fontSize: 20),
          ),
          Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              ElevatedButton(
                onPressed: () => setState(() => _selectedTeam = 'A'),
                child: Text('チームA'),
                style: ElevatedButton.styleFrom(
                  backgroundColor:
                      _selectedTeam == 'A' ? Colors.blue : Colors.grey,
                ),
              ),
              SizedBox(width: 20),
              ElevatedButton(
                onPressed: () => setState(() => _selectedTeam = 'B'),
                child: Text('チームB'),
                style: ElevatedButton.styleFrom(
                  backgroundColor:
                      _selectedTeam == 'B' ? Colors.blue : Colors.grey,
                ),
              ),
            ],
          ),
          SizedBox(height: 20),
          Text(
            'プレイヤーを選択してください:',
            style: TextStyle(fontSize: 20),
          ),
          Padding(
            padding: const EdgeInsets.symmetric(horizontal: 16.0),
            child: Wrap(
              spacing: 10,
              children: List.generate(
                5,
                (int index) {
                  int playerNumber = index + 1;
                  return ElevatedButton(
                    onPressed: () => _setPlayer(playerNumber.toString()),
                    child: Text('$playerNumber'),
                    style: ElevatedButton.styleFrom(
                      backgroundColor:
                          _selectedPlayer == playerNumber.toString()
                              ? Colors.blue
                              : Colors.grey,
                    ),
                  );
                },
              ).toList()
                ..add(
                  ElevatedButton(
                    onPressed: () => _setPlayer('TEAM'),
                    child: Text('TEAM'),
                    style: ElevatedButton.styleFrom(
                      backgroundColor:
                          _selectedPlayer == 'TEAM' ? Colors.blue : Colors.grey,
                    ),
                  ),
                ),
            ),
          ),
          SizedBox(height: 20),
          Text(
            'プレイ内容を選択してください:',
            style: TextStyle(fontSize: 20),
          ),
          Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              ElevatedButton(
                onPressed: _selectedTeam == null || _selectedPlayer == null
                    ? null
                    : () => _addPlay(_selectedTeam!, 1, 'FT'),
                child: Text('FT'),
              ),
              SizedBox(width: 10),
              ElevatedButton(
                onPressed: _selectedTeam == null || _selectedPlayer == null
                    ? null
                    : () => _addPlay(_selectedTeam!, 2, '2P'),
                child: Text('2P'),
              ),
              SizedBox(width: 10),
              ElevatedButton(
                onPressed: _selectedTeam == null || _selectedPlayer == null
                    ? null
                    : () => _addPlay(_selectedTeam!, 3, '3P'),
                child: Text('3P'),
              ),
              SizedBox(width: 10),
              ElevatedButton(
                onPressed: _selectedTeam == null || _selectedPlayer == null
                    ? null
                    : () => _addPlay(_selectedTeam!, 0, 'ファウル'),
                child: Text('ファウル'),
              ),
              SizedBox(width: 10),
              ElevatedButton(
                onPressed: _selectedPlayer != 'TEAM'
                    ? null
                    : () => _addPlay(_selectedTeam!, 0, 'タイムアウト'),
                child: Text('タイムアウト'),
              ),
            ],
          ),
          SizedBox(height: 20),
          Text(
            'プレイ内容一覧:',
            style: TextStyle(fontSize: 20),
          ),
          Container(
            padding: EdgeInsets.symmetric(vertical: 4.0),
            color: Colors.grey[300],
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                Expanded(child: Text('クォーター', textAlign: TextAlign.center)),
                Expanded(child: Text('チーム名', textAlign: TextAlign.center)),
                Expanded(child: Text('番号', textAlign: TextAlign.center)),
                Expanded(child: Text('内容', textAlign: TextAlign.center)),
                Expanded(child: Text('時間', textAlign: TextAlign.center)),
                Expanded(child: Text('操作', textAlign: TextAlign.center)),
              ],
            ),
          ),
          Expanded(
            child: ReorderableListView.builder(
              itemCount: _plays.length,
              onReorder: (int oldIndex, int newIndex) {
                setState(() {
                  if (newIndex > oldIndex) {
                    newIndex -= 1;
                  }
                  final PlayEntry play = _plays.removeAt(oldIndex);
                  _plays.insert(newIndex, play);
                });
              },
              itemBuilder: (context, index) {
                final play = _plays[index];
                return ListTile(
                  key: ValueKey(play.id),
                  title: Row(
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    children: [
                      Expanded(
                          child: Text('${play.quarter}Q',
                              textAlign: TextAlign.center)),
                      Expanded(
                          child: Text('${play.team}',
                              textAlign: TextAlign.center)),
                      Expanded(
                          child: Text('#${play.playerNumber}',
                              textAlign: TextAlign.center)),
                      Expanded(
                          child: Text('${play.playType}',
                              textAlign: TextAlign.center)),
                      Expanded(
                          child: Text('${play.time}',
                              textAlign: TextAlign.center)),
                      Expanded(
                        child: Row(
                          mainAxisAlignment: MainAxisAlignment.center,
                          children: [
                            IconButton(
                              icon: Icon(Icons.delete),
                              onPressed: () {
                                setState(() {
                                  _plays.removeAt(index);
                                });
                                _playProvider.deletePlay(play.id!);
                              },
                            ),
                            ReorderableDragStartListener(
                              index: index,
                              child: Icon(Icons.drag_handle),
                            ),
                          ],
                        ),
                      ),
                    ],


 ),
                );
              },
            ),
          ),
        ],
      ),
    );
  }

  int _getTotalScore(String team) {
    return _plays
        .where((play) => play.team == team)
        .fold(0, (total, play) => total + play.points);
  }

  void _setPlayer(String playerNumber) {
    setState(() {
      _selectedPlayer = playerNumber;
    });
  }
}

manage_games_screen.dart

import 'package:flutter/material.dart';
import 'game_entry_provider.dart';

class ManageGamesScreen extends StatefulWidget {
  final ValueChanged<GameEntry> onGameSelected;
  final int? currentGameId;

  ManageGamesScreen({required this.onGameSelected, this.currentGameId});

  @override
  _ManageGamesScreenState createState() => _ManageGamesScreenState();
}

class _ManageGamesScreenState extends State<ManageGamesScreen> {
  List<GameEntry> _games = [];
  final GameEntryProvider _gameProvider = GameEntryProvider();

  @override
  void initState() {
    super.initState();
    _loadGames();
  }

  Future<void> _loadGames() async {
    List<GameEntry> games = await _gameProvider.getAllGames();
    setState(() {
      _games = games;
    });
  }

  void _showEditGameDialog(GameEntry game) async {
    TextEditingController nameController =
        TextEditingController(text: game.name);
    TextEditingController venueController =
        TextEditingController(text: game.venue);
    showDialog(
      context: context,
      builder: (BuildContext context) {
        return AlertDialog(
          title: Text("試合情報を編集"),
          content: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              TextField(
                controller: nameController,
                decoration: InputDecoration(hintText: '試合名'),
              ),
              TextField(
                controller: venueController,
                decoration: InputDecoration(hintText: '会場名'),
              ),
            ],
          ),
          actions: [
            TextButton(
              onPressed: () => Navigator.of(context).pop(),
              child: Text('キャンセル'),
            ),
            TextButton(
              onPressed: () async {
                GameEntry updatedGame = GameEntry(
                    id: game.id,
                    name: nameController.text,
                    venue: venueController.text,
                    date: game.date);
                await _gameProvider.updateGame(updatedGame);
                _loadGames();
                Navigator.of(context).pop();
              },
              child: Text('保存'),
            ),
          ],
        );
      },
    );
  }

  void _showDeleteConfirmationDialog(GameEntry game) {
    showDialog(
      context: context,
      builder: (BuildContext context) {
        return AlertDialog(
          title: Text("試合削除"),
          content: Text("本当にこの試合を削除しますか?"),
          actions: [
            TextButton(
              onPressed: () async {
                await _gameProvider.deleteGame(game.id!);
                _loadGames();
                Navigator.of(context).pop();
              },
              child: Text("はい"),
            ),
            TextButton(
              onPressed: () {
                Navigator.of(context).pop();
              },
              child: Text("いいえ"),
            ),
          ],
        );
      },
    );
  }

  void _showLoadConfirmationDialog(GameEntry game) {
    showDialog(
      context: context,
      builder: (BuildContext context) {
        return AlertDialog(
          title: Text("試合読み込み"),
          content: Text("本当にこの試合を読み込みますか?"),
          actions: [
            TextButton(
              onPressed: () {
                Navigator.of(context).pop(); // ダイアログを閉じる
              },
              child: Text("キャンセル"),
            ),
            TextButton(
              onPressed: () {
                Navigator.of(context).pop(); // ダイアログを閉じる
                widget.onGameSelected(game); // 試合データを戻す
                Navigator.of(context).pop(game); // メイン画面に戻る
              },
              child: Text("読み込む"),
            ),
          ],
        );
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('試合管理'),
      ),
      body: _games.isEmpty
          ? Center(child: Text('保存された試合はありません'))
          : ListView.builder(
              itemCount: _games.length,
              itemBuilder: (context, index) {
                final game = _games[index];
                return ListTile(
                  title: Text(game.name),
                  subtitle: Text(game.date),
                  trailing: Row(
                    mainAxisSize: MainAxisSize.min,
                    children: [
                      IconButton(
                        icon: Icon(Icons.edit),
                        onPressed: () => _showEditGameDialog(game),
                      ),
                      if (game.id != widget.currentGameId)
                        IconButton(
                          icon: Icon(Icons.delete),
                          onPressed: () => _showDeleteConfirmationDialog(game),
                        ),
                    ],
                  ),
                  onTap: () => _showLoadConfirmationDialog(game),
                );
              },
            ),
    );
  }
}

play_entry_provider.dart

import 'package:sqflite/sqflite.dart';
import 'database_helper.dart';

class PlayEntry {
  final int? id;
  final String team;
  final int points;
  final int quarter;
  final String playType;
  final String time;
  final String playerNumber;
  final int gameId;

  PlayEntry({
    this.id,
    required this.team,
    required this.points,
    required this.quarter,
    required this.playType,
    required this.time,
    required this.playerNumber,
    required this.gameId,
  });

  Map<String, dynamic> toMap() {
    return {
      'id': id,
      'team': team,
      'points': points,
      'quarter': quarter,
      'playType': playType,
      'time': time,
      'playerNumber': playerNumber,
      'gameId': gameId,
    };
  }

  factory PlayEntry.fromMap(Map<String, dynamic> map) {
    return PlayEntry(
      id: map['id'],
      team: map['team'],
      points: map['points'],
      quarter: map['quarter'],
      playType: map['playType'],
      time: map['time'],
      playerNumber: map['playerNumber'],
      gameId: map['gameId'],
    );
  }
}

class PlayEntryProvider {
  final DatabaseHelper _dbHelper = DatabaseHelper.instance;

  Future<int> insertPlay(PlayEntry play) async {
    Database db = await _dbHelper.database;
    return await db.insert('plays', play.toMap(), conflictAlgorithm: ConflictAlgorithm.replace);
  }

  Future<List<PlayEntry>> getPlaysByGameId(int gameId) async {
    Database db = await _dbHelper.database;
    final List<Map<String, dynamic>> maps = await db.query(
      'plays',
      where: 'gameId = ?',
      whereArgs: [gameId],
    );
    return List.generate(maps.length, (i) {
      return PlayEntry.fromMap(maps[i]);
    });
  }

  Future<int> deletePlay(int id) async {
    Database db = await _dbHelper.database;
    return await db.delete(
      'plays',
      where: 'id = ?',
      whereArgs: [id],
    );
  }
}

関連記事

コメント

タイトルとURLをコピーしました