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

251 lines
9.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';
import '../main.dart'; // Import isProVersion flag
import '../providers/theme_provider.dart'; // Access userProfileProvider
import '../providers/navigation_provider.dart'; // Track current tab index
import '../utils/translations.dart'; // Translation helper
import '../theme/app_colors.dart'; // AppColors ThemeExtension
import 'home_screen.dart';
import 'soul_screen.dart';
import 'shop_settings_screen.dart';
import 'features/placeholders.dart';
/// 王冠バッジ付きアイコンウィジェットPro限定機能用
class _IconWithCrownBadge extends StatelessWidget {
final IconData icon;
const _IconWithCrownBadge({required this.icon});
@override
Widget build(BuildContext context) {
return Stack(
clipBehavior: Clip.none,
children: [
Icon(icon),
Positioned(
right: -4,
top: -4,
child: Container(
padding: const EdgeInsets.all(2),
decoration: BoxDecoration(
color: Colors.amber.shade600,
shape: BoxShape.circle,
),
child: const Icon(
LucideIcons.crown,
size: 10,
color: Colors.white,
),
),
),
],
);
}
}
class MainScreen extends ConsumerStatefulWidget {
const MainScreen({super.key});
@override
ConsumerState<MainScreen> createState() => _MainScreenState();
}
class _MainScreenState extends ConsumerState<MainScreen> {
int _currentIndex = 0;
/// Pro限定機能ダイアログを表示
void _showProOnlyDialog(BuildContext context, String featureName, IconData featureIcon, String description) {
final appColors = Theme.of(context).extension<AppColors>()!;
showDialog(
context: context,
builder: (context) => AlertDialog(
icon: Stack(
clipBehavior: Clip.none,
alignment: Alignment.center,
children: [
Icon(featureIcon, size: 48, color: Colors.grey.shade400),
Positioned(
right: -8,
top: -8,
child: Icon(LucideIcons.crown, size: 32, color: Colors.amber.shade600),
),
],
),
title: const Text('Pro版限定機能', textAlign: TextAlign.center),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(
featureName,
style: const TextStyle(fontSize: 18, fontWeight: FontWeight.w600),
textAlign: TextAlign.center,
),
const SizedBox(height: 12),
Text(
description,
style: TextStyle(fontSize: 14, color: appColors.textSecondary),
textAlign: TextAlign.center,
),
const SizedBox(height: 16),
Text(
'Ponshu Room Pro版でこの機能をご利用いただけます。',
style: TextStyle(fontSize: 12, color: appColors.textSecondary),
textAlign: TextAlign.center,
),
],
),
actions: [
TextButton(
onPressed: () => Navigator.of(context).pop(),
child: const Text('閉じる'),
),
],
),
);
}
@override
Widget build(BuildContext context) {
// Listen for mode changes to reset navigation to Home
ref.listen(userProfileProvider.select((value) => value.isBusinessMode), (previous, next) {
if (previous != next) {
setState(() {
_currentIndex = 0;
ref.read(currentTabIndexProvider.notifier).setIndex(0); // Reset to home tab
});
}
});
// CRITICAL FIX: Listen for external tab index changes (e.g. from SoulScreen)
ref.listen(currentTabIndexProvider, (previous, next) {
if (next != _currentIndex) {
setState(() {
_currentIndex = next;
});
}
});
final userProfile = ref.watch(userProfileProvider);
final isBusiness = userProfile.isBusinessMode;
final t = Translations(userProfile.locale); // Translation helper
// 🔍 DEBUG: Check IS_PRO_VERSION flag
debugPrint('🔍 MainScreen: IS_PRO_VERSION = $isProVersion, isBusiness = $isBusiness');
// Define Screens for each mode
// Lite版のPro限定タブは表示されないようにダミー画面を配置
// (タップ時にダイアログで対応するため、画面遷移は発生しない)
final List<Widget> screens = isBusiness
? [
const HomeScreen(), // Inventory Management
isProVersion ? const InstaSupportScreen() : const HomeScreen(), // Instagram Support (Pro only)
isProVersion ? const AnalyticsScreen() : const HomeScreen(), // Analytics (Pro only)
const ShopSettingsScreen(), // Shop Settings
]
: [
const HomeScreen(), // My Sake List
isProVersion ? const ScanARScreen() : const HomeScreen(), // QR Scan (Pro only)
const SommelierScreen(), // Sommelier
const BreweryMapScreen(), // Map
const SoulScreen(), // MyPage/Settings
];
// Define Navigation Items (with translation)
// Lite版では王冠バッジを表示
final List<NavigationDestination> destinations = isBusiness
? [
NavigationDestination(
icon: const Padding(padding: EdgeInsets.only(bottom: 2), child: Text('🍶', style: TextStyle(fontSize: 22))),
label: t['home'],
),
NavigationDestination(
icon: isProVersion ? const Icon(LucideIcons.instagram) : const _IconWithCrownBadge(icon: LucideIcons.instagram),
label: t['promo'],
),
NavigationDestination(
icon: isProVersion ? const Icon(LucideIcons.barChart) : const _IconWithCrownBadge(icon: LucideIcons.barChart),
label: t['analytics'],
),
NavigationDestination(icon: const Icon(LucideIcons.store), label: t['shop']),
]
: [
NavigationDestination(
icon: const Padding(padding: EdgeInsets.only(bottom: 2), child: Text('🍶', style: TextStyle(fontSize: 22))),
label: t['home'],
),
NavigationDestination(
icon: isProVersion ? const Icon(LucideIcons.scanLine) : const _IconWithCrownBadge(icon: LucideIcons.scanLine),
label: t['scan'],
),
NavigationDestination(icon: const Icon(LucideIcons.sparkles), label: t['sommelier']),
NavigationDestination(icon: const Icon(LucideIcons.map), label: t['map']),
NavigationDestination(icon: const Icon(LucideIcons.user), label: t['myPage']),
];
// Safety: Reset index if out of bounds (shouldn't happen if lengths match)
if (_currentIndex >= screens.length) _currentIndex = 0;
return Scaffold(
body: SafeArea(
child: IndexedStack(
index: _currentIndex,
children: screens,
),
),
bottomNavigationBar: NavigationBar(
selectedIndex: _currentIndex,
onDestinationSelected: (index) {
// Lite版でPro限定タブをタップした場合はダイアログを表示
if (!isProVersion) {
if (isBusiness) {
// ビジネスモード: Instagram (index 1) と Analytics (index 2) がPro限定
if (index == 1) {
_showProOnlyDialog(
context,
t['promo'],
LucideIcons.instagram,
userProfile.locale == 'ja'
? 'Instagram用の魅力的な投稿を自動生成。酒の写真とAI解析を活用して、プロモーションをサポートします。'
: 'Auto-generate attractive Instagram posts. Leverage sake photos and AI analysis to boost your promotion.',
);
return;
} else if (index == 2) {
_showProOnlyDialog(
context,
t['analytics'],
LucideIcons.barChart,
userProfile.locale == 'ja'
? '在庫状況や人気銘柄を分析。ビジネスの意思決定をデータで支援します。'
: 'Analyze inventory and popular brands. Support business decisions with data insights.',
);
return;
}
} else {
// 個人モード: Scan (index 1) がPro限定
if (index == 1) {
_showProOnlyDialog(
context,
t['scan'],
LucideIcons.scanLine,
userProfile.locale == 'ja'
? 'QRコードをスキャンして、酒の情報を素早く登録。AR表示で楽しく記録できます。'
: 'Scan QR codes to quickly register sake information. Enjoy recording with AR display.',
);
return;
}
}
}
// 通常のタブ遷移
setState(() {
_currentIndex = index;
ref.read(currentTabIndexProvider.notifier).setIndex(index); // Update global tab state
});
},
destinations: destinations,
),
);
}
}