Initial commit
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
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))]))]),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user