lab5 вроде done
This commit is contained in:
parent
0e8ce38c33
commit
76dcbb954b
@ -13,11 +13,11 @@ class QuotesDto {
|
||||
|
||||
@JsonSerializable(createToJson: false)
|
||||
class QuoteDataDto {
|
||||
final String? text;
|
||||
final String? body;
|
||||
final String? author;
|
||||
final String? imageUrl;
|
||||
|
||||
const QuoteDataDto({this.text, this.author, this.imageUrl});
|
||||
const QuoteDataDto({this.body, this.author, this.imageUrl});
|
||||
|
||||
factory QuoteDataDto.fromJson(Map<String, dynamic> json) => _$QuoteDataDtoFromJson(json);
|
||||
}
|
@ -13,7 +13,7 @@ QuotesDto _$QuotesDtoFromJson(Map<String, dynamic> json) => QuotesDto(
|
||||
);
|
||||
|
||||
QuoteDataDto _$QuoteDataDtoFromJson(Map<String, dynamic> json) => QuoteDataDto(
|
||||
text: json['text'] as String?,
|
||||
body: json['body'] as String?,
|
||||
author: json['author'] as String?,
|
||||
imageUrl: json['imageUrl'] as String?,
|
||||
);
|
||||
|
@ -6,7 +6,7 @@ const _imagePlaceholder =
|
||||
|
||||
extension QuoteDtoToModel on QuoteDataDto {
|
||||
Quote toDomain() => Quote(
|
||||
text ?? 'Без текста',
|
||||
body ?? 'Без текста',
|
||||
author ?? 'Неизвестный автор',
|
||||
imageUrl ?? _imagePlaceholder,
|
||||
);
|
||||
|
@ -13,19 +13,32 @@ class QuotesRepository extends ApiInterface {
|
||||
requestBody: true,
|
||||
))
|
||||
..options.headers = {
|
||||
'Authorization': 'Bearer 82ccaa45c8344de4ac008b2487d33361', // Add the API key here
|
||||
'Authorization': 'Bearer 82ccaa45c8344de4ac008b2487d33361',
|
||||
};
|
||||
|
||||
static const String _baseUrl = 'https://favqs.com/api';
|
||||
|
||||
@override
|
||||
Future<List<Quote>?> loadData({String? q, OnErrorCallback? onError}) async {
|
||||
Future<List<Quote>?> loadData({String? q, String? author, OnErrorCallback? onError}) async {
|
||||
try {
|
||||
final Map<String, dynamic> queryParams = {};
|
||||
|
||||
// Добавляем фильтрацию по тексту цитаты
|
||||
if (q != null && q.isNotEmpty) {
|
||||
queryParams['filter'] = q; // Фильтруем по слову
|
||||
}
|
||||
|
||||
// Добавляем фильтрацию по автору
|
||||
if (author != null && author.isNotEmpty) {
|
||||
queryParams['type'] = 'author';
|
||||
queryParams['filter'] = author;
|
||||
}
|
||||
|
||||
const String url = '$_baseUrl/quotes';
|
||||
|
||||
final Response<dynamic> response = await _dio.get<Map<dynamic, dynamic>>(
|
||||
url,
|
||||
queryParameters: q != null ? {'filter[text_cont]': q} : null,
|
||||
queryParameters: queryParams.isNotEmpty ? queryParams : null,
|
||||
);
|
||||
|
||||
final QuotesDto dto = QuotesDto.fromJson(response.data as Map<String, dynamic>);
|
||||
@ -37,3 +50,4 @@ class QuotesRepository extends ApiInterface {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -44,48 +44,70 @@ class MyHomePage extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _MyHomePageState extends State<MyHomePage> {
|
||||
final TextEditingController searchController = TextEditingController();
|
||||
final List<Quote> _quotes = [];
|
||||
final List<Quote> _filteredQuotes = [];
|
||||
|
||||
final QuotesRepository _quotesRepository = QuotesRepository();
|
||||
|
||||
final TextEditingController searchController = TextEditingController();
|
||||
final TextEditingController authorController = TextEditingController();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_loadQuotes();
|
||||
|
||||
searchController.addListener(() {
|
||||
_filterQuotes(searchController.text);
|
||||
_loadQuotes();
|
||||
});
|
||||
|
||||
authorController.addListener(() {
|
||||
_loadQuotes();
|
||||
});
|
||||
}
|
||||
|
||||
// Метод для загрузки цитат с учетом обоих фильтров
|
||||
Future<void> _loadQuotes() async {
|
||||
final quotes = await _quotesRepository.loadData(onError: (error) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text('Ошибка загрузки: $error')),
|
||||
);
|
||||
});
|
||||
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')),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
if (quotes != null) {
|
||||
setState(() {
|
||||
_quotes.clear();
|
||||
_quotes.addAll(quotes);
|
||||
_filteredQuotes.addAll(quotes);
|
||||
_filterQuotes();
|
||||
});
|
||||
}
|
||||
print('Загружено цитат: ${_quotes.length}');
|
||||
print('Отфильтрованные цитаты: ${_filteredQuotes.length}');
|
||||
}
|
||||
|
||||
void _filterQuotes(String query) {
|
||||
// Фильтрация цитат по введенным значениям
|
||||
void _filterQuotes() {
|
||||
setState(() {
|
||||
if (query.isEmpty) {
|
||||
_filteredQuotes.clear();
|
||||
_filteredQuotes.addAll(_quotes);
|
||||
} else {
|
||||
_filteredQuotes.clear();
|
||||
_filteredQuotes.addAll(
|
||||
_quotes.where((quote) =>
|
||||
quote.text.toLowerCase().contains(query.toLowerCase()) ||
|
||||
quote.author.toLowerCase().contains(query.toLowerCase())),
|
||||
);
|
||||
_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()));
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -95,8 +117,6 @@ class _MyHomePageState extends State<MyHomePage> {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('Цитаты'),
|
||||
backgroundColor: Theme.of(context).colorScheme.primaryContainer,
|
||||
foregroundColor: Theme.of(context).colorScheme.onPrimaryContainer,
|
||||
),
|
||||
body: Column(
|
||||
children: [
|
||||
@ -105,11 +125,21 @@ class _MyHomePageState extends State<MyHomePage> {
|
||||
child: TextField(
|
||||
controller: searchController,
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'Поиск',
|
||||
labelText: 'Поиск по цитате',
|
||||
prefixIcon: Icon(Icons.search),
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: TextField(
|
||||
controller: authorController,
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'Поиск по автору',
|
||||
prefixIcon: Icon(Icons.person),
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: _filteredQuotes.isEmpty
|
||||
? const Center(
|
||||
@ -121,7 +151,7 @@ class _MyHomePageState extends State<MyHomePage> {
|
||||
: ListView.builder(
|
||||
itemCount: _filteredQuotes.length,
|
||||
itemBuilder: (context, index) {
|
||||
final quote = _filteredQuotes[index];
|
||||
final quote = _filteredQuotes[index]; // Используем _filteredQuotes для отображения
|
||||
return Card(
|
||||
margin: const EdgeInsets.symmetric(
|
||||
vertical: 8.0,
|
||||
|
Loading…
x
Reference in New Issue
Block a user