diff --git a/lib/screens/sales_screen.dart b/lib/screens/sales_screen.dart index 6c90720..8f35ace 100644 --- a/lib/screens/sales_screen.dart +++ b/lib/screens/sales_screen.dart @@ -1,4 +1,4 @@ -// Version: 1.0.0 +// Version: 1.0.1 - Sprint 4-M2 実装開始 import 'package:flutter/material.dart'; /// 売上入力画面(レジモードの主戦場)(Material Design テンプレート) @@ -12,85 +12,182 @@ class SalesScreen extends StatelessWidget { title: const Text('売上入力'), actions: [ IconButton( - icon: const Icon(Icons.receipt_long), + icon: const Icon(Icons.save), onPressed: () => _showSaveDialog(context), ), ], ), - body: ListView( - padding: const EdgeInsets.all(16), + body: Column( children: [ - // レジモードのメイン表示エリア - Card( - margin: EdgeInsets.zero, - child: Padding( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - // 合計金額表示 - Text( - '合計:¥0', - style: const TextStyle( - fontSize: 32, - fontWeight: FontWeight.bold, - color: Colors.black87, + // ダッシュボードエリア(合計金額表示) + Padding( + padding: const EdgeInsets.all(16), + child: Card( + elevation: 4, + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + // タイトル + Text( + 'レジモード', + style: Theme.of(context).textTheme.titleLarge?.copyWith( + fontWeight: FontWeight.bold, + ), ), - ), - const SizedBox(height: 16), + const SizedBox(height: 8), - // 税率/税額表示 - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text('税別:¥0'), - Text('税込:¥0', style: const TextStyle(fontWeight: FontWeight.bold)), - ], - ), - ], + // 合計金額表示 + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + '合計', + style: TextStyle( + fontSize: 18, + color: Colors.grey.shade600, + ), + ), + const Icon(Icons.payments, size: 32), + ], + ), + const SizedBox(height: 4), + + // 合計金額(大きな表示) + Text( + '¥0', + style: const TextStyle( + fontSize: 48, + fontWeight: FontWeight.bold, + color: Colors.teal, + ), + ), + const SizedBox(height: 16), + + // 税率/税額表示 + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('税別', style: TextStyle(fontSize: 14)), + Text('¥0'), + ], + ), + Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text('税込', style: TextStyle(fontWeight: FontWeight.bold)), + Text('¥0', style: const TextStyle(fontWeight: FontWeight.bold)), + ], + ), + ], + ), + ], + ), ), ), ), - const SizedBox(height: 16), - // 商品入力エリア - TextField( - decoration: const InputDecoration( - labelText: '商品検索', - hintText: 'JAN コードまたは商品名を入力', - prefixIcon: Icon(Icons.search), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: TextField( + decoration: InputDecoration( + labelText: '商品検索', + hintText: 'JAN コードまたは商品名を入力して選択', + prefixIcon: const Icon(Icons.search), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + ), + filled: true, + ), ), - onChanged: (value) { /* TODO: 商品検索 */ }, ), + const SizedBox(height: 8), - const SizedBox(height: 16), - - // 商品リスト - Card( - margin: EdgeInsets.zero, - child: ExpansionTile( - title: const Text('売上商品'), + // 売上商品リスト(ダミーデータ用) + Expanded( + child: ListView( children: [ - ListView.builder( - shrinkWrap: true, - padding: EdgeInsets.zero, - itemCount: 0, // デモ用 - itemBuilder: (context, index) => Card( - margin: const EdgeInsets.symmetric(vertical: 4), - child: ListTile( - leading: CircleAvatar( - backgroundColor: Colors.orange.shade100, - child: Icon(Icons.store, color: Colors.orange), - ), - title: Text('商品${index + 1}'), - subtitle: Text('数量:0 pcs / 単価:¥0'), + Card( + margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 4), + child: ExpansionTile( + title: Text( + '📦 売上商品', + style: TextStyle(fontWeight: FontWeight.bold), ), + subtitle: const Text('商品を登録'), + children: [ + ListView.builder( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemCount: 0, // TODO: 実際のデータに差し替える + itemBuilder: (context, index) { + return Padding( + padding: const EdgeInsets.symmetric(vertical: 4), + child: Card( + child: ListTile( + leading: CircleAvatar( + backgroundColor: Colors.orange.shade100, + child: Icon(Icons.store, color: Colors.orange), + ), + title: Text('商品${index + 1}'), + subtitle: const Row( + children: [ + SizedBox(width: 8), + Icon(Icons.remove_circle_outline), + SizedBox(width: 4), + Text('数量:0 pcs / 単価:¥0'), + ], + ), + ), + ), + ); + }, + ), + ], ), ), ], ), ), + + const SizedBox(height: 16), + ], + ), + ); + } + + /// 保存ダイアログ表示(TODO: DatabaseHelper.insertSales を呼び出す) + void _showSaveDialog(BuildContext context) { + showDialog( + context: context, + builder: (context) => AlertDialog( + title: const Text('売上データを保存'), + content: const Text( + '入力した商品情報を販売アシストに保存します。\n\n DatabaseHelper.insertSales を呼び出す予定です。', + ), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: const Text('キャンセル'), + ), + ElevatedButton( + onPressed: () { + // TODO: DatabaseHelper.insertSales(context) 呼び出し + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text('売上データ保存処理中...'), + duration: Duration(seconds: 2), + ), + ); + Navigator.pop(context); + }, + child: const Text('保存'), + ), ], ), );