This commit is contained in:
allllen4a 2024-10-28 16:07:37 +03:00
parent fad9c2a19f
commit e72bed02f8
7 changed files with 184 additions and 0 deletions

View 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);
}

View 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?,
);

View 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'
: '';
}
}

View 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});
}

View 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',
),
];
}
}

View 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;
}
}
}

View 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,
});
}