Files
pokedex_flutter/lib/modules/PokemonDetails/pokemon_details_page.dart
2023-07-12 01:22:45 +03:00

215 lines
7.9 KiB
Dart

import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:pokemon_api/pokemon_api.dart';
import '../../core/models/pokemon_helper.dart';
import '../../core/utils/extensions/string_extensions.dart';
import '../../widgets/pokemon_move.dart';
import 'pokemon_details_args.dart';
import '../PokemonList/pokemon_list_controller.dart';
import '../../widgets/pokemon_image.dart';
class PokemonDetailsPage extends StatelessWidget {
const PokemonDetailsPage({super.key});
PokemonDetailsArgs argsOf(BuildContext context) => PokemonDetailsArgs.of(context);
@override
Widget build(BuildContext context) {
final ctrl = PokemonListController.of(context);
final args = argsOf(context);
final poke = ctrl.pokemonMap[args.name]!;
final species = ctrl.speciesMap[poke.species.name]!;
final imgSize = 96.0;
final levelMoves = poke.moves
.where((move) => move.versionGroupDetails.any((det) => det.moveLearnMethod?.name == 'level-up'))
.toList()
..sort((a, b) => (a.versionGroupDetails
.firstWhere((det) => det.moveLearnMethod?.name == 'level-up')
.levelLearnedAt ??
99)
.compareTo(
b.versionGroupDetails.firstWhere((det) => det.moveLearnMethod?.name == 'level-up').levelLearnedAt ?? 99));
final tmMoves = poke.moves
.where((move) => move.versionGroupDetails.any((det) => det.moveLearnMethod?.name == 'machine'))
.toList()
..sort((a, b) => a.move?.name.compareTo(b.move?.name ?? "") ?? 1);
final children = <Widget Function()>[
() => Text(PokemonHelper.displayName(poke, species)),
() => Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Hero(
tag: 'pokemon-${poke.name}',
child: PokemonImage(poke: poke, size: imgSize),
),
PokemonImage(poke: poke, size: imgSize, shiny: true),
],
),
() => const Text('Weak against', textScaleFactor: 1.2),
() => FutureBuilder(
future: Future.wait(poke.types.map((t) => t.type.get())),
builder: (context, snapshot) {
final data = snapshot.hasData
? PokemonHelper.getTypeDefenseMultipliers(snapshot.data!.toList()).where((e) => e.multiplier >= 2)
: <TypeMultiplier>[];
return Wrap(
children: [
for (final type in data)
Padding(
padding: const EdgeInsets.all(4.0),
child: Chip(
label: Text('${type.type.name.capitalize()} x ${type.multiplierString}'),
),
)
],
);
},
),
() => const Text('Resistant to', textScaleFactor: 1.2),
() => FutureBuilder(
future: Future.wait(poke.types.map((t) => t.type.get())),
builder: (context, snapshot) {
final data = snapshot.hasData
? PokemonHelper.getTypeDefenseMultipliers(snapshot.data!.toList()).where((e) => e.multiplier < 1 && e.multiplier > 0)
: <TypeMultiplier>[];
return Wrap(
children: [
for (final type in data)
Padding(
padding: const EdgeInsets.all(4.0),
child: Chip(
label: Text('${type.type.name.capitalize()} x ${type.multiplierString}'),
),
)
],
);
},
),
() => const Text('No damage from', textScaleFactor: 1.2),
() => FutureBuilder(
future: Future.wait(poke.types.map((t) => t.type.get())),
builder: (context, snapshot) {
final data = snapshot.hasData
? PokemonHelper.getTypeDefenseMultipliers(snapshot.data!.toList()).where((e) => e.multiplier == 0)
: <TypeMultiplier>[];
return Wrap(
children: [
for (final type in data)
Padding(
padding: const EdgeInsets.all(4.0),
child: Chip(
label: Text('${type.type.name.capitalize()} x ${type.multiplierString}'),
),
)
],
);
},
),
() => const Text('Abilities', textScaleFactor: 1.2),
() => Wrap(
children: [
for (final ability in poke.abilities)
FutureBuilder(
future: ability.ability.get(),
builder: (context, snapshot) {
return Padding(
padding: const EdgeInsets.all(4.0),
child: Chip(
label: Text(snapshot.data?.name.capitalize() ?? '...'),
),
);
},
),
],
),
() => const Text('Moves', textScaleFactor: 1.2),
() => const Text('Level Moves', textScaleFactor: 1.2),
() => LayoutBuilder(
builder: (context, constraints) {
return Wrap(
children: [
for (final move in levelMoves)
FutureBuilder(
future: move.move?.get(),
builder: (context, snapshot) {
return SizedBox(
width: constraints.maxWidth / 2,
child: PokemonMoveCard.level(
move: snapshot.data,
versionDetails: move.versionGroupDetails,
loading: !snapshot.hasData,
),
);
},
),
],
);
},
),
() => const SizedBox(height: 16),
() => const Text('TM Moves', textScaleFactor: 1.2),
() => LayoutBuilder(
builder: (context, constraints) {
return Wrap(
children: [
for (final move in tmMoves)
FutureBuilder(
future: move.move?.get(),
builder: (context, snapshot) {
return SizedBox(
width: constraints.maxWidth / 2,
child: PokemonMoveCard.tm(
move: snapshot.data,
versionDetails: move.versionGroupDetails,
loading: !snapshot.hasData,
),
);
},
),
],
);
},
),
() => Text('Order: ${poke.order}'),
() => SelectableText('img: ${PokemonHelper.imageUrl(poke)}')
];
final icon = PokemonHelper.iconImageUrl(poke);
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
if (icon != null)
Container(
// color: Colors.purple,
child: CachedNetworkImage(
imageUrl: icon,
width: 40,
height: 40,
fit: BoxFit.cover,
),
),
// const SizedBox(width: 8),
Text(PokemonHelper.displayName(poke, species)),
],
),
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: ListView.builder(
itemBuilder: (context, index) => children[index].call(),
itemCount: children.length,
),
),
);
}
}