251 lines
9.3 KiB
Dart
251 lines
9.3 KiB
Dart
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,
|
||
),
|
||
);
|
||
}
|
||
}
|