Files
FinanceApp2/lib/screens/settings_screen.dart
T
2025-05-12 19:08:22 +03:00

212 lines
9.2 KiB
Dart

import 'package:flutter/material.dart';
import 'package:drift/drift.dart' show Value;
import '../database/database.dart' as db;
import '../utils/category_utils.dart';
import '../widgets/edit_category_dialog.dart'; // Импортируем диалог
// Переименован класс SettingsScreen в CategorySettingsScreen
class CategorySettingsScreen extends StatefulWidget {
final db.AppDatabase database;
const CategorySettingsScreen({Key? key, required this.database}) : super(key: key);
@override
State<CategorySettingsScreen> createState() => _CategorySettingsScreenState();
}
// Переименован класс _SettingsScreenState в _CategorySettingsScreenState
class _CategorySettingsScreenState extends State<CategorySettingsScreen> {
late Stream<List<db.CategoryDb>> _categoriesStream;
@override
void initState() {
super.initState();
_categoriesStream = widget.database.watchAllCategoriesDb();
}
// Функция для показа диалога добавления/редактирования
void _showEditCategoryDialog({db.CategoryDb? categoryToEdit}) async {
final result = await showDialog<bool>( // Ожидаем bool (true если сохранено)
context: context,
builder: (context) => EditCategoryDialog(
database: widget.database,
categoryToEdit: categoryToEdit, // Передаем категорию для редактирования или null для добавления
),
);
if (result == true && mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(categoryToEdit == null ? 'Категория добавлена' : 'Категория обновлена'),
duration: const Duration(seconds: 2),
behavior: SnackBarBehavior.floating,
),
);
}
}
// Функция для удаления категории (с подтверждением)
void _deleteCategory(db.CategoryDb category) async {
// Не позволяем удалять 'Income'
if (category.name == 'Income') {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Категорию "Income" нельзя удалить.'),
backgroundColor: Colors.orange,
behavior: SnackBarBehavior.floating,
),
);
return;
}
final confirm = await showDialog<bool>(
context: context,
builder: (context) => AlertDialog(
title: const Text('Удалить категорию?'),
content: Text('Вы уверены, что хотите удалить категорию "${category.name}"? Это действие нельзя отменить.\n\nТранзакции с этой категорией могут отображаться некорректно или вызвать ошибки при попытке их отображения, если они не будут переназначены.'),
actions: [
TextButton(
onPressed: () => Navigator.of(context).pop(false), // Отмена
child: const Text('Отмена'),
),
TextButton(
onPressed: () => Navigator.of(context).pop(true), // Подтвердить
style: TextButton.styleFrom(foregroundColor: Colors.red),
child: const Text('Удалить'),
),
],
),
);
if (confirm == true) {
try {
// Попытка удаления категории из базы данных
final deletedRows = await widget.database.deleteCategory(category.id);
if (deletedRows > 0 && mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Категория "${category.name}" удалена.'),
duration: const Duration(seconds: 2),
behavior: SnackBarBehavior.floating,
),
);
} else if (deletedRows == 0 && mounted) {
// Это может произойти, если deleteCategory вернул 0 (например, из-за наличия транзакций)
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Не удалось удалить категорию "${category.name}". Возможно, она используется в транзакциях.'),
backgroundColor: Colors.red,
duration: const Duration(seconds: 3),
behavior: SnackBarBehavior.floating,
),
);
}
} catch (e) {
if (mounted) {
print("Error deleting category: $e"); // Логируем ошибку
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Ошибка при удалении категории: ${e.toString()}'),
backgroundColor: Colors.red,
behavior: SnackBarBehavior.floating,
),
);
}
}
}
}
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
final isDark = theme.brightness == Brightness.dark;
return Scaffold(
appBar: AppBar(
title: const Text('Редактирование категорий'), // Обновленный заголовок
centerTitle: true,
backgroundColor: theme.appBarTheme.backgroundColor, // Ensure AppBar color matches theme
elevation: theme.appBarTheme.elevation, // Ensure elevation matches theme
),
body: StreamBuilder<List<db.CategoryDb>>(
stream: _categoriesStream,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting && !snapshot.hasData) {
return const Center(child: CircularProgressIndicator());
}
if (snapshot.hasError) {
return Center(child: Text('Ошибка загрузки категорий: ${snapshot.error}'));
}
final categories = snapshot.data ?? [];
// Фильтруем категорию 'Income', чтобы ее нельзя было редактировать/удалять отсюда
final editableCategories = categories.where((c) => c.name != 'Income').toList();
if (editableCategories.isEmpty && snapshot.connectionState != ConnectionState.waiting) {
return Center(
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Text(
'Нет категорий для редактирования.\nНажмите "+", чтобы добавить новую категорию расходов.',
textAlign: TextAlign.center,
style: theme.textTheme.bodyLarge?.copyWith(color: Colors.grey),
),
),
);
}
return ListView.separated(
padding: const EdgeInsets.symmetric(vertical: 8.0), // Add padding around the list
itemCount: editableCategories.length,
separatorBuilder: (context, index) => Divider(
height: 1,
thickness: 1,
indent: 72, // Indent to align with text after avatar
endIndent: 16,
color: theme.dividerColor.withOpacity(0.3),
),
itemBuilder: (context, index) {
final category = editableCategories[index];
final iconData = CategoryUtils.getIconFromString(category.icon);
final colorData = Color(category.color);
return ListTile(
leading: CircleAvatar(
radius: 22, // Slightly larger avatar
backgroundColor: colorData.withOpacity(isDark ? 0.3 : 0.15),
child: Icon(iconData, color: colorData, size: 24),
),
title: Text(category.name, style: theme.textTheme.titleMedium),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
IconButton(
icon: Icon(Icons.edit_outlined, color: theme.colorScheme.primary.withOpacity(0.8)),
tooltip: 'Редактировать',
splashRadius: 24,
onPressed: () => _showEditCategoryDialog(categoryToEdit: category),
),
IconButton(
icon: Icon(Icons.delete_outline, color: Colors.red.shade400.withOpacity(0.8)),
tooltip: 'Удалить',
splashRadius: 24,
onPressed: () => _deleteCategory(category),
),
],
),
onTap: () => _showEditCategoryDialog(categoryToEdit: category), // Тоже открывает редактирование
);
},
);
},
),
floatingActionButton: FloatingActionButton(
onPressed: () => _showEditCategoryDialog(), // Вызов без аргумента для добавления
tooltip: 'Добавить категорию',
child: const Icon(Icons.add),
),
);
}
}