import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import '../../../core/api/api_error_mapper.dart'; import '../../../core/l10n/l10n.dart'; import 'admin_ai_panel.dart'; import 'admin_aliases_panel.dart'; import 'admin_inventory_panel.dart'; import 'admin_pantry_panel.dart'; import 'admin_private_products_panel.dart'; import 'admin_pending_products_panel.dart'; import 'admin_products_panel.dart'; import '../../profile/data/profile_repository.dart'; enum _DatabaseTab { inventory, pantry, products, privateProducts, pending, aliases, ai } class _DatabaseTabConfig { final _DatabaseTab tab; final String title; final String summary; final Widget Function(BuildContext context) buildPanel; const _DatabaseTabConfig({ required this.tab, required this.title, required this.summary, required this.buildPanel, }); } class AdminDatabasePanel extends ConsumerStatefulWidget { final bool embedded; const AdminDatabasePanel({super.key, this.embedded = false}); @override ConsumerState createState() => _AdminDatabasePanelState(); } class _AdminDatabasePanelState extends ConsumerState { _DatabaseTab _activeTab = _DatabaseTab.inventory; bool _isRefreshingCategories = false; List<_DatabaseTabConfig> get _tabConfigs => [ _DatabaseTabConfig( tab: _DatabaseTab.inventory, title: context.l10n.profileInventoryTab, summary: 'Granska, filtrera och redigera inventory-poster. Välj användare för att arbeta på en specifik ägares data.', buildPanel: (_) => const AdminInventoryPanel(embedded: true), ), _DatabaseTabConfig( tab: _DatabaseTab.pantry, title: context.l10n.profilePantryTab, summary: 'Granska och redigera användarnas baslager. Flytta poster till inventarie eller ta bort dem vid behov.', buildPanel: (_) => const AdminPantryPanel(embedded: true), ), _DatabaseTabConfig( tab: _DatabaseTab.products, title: context.l10n.profileProductsTab, summary: 'Hantera globala produkter: kategorisering, restaurering, merge och AI-stöd.', buildPanel: (_) => const AdminProductsPanel(embedded: true), ), _DatabaseTabConfig( tab: _DatabaseTab.privateProducts, title: 'Privata produkter', summary: 'Promotera privata produkter till den globala produkt-tabellen.', buildPanel: (_) => const AdminPrivateProductsPanel(embedded: true), ), _DatabaseTabConfig( tab: _DatabaseTab.pending, title: context.l10n.profilePendingTab, summary: 'Godkänn eller avslå nya produkter som föreslagits av användare.', buildPanel: (_) => const AdminPendingProductsPanel(embedded: true), ), _DatabaseTabConfig( tab: _DatabaseTab.aliases, title: 'Alias', summary: 'Hantera globala alias som används i receipt-importens första matchningssteg.', buildPanel: (_) => const AdminAliasesPanel(embedded: true), ), _DatabaseTabConfig( tab: _DatabaseTab.ai, title: 'AI', summary: 'Se vilka AI-modeller som används och hur de är exponerade i systemet.', buildPanel: (_) => const AdminAiPanel(embedded: true), ), ]; Future _refreshCategories() async { setState(() => _isRefreshingCategories = true); try { await ref.read(profileRepositoryProvider).refreshCategories(); if (!mounted) return; ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Kategorier har uppdaterats.')), ); } catch (e) { if (!mounted) return; ScaffoldMessenger.of(context).showSnackBar( buildCopyableErrorSnackBar(context, mapErrorToUserMessage(e, context)), ); } finally { if (mounted) setState(() => _isRefreshingCategories = false); } } Widget _panelShell({ required String title, required String description, required Widget child, }) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Card( child: Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(title, style: Theme.of(context).textTheme.titleMedium), const SizedBox(height: 8), Text(description), ], ), ), ), const SizedBox(height: 12), Expanded(child: child), ], ); } @override Widget build(BuildContext context) { final currentTab = _tabConfigs.firstWhere((config) => config.tab == _activeTab); final header = Card( child: Padding( padding: const EdgeInsets.all(12), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Expanded( child: SingleChildScrollView( scrollDirection: Axis.horizontal, child: Row( children: _tabConfigs .map( (config) => Padding( padding: const EdgeInsets.only(right: 8), child: ChoiceChip( label: Text(config.title), selected: _activeTab == config.tab, onSelected: (_) => setState(() => _activeTab = config.tab), ), ), ) .toList(), ), ), ), const SizedBox(width: 8), IconButton( tooltip: 'Uppdatera kategorier', onPressed: _isRefreshingCategories ? null : _refreshCategories, icon: _isRefreshingCategories ? const SizedBox( height: 16, width: 16, child: CircularProgressIndicator(strokeWidth: 2), ) : const Icon(Icons.refresh), ), ], ), const SizedBox(height: 8), Text( currentTab.summary, style: Theme.of(context).textTheme.bodySmall, ), ], ), ), ); return Padding( padding: widget.embedded ? EdgeInsets.zero : const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Expanded(flex: 1, child: header), const SizedBox(height: 12), Expanded(flex: 6, child: _panelShell(title: currentTab.title, description: currentTab.summary, child: currentTab.buildPanel(context))), ], ), ); } }