Skip to content
Merged
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:jive_money/models/category.dart';
import 'package:jive_money/models/category_template.dart';
import 'package:jive_money/providers/category_provider.dart';
import 'package:jive_money/providers/ledger_provider.dart';
import 'package:jive_money/services/api/category_service.dart';
import 'package:jive_money/widgets/bottom_sheets/import_details_sheet.dart';
import '../../models/category.dart';
import '../../models/category_template.dart';
import '../../providers/category_provider.dart';
import '../../providers/ledger_provider.dart';
import '../../services/api/category_service.dart';
import '../../widgets/bottom_sheets/import_details_sheet.dart';

class CategoryManagementEnhancedPage extends ConsumerStatefulWidget {
const CategoryManagementEnhancedPage({super.key});
Expand All @@ -17,6 +17,22 @@ class CategoryManagementEnhancedPage extends ConsumerStatefulWidget {
class _CategoryManagementEnhancedPageState extends ConsumerState<CategoryManagementEnhancedPage> {
bool _busy = false;

String _renderDryRunSubtitle(ImportActionDetail d) {
switch (d.action) {
case 'renamed':
return '将重命名' + (d.predictedName != null ? ' → ${d.predictedName}' : '');
Copy link

Copilot AI Sep 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the 'renamed' case, if predictedName is absent but finalName is present, the subtitle omits the target name. Consider falling back to finalName so users always see the rename target: for example, use final target = d.predictedName ?? d.finalName ?? d.originalName; then return '将重命名 → $target'.

Suggested change
return '将重命名' + (d.predictedName != null ? ' → ${d.predictedName}' : '');
final target = d.predictedName ?? d.finalName ?? d.originalName;
return '将重命名' + (target != null ? ' → $target' : '');

Copilot uses AI. Check for mistakes.

case 'updated':
return '将覆盖同名分类';
case 'skipped':
return '将跳过' + (d.reason != null ? '(${d.reason})' : '');
case 'failed':
return '预检失败' + (d.reason != null ? '(${d.reason})' : '');
case 'imported':
default:
return '将创建';
}
}

@override
Widget build(BuildContext context) {
return Scaffold(
Expand Down Expand Up @@ -183,8 +199,8 @@ class _CategoryManagementEnhancedPageState extends ConsumerState<CategoryManagem
final color = (d.action == 'failed' || d.action == 'skipped') ? Colors.orange : Colors.green;
return ListTile(
dense: true,
title: Text(d.finalName ?? d.originalName),
subtitle: Text(d.action + (d.reason!=null ? ' (${d.reason})' : '')),
title: Text(d.predictedName ?? d.finalName ?? d.originalName),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The UI is attempting to use d.predictedName, but the ImportActionDetail class in lib/services/api/category_service.dart does not seem to have this field defined. This will lead to a compile-time or runtime error.

The backend has been updated to provide predicted_name, so the frontend ImportActionDetail model needs to be updated accordingly to include this new field and parse it from the JSON response.

subtitle: Text(_renderDryRunSubtitle(d)),
trailing: Icon(
d.action == 'failed' ? Icons.error : (d.action=='skipped'? Icons.warning_amber : Icons.check_circle),
color: color,
Expand Down Expand Up @@ -239,8 +255,8 @@ class _CategoryManagementEnhancedPageState extends ConsumerState<CategoryManagem
child: const Text('确认导入'),
),
],
),
);
);
});
},
);
}
Expand Down
Loading