ponshu-room-lite/lib/screens/guide_screen.dart

187 lines
7.3 KiB
Dart
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:lucide_icons/lucide_icons.dart';
class GuideScreen extends ConsumerWidget {
const GuideScreen({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
return Scaffold(
appBar: AppBar(
title: const Text('ガイド・ヘルプ'),
centerTitle: true,
),
body: ListView(
padding: const EdgeInsets.all(16.0),
children: [
_buildSectionHeader(context, 'レベルと称号', LucideIcons.trophy),
_buildCard(
context,
children: [
_buildGuideItem(context, 'レベルの上げ方', '日本酒を1本登録するごとに 10 EXP 獲得できます。\nメニューを作成するとボーナスが入ることも!'),
const Divider(),
_buildGuideItem(context, '称号一覧', '獲得したEXPに応じて称号が変わります。'),
_buildLevelTable(context),
],
),
const SizedBox(height: 24),
_buildSectionHeader(context, 'バッジコレクション', LucideIcons.medal),
_buildCard(
context,
children: [
_buildBadgeGuide(context, '👹 東北制覇', '「青森・岩手・宮城・秋田・山形・福島」すべての県の日本酒を登録する', '条件: 6県制覇'),
const Divider(),
_buildBadgeGuide(context, '🌶️ 辛口党', '日本酒度が「+5」以上の辛口酒を10本登録する', '条件: 10本登録'),
const Divider(),
_buildBadgeGuide(context, '🍶 初めての一歩', '最初の日本酒を登録する', '条件: 1本登録'),
],
),
const SizedBox(height: 24),
_buildSectionHeader(context, 'AIソムリエ', LucideIcons.sparkles),
_buildCard(
context,
children: [
_buildGuideItem(context, '酒向タイプ診断', 'あなたが登録した日本酒の味覚データ甘辛、酸度などをAIが分析し、あなたの好みの傾向をチャート化します。'),
const Divider(),
_buildGuideItem(context, 'チャートの見方', '• 華やか: 香りが高い\n• 芳醇: コク・旨味が強い\n• 重厚: 苦味やボディ感\n• 穏やか: アルコール感が控えめ'),
],
),
],
),
);
}
Widget _buildSectionHeader(BuildContext context, String title, IconData icon) {
return Padding(
padding: const EdgeInsets.only(bottom: 12.0, left: 4.0),
child: Row(
children: [
// Use secondary color for section headers (warm accent)
Icon(icon, color: Theme.of(context).colorScheme.secondary),
const SizedBox(width: 8),
Text(
title,
style: Theme.of(context).textTheme.titleMedium?.copyWith(
fontWeight: FontWeight.bold,
color: Theme.of(context).colorScheme.secondary,
),
),
],
),
);
}
Widget _buildCard(BuildContext context, {required List<Widget> children}) {
return Card(
elevation: 0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
side: BorderSide(color: Theme.of(context).dividerColor.withValues(alpha: 0.5)),
),
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: children,
),
),
);
}
Widget _buildGuideItem(BuildContext context, String title, String content) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: Theme.of(context).textTheme.titleMedium?.copyWith(
fontWeight: FontWeight.bold,
// Force White in Dark Mode
color: Theme.of(context).brightness == Brightness.dark ? Colors.white : null,
),
),
const SizedBox(height: 4),
Text(content, style: Theme.of(context).textTheme.bodyMedium?.copyWith(height: 1.5)),
],
),
);
}
Widget _buildBadgeGuide(BuildContext context, String emojiAndName, String desc, String condition) {
return ListTile(
contentPadding: EdgeInsets.zero,
title: Text(
emojiAndName,
style: Theme.of(context).textTheme.titleSmall?.copyWith(
fontWeight: FontWeight.bold,
color: Theme.of(context).brightness == Brightness.dark ? Colors.white : null,
),
),
subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(desc, style: Theme.of(context).textTheme.bodyMedium),
const SizedBox(height: 4),
Text(
condition,
style: Theme.of(context).textTheme.bodySmall?.copyWith(
color: Theme.of(context).primaryColor,
),
),
],
),
);
}
Widget _buildLevelTable(BuildContext context) {
// Manually recreating table from LevelCalculator concepts since _levelTable is private.
// Ideally LevelCalculator exposes the table, but hardcoding for display is safer than reflection for now.
const levels = [
{'level': 1, 'exp': 0, 'title': '見習い'},
{'level': 2, 'exp': 10, 'title': '歩き飲み'},
{'level': 5, 'exp': 50, 'title': '嗜み人'},
{'level': 10, 'exp': 100, 'title': '呑兵衛'},
{'level': 20, 'exp': 200, 'title': '酒豪'},
{'level': 30, 'exp': 300, 'title': '利き酒師'},
{'level': 50, 'exp': 500, 'title': '日本酒伝道師'},
{'level': 100, 'exp': 1000, 'title': 'ポンシュマスター'},
];
return Container(
margin: const EdgeInsets.only(top: 12),
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.surfaceContainerHighest.withValues(alpha: 0.3),
borderRadius: BorderRadius.circular(8),
),
child: DataTable(
headingRowHeight: 40,
dataRowMinHeight: 36,
dataRowMaxHeight: 36,
columnSpacing: 20,
columns: [
DataColumn(label: Text('Lv', style: Theme.of(context).textTheme.bodySmall?.copyWith(color: Theme.of(context).brightness == Brightness.dark ? Colors.white70 : null))),
DataColumn(label: Text('必要EXP', style: Theme.of(context).textTheme.bodySmall?.copyWith(color: Theme.of(context).brightness == Brightness.dark ? Colors.white70 : null))),
DataColumn(label: Text('称号', style: Theme.of(context).textTheme.bodySmall?.copyWith(color: Theme.of(context).brightness == Brightness.dark ? Colors.white70 : null))),
],
rows: levels.map((e) {
return DataRow(cells: [
DataCell(Text('${e['level']}', style: Theme.of(context).textTheme.bodyMedium)),
DataCell(Text('${e['exp']}', style: Theme.of(context).textTheme.bodyMedium)),
DataCell(Text(
'${e['title']}',
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
fontWeight: FontWeight.bold,
color: Theme.of(context).brightness == Brightness.dark ? Colors.white : null,
),
)),
]);
}).toList(),
),
);
}
}