From e72bed02f8455d6244501a941a9e0263239b4de4 Mon Sep 17 00:00:00 2001 From: allllen4a Date: Mon, 28 Oct 2024 16:07:37 +0300 Subject: [PATCH] lab_5 --- lib/data/dtos/characters_dto.dart | 36 ++++++++++++++++++++ lib/data/dtos/characters_dto.g.dart | 33 ++++++++++++++++++ lib/data/mappers/characters_mapper.dart | 23 +++++++++++++ lib/data/repositories/api_interface.dart | 7 ++++ lib/data/repositories/mock_repository.dart | 35 +++++++++++++++++++ lib/data/repositories/potter_repository.dart | 35 +++++++++++++++++++ lib/domain/models/card.dart | 15 ++++++++ 7 files changed, 184 insertions(+) create mode 100644 lib/data/dtos/characters_dto.dart create mode 100644 lib/data/dtos/characters_dto.g.dart create mode 100644 lib/data/mappers/characters_mapper.dart create mode 100644 lib/data/repositories/api_interface.dart create mode 100644 lib/data/repositories/mock_repository.dart create mode 100644 lib/data/repositories/potter_repository.dart create mode 100644 lib/domain/models/card.dart diff --git a/lib/data/dtos/characters_dto.dart b/lib/data/dtos/characters_dto.dart new file mode 100644 index 0000000..c9888d3 --- /dev/null +++ b/lib/data/dtos/characters_dto.dart @@ -0,0 +1,36 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'characters_dto.g.dart'; + +@JsonSerializable(createToJson: false) +class CharactersDto { + final List? data; + + const CharactersDto({this.data}); + + factory CharactersDto.fromJson(Map 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 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 json) => + _$CharacterAttributesDataDtoFromJson(json); +} \ No newline at end of file diff --git a/lib/data/dtos/characters_dto.g.dart b/lib/data/dtos/characters_dto.g.dart new file mode 100644 index 0000000..bd8c5d9 --- /dev/null +++ b/lib/data/dtos/characters_dto.g.dart @@ -0,0 +1,33 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'characters_dto.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +CharactersDto _$CharactersDtoFromJson(Map json) => + CharactersDto( + data: (json['data'] as List?) + ?.map((e) => CharacterDataDto.fromJson(e as Map)) + .toList(), + ); + +CharacterDataDto _$CharacterDataDtoFromJson(Map json) => + CharacterDataDto( + id: json['id'] as String?, + type: json['type'] as String?, + attributes: json['attributes'] == null + ? null + : CharacterAttributesDataDto.fromJson( + json['attributes'] as Map), + ); + +CharacterAttributesDataDto _$CharacterAttributesDataDtoFromJson( + Map json) => + CharacterAttributesDataDto( + name: json['name'] as String?, + born: json['born'] as String?, + died: json['died'] as String?, + image: json['image'] as String?, + ); diff --git a/lib/data/mappers/characters_mapper.dart b/lib/data/mappers/characters_mapper.dart new file mode 100644 index 0000000..0eccf08 --- /dev/null +++ b/lib/data/mappers/characters_mapper.dart @@ -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' + : ''; + } +} \ No newline at end of file diff --git a/lib/data/repositories/api_interface.dart b/lib/data/repositories/api_interface.dart new file mode 100644 index 0000000..25787ca --- /dev/null +++ b/lib/data/repositories/api_interface.dart @@ -0,0 +1,7 @@ +import 'package:pmd_labs/domain/models/card.dart'; + +typedef OnErrorCallback = void Function(String? error); + +abstract class ApiInterface { + Future?> loadData({OnErrorCallback? onError}); +} \ No newline at end of file diff --git a/lib/data/repositories/mock_repository.dart b/lib/data/repositories/mock_repository.dart new file mode 100644 index 0000000..dfac6bd --- /dev/null +++ b/lib/data/repositories/mock_repository.dart @@ -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?> 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', + ), + ]; + } +} \ No newline at end of file diff --git a/lib/data/repositories/potter_repository.dart b/lib/data/repositories/potter_repository.dart new file mode 100644 index 0000000..5ce1b4d --- /dev/null +++ b/lib/data/repositories/potter_repository.dart @@ -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?> loadData({String? q, OnErrorCallback? onError}) async { + try { + const String url = '$_baseUrl/v1/characters'; + + final Response response = await _dio.get>( + url, + queryParameters: q != null ? {'filter[name_cont]': q} : null, + ); + + final CharactersDto dto = CharactersDto.fromJson(response.data as Map); + final List? data = dto.data?.map((e) => e.toDomain()).toList(); + return data; + } on DioException catch (e) { + onError?.call(e.response?.statusMessage); + return null; + } + } +} \ No newline at end of file diff --git a/lib/domain/models/card.dart b/lib/domain/models/card.dart new file mode 100644 index 0000000..fc9fac3 --- /dev/null +++ b/lib/domain/models/card.dart @@ -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, + }); +} \ No newline at end of file