112 lines
5.5 KiB
Dart
112 lines
5.5 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:provider/provider.dart';
|
|
import '../models/dinosaur.dart';
|
|
import '../providers/dino_provider.dart';
|
|
|
|
class DetailScreen extends StatelessWidget {
|
|
final Dinosaur dinosaur;
|
|
const DetailScreen({super.key, required this.dinosaur});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final provider = Provider.of<DinoProvider>(context);
|
|
|
|
return Scaffold(
|
|
appBar: AppBar(
|
|
actions: [
|
|
IconButton(
|
|
icon: Icon(provider.isFavorite(dinosaur.name) ? Icons.favorite : Icons.favorite_border, color: provider.isFavorite(dinosaur.name) ? Colors.red : null),
|
|
onPressed: () => provider.toggleFavorite(dinosaur.name),
|
|
)
|
|
],
|
|
),
|
|
body: SingleChildScrollView(
|
|
child: Column(
|
|
children: [
|
|
Hero(tag: dinosaur.name, child: Container(height: 250, width: double.infinity, padding: const EdgeInsets.all(20), child: Image.asset(dinosaur.imagePath, fit: BoxFit.contain, errorBuilder: (_,__,___) => const Icon(Icons.pets, size: 80)))),
|
|
Padding(
|
|
padding: const EdgeInsets.all(20),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(dinosaur.name, style: const TextStyle(fontSize: 32, fontWeight: FontWeight.bold)),
|
|
Text(dinosaur.pronunciation, style: const TextStyle(fontStyle: FontStyle.italic, color: Colors.green)),
|
|
const SizedBox(height: 20),
|
|
|
|
// Bento Box with dynamic units
|
|
GridView.count(
|
|
shrinkWrap: true, physics: const NeverScrollableScrollPhysics(),
|
|
crossAxisCount: 2, childAspectRatio: 2.5, mainAxisSpacing: 10, crossAxisSpacing: 10,
|
|
children: [
|
|
_buildTile("DIET", dinosaur.dietType, Icons.restaurant),
|
|
_buildTile("LENGTH", provider.formatLength(dinosaur.lengthMeters), Icons.straighten),
|
|
_buildTile("LOCOMOTION", dinosaur.locomotion, Icons.directions_run),
|
|
_buildTile("WEIGHT", provider.formatWeight(dinosaur.weightKg), Icons.scale),
|
|
],
|
|
),
|
|
|
|
const SizedBox(height: 30),
|
|
_buildTimeline(dinosaur.periodIndex),
|
|
const SizedBox(height: 30),
|
|
_buildCladogram(provider, context),
|
|
const SizedBox(height: 30),
|
|
|
|
const Text("FIELD NOTES", style: TextStyle(fontWeight: FontWeight.bold, letterSpacing: 1.2)),
|
|
const Divider(),
|
|
Text("Meaning: ${dinosaur.meaning}", style: const TextStyle(fontWeight: FontWeight.bold)),
|
|
const SizedBox(height: 10),
|
|
Text(dinosaur.description, style: const TextStyle(fontSize: 16, height: 1.6)),
|
|
const SizedBox(height: 40),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildTimeline(int periodIndex) {
|
|
final List<String> eras = ["Triassic", "Jurassic", "Cretaceous"];
|
|
return Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
const Text("GEOLOGICAL TIMELINE", style: TextStyle(fontSize: 12, fontWeight: FontWeight.bold)),
|
|
const SizedBox(height: 10),
|
|
Row(children: List.generate(3, (i) => Expanded(child: Container(
|
|
height: 35, margin: const EdgeInsets.symmetric(horizontal: 2),
|
|
decoration: BoxDecoration(color: i == periodIndex ? Colors.green : Colors.grey.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(8)),
|
|
child: Center(child: Text(eras[i], style: TextStyle(fontSize: 10, color: i == periodIndex ? Colors.white : Colors.grey))),
|
|
)))),
|
|
],
|
|
);
|
|
}
|
|
|
|
Widget _buildCladogram(DinoProvider p, BuildContext context) {
|
|
final related = p.getRelated(dinosaur);
|
|
if (related.isEmpty) return const SizedBox();
|
|
return Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text("RELATED SPECIES (${dinosaur.family})", style: const TextStyle(fontSize: 12, fontWeight: FontWeight.bold)),
|
|
const SizedBox(height: 10),
|
|
SizedBox(height: 100, child: ListView.builder(
|
|
scrollDirection: Axis.horizontal,
|
|
itemCount: related.length,
|
|
itemBuilder: (context, i) => GestureDetector(
|
|
onTap: () => Navigator.push(context, MaterialPageRoute(builder: (_) => DetailScreen(dinosaur: related[i]))),
|
|
child: Container(width: 80, margin: const EdgeInsets.only(right: 15), child: Column(children: [Expanded(child: Image.asset(related[i].imagePath, errorBuilder: (_,__,___) => const Icon(Icons.pets))), Text(related[i].name, style: const TextStyle(fontSize: 9), textAlign: TextAlign.center)]))
|
|
)
|
|
))
|
|
],
|
|
);
|
|
}
|
|
|
|
Widget _buildTile(String label, String val, IconData icon) {
|
|
return Container(
|
|
padding: const EdgeInsets.all(12),
|
|
decoration: BoxDecoration(color: Colors.grey.withValues(alpha: 0.05), borderRadius: BorderRadius.circular(12)),
|
|
child: Row(children: [Icon(icon, size: 20, color: Colors.green), const SizedBox(width: 8), Expanded(child: Column(crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.center, children: [Text(label, style: const TextStyle(fontSize: 9, color: Colors.grey)), Text(val, style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 12))]))]),
|
|
);
|
|
}
|
|
} |