Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Recommendation #242

Merged
merged 19 commits into from
Mar 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions lib/recommendation/class/recommendation.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
class Recommendation {
final String? id;
final DateTime? creation;
final String title;
final String? code;
final String summary;
final String description;

Recommendation({
this.id,
this.creation,
required this.title,
required this.code,
required this.summary,
required this.description,
});

Recommendation.fromJson(Map<String, dynamic> json)
: id = json["id"],
creation = DateTime.parse(json["creation"]),
title = json["title"],
code = json["code"],
summary = json["summary"],
description = json["description"];

Map<String, dynamic> toJson() {
final data = <String, dynamic>{};
data["title"] = title;
data["code"] = code;
data["summary"] = summary;
data["description"] = description;
return data;
}

Recommendation copyWith({id, creation, title, code, summary, description}) {
return Recommendation(
id: id ?? this.id,
creation: creation ?? this.creation,
title: title ?? this.title,
code: code ?? this.code,
summary: summary ?? this.summary,
description: description ?? this.description,
);
}

static Recommendation empty() {
return Recommendation(
title: "",
code: null,
summary: "",
description: "",
);
}

@override
String toString() {
return 'Recommendation{id: $id, creation: $creation, title: $title, code: $code, summary: $summary, description: $description}';
}
}
11 changes: 11 additions & 0 deletions lib/recommendation/providers/is_recommendation_admin_provider.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:myecl/user/providers/user_provider.dart';

final isRecommendationAdminProvider = StateProvider<bool>(
(ref) {
final me = ref.watch(userProvider);
return me.groups
.map((e) => e.id)
.contains("53a669d6-84b1-4352-8d7c-421c1fbd9c6a");
},
);
57 changes: 57 additions & 0 deletions lib/recommendation/providers/recommendation_list_provider.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:myecl/recommendation/class/recommendation.dart';
import 'package:myecl/recommendation/repositories/recommendation_repository.dart';
import 'package:myecl/tools/providers/list_notifier.dart';
import 'package:myecl/tools/token_expire_wrapper.dart';

class RecommendationListNotifier extends ListNotifier<Recommendation> {
final RecommendationRepository recommendationRepository;

RecommendationListNotifier({required this.recommendationRepository})
: super(const AsyncValue.loading());

Future<AsyncValue<List<Recommendation>>> loadRecommendation() async {
return await loadList(recommendationRepository.getRecommendationList);
}

Future<bool> addRecommendation(Recommendation recommendation) async {
return await add(
recommendationRepository.createRecommendation, recommendation);
}

Future<bool> updateRecommendation(Recommendation recommendation) async {
return await update(
recommendationRepository.updateRecommendation,
(recommendations, recommendation) => recommendations
..[recommendations.indexWhere((r) => r.id == recommendation.id)] =
recommendation,
recommendation,
);
}

Future<bool> deleteRecommendation(Recommendation recommendation) async {
return await delete(
recommendationRepository.deleteRecommendation,
(recommendations, recommendation) =>
recommendations..removeWhere((r) => r.id == recommendation.id),
recommendation.id!,
recommendation,
);
}
}

final recommendationListProvider = StateNotifierProvider<
RecommendationListNotifier, AsyncValue<List<Recommendation>>>(
(ref) {
final recommendatioRepository = ref.watch(recommendationRepositoryProvider);
final provider = RecommendationListNotifier(
recommendationRepository: recommendatioRepository);
tokenExpireWrapperAuth(
ref,
() async {
await provider.loadRecommendation();
},
);
return provider;
},
);
35 changes: 35 additions & 0 deletions lib/recommendation/providers/recommendation_logo_map_provider.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:myecl/recommendation/class/recommendation.dart';
import 'package:myecl/recommendation/providers/recommendation_list_provider.dart';
import 'package:myecl/tools/providers/map_provider.dart';
import 'package:myecl/tools/token_expire_wrapper.dart';

class RecommendationLogoMapNotifier extends MapNotifier<Recommendation, Image> {
RecommendationLogoMapNotifier() : super();
}

final recommendationLogoMapProvider = StateNotifierProvider<
RecommendationLogoMapNotifier,
AsyncValue<Map<Recommendation, AsyncValue<List<Image>>?>>>(
(ref) {
RecommendationLogoMapNotifier recommendationLogoMapNotifier =
RecommendationLogoMapNotifier();
tokenExpireWrapperAuth(
ref,
() async {
ref.watch(recommendationListProvider).maybeWhen(
data: (data) {
recommendationLogoMapNotifier.loadTList(data);
return recommendationLogoMapNotifier;
},
orElse: () {
recommendationLogoMapNotifier.loadTList([]);
return recommendationLogoMapNotifier;
},
);
},
);
return recommendationLogoMapNotifier;
},
);
30 changes: 30 additions & 0 deletions lib/recommendation/providers/recommendation_logo_provider.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import 'dart:typed_data';

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:myecl/recommendation/repositories/recommendation_logo_repository.dart';
import 'package:myecl/tools/providers/single_notifier.dart';

class RecommendationLogoNotifier extends SingleNotifier<Image> {
final RecommendationLogoRepository recommendationLogoRepository;
RecommendationLogoNotifier({required this.recommendationLogoRepository})
: super(const AsyncValue.loading());

Future<Image> getRecommendationLogo(String id) async {
return await recommendationLogoRepository.getRecommendationLogo(id);
}

Future<Image> updateRecommendationLogo(String id, Uint8List bytes) async {
return await recommendationLogoRepository.addRecommendationLogo(bytes, id);
}
}

final recommendationLogoProvider =
StateNotifierProvider<RecommendationLogoNotifier, AsyncValue<Image>>(
(ref) {
final recommendationLogoRepository =
ref.watch(recommendationLogoRepositoryProvider);
return RecommendationLogoNotifier(
recommendationLogoRepository: recommendationLogoRepository);
},
);
17 changes: 17 additions & 0 deletions lib/recommendation/providers/recommendation_provider.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:myecl/recommendation/class/recommendation.dart';

class RecommendationNotifier extends StateNotifier<Recommendation> {
RecommendationNotifier() : super(Recommendation.empty());

void setRecommendation(Recommendation r) {
state = r;
}
}

final recommendationProvider =
StateNotifierProvider<RecommendationNotifier, Recommendation>(
(ref) {
return RecommendationNotifier();
},
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import 'dart:async';
import 'dart:typed_data';

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:myecl/auth/providers/openid_provider.dart';
import 'package:myecl/tools/repository/logo_repository.dart';

class RecommendationLogoRepository extends LogoRepository {
@override
// ignore: overridden_fields
final ext = "recommendation/recommendations";

Future<Image> getRecommendationLogo(String id) async {
final uint8List = await getLogo("", suffix: "/$id/picture");
return Image.memory(uint8List);
}

Future<Image> addRecommendationLogo(Uint8List bytes, String id) async {
final uint8List = await addLogo(bytes, "", suffix: "/$id/picture");
return Image.memory(uint8List);
}
}

final recommendationLogoRepositoryProvider =
Provider<RecommendationLogoRepository>(
(ref) {
final token = ref.watch(tokenProvider);
return RecommendationLogoRepository()..setToken(token);
},
);
35 changes: 35 additions & 0 deletions lib/recommendation/repositories/recommendation_repository.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:myecl/auth/providers/openid_provider.dart';
import 'package:myecl/recommendation/class/recommendation.dart';
import 'package:myecl/tools/repository/repository.dart';

class RecommendationRepository extends Repository {
@override
// ignore: overridden_fields
final ext = 'recommendation/recommendations';

Future<List<Recommendation>> getRecommendationList() async {
return List<Recommendation>.from(
(await getList()).map((x) => Recommendation.fromJson(x)));
}

Future<Recommendation> createRecommendation(
Recommendation recommendation) async {
return Recommendation.fromJson(await create(recommendation.toJson()));
}

Future<bool> updateRecommendation(Recommendation recommendation) async {
return await update(recommendation.toJson(), "/${recommendation.id}");
}

Future<bool> deleteRecommendation(String recommendationId) async {
return await delete("/$recommendationId");
}
}

final recommendationRepositoryProvider = Provider<RecommendationRepository>(
(ref) {
final token = ref.watch(tokenProvider);
return RecommendationRepository()..setToken(token);
},
);
57 changes: 57 additions & 0 deletions lib/recommendation/router.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import 'package:either_dart/either.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:heroicons/heroicons.dart';
import 'package:myecl/drawer/class/module.dart';
import 'package:myecl/recommendation/providers/is_recommendation_admin_provider.dart';
import 'package:myecl/recommendation/ui/pages/main_page.dart'
deferred as main_page;
import 'package:myecl/recommendation/ui/pages/information_page.dart'
deferred as information_page;
import 'package:myecl/recommendation/ui/pages/add_edit_page.dart'
deferred as add_edit_page;
import 'package:myecl/tools/middlewares/admin_middleware.dart';
import 'package:myecl/tools/middlewares/authenticated_middleware.dart';
import 'package:myecl/tools/middlewares/deferred_middleware.dart';
import 'package:qlevar_router/qlevar_router.dart';

class RecommendationRouter {
final ProviderRef ref;

static const String root = '/recommendation';
static const String information = '/information';
static const String addEdit = '/add_edit';
static final Module module = Module(
name: "Bons plans",
icon: const Left(HeroIcons.newspaper),
root: RecommendationRouter.root,
selected: false,
);

RecommendationRouter(this.ref);

QRoute route() => QRoute(
path: RecommendationRouter.root,
builder: () => main_page.RecommendationMainPage(),
middleware: [
AuthenticatedMiddleware(ref),
DeferredLoadingMiddleware(main_page.loadLibrary),
],
children: [
QRoute(
path: information,
builder: () => information_page.InformationRecommendationPage(),
middleware: [
DeferredLoadingMiddleware(information_page.loadLibrary)
],
),
QRoute(
path: addEdit,
builder: () => add_edit_page.AddEditRecommendationPage(),
middleware: [
AdminMiddleware(ref, isRecommendationAdminProvider),
DeferredLoadingMiddleware(add_edit_page.loadLibrary)
],
),
],
);
}
25 changes: 25 additions & 0 deletions lib/recommendation/tools/constants.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
class RecommendationTextConstants {
static const String recommendation = "Bons plans";
static const String title = "Titre";
static const String logo = "Logo";
static const String code = "Code";
static const String summary = "Court résumé";
static const String description = "Description";
static const String add = "Ajouter";
static const String edit = "Modifier";
static const String delete = "Supprimer";
static const String addImage = "Veuillez ajouter une image";
static const String addedRecommendation = "Bon plan ajouté";
static const String editedRecommendation = "Bon plan modifié";
static const String deleteRecommendationConfirmation =
"Êtes-vous sûr de vouloir supprimer ce bon plan ?";
static const String deleteRecommendation = "Suppresion";
static const String deletingRecommendationError =
"Erreur lors de la suppression";
static const String deletedRecommendation = "Bon plan supprimé";
static const String incorrectOrMissingFields =
'Champs incorrects ou manquants';
static const String editingError = "Échec de la modification";
static const String addingError = "Échec de l'ajout";
static const String copiedCode = "Code de réduction copié";
}
Loading