Pibd-33_Tikhonenkov_Alexey_PMU/lib/main.dart

282 lines
8.4 KiB
Dart
Raw Normal View History

2024-11-07 16:23:34 +04:00
import 'package:flutter/material.dart';
2024-12-11 05:09:29 +04:00
import '/data/repositories/quotes_repository.dart';
2024-11-07 16:23:34 +04:00
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
2024-11-13 02:38:05 +04:00
@override
2024-11-07 16:23:34 +04:00
Widget build(BuildContext context) {
return MaterialApp(
2024-11-13 02:38:05 +04:00
title: 'Цитаты',
2024-11-07 16:23:34 +04:00
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.indigo),
useMaterial3: true,
),
2024-11-13 02:38:05 +04:00
home: const MyHomePage(title: 'Цитаты'),
2024-11-07 16:23:34 +04:00
);
}
}
2024-11-13 02:38:05 +04:00
class Quote {
final String text;
final String author;
2024-11-20 01:35:31 +04:00
final String imagePath;
2024-11-27 13:34:01 +04:00
bool isFavorite;
2024-11-20 01:35:31 +04:00
2024-11-27 13:34:01 +04:00
Quote(this.text, this.author, this.imagePath, [this.isFavorite = false]);
2024-12-11 05:09:29 +04:00
2024-11-27 13:34:01 +04:00
void toggleFavorite() {
isFavorite = !isFavorite;
}
2024-11-13 02:38:05 +04:00
}
2024-11-07 16:23:34 +04:00
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
2024-12-11 05:09:29 +04:00
2024-11-07 16:23:34 +04:00
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final List<Quote> _quotes = [];
2024-12-11 05:09:29 +04:00
final List<Quote> _filteredQuotes = [];
final QuotesRepository _quotesRepository = QuotesRepository();
2024-11-13 02:38:05 +04:00
2024-12-11 06:12:20 +04:00
final TextEditingController searchController = TextEditingController();
final TextEditingController authorController = TextEditingController();
2024-11-20 01:35:31 +04:00
@override
void initState() {
super.initState();
2024-12-11 05:09:29 +04:00
_loadQuotes();
searchController.addListener(() {
2024-12-11 06:12:20 +04:00
_loadQuotes();
});
authorController.addListener(() {
_loadQuotes();
2024-12-11 05:09:29 +04:00
});
2024-11-20 01:35:31 +04:00
}
2024-12-11 06:12:20 +04:00
// Метод для загрузки цитат с учетом обоих фильтров
2024-12-11 05:09:29 +04:00
Future<void> _loadQuotes() async {
2024-12-11 06:12:20 +04:00
final query = searchController.text;
final author = authorController.text;
final quotes = await _quotesRepository.loadData(
q: query, // Поиск по цитате
author: author, // Поиск по автору
onError: (error) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Ошибка загрузки: $error')),
);
},
);
2024-12-11 05:09:29 +04:00
if (quotes != null) {
setState(() {
2024-12-11 06:12:20 +04:00
_quotes.clear();
2024-12-11 05:09:29 +04:00
_quotes.addAll(quotes);
2024-12-11 06:12:20 +04:00
_filterQuotes();
2024-12-11 05:09:29 +04:00
});
}
2024-12-11 06:12:20 +04:00
print('Загружено цитат: ${_quotes.length}');
print('Отфильтрованные цитаты: ${_filteredQuotes.length}');
2024-11-20 01:35:31 +04:00
}
2024-11-07 16:23:34 +04:00
2024-12-11 06:12:20 +04:00
// Фильтрация цитат по введенным значениям
void _filterQuotes() {
2024-11-20 01:35:31 +04:00
setState(() {
2024-12-11 06:12:20 +04:00
_filteredQuotes.clear(); // Очистите список фильтрации
_filteredQuotes.addAll(_quotes); // Изначально показываем все цитаты
// Применяем фильтрацию по цитате
if (searchController.text.isNotEmpty) {
_filteredQuotes.retainWhere((quote) =>
quote.text.toLowerCase().contains(searchController.text.toLowerCase()));
}
// Применяем фильтрацию по автору
if (authorController.text.isNotEmpty) {
_filteredQuotes.retainWhere((quote) =>
quote.author.toLowerCase().contains(authorController.text.toLowerCase()));
2024-12-11 05:09:29 +04:00
}
2024-11-20 01:35:31 +04:00
});
2024-11-07 16:23:34 +04:00
}
@override
Widget build(BuildContext context) {
2024-11-13 02:38:05 +04:00
return Scaffold(
2024-11-07 16:23:34 +04:00
appBar: AppBar(
2024-11-20 01:35:31 +04:00
title: const Text('Цитаты'),
2024-11-07 16:23:34 +04:00
),
2024-11-27 13:34:01 +04:00
body: Column(
2024-11-13 02:38:05 +04:00
children: [
2024-12-11 05:09:29 +04:00
Padding(
padding: const EdgeInsets.all(16.0),
child: TextField(
controller: searchController,
decoration: const InputDecoration(
2024-12-11 06:12:20 +04:00
labelText: 'Поиск по цитате',
2024-12-11 05:09:29 +04:00
prefixIcon: Icon(Icons.search),
),
2024-11-27 13:34:01 +04:00
),
),
2024-12-11 06:12:20 +04:00
Padding(
padding: const EdgeInsets.all(16.0),
child: TextField(
controller: authorController,
decoration: const InputDecoration(
labelText: 'Поиск по автору',
prefixIcon: Icon(Icons.person),
),
),
),
2024-11-27 13:34:01 +04:00
Expanded(
2024-12-11 05:09:29 +04:00
child: _filteredQuotes.isEmpty
2024-11-27 13:34:01 +04:00
? const Center(
child: Text(
2024-12-11 05:09:29 +04:00
'Нет цитат для отображения.',
2024-11-27 13:34:01 +04:00
style: TextStyle(fontSize: 18, color: Colors.grey),
2024-11-20 01:35:31 +04:00
),
2024-11-27 13:34:01 +04:00
)
: ListView.builder(
2024-12-11 05:09:29 +04:00
itemCount: _filteredQuotes.length,
2024-11-27 13:34:01 +04:00
itemBuilder: (context, index) {
2024-12-11 06:12:20 +04:00
final quote = _filteredQuotes[index]; // Используем _filteredQuotes для отображения
2024-11-27 13:34:01 +04:00
return Card(
margin: const EdgeInsets.symmetric(
vertical: 8.0,
horizontal: 10.0,
2024-11-20 01:35:31 +04:00
),
2024-11-27 13:34:01 +04:00
child: ListTile(
contentPadding: const EdgeInsets.all(8.0),
leading: SizedBox(
width: 50.0,
child: Image.network(
quote.imagePath,
fit: BoxFit.cover,
errorBuilder: (_, __, ___) =>
const Icon(Icons.error, color: Colors.red),
2024-11-20 01:35:31 +04:00
),
2024-11-27 13:34:01 +04:00
),
title: Text(
quote.text,
style: const TextStyle(
fontSize: 18, fontWeight: FontWeight.w500),
),
subtitle: Text('- ${quote.author}'),
2024-12-11 05:09:29 +04:00
trailing: IconButton(
icon: Icon(
quote.isFavorite
? Icons.favorite
: Icons.favorite_border,
color: quote.isFavorite ? Colors.red : null,
),
onPressed: () {
setState(() {
quote.toggleFavorite();
});
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(quote.isFavorite
? 'Цитата добавлена в избранное'
: 'Цитата удалена из избранного'),
duration: const Duration(seconds: 2),
2024-11-20 01:35:31 +04:00
),
2024-12-11 05:09:29 +04:00
);
},
2024-11-27 13:34:01 +04:00
),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
QuoteDetailScreen(quote: quote),
),
);
},
),
);
},
),
2024-11-13 02:38:05 +04:00
),
],
2024-11-07 16:23:34 +04:00
),
2024-11-13 02:38:05 +04:00
);
}
}
2024-11-27 13:34:01 +04:00
class QuoteDetailScreen extends StatelessWidget {
final Quote quote;
2024-12-11 05:09:29 +04:00
2024-11-27 13:34:01 +04:00
const QuoteDetailScreen({super.key, required this.quote});
@override
Widget build(BuildContext context) {
2024-11-27 13:34:01 +04:00
return Scaffold(
appBar: AppBar(
title: const Text('Детали цитаты'),
),
body: Center(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.network(
quote.imagePath,
height: 150,
errorBuilder: (_, __, ___) =>
const Icon(Icons.error, color: Colors.red),
),
const SizedBox(height: 20),
Text(
quote.text,
style:
const TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
textAlign: TextAlign.center,
),
const SizedBox(height: 10),
Text(
'- ${quote.author}',
style: const TextStyle(fontSize: 18, color: Colors.grey),
),
],
),
),
),
);
}
}
2024-12-11 05:09:29 +04:00
2024-11-13 02:38:05 +04:00
extension StringExtension on String {
String capitalize() {
return split(' ').map((word) {
if (word.isNotEmpty) {
return '${word[0].toUpperCase()}${word.substring(1).toLowerCase()}';
}
return word;
}).join(' ');
}
2024-11-13 02:38:05 +04:00
String addQuotesIfMissing() {
if (startsWith('\"') && endsWith('\"')) return this;
if (startsWith('\"') && !endsWith('\"')) return '$this\"';
if (endsWith('\"') && !startsWith('\"')) return '\"$this';
2024-11-13 02:38:05 +04:00
return '\"$this\"';
2024-11-07 16:23:34 +04:00
}
}