feat(ai): add AI trace tracking and admin panel
- Add AiTrace model to Prisma schema with relations to User - Implement AiTraceService with CRUD operations for AI traces - Add new admin panel for AI traces with filtering and detail views - Integrate trace persistence in receipt import flow - Add API endpoints for listing and retrieving AI traces - Update Flutter admin UI with new AI tab and navigation - Add new domain models for AI traces and details - Add migration for AiTrace table creation BREAKING CHANGE: None
This commit is contained in:
@@ -5,7 +5,6 @@ import 'dart:async';
|
||||
import '../../../core/api/api_error_mapper.dart';
|
||||
import '../../../core/l10n/l10n.dart';
|
||||
import '../../../core/realtime/realtime_sync.dart';
|
||||
import 'admin_ai_panel.dart';
|
||||
import 'admin_aliases_panel.dart';
|
||||
import 'admin_inventory_panel.dart';
|
||||
import 'admin_pantry_panel.dart';
|
||||
@@ -14,7 +13,14 @@ 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 }
|
||||
enum _DatabaseTab {
|
||||
inventory,
|
||||
pantry,
|
||||
products,
|
||||
privateProducts,
|
||||
pending,
|
||||
aliases
|
||||
}
|
||||
|
||||
class _DatabaseTabConfig {
|
||||
final _DatabaseTab tab;
|
||||
@@ -98,11 +104,6 @@ class _AdminDatabasePanelState extends ConsumerState<AdminDatabasePanel> {
|
||||
title: 'Alias',
|
||||
panel: const AdminAliasesPanel(embedded: true),
|
||||
),
|
||||
_DatabaseTabConfig(
|
||||
tab: _DatabaseTab.ai,
|
||||
title: 'AI',
|
||||
panel: const AdminAiPanel(embedded: true),
|
||||
),
|
||||
];
|
||||
|
||||
Future<void> _refreshCategories() async {
|
||||
@@ -125,7 +126,8 @@ class _AdminDatabasePanelState extends ConsumerState<AdminDatabasePanel> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final currentTab = _tabConfigs.firstWhere((config) => config.tab == _activeTab);
|
||||
final currentTab =
|
||||
_tabConfigs.firstWhere((config) => config.tab == _activeTab);
|
||||
|
||||
final header = Card(
|
||||
child: Padding(
|
||||
@@ -146,7 +148,8 @@ class _AdminDatabasePanelState extends ConsumerState<AdminDatabasePanel> {
|
||||
child: ChoiceChip(
|
||||
label: Text(config.title),
|
||||
selected: _activeTab == config.tab,
|
||||
onSelected: (_) => setState(() => _activeTab = config.tab),
|
||||
onSelected: (_) =>
|
||||
setState(() => _activeTab = config.tab),
|
||||
),
|
||||
),
|
||||
)
|
||||
@@ -157,7 +160,8 @@ class _AdminDatabasePanelState extends ConsumerState<AdminDatabasePanel> {
|
||||
const SizedBox(width: 8),
|
||||
IconButton(
|
||||
tooltip: 'Uppdatera kategorier',
|
||||
onPressed: _isRefreshingCategories ? null : _refreshCategories,
|
||||
onPressed:
|
||||
_isRefreshingCategories ? null : _refreshCategories,
|
||||
icon: _isRefreshingCategories
|
||||
? const SizedBox(
|
||||
height: 16,
|
||||
@@ -183,7 +187,8 @@ class _AdminDatabasePanelState extends ConsumerState<AdminDatabasePanel> {
|
||||
const SizedBox(height: 12),
|
||||
Expanded(
|
||||
child: KeyedSubtree(
|
||||
key: ValueKey('admin-db-${_activeTab.name}-$_panelRefreshVersion'),
|
||||
key:
|
||||
ValueKey('admin-db-${_activeTab.name}-$_panelRefreshVersion'),
|
||||
child: currentTab.panel,
|
||||
),
|
||||
),
|
||||
@@ -192,4 +197,3 @@ class _AdminDatabasePanelState extends ConsumerState<AdminDatabasePanel> {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user