Compare commits
2 Commits
57d946a8a2
...
bcec27d193
Author | SHA1 | Date | |
---|---|---|---|
bcec27d193 | |||
1d53a1c62b |
Before Width: | Height: | Size: 544 B After Width: | Height: | Size: 4.2 KiB |
Before Width: | Height: | Size: 442 B After Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 721 B After Width: | Height: | Size: 6.3 KiB |
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 49 KiB |
BIN
flutter_app/assets/icon.png
Normal file
After Width: | Height: | Size: 112 KiB |
24
flutter_app/assets/svg/flag-gb-svgrepo-com.svg
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||||
|
<svg width="800px" height="800px" viewBox="0 -4 28 28" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g clip-path="url(#clip0_503_2952)">
|
||||||
|
<rect width="28" height="20" rx="2" fill="white"/>
|
||||||
|
<mask id="mask0_503_2952" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="28" height="20">
|
||||||
|
<rect width="28" height="20" rx="2" fill="white"/>
|
||||||
|
</mask>
|
||||||
|
<g mask="url(#mask0_503_2952)">
|
||||||
|
<rect width="28" height="20" fill="#0A17A7"/>
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M-1.28244 -1.91644L10.6667 6.14335V-1.33333H17.3334V6.14335L29.2825 -1.91644L30.7737 0.294324L21.3263 6.66667H28V13.3333H21.3263L30.7737 19.7057L29.2825 21.9165L17.3334 13.8567V21.3333H10.6667V13.8567L-1.28244 21.9165L-2.77362 19.7057L6.67377 13.3333H2.95639e-05V6.66667H6.67377L-2.77362 0.294324L-1.28244 -1.91644Z" fill="white"/>
|
||||||
|
<path d="M18.668 6.33219L31.3333 -2" stroke="#DB1F35" stroke-width="0.666667" stroke-linecap="round"/>
|
||||||
|
<path d="M20.0128 13.6975L31.3666 21.3503" stroke="#DB1F35" stroke-width="0.666667" stroke-linecap="round"/>
|
||||||
|
<path d="M8.00555 6.31046L-3.83746 -1.67099" stroke="#DB1F35" stroke-width="0.666667" stroke-linecap="round"/>
|
||||||
|
<path d="M9.29006 13.6049L-3.83746 22.3105" stroke="#DB1F35" stroke-width="0.666667" stroke-linecap="round"/>
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M0 12H12V20H16V12H28V8H16V0H12V8H0V12Z" fill="#E6273E"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<defs>
|
||||||
|
<clipPath id="clip0_503_2952">
|
||||||
|
<rect width="28" height="20" rx="2" fill="white"/>
|
||||||
|
</clipPath>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.6 KiB |
19
flutter_app/assets/svg/flag-ru-svgrepo-com.svg
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||||
|
<svg width="800px" height="800px" viewBox="0 -4 28 28" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g clip-path="url(#clip0_503_2726)">
|
||||||
|
<rect x="0.25" y="0.25" width="27.5" height="19.5" rx="1.75" fill="white" stroke="#F5F5F5" stroke-width="0.5"/>
|
||||||
|
<mask id="mask0_503_2726" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="28" height="20">
|
||||||
|
<rect x="0.25" y="0.25" width="27.5" height="19.5" rx="1.75" fill="white" stroke="white" stroke-width="0.5"/>
|
||||||
|
</mask>
|
||||||
|
<g mask="url(#mask0_503_2726)">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M0 13.3333H28V6.66667H0V13.3333Z" fill="#0C47B7"/>
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M0 20H28V13.3333H0V20Z" fill="#E53B35"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<defs>
|
||||||
|
<clipPath id="clip0_503_2726">
|
||||||
|
<rect width="28" height="20" rx="2" fill="white"/>
|
||||||
|
</clipPath>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 968 B |
@ -3,56 +3,26 @@ import 'package:json_annotation/json_annotation.dart';
|
|||||||
part 'thrones_character_dto.g.dart';
|
part 'thrones_character_dto.g.dart';
|
||||||
|
|
||||||
@JsonSerializable(createToJson: false)
|
@JsonSerializable(createToJson: false)
|
||||||
class ThronesCharactersDto {
|
class ThronesCharacterDto {
|
||||||
final List<ThronesCharacterDataDto> characters;
|
final int id;
|
||||||
final InfoDto? info;
|
final String firstName;
|
||||||
|
final String lastName;
|
||||||
|
final String fullName;
|
||||||
|
final String title;
|
||||||
|
final String family;
|
||||||
|
final String image;
|
||||||
|
final String imageUrl;
|
||||||
|
|
||||||
const ThronesCharactersDto({required this.characters, this.info});
|
ThronesCharacterDto({
|
||||||
|
required this.id,
|
||||||
|
required this.firstName,
|
||||||
|
required this.lastName,
|
||||||
|
required this.fullName,
|
||||||
|
required this.title,
|
||||||
|
required this.family,
|
||||||
|
required this.image,
|
||||||
|
required this.imageUrl,
|
||||||
|
});
|
||||||
|
|
||||||
factory ThronesCharactersDto.fromJson(List<dynamic> json) {
|
factory ThronesCharacterDto.fromJson(Map<String, dynamic> json) => _$ThronesCharacterDtoFromJson(json);
|
||||||
final List<ThronesCharacterDataDto> characters = json
|
|
||||||
.map((item) => ThronesCharacterDataDto.fromJson(item as Map<String, dynamic>))
|
|
||||||
.toList();
|
|
||||||
return ThronesCharactersDto(characters: characters);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@JsonSerializable(createToJson: false)
|
|
||||||
class ThronesCharacterDataDto {
|
|
||||||
final int? id;
|
|
||||||
final String? firstName;
|
|
||||||
final String? lastName;
|
|
||||||
final String? fullName;
|
|
||||||
final String? title;
|
|
||||||
final String? family;
|
|
||||||
final String? image;
|
|
||||||
final String? imageUrl;
|
|
||||||
|
|
||||||
const ThronesCharacterDataDto(
|
|
||||||
{this.id, this.firstName, this.lastName, this.fullName, this.title, this.family, this.image, this.imageUrl,});
|
|
||||||
|
|
||||||
factory ThronesCharacterDataDto.fromJson(Map<String, dynamic> json) =>
|
|
||||||
_$ThronesCharacterDataDtoFromJson(json);
|
|
||||||
}
|
|
||||||
|
|
||||||
@JsonSerializable(createToJson: false)
|
|
||||||
class InfoDto {
|
|
||||||
final String? next;
|
|
||||||
final String? last;
|
|
||||||
final int? nextPage;
|
|
||||||
final int? lastPage;
|
|
||||||
|
|
||||||
InfoDto({this.next, this.last})
|
|
||||||
: nextPage = _extractPageNumber(next),
|
|
||||||
lastPage = _extractPageNumber(last);
|
|
||||||
|
|
||||||
static int? _extractPageNumber(String? url) {
|
|
||||||
if (url == null) return null;
|
|
||||||
final RegExp regExp = RegExp(r'page=(\d+)');
|
|
||||||
final Match? match = regExp.firstMatch(url);
|
|
||||||
return match != null ? int.parse(match.group(1)!) : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
factory InfoDto.fromJson(Map<String, dynamic> json) =>
|
|
||||||
_$InfoDtoFromJson(json);
|
|
||||||
}
|
}
|
@ -6,32 +6,14 @@ part of 'thrones_character_dto.dart';
|
|||||||
// JsonSerializableGenerator
|
// JsonSerializableGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
ThronesCharactersDto _$ThronesCharactersDtoFromJson(
|
ThronesCharacterDto _$ThronesCharacterDtoFromJson(Map<String, dynamic> json) =>
|
||||||
Map<String, dynamic> json) =>
|
ThronesCharacterDto(
|
||||||
ThronesCharactersDto(
|
id: (json['id'] as num).toInt(),
|
||||||
characters: (json['characters'] as List<dynamic>)
|
firstName: json['firstName'] as String,
|
||||||
.map((e) =>
|
lastName: json['lastName'] as String,
|
||||||
ThronesCharacterDataDto.fromJson(e as Map<String, dynamic>))
|
fullName: json['fullName'] as String,
|
||||||
.toList(),
|
title: json['title'] as String,
|
||||||
info: json['info'] == null
|
family: json['family'] as String,
|
||||||
? null
|
image: json['image'] as String,
|
||||||
: InfoDto.fromJson(json['info'] as Map<String, dynamic>),
|
imageUrl: json['imageUrl'] as String,
|
||||||
);
|
|
||||||
|
|
||||||
ThronesCharacterDataDto _$ThronesCharacterDataDtoFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
ThronesCharacterDataDto(
|
|
||||||
id: (json['id'] as num?)?.toInt(),
|
|
||||||
firstName: json['firstName'] as String?,
|
|
||||||
lastName: json['lastName'] as String?,
|
|
||||||
fullName: json['fullName'] as String?,
|
|
||||||
title: json['title'] as String?,
|
|
||||||
family: json['family'] as String?,
|
|
||||||
image: json['image'] as String?,
|
|
||||||
imageUrl: json['imageUrl'] as String?,
|
|
||||||
);
|
|
||||||
|
|
||||||
InfoDto _$InfoDtoFromJson(Map<String, dynamic> json) => InfoDto(
|
|
||||||
next: json['next'] as String?,
|
|
||||||
last: json['last'] as String?,
|
|
||||||
);
|
);
|
||||||
|
@ -5,7 +5,7 @@ import 'package:flutter_app/domain/models/home.dart';
|
|||||||
const _imagePlaceholder =
|
const _imagePlaceholder =
|
||||||
'https://upload.wikimedia.org/wikipedia/en/archive/b/b1/20210811082420%21Portrait_placeholder.png';
|
'https://upload.wikimedia.org/wikipedia/en/archive/b/b1/20210811082420%21Portrait_placeholder.png';
|
||||||
|
|
||||||
extension ThronesCharacterDtoToModel on ThronesCharacterDataDto {
|
extension ThronesCharacterDtoToModel on ThronesCharacterDto {
|
||||||
CardData toDomain() => CardData(
|
CardData toDomain() => CardData(
|
||||||
descriptionText: _makeDescriptionText(title, family),
|
descriptionText: _makeDescriptionText(title, family),
|
||||||
firstName: firstName,
|
firstName: firstName,
|
||||||
@ -27,10 +27,3 @@ extension ThronesCharacterDtoToModel on ThronesCharacterDataDto {
|
|||||||
: '';
|
: '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension ThronesCharactersDtoToModel on ThronesCharactersDto {
|
|
||||||
HomeData toDomain() => HomeData(
|
|
||||||
data: characters.map((e) => e.toDomain()).toList(),
|
|
||||||
nextPage: info?.nextPage,
|
|
||||||
);
|
|
||||||
}
|
|
@ -7,11 +7,7 @@ import 'package:flutter_app/domain/models/home.dart';
|
|||||||
import 'package:pretty_dio_logger/pretty_dio_logger.dart';
|
import 'package:pretty_dio_logger/pretty_dio_logger.dart';
|
||||||
|
|
||||||
class ThronesRepository extends ApiInterface {
|
class ThronesRepository extends ApiInterface {
|
||||||
static final Dio _dio = Dio()
|
static final Dio _dio = Dio();
|
||||||
..interceptors.add(PrettyDioLogger(
|
|
||||||
requestHeader: true,
|
|
||||||
requestBody: true,
|
|
||||||
));
|
|
||||||
|
|
||||||
static const String _baseUrl = 'https://thronesapi.com';
|
static const String _baseUrl = 'https://thronesapi.com';
|
||||||
|
|
||||||
@ -24,16 +20,14 @@ class ThronesRepository extends ApiInterface {
|
|||||||
try {
|
try {
|
||||||
const String url = '$_baseUrl/api/v2/Characters';
|
const String url = '$_baseUrl/api/v2/Characters';
|
||||||
|
|
||||||
final Response<dynamic> response = await _dio.get<List<dynamic>>(
|
final Response<dynamic> response = await _dio.get<List<dynamic>>(url);
|
||||||
url,
|
|
||||||
);
|
|
||||||
|
|
||||||
final List<ThronesCharacterDataDto> characters = (response.data as List<dynamic>)
|
final List<ThronesCharacterDto> characters = (response.data as List<dynamic>)
|
||||||
.map((e) => ThronesCharacterDataDto.fromJson(e as Map<String, dynamic>))
|
.map((e) => ThronesCharacterDto.fromJson(e as Map<String, dynamic>))
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
final List<CardData> data = characters
|
final List<CardData> data = characters
|
||||||
.where((character) => q == null || character.fullName!.toLowerCase().contains(q.toLowerCase()))
|
.where((character) => q == null || character.fullName.toLowerCase().contains(q.toLowerCase()))
|
||||||
.map((e) => e.toDomain())
|
.map((e) => e.toDomain())
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
|