projet debut
BIN
my_travel/assets/images/activities/chaumont.jpg
Normal file
|
After Width: | Height: | Size: 7.7 KiB |
BIN
my_travel/assets/images/activities/dame.jpg
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
my_travel/assets/images/activities/defense.jpg
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
my_travel/assets/images/activities/louvre.jpg
Normal file
|
After Width: | Height: | Size: 5.8 KiB |
BIN
my_travel/assets/images/lyon.jpg
Normal file
|
After Width: | Height: | Size: 8.0 KiB |
BIN
my_travel/assets/images/nice.jpg
Normal file
|
After Width: | Height: | Size: 90 KiB |
BIN
my_travel/assets/images/paris.jpg
Normal file
|
After Width: | Height: | Size: 44 KiB |
29
my_travel/lib/data/data.dart
Normal file
@@ -0,0 +1,29 @@
|
||||
// lib/data/data.dart
|
||||
import '../models/activity.model.dart';
|
||||
|
||||
List<Activity> activities = [
|
||||
Activity(
|
||||
image: 'assets/images/activities/louvre.jpg',
|
||||
name: 'Le Louvre',
|
||||
id: 'a1',
|
||||
city: 'Paris',
|
||||
),
|
||||
Activity(
|
||||
image: 'assets/images/activities/chaumont.jpg',
|
||||
name: 'Les buttes Chaumont',
|
||||
id: 'a2',
|
||||
city: 'Paris',
|
||||
),
|
||||
Activity(
|
||||
image: 'assets/images/activities/dame.jpg',
|
||||
name: 'Notre Dame',
|
||||
id: 'a3',
|
||||
city: 'Paris',
|
||||
),
|
||||
Activity(
|
||||
image: 'assets/images/activities/defense.jpg',
|
||||
name: 'La Défense',
|
||||
id: 'a4',
|
||||
city: 'Paris',
|
||||
),
|
||||
];
|
||||
@@ -1,22 +1,15 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'views/city/city.dart';
|
||||
|
||||
void main() => runApp(const DrEvaristenTrip());
|
||||
|
||||
class DrEvaristenTrip extends StatelessWidget {
|
||||
|
||||
const DrEvaristenTrip({super.key});
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
debugShowCheckedModeBanner: false,
|
||||
home: Scaffold(
|
||||
appBar: AppBar(
|
||||
leading: const Icon(Icons.home),
|
||||
title: const Text('DrEvaristen Trip'),
|
||||
actions: const <Widget>[Icon(Icons.more_vert)],
|
||||
),
|
||||
body: const Text('DrEvaristen'),
|
||||
),
|
||||
home: City(), // affichage direct pour développement
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
13
my_travel/lib/models/activity.model.dart
Normal file
@@ -0,0 +1,13 @@
|
||||
// lib/models/activity.model.dart
|
||||
class Activity {
|
||||
String name;
|
||||
String image;
|
||||
String? id;
|
||||
String city;
|
||||
Activity({
|
||||
required this.name,
|
||||
required this.city,
|
||||
this.id,
|
||||
required this.image,
|
||||
});
|
||||
}
|
||||
37
my_travel/lib/views/city/city.dart
Normal file
@@ -0,0 +1,37 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import '../../data/data.dart' as data;
|
||||
import '../../models/activity.model.dart';
|
||||
import '../widgets/activity_card.dart';
|
||||
|
||||
class City extends StatefulWidget {
|
||||
final List<Activity> activities = data.activities;
|
||||
City({super.key});
|
||||
@override
|
||||
State<City> createState() => _CityState();
|
||||
}
|
||||
|
||||
class _CityState extends State<City> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
leading: const Icon(Icons.chevron_left),
|
||||
title: const Text('Paris'),
|
||||
actions: const [Icon(Icons.more_vert)],
|
||||
),
|
||||
|
||||
// ==================== GridView.extent (taille max par item) - VERSION ACTIVE ✅ ====================
|
||||
body: Container(
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: GridView.extent(
|
||||
maxCrossAxisExtent: 150, // largeur max d'un item
|
||||
mainAxisSpacing: 2,
|
||||
crossAxisSpacing: 5,
|
||||
children: widget.activities
|
||||
.map((a) => ActivityCard(activity: a))
|
||||
.toList(),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
53
my_travel/lib/views/home/home.dart
Normal file
@@ -0,0 +1,53 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import '../widgets/city_card.dart';
|
||||
|
||||
class Home extends StatefulWidget {
|
||||
const Home({super.key});
|
||||
|
||||
@override
|
||||
State<Home> createState() => _HomeState();
|
||||
}
|
||||
|
||||
class _HomeState extends State<Home> {
|
||||
// Liste "source de vérité" affichée dans l'UI
|
||||
final List<Map<String, dynamic>> cities = [
|
||||
{'name': 'Paris', 'image': 'assets/images/paris.jpg', 'checked': false},
|
||||
{'name': 'Lyon', 'image': 'assets/images/lyon.jpg', 'checked': false},
|
||||
{'name': 'Nice', 'image': 'assets/images/nice.jpg', 'checked': false},
|
||||
];
|
||||
|
||||
// Fonction pour basculer l'état favori d'une ville
|
||||
void switchChecked(Map<String, dynamic> city) {
|
||||
setState(() {
|
||||
city['checked'] = !(city['checked'] ?? false);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
leading: const Icon(Icons.home),
|
||||
title: const Text('DrEvaristen Trip'),
|
||||
actions: const [Icon(Icons.more_vert)],
|
||||
),
|
||||
body: Container(
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
// On transforme chaque map en CityCard
|
||||
children: [
|
||||
for (final city in cities)
|
||||
CityCard(
|
||||
name: city['name'],
|
||||
image: city['image'],
|
||||
checked: city['checked'] ?? false,
|
||||
updateChecked: () =>
|
||||
switchChecked(city), // capture la bonne ville
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
23
my_travel/lib/views/widgets/activity_card.dart
Normal file
@@ -0,0 +1,23 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import '../../models/activity.model.dart';
|
||||
|
||||
class ActivityCard extends StatelessWidget {
|
||||
final Activity activity;
|
||||
const ActivityCard({super.key, required this.activity});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ListTile(
|
||||
leading: CircleAvatar(backgroundImage: AssetImage(activity.image)),
|
||||
title: Text(activity.name),
|
||||
subtitle: Text(activity.city),
|
||||
trailing: Checkbox(
|
||||
value: true,
|
||||
tristate: true,
|
||||
onChanged: (e) {}, // nécessite un état pour évoluer
|
||||
activeColor: Colors.black,
|
||||
checkColor: Colors.red,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
67
my_travel/lib/views/widgets/city_card.dart
Normal file
@@ -0,0 +1,67 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class CityCard extends StatelessWidget {
|
||||
final String name;
|
||||
final String image;
|
||||
final bool checked; // devient requis
|
||||
final VoidCallback updateChecked;
|
||||
const CityCard({
|
||||
super.key,
|
||||
required this.name,
|
||||
required this.image,
|
||||
required this.checked,
|
||||
required this.updateChecked,
|
||||
});
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Card(
|
||||
elevation: 5,
|
||||
clipBehavior: Clip.antiAlias,
|
||||
child: SizedBox(
|
||||
height: 150,
|
||||
child: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
Ink.image(
|
||||
image: AssetImage(image),
|
||||
fit: BoxFit.cover,
|
||||
child: InkWell(onTap: updateChecked), // notifie le parent
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: Column(
|
||||
children: [
|
||||
// Icône favori : pleine si checked, sinon contour
|
||||
Expanded(
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Icon(
|
||||
checked ? Icons.star : Icons.star_border,
|
||||
size: 30,
|
||||
color: Colors.white,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
name,
|
||||
style: const TextStyle(
|
||||
fontSize: 30,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -58,7 +58,9 @@ flutter:
|
||||
uses-material-design: true
|
||||
|
||||
# To add assets to your application, add an assets section, like this:
|
||||
# assets:
|
||||
assets:
|
||||
- assets/images/
|
||||
- assets/images/activities/
|
||||
# - images/a_dot_burr.jpeg
|
||||
# - images/a_dot_ham.jpeg
|
||||
|
||||
|
||||