feat(app): add evaluation history, bot control panel, simulation visualizer, and vendored signalr_core

This commit is contained in:
2026-08-24 21:37:43 +02:00
parent 676496b77d
commit 0894c40f07
113 changed files with 12413 additions and 3613 deletions
@@ -10,12 +10,19 @@ import '../bloc/search_bloc.dart';
import '../repositories/search_repository.dart';
/// Focused Spotlight Asset Search Dialog with reactive Favorite Star Button, Hero transitions, and Shimmer loading states.
///
/// By default, tapping a result navigates straight to [AssetDetailScreen] (the main search-feature use case).
/// Pass [onAssetSelected] to repurpose this as a reusable asset PICKER instead - e.g. the simulation screen's
/// ISIN input - in which case a tap pops the dialog and invokes the callback with the picked ISIN/name instead
/// of navigating anywhere.
class AssetSearchDialog extends StatelessWidget {
final ApiClient apiClient;
final void Function(String isin, String name)? onAssetSelected;
const AssetSearchDialog({
super.key,
required this.apiClient,
this.onAssetSelected,
});
@override
@@ -24,15 +31,16 @@ class AssetSearchDialog extends StatelessWidget {
create: (context) => SearchBloc(
repository: SearchRepository(apiClient: apiClient),
)..add(const SearchQueryChanged('')),
child: _AssetSearchDialogContent(apiClient: apiClient),
child: _AssetSearchDialogContent(apiClient: apiClient, onAssetSelected: onAssetSelected),
);
}
}
class _AssetSearchDialogContent extends StatefulWidget {
final ApiClient apiClient;
final void Function(String isin, String name)? onAssetSelected;
const _AssetSearchDialogContent({required this.apiClient});
const _AssetSearchDialogContent({required this.apiClient, this.onAssetSelected});
@override
State<_AssetSearchDialogContent> createState() => _AssetSearchDialogContentState();
@@ -162,6 +170,10 @@ class _AssetSearchDialogContentState extends State<_AssetSearchDialogContent> {
),
onTap: () {
Navigator.pop(context);
if (widget.onAssetSelected != null) {
widget.onAssetSelected!(isin, assetName);
return;
}
Navigator.push(
context,
MaterialPageRoute(