lab_5
This commit is contained in:
parent
fad9c2a19f
commit
e72bed02f8
36
lib/data/dtos/characters_dto.dart
Normal file
36
lib/data/dtos/characters_dto.dart
Normal file
@ -0,0 +1,36 @@
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
|
||||
part 'characters_dto.g.dart';
|
||||
|
||||
@JsonSerializable(createToJson: false)
|
||||
class CharactersDto {
|
||||
final List<CharacterDataDto>? data;
|
||||
|
||||
const CharactersDto({this.data});
|
||||
|
||||
factory CharactersDto.fromJson(Map<String, dynamic> json) => _$CharactersDtoFromJson(json);
|
||||
}
|
||||
|
||||
@JsonSerializable(createToJson: false)
|
||||
class CharacterDataDto {
|
||||
final String? id;
|
||||
final String? type;
|
||||
final CharacterAttributesDataDto? attributes;
|
||||
|
||||
const CharacterDataDto({this.id, this.type, this.attributes});
|
||||
|
||||
factory CharacterDataDto.fromJson(Map<String, dynamic> json) => _$CharacterDataDtoFromJson(json);
|
||||
}
|
||||
|
||||
@JsonSerializable(createToJson: false)
|
||||
class CharacterAttributesDataDto {
|
||||
final String? name;
|
||||
final String? born;
|
||||
final String? died;
|
||||
final String? image;
|
||||
|
||||
const CharacterAttributesDataDto({this.name, this.born, this.died, this.image});
|
||||
|
||||
factory CharacterAttributesDataDto.fromJson(Map<String, dynamic> json) =>
|
||||
_$CharacterAttributesDataDtoFromJson(json);
|
||||
}
|
33
lib/data/dtos/characters_dto.g.dart
Normal file
33
lib/data/dtos/characters_dto.g.dart
Normal file
@ -0,0 +1,33 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'characters_dto.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
CharactersDto _$CharactersDtoFromJson(Map<String, dynamic> json) =>
|
||||
CharactersDto(
|
||||
data: (json['data'] as List<dynamic>?)
|
||||
?.map((e) => CharacterDataDto.fromJson(e as Map<String, dynamic>))
|
||||
.toList(),
|
||||
);
|
||||
|
||||
CharacterDataDto _$CharacterDataDtoFromJson(Map<String, dynamic> json) =>
|
||||
CharacterDataDto(
|
||||
id: json['id'] as String?,
|
||||
type: json['type'] as String?,
|
||||
attributes: json['attributes'] == null
|
||||
? null
|
||||
: CharacterAttributesDataDto.fromJson(
|
||||
json['attributes'] as Map<String, dynamic>),
|
||||
);
|
||||
|
||||
CharacterAttributesDataDto _$CharacterAttributesDataDtoFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
CharacterAttributesDataDto(
|
||||
name: json['name'] as String?,
|
||||
born: json['born'] as String?,
|
||||
died: json['died'] as String?,
|
||||
image: json['image'] as String?,
|
||||
);
|
23
lib/data/mappers/characters_mapper.dart
Normal file
23
lib/data/mappers/characters_mapper.dart
Normal file
@ -0,0 +1,23 @@
|
||||
import 'package:pmd_labs/data/dtos/characters_dto.dart';
|
||||
import 'package:pmd_labs/domain/models/card.dart';
|
||||
|
||||
const _imagePlaceholder =
|
||||
'https://upload.wikimedia.org/wikipedia/en/archive/b/b1/20210811082420%21Portrait_placeholder.png';
|
||||
|
||||
extension CharacterDataDtoToModel on CharacterDataDto {
|
||||
CardData toDomain() => CardData(
|
||||
attributes?.name ?? 'UNKNOWN',
|
||||
imageUrl: attributes?.image ?? _imagePlaceholder,
|
||||
descriptionText: _makeDescriptionText(attributes?.born, attributes?.died),
|
||||
);
|
||||
|
||||
String _makeDescriptionText(String? born, String? died) {
|
||||
return born != null && died != null
|
||||
? '$born - $died'
|
||||
: born != null
|
||||
? 'born: $born'
|
||||
: died != null
|
||||
? 'died: $died'
|
||||
: '';
|
||||
}
|
||||
}
|
7
lib/data/repositories/api_interface.dart
Normal file
7
lib/data/repositories/api_interface.dart
Normal file
@ -0,0 +1,7 @@
|
||||
import 'package:pmd_labs/domain/models/card.dart';
|
||||
|
||||
typedef OnErrorCallback = void Function(String? error);
|
||||
|
||||
abstract class ApiInterface {
|
||||
Future<List<CardData>?> loadData({OnErrorCallback? onError});
|
||||
}
|
35
lib/data/repositories/mock_repository.dart
Normal file
35
lib/data/repositories/mock_repository.dart
Normal file
@ -0,0 +1,35 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:pmd_labs/data/repositories/api_interface.dart';
|
||||
import 'package:pmd_labs/domain/models/card.dart';
|
||||
|
||||
class MockRepository extends ApiInterface {
|
||||
@override
|
||||
Future<List<CardData>?> loadData({OnErrorCallback? onError}) async {
|
||||
return [
|
||||
CardData(
|
||||
'Анекдот №1',
|
||||
descriptionText: '— Итак, Сара, вот ваша диета: одно яблоко, одно вареное яйцо, нежирный творог, зелень\n'
|
||||
'— Ясно, доктор, но это до или после еды?',
|
||||
icon: Icons.favorite,
|
||||
imageUrl: 'https://i.pinimg.com/474x/97/ee/af/97eeaffa3171b0a53bb4161bfc9e3756.jpg',
|
||||
),
|
||||
CardData(
|
||||
'Анекдот №2',
|
||||
descriptionText: '– Яна Моисеевна, а что вам муженек на день рождения подарил?\n'
|
||||
'– Вон видите феррари за окном стоит?\n'
|
||||
'– Не может быть!\n'
|
||||
'– Вот точно такого же цвета шарфик.\n',
|
||||
icon: Icons.favorite,
|
||||
imageUrl:
|
||||
'https://i.pinimg.com/474x/8c/4f/40/8c4f4093ab3ff9ddb1d8880a94b4d586.jpg',
|
||||
),
|
||||
CardData(
|
||||
'Анекдот №3',
|
||||
descriptionText: 'Чем дольше звонят в дверь, тем больше Рабиновича нет дома.',
|
||||
icon: Icons.favorite,
|
||||
imageUrl:
|
||||
'https://i.pinimg.com/474x/3a/1f/3c/3a1f3ca4a57ff8a16882093c2f278922.jpg',
|
||||
),
|
||||
];
|
||||
}
|
||||
}
|
35
lib/data/repositories/potter_repository.dart
Normal file
35
lib/data/repositories/potter_repository.dart
Normal file
@ -0,0 +1,35 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:pmd_labs/data/dtos/characters_dto.dart';
|
||||
import 'package:pmd_labs/data/mappers/characters_mapper.dart';
|
||||
import 'package:pmd_labs/data/repositories/api_interface.dart';
|
||||
import 'package:pmd_labs/domain/models/card.dart';
|
||||
import 'package:pretty_dio_logger/pretty_dio_logger.dart';
|
||||
|
||||
class PotterRepository extends ApiInterface {
|
||||
static final Dio _dio = Dio()
|
||||
..interceptors.add(PrettyDioLogger(
|
||||
requestHeader: true,
|
||||
requestBody: true,
|
||||
));
|
||||
|
||||
static const String _baseUrl = 'https://api.potterdb.com';
|
||||
|
||||
@override
|
||||
Future<List<CardData>?> loadData({String? q, OnErrorCallback? onError}) async {
|
||||
try {
|
||||
const String url = '$_baseUrl/v1/characters';
|
||||
|
||||
final Response<dynamic> response = await _dio.get<Map<dynamic, dynamic>>(
|
||||
url,
|
||||
queryParameters: q != null ? {'filter[name_cont]': q} : null,
|
||||
);
|
||||
|
||||
final CharactersDto dto = CharactersDto.fromJson(response.data as Map<String, dynamic>);
|
||||
final List<CardData>? data = dto.data?.map((e) => e.toDomain()).toList();
|
||||
return data;
|
||||
} on DioException catch (e) {
|
||||
onError?.call(e.response?.statusMessage);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
15
lib/domain/models/card.dart
Normal file
15
lib/domain/models/card.dart
Normal file
@ -0,0 +1,15 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class CardData {
|
||||
final String text;
|
||||
final String descriptionText;
|
||||
final IconData icon;
|
||||
final String? imageUrl;
|
||||
|
||||
CardData(
|
||||
this.text, {
|
||||
required this.descriptionText,
|
||||
this.icon = Icons.favorite,
|
||||
this.imageUrl,
|
||||
});
|
||||
}
|
Loading…
Reference in New Issue
Block a user