stylise la page profil, ajoute 2 bouttons avec des bords arrondis qui prennet tout la largeur avec le premier qui est "mes reservations" , "mes annonces" , quand on clique sur ces bouttons on sera redirigé vers la page annonce qui cette fois - ci va appeler une fonction différente en fonction de quel bouton on a cliquén respecte l'architecture suivante : . import 'package:flutter/material.dart';
import 'package:supabase_flutter/supabase_flutter.dart';

import 'package:sae_mobile/views/signout.dart';

import 'package:sae_mobile/models/User.dart' as user_model;

final SupabaseClient supabaseClient = Supabase.instance.client;

class ProfileView extends StatefulWidget {
  final user_model.User user;
  const ProfileView({super.key, required this.user});

  @override
  State<ProfileView> createState() => _ProfileState();
}

class _ProfileState extends State<ProfileView> {
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Text('Profile'),
        Text('Email: ${widget.user.email}'),
        Text('Name: ${widget.user.username}'),
        const SignOut(),
      ],
    );
  }
}
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:sae_mobile/models/auth/signin.dart';
import 'package:sae_mobile/views/accountcreated.dart';
import 'package:sae_mobile/models/queries/distant/user.dart';
import 'package:supabase_flutter/supabase_flutter.dart';

import 'package:sae_mobile/views/signin.dart';
import 'package:sae_mobile/views/signup.dart';
import 'package:sae_mobile/views/profile.dart';
import 'package:sae_mobile/views/home.dart';
import 'package:sae_mobile/views/createAnnonce.dart';
import 'package:sae_mobile/views/annonces.dart';
import 'package:sae_mobile/views/category.dart';
import 'package:sae_mobile/models/User.dart' as user_model;
import 'package:sae_mobile/models/Builder.dart' as user_builder;
import 'package:sae_mobile/views/components/Navbar.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  await Supabase.initialize(
    url: 'https://yrlokmgbwiaahzzcczpt.supabase.co',
    anonKey:
=  );

  runApp(const MyApp());
}

final SupabaseClient supabaseClient = Supabase.instance.client;

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: 'Flutter Demo',
        debugShowCheckedModeBanner: false,
        theme: ThemeData(
          colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
          useMaterial3: true,
        ),
        initialRoute: '/home',
        routes: {
          '/': (context) => Scaffold(
                body: HomePage(),
              ),
          '/account_created': (context) => Scaffold(
                body: AccountCreatedPage(),
              ),
          '/signup': (context) => const Scaffold(
                body: SignUpView(),
              ),
          '/signin': (context) => const Scaffold(
                body: SignInView(),
              ),
          '/categorie': (context) => Scaffold(
                body: CategoryListPage(),
                bottomNavigationBar: Navbar(
                  selectedIndex: 0,
                  onItemTapped: (index) {},
                ),
              ),
          '/createAnnonce': (context) => Scaffold(
                body: CreateAnnonce(),
                bottomNavigationBar: Navbar(
                  selectedIndex: 2,
                  onItemTapped: (index) {},
                ),
              ),
          '/accountCreated': (context) => Scaffold(
                body: AccountCreatedPage(),
              ),
          '/annonces': (context) {
            final Map<String, String> args = ModalRoute.of(context)!
                .settings
                .arguments as Map<String, String>;
            final String categoryId = args['categoryId']!;
            final String categoryName = args['categoryName']!;
            return Scaffold(
              body: AnnoncesView(
                  categoryId: categoryId, categoryName: categoryName),
              bottomNavigationBar: Navbar(
                selectedIndex: 0,
                onItemTapped: (index) {},
              ),
            );
          },
          '/profile': (context) => Scaffold(
                  body: FutureBuilder(
                future: UserQueries.getUserById(
                    supabaseClient.auth.currentUser!.id),
                builder: (context, snapshot) {
                  if (snapshot.connectionState == ConnectionState.waiting) {
                    return const CircularProgressIndicator();
                  }
                  if (snapshot.hasError) {
                    return Text('Error: ${snapshot.error}');
                  }
                  final user = user_model.User.fromJson(snapshot.data![0]);
                  return ProfileView(user: user);
                },
              )),
        });
  }
}
import 'package:sae_mobile/models/Objet.dart';
import 'package:sae_mobile/models/TypeAnnonce.dart';
import 'package:sae_mobile/models/annonce.dart';
import 'package:sae_mobile/models/queries/distant/user.dart' as uqd;
import 'package:sae_mobile/models/queries/distant/annonce.dart' as aqd;

import 'package:sae_mobile/models/queries/local/annonce.dart' as aql;
import 'package:sae_mobile/models/queries/local/objet.dart';
import 'package:sae_mobile/models/queries/local/typeAnnonce.dart';

import 'package:sae_mobile/models/User.dart' as user_model;

import 'package:supabase_flutter/supabase_flutter.dart';
import 'package:sae_mobile/models/queries/distant/typeAnnonce.dart' as tqd;

final SupabaseClient supabaseClient = Supabase.instance.client;

/// Classe Builder
///
/// Cette classe permet de construire des objets à partir de données distantes ou locales.
class Builder {
  /// Construit un utilisateur à partir de son id.
  ///
  /// [id] est l'id de l'utilisateur.
  ///
  /// Retourne un objet de type [user_model.User].
  static Future<user_model.User> buildUserById(String id) async {
    final data =
        await uqd.UserQueries.getUserById(id).then((value) => value.first);

    return user_model.User.fromJson(data);
  }

  /// Construit une liste d'annonces à partir de données distantes.
  ///
  /// Retourne une liste d'annonces.
  static Future<List<Annonce>> buildAnnoncesDistant() async {
    final data = await aqd.AnnonceQueries.getAnnonces().then((value) => value);

    List<Annonce> annonces = [];
    for (var annonce in data) {
      String user_id = await aqd.AnnonceQueries.getAuteurAnnonce(annonce['id']);
      annonces.add(Annonce.fromJson(annonce, (await buildUserById(user_id))));
    }

    return annonces;
  }

  static Future<List<Annonce>> buildAnnoncesDistantByType(String type) async {
    final data =
        await aqd.AnnonceQueries.getAnnoncesByType(type).then((value) => value);

    List<Annonce> annonces = [];
    for (var annonce in data) {
      print("les annonces du type $type sont : $annonce");
      String user_id = await aqd.AnnonceQueries.getAuteurAnnonce(annonce['id']);
      annonces.add(Annonce.fromJson(annonce, (await buildUserById(user_id))));
    }

    return annonces;
  }

  /// Construit une liste d'annonces non répondues à partir de données distantes.
  ///
  /// Retourne une liste d'annonces.
  static Future<List<Annonce>> buildAnnoncesDistantNonRepondu() async {
    final data =
        await aqd.AnnonceQueries.getAnnonceNonRepondu().then((value) => value);

    List<Annonce> annonces = [];
    for (var annonce in data) {
      String user_id = await aqd.AnnonceQueries.getAuteurAnnonce(annonce['id']);
      annonces.add(Annonce.fromJson(annonce, (await buildUserById(user_id))));
    }

    return annonces;
  }

  /// Construit une liste d'annonces répondues par l'utilisateur à partir de données distantes.
  ///
  /// [id] est l'id de l'utilisateur.
  ///
  /// Retourne une liste d'annonces.
  static Future<List<Annonce>> buildAnnoncesDistantRepondu(String id) async {
    final data =
        await aqd.AnnonceQueries.getAnnonceRepondu(id).then((value) => value);

    List<Annonce> annonces = [];
    for (var annonce in data) {
      String user_id = await aqd.AnnonceQueries.getAuteurAnnonce(annonce['id']);
      annonces.add(Annonce.fromJson(annonce, (await buildUserById(user_id))));
    }

    return annonces;
  }

  /// Construit une liste d'annonces par id de l'annonce à partir de données distantes.
  ///
  /// [id] est l'id de l'annonce.
  ///
  /// Retourne une liste d'annonces.
  static Future<Annonce> buildAnnonceByIdDistant(String id) async {
    final data = await aqd.AnnonceQueries.getAnnonceById(id)
        .then((value) => value.first);

    String user_id = await aqd.AnnonceQueries.getAnnonceById(data['id'])
        .then((value) => value.first['id_user']);
    return Annonce.fromJson(data, await buildUserById(user_id));
  }

  /// Construit une liste d'annonces à partir de données locales.
  static Future<List<Annonce>> buildAnnoncesLocal() async {
    final data = await aql.AnnonceQueries.getAnnonces().then((value) => value);
    List<Annonce> annonces = [];
    print(data);
    for (var annonce in data) {
      annonces.add(Annonce.fromJson(
          annonce, await buildUserById(supabaseClient.auth.currentUser!.id)));
    }

    return annonces;
  }

  /// Construit une liste d'annonces par id de l'annonce à partir de données locales.
  static Future<Annonce> buildAnnonceByIdLocal(String id) async {
    final data = await aql.AnnonceQueries.getAnnonceById(id);

    return Annonce.fromJson(
        data, await buildUserById(supabaseClient.auth.currentUser!.id));
  }

  /// Construit une liste d'objets à partir de données locales.
  ///
  /// Retourne une liste d'objets.
  static Future<List<Objet>> buildObjets() async {
    final data = await ObjetQueries.getObjets().then((value) => value);

    List<Objet> objets = [];
    for (var objet in data) {
      objets.add(Objet.fromJson(objet));
    }

    return objets;
  }

  /// Construit une liste de types d'annonces à partir de données locales.
  ///
  /// Retourne une liste de types d'annonces.
  static Future<List<TypeAnnonce>> buildTypesAnnonce() async {
    final data =
        await TypeAnnoncesQueries.getTypeAnnonces().then((value) => value);

    List<TypeAnnonce> typesAnnonce = [];
    for (var typeAnnonce in data) {
      print('la categorie est : $typeAnnonce');
      typesAnnonce.add(TypeAnnonce.fromJson(typeAnnonce));
    }

    return typesAnnonce;
  }

  static Future<List<TypeAnnonce>> buildTypesAnnonceDistant() async {
    final data =
        await tqd.TypeAnnonceQueries.getTypeAnnonces().then((value) => value);

    List<TypeAnnonce> typesAnnonce = [];
    for (var typeAnnonce in data) {
      print(typeAnnonce);
      typesAnnonce.add(TypeAnnonce.fromJson(typeAnnonce));
    }

    return typesAnnonce;
  }
}
import 'package:sae_mobile/models/User.dart';
import 'package:sae_mobile/models/queries/distant/annonce.dart' as dist;
import 'package:sae_mobile/models/queries/local/annonce.dart' as local;

class Annonce {
  final String id;
  final String titre;
  final String description;
  final DateTime dateDeb;
  final DateTime dateFin;
  final User auteur;
  late final int etat;
  late AnnonceController controller;

  Annonce(this.id, this.titre, this.description, this.dateDeb, this.dateFin,
      this.auteur, this.etat) {
    switch (etat) {
      case 1:
        controller = AnnonceController(this, AnnonceNonPublie());
        break;
      case 2:
        controller = AnnonceController(this, AnnonceNonRepondu());
        break;
      case 3:
        controller = AnnonceController(this, AnnonceRepondu());
        break;
      case 4:
        controller = AnnonceController(this, AnnonceCloture());
        break;
    }
  }

  factory Annonce.fromJson(Map<String, dynamic> json, User auteur) {
    print(json);
    return Annonce(
      json['id'],
      json['titre'],
      json['description'],
      DateTime.parse(json['dateDeb']),
      DateTime.parse(json['dateFin']),
      auteur,
      json['idEtat'],
    );
  }

  void setEtat(int etat) {
    this.etat = etat;
  }

  void publier() {
    controller.publier();
  }

  void repondre(String id_u) {
    print(controller.etat);
    controller.repondre(id_u);
  }

  void cloturer() {
    controller.cloturer();
  }

  void mettreAvis(String id_u, String avis) {
    controller.mettreAvis(id_u, avis);
  }
}

class AnnonceController {
  final Annonce annonce;
  late EtatAnnonce etat;

  AnnonceController(this.annonce, this.etat);

  void setEtat(EtatAnnonce etat) {
    this.etat = etat;
  }

  void publier() {
    etat.publier(this.annonce);
  }

  void repondre(String id_u) {
    etat.repondre(this.annonce, id_u);
  }

  void cloturer() {
    etat.cloturer(this.annonce);
  }

  void mettreAvis(String id_u, String avis) {
    etat.mettreAvis(this.annonce, id_u, avis);
  }
}

class EtatAnnonce {
  void publier(Annonce a) async {}

  void repondre(Annonce a, String id_u) async {}

  void cloturer(Annonce a) async {}

  void mettreAvis(Annonce a, String id_u, String avis) async {}
}

class AnnonceNonPublie extends EtatAnnonce {
  @override
  void publier(Annonce a) async {
    await local.AnnonceQueries.updateAnnonceEtat(a.id, 2);
    String newId = await dist.AnnonceQueries.publishAnnonce(a);
    await local.AnnonceQueries.updateAnnonceId(a.id, newId);
    a.controller.setEtat(AnnonceNonRepondu());
  }
}

class AnnonceNonRepondu extends EtatAnnonce {
  @override
  void repondre(Annonce a, String id_u) async {
    await dist.AnnonceQueries.accepterAnnonce(a.id, id_u);
    await local.AnnonceQueries.updateAnnonceEtat(a.id, 3);
    await dist.AnnonceQueries.updateAnnonceEtat(a.id, 3);
    a.controller.setEtat(AnnonceRepondu());
  }
}

class AnnonceRepondu extends EtatAnnonce {
  @override
  void cloturer(Annonce a) async {
    await local.AnnonceQueries.updateAnnonceEtat(a.id, 4);
    await dist.AnnonceQueries.updateAnnonceEtat(a.id, 4);
    a.controller.setEtat(AnnonceCloture());
  }
}

class AnnonceCloture extends EtatAnnonce {
  @override
  void mettreAvis(Annonce a, String id_u, String avis) async {
    await dist.AnnonceQueries.mettreAvis(a.id, id_u, avis);
  }
}