feat: eventbus to refresh

release/mobdr-v0.0.1
Frédérik Benoist 2023-05-01 18:31:53 +02:00
parent f940638264
commit abb13b588b
21 changed files with 1432 additions and 649 deletions

View File

@ -9,7 +9,7 @@ import 'package:flutter/material.dart';
const String APP_NAME = 'Mobile DR';
// color for apps
const Color PRIMARY_COLOR = Color(0xFF07ac12);
const Color PRIMARY_COLOR = Color(0xff01aed6);
const Color ASSENT_COLOR = Color(0xFFe75f3f);
const Color CHARCOAL = Color(0xFF515151);

View File

@ -5,13 +5,16 @@ import 'package:mobdr/config/constant.dart';
// ignore_for_file: public_member_api_docs
@Entity()
class Visite {
class Visit {
// specify the id
@Id()
int id = 0;
int id_visite;
DateTime date_visite;
DateTime date_debut;
DateTime? date_fin;
DateTime? date_validation;
String type_visite;
String title;
bool allDay;
@ -21,10 +24,13 @@ class Visite {
String url_photo_principale;
String langage;
Visite(
Visit(
{this.id = 0,
required this.id_visite,
required this.date_visite,
required this.date_debut,
required this.date_fin,
required this.date_validation,
required this.type_visite,
required this.title,
required this.allDay,
@ -34,9 +40,14 @@ class Visite {
required this.url_photo_principale,
required this.langage});
Visite.fromJson(Map<String, dynamic> json)
Visit.fromJson(Map<String, dynamic> json)
: id_visite = json['id_visite'],
date_visite = DateTime.parse(json['start']),
date_debut = DateTime.parse(json['start']),
date_fin = json['end'].isNotEmpty ? DateTime.parse(json['end']) : null,
date_validation = json['validation'].isNotEmpty
? DateTime.parse(json['validation'])
: null,
type_visite = json['type_visite'],
title = json['title'],
allDay = json['allDay'],

View File

@ -4,7 +4,7 @@ import 'package:mobdr/objectbox.g.dart';
// ignore_for_file: public_member_api_docs
@Entity()
class VisiteTag {
class VisitTag {
// specify the id
@Id()
int id = 0;
@ -14,14 +14,14 @@ class VisiteTag {
String libelle;
String langage;
VisiteTag(
VisitTag(
{this.id = 0,
required this.id_visite_tag,
required this.id_distrib,
required this.libelle,
required this.langage});
VisiteTag.fromJson(Map<String, dynamic> json)
VisitTag.fromJson(Map<String, dynamic> json)
: id_visite_tag = json['id_visite_tag'],
id_distrib = json['id_distrib'],
libelle = json['libelle'],

View File

@ -26,3 +26,13 @@ class UrlEvent extends AppEvent {
@override
List<Object?> get props => [url];
}
class VisitPhotoCountEvent extends AppEvent {
VisitPhotoCountEvent(this.id_visite, this.photoCount);
final int id_visite;
final int photoCount;
@override
List<Object?> get props => [id_visite, photoCount];
}

View File

@ -22,9 +22,53 @@ class VisiteModel {
required this.type_visite,
required this.langage});
static Future<List<VisiteModel>> getAllVisites() async {
// Retrieve all visits from the database using the getAllVisites() method
final visites = await objectbox.getAllVisites();
static Future<List<VisiteModel>> getTodayVisit() async {
// Retrieve all today visits from the database
final visites = await objectbox.getTodayVisit();
// Map each retrieved visit to VisiteModel
final visiteModels = visites
.map((visite) => VisiteModel(
id_distrib: visite.id_distrib_visite,
id: visite.id,
id_visite: visite.id_visite,
name: visite.id_etab.toString() + ' - ' + visite.title,
photoCount: objectbox.getVisitPhotoCount(visite.id_visite),
date: visite.date_visite.toString(),
image: visite.url_photo_principale,
type_visite: visite.type_visite,
langage: visite.langage))
.toList();
// Return the list of VisiteModel
return visiteModels;
}
static Future<List<VisiteModel>> getPreviousVisit() async {
// Retrieve all previsous visits from the database
final visites = await objectbox.getPreviousVisit();
// Map each retrieved visit to VisiteModel
final visiteModels = visites
.map((visite) => VisiteModel(
id_distrib: visite.id_distrib_visite,
id: visite.id,
id_visite: visite.id_visite,
name: visite.id_etab.toString() + ' - ' + visite.title,
photoCount: objectbox.getVisitPhotoCount(visite.id_visite),
date: visite.date_visite.toString(),
image: visite.url_photo_principale,
type_visite: visite.type_visite,
langage: visite.langage))
.toList();
// Return the list of VisiteModel
return visiteModels;
}
static Future<List<VisiteModel>> getAllVisit() async {
// Retrieve all visits from the database
final visites = await objectbox.getAllVisit();
// Map each retrieved visit to VisiteModel
final visiteModels = visites

View File

@ -201,100 +201,108 @@ class ApiProvider {
}
}
/// Synchronize "stores & competing stores"
Future<String> SyncEtablissements() async {
Response response;
Response response2;
/// Synchronize all informations about store, competitor, calendar
Future<String> SyncCalendar() async {
try {
/// get "Etablissement" list
response = await getCrud(
final responseFutures = Future.wait([
getCrud(
ApiConstants.baseUrl +
ApiConstants.externalEndpoint +
ApiConstants.restEndpoint +
'/mobDR/etablissement',
null);
/// get "concurrent" list
response2 = await getCrud(
null,
),
getCrud(
ApiConstants.baseUrl +
ApiConstants.externalEndpoint +
ApiConstants.restEndpoint +
'/mobDR/etablissement/concurrent',
null);
//await new Future.delayed(const Duration(seconds: 5));
if (response.statusCode == STATUS_OK) {
/// fill box "etab"
objectbox.addEtabs(response.data['boutiques']);
}
if (response2.statusCode == STATUS_OK) {
/// fill box "concurrence"
objectbox.addPhotoCompetitors(response2.data['concurrents']);
}
/// all ok
if (response.statusCode == STATUS_OK &&
response2.statusCode == STATUS_OK) {
return 'OK';
} else {
return response.statusMessage ?? 'Unknow error ...';
}
} catch (ex) {
return ex.toString(); // return ex.response!.data;
}
}
/// Synchronize "visites"
Future<String> SyncVisites() async {
Response response;
Response response2;
try {
var body = null;
/// get "Visite list"
response = await getCrud(
null,
),
getCrud(
ApiConstants.baseUrl +
ApiConstants.externalEndpoint +
ApiConstants.restEndpoint +
'/mobDR/visite/calendrier',
{"id_utilisateur": 6, "start": 20230101, "end": 20230501});
/// get "Visite tags" list
response2 = await getCrud(
{"id_utilisateur": 6, "start": 20230101, "end": 20230501},
),
getCrud(
ApiConstants.baseUrl +
ApiConstants.externalEndpoint +
ApiConstants.restEndpoint +
'/mobDR/visite/tag',
body);
null,
),
getCrud(
ApiConstants.baseUrl +
ApiConstants.externalEndpoint +
ApiConstants.restEndpoint +
'/mobDR/visite/typologie',
null),
]);
//await new Future.delayed(const Duration(seconds: 5));
final List<Response<dynamic>> responses =
await responseFutures.timeout(Duration(seconds: 30));
if (response.statusCode == STATUS_OK) {
/// fill box "visite"
objectbox.addVisites(response.data['events']);
final etabResponse = responses[0];
final competitorResponse = responses[1];
final visitResponse = responses[2];
final visitTagResponse = responses[3];
final PhotoTypologyResponse = responses[4];
if (etabResponse.statusCode == STATUS_OK) {
// remove all objects
objectbox.etabBox.removeAll();
// fill box "Etabs"
objectbox.addEtabs(etabResponse.data['boutiques']);
}
if (response2.statusCode == STATUS_OK) {
if (competitorResponse.statusCode == STATUS_OK) {
// remove all objects
objectbox.etabCompetitorBox.removeAll();
// fill box "Etabs"
objectbox.addEtabCompetitors(competitorResponse.data['concurrents']);
}
if (visitResponse.statusCode == STATUS_OK) {
/// fill box "visite"
objectbox.syncVisits(visitResponse.data['events']);
}
if (visitTagResponse.statusCode == STATUS_OK) {
// remove all objects
objectbox.visitTagBox.removeAll();
/// fill box "visiteTag"
objectbox.addVisiteTags(response2.data['tags']);
objectbox.addVisitTags(visitTagResponse.data['tags']);
}
/// all ok
if (response.statusCode == STATUS_OK &&
response2.statusCode == STATUS_OK) {
if (PhotoTypologyResponse.statusCode == STATUS_OK) {
// remove all objects
objectbox.PhotoTypologyBox.removeAll();
/// fill box "PhotoTypology"
objectbox.addPhotoTypologies(PhotoTypologyResponse.data['typologies']);
}
if (etabResponse.statusCode == STATUS_OK &&
competitorResponse.statusCode == STATUS_OK &&
visitResponse.statusCode == STATUS_OK &&
visitTagResponse.statusCode == STATUS_OK &&
PhotoTypologyResponse.statusCode == STATUS_OK) {
return 'OK';
} else {
return response.statusMessage ?? 'Unknow error ...';
return etabResponse.statusMessage ??
competitorResponse.statusMessage ??
visitResponse.statusMessage ??
visitTagResponse.statusMessage ??
PhotoTypologyResponse.statusMessage ??
'Unknown error';
}
} catch (ex) {
return ex.toString(); // return ex.response!.data;
return ex.toString();
}
}

View File

@ -164,104 +164,6 @@
],
"relations": []
},
{
"id": "7:8290500625256822711",
"lastPropertyId": "14:5831680857919010234",
"name": "Visite",
"properties": [
{
"id": "1:4764888137112024855",
"name": "id",
"type": 6,
"flags": 1
},
{
"id": "2:5254234731633944539",
"name": "id_visite",
"type": 6
},
{
"id": "3:8500424631546195124",
"name": "type_visite",
"type": 9
},
{
"id": "4:307259370424642142",
"name": "title",
"type": 9
},
{
"id": "5:3383534011872507610",
"name": "allDay",
"type": 1
},
{
"id": "7:3559563062004847001",
"name": "id_distrib_visite",
"type": 6
},
{
"id": "8:702894233960499092",
"name": "id_etab",
"type": 6
},
{
"id": "9:5734787836187957444",
"name": "abandon",
"type": 6
},
{
"id": "11:3119168728902810585",
"name": "date_visite",
"type": 10
},
{
"id": "13:1900114397693432703",
"name": "url_photo_principale",
"type": 9
},
{
"id": "14:5831680857919010234",
"name": "langage",
"type": 9
}
],
"relations": []
},
{
"id": "8:637444607663700174",
"lastPropertyId": "5:1603887098520719919",
"name": "VisiteTag",
"properties": [
{
"id": "1:6166685814637290118",
"name": "id",
"type": 6,
"flags": 1
},
{
"id": "2:2059771745036116529",
"name": "id_visite_tag",
"type": 6
},
{
"id": "3:102253757473665009",
"name": "id_distrib",
"type": 6
},
{
"id": "4:1526411175344533047",
"name": "libelle",
"type": 9
},
{
"id": "5:1603887098520719919",
"name": "langage",
"type": 9
}
],
"relations": []
},
{
"id": "10:2779194860339140505",
"lastPropertyId": "4:5588276375011055284",
@ -378,9 +280,122 @@
}
],
"relations": []
},
{
"id": "14:8708899666252263604",
"lastPropertyId": "14:2141854824886685065",
"name": "Visit",
"properties": [
{
"id": "1:1616706753952341931",
"name": "id",
"type": 6,
"flags": 1
},
{
"id": "2:481724387420447256",
"name": "id_visite",
"type": 6
},
{
"id": "3:4117089501376875705",
"name": "date_visite",
"type": 10
},
{
"id": "4:6960359036987777529",
"name": "date_debut",
"type": 10
},
{
"id": "5:2625279579039264654",
"name": "date_fin",
"type": 10
},
{
"id": "6:7413956781075545593",
"name": "date_validation",
"type": 10
},
{
"id": "7:1634711659019811476",
"name": "type_visite",
"type": 9
},
{
"id": "8:8990646204619539770",
"name": "title",
"type": 9
},
{
"id": "9:392889911199239462",
"name": "allDay",
"type": 1
},
{
"id": "10:7419826409064780644",
"name": "id_distrib_visite",
"type": 6
},
{
"id": "11:4334641330182955845",
"name": "id_etab",
"type": 6
},
{
"id": "12:9153440695191140990",
"name": "abandon",
"type": 6
},
{
"id": "13:2729810367696493366",
"name": "url_photo_principale",
"type": 9
},
{
"id": "14:2141854824886685065",
"name": "langage",
"type": 9
}
],
"relations": []
},
{
"id": "15:8818692504823914757",
"lastPropertyId": "5:7051299843455307303",
"name": "VisitTag",
"properties": [
{
"id": "1:43397073361653900",
"name": "id",
"type": 6,
"flags": 1
},
{
"id": "2:3130658169202818866",
"name": "id_visite_tag",
"type": 6
},
{
"id": "3:3266967171909331007",
"name": "id_distrib",
"type": 6
},
{
"id": "4:1055850760280831759",
"name": "libelle",
"type": 9
},
{
"id": "5:7051299843455307303",
"name": "langage",
"type": 9
}
],
"relations": []
}
],
"lastEntityId": "13:6298506278273268036",
"lastEntityId": "15:8818692504823914757",
"lastIndexId": "1:7907819717055295102",
"lastRelationId": "0:0",
"lastSequenceId": "0:0",
@ -390,7 +405,9 @@
7401686910042688313,
1805690312272107423,
6788844671665652158,
2910300629980903548
2910300629980903548,
8290500625256822711,
637444607663700174
],
"retiredIndexUids": [
7907819717055295102
@ -426,7 +443,26 @@
6313899520679425027,
4752064214129719799,
319372524127232986,
783761731187897018
783761731187897018,
4764888137112024855,
5254234731633944539,
8500424631546195124,
307259370424642142,
3383534011872507610,
3559563062004847001,
702894233960499092,
5734787836187957444,
3119168728902810585,
1900114397693432703,
5831680857919010234,
6072666250573656763,
138766887652455581,
4185186663484548877,
6166685814637290118,
2059771745036116529,
102253757473665009,
1526411175344533047,
1603887098520719919
],
"retiredRelationUids": [],
"version": 1

View File

@ -30,10 +30,10 @@ class ObjectBox {
late final Box<EtabCompetitor> etabCompetitorBox;
/// A Box of visit
late final Box<Visite> visitBox;
late final Box<Visit> visitBox;
/// A Box for all visit tag by distributor / language
late final Box<VisiteTag> visitTagBox;
late final Box<VisitTag> visitTagBox;
/// A Box of visit Photo
late final Box<VisitPhoto> visitPhotoBox;
@ -49,8 +49,8 @@ class ObjectBox {
userBox = Box<User>(store);
etabBox = Box<Etab>(store);
etabCompetitorBox = Box<EtabCompetitor>(store);
visitBox = Box<Visite>(store);
visitTagBox = Box<VisiteTag>(store);
visitBox = Box<Visit>(store);
visitTagBox = Box<VisitTag>(store);
PhotoTypologyBox = Box<PhotoTypology>(store);
visitPhotoBox = Box<VisitPhoto>(store);
logBox = Box<Log>(store);
@ -62,12 +62,14 @@ class ObjectBox {
userBox.removeAll();
//etabBox.removeAll();
//etabCompetitorBox.removeAll();
//visitBox.removeAll();
//visitTagBox.removeAll();
//visitPhotoBox.removeAll();
//PhotoTypologyBox.removeAll();
/*
etabBox.removeAll();
etabCompetitorBox.removeAll();
visitBox.removeAll();
visitTagBox.removeAll();
visitPhotoBox.removeAll();
PhotoTypologyBox.removeAll();
*/
// Add some demo data if the box is empty.
if (userBox.isEmpty()) {
@ -200,41 +202,41 @@ class ObjectBox {
return etabBox.count();
}
/// PHOTO COMPETITOR ---------------------------------------------------------------
/// ETAB COMPETITOR ---------------------------------------------------------------
///
// A function that converts a response body list into a List<Competitor>.
List<EtabCompetitor> parsePhotoCompetitor(List responseDataList) {
List<EtabCompetitor> parseEtabCompetitor(List responseDataList) {
final parsed = responseDataList.cast<Map<String, dynamic>>();
return parsed
.map<EtabCompetitor>((json) => EtabCompetitor.fromJson(json))
.toList();
}
Future<void> addPhotoCompetitors(List<dynamic> _listPhotoCompetitors) =>
store.runInTransactionAsync(TxMode.write, _addPhotoCompetitorsInTx,
parsePhotoCompetitor(_listPhotoCompetitors));
Future<void> addEtabCompetitors(List<dynamic> _listPhotoCompetitors) =>
store.runInTransactionAsync(TxMode.write, _addEtabCompetitorsInTx,
parseEtabCompetitor(_listPhotoCompetitors));
static void _addPhotoCompetitorsInTx(Store store, _Competitors) {
static void _addEtabCompetitorsInTx(Store store, _Competitors) {
store.box<EtabCompetitor>().putMany(_Competitors);
}
Future<void> addPhotoCompetitor(
Future<void> addEtabCompetitor(
int _id_concurrence_lien, int _id_etab, _nom) =>
store.runInTransactionAsync(
TxMode.write,
_addPhotoCompetitorInTx,
_addEtabCompetitorInTx,
EtabCompetitor(
id_concurrence_lien: _id_concurrence_lien,
id_etab: _id_etab,
nom: _nom,
));
static void _addPhotoCompetitorInTx(Store store, _Competitor) {
static void _addEtabCompetitorInTx(Store store, _Competitor) {
store.box<EtabCompetitor>().put(_Competitor);
}
List<EtabCompetitor> getPhotoCompetitorList() {
List<EtabCompetitor> getEtabCompetitorList() {
final query = etabCompetitorBox
.query(EtabCompetitor_.id_etab.equals(1417))
.order(EtabCompetitor_.nom)
@ -244,18 +246,18 @@ class ObjectBox {
return photoCompetitors.toList();
}
int getPhotoCompetitorsCount() {
int getEtabCompetitorsCount() {
return etabCompetitorBox.count();
}
/// VISITE ------------------------------------------------------------------
///
Stream<List<Visite>> getVisitesStream() {
Stream<List<Visit>> getVisitStream() {
// Query for all visites, sorted by their date.
// https://docs.objectbox.io/queries
final builder =
visitBox.query().order(Visite_.date_visite, flags: Order.descending);
visitBox.query().order(Visit_.date_visite, flags: Order.descending);
// Build and watch the query,
// set triggerImmediately to emit the query immediately on listen.
return builder
@ -264,34 +266,78 @@ class ObjectBox {
.map((query) => query.find());
}
List<Visite> getAllVisites() {
List<Visit> getAllVisit() {
// Query for all visites, sorted by their date.
final builder = visitBox
.query()
.order(Visite_.date_visite, flags: Order.descending)
.order(Visit_.date_visite, flags: Order.descending)
.build();
// Execute the query and return the result.
return builder.find();
}
List<Visit> getTodayVisit() {
final now = DateTime.now();
// Get the start and end of the current day as timestamps.
final startOfDay =
DateTime(now.year, now.month, now.day).millisecondsSinceEpoch;
final endOfDay = DateTime(now.year, now.month, now.day, 23, 59, 59)
.millisecondsSinceEpoch;
// Query for all visits that occur on the current day and have not been abandoned.
final builder = visitBox
.query(Visit_.date_visite.between(startOfDay, endOfDay) &
Visit_.abandon.equals(0))
.order(Visit_.date_visite, flags: Order.descending)
.build();
// Execute the query and return the result.
return builder.find();
}
List<Visit> getPreviousVisit() {
// Get the previous date at midnight.
final now = DateTime.now();
final midnight = DateTime(now.year, now.month, now.day);
// Convert the date to an integer.
final millisecondsSinceEpoch = midnight.millisecondsSinceEpoch;
// Query for all visits that match the date and abandonment criteria, sorted by their date.
final builder = visitBox
.query(
Visit_.date_visite.lessThan(millisecondsSinceEpoch) &
Visit_.abandon.equals(0),
)
.order(Visit_.date_visite, flags: Order.descending)
.build();
// Execute the query and return the result.
return builder.find();
}
// A function that converts a response body list into a List<Visite>.
List<Visite> parseVisites(List responseDataList) {
List<Visit> parseVisit(List responseDataList) {
final parsed = responseDataList.cast<Map<String, dynamic>>();
return parsed.map<Visite>((json) => Visite.fromJson(json)).toList();
return parsed.map<Visit>((json) => Visit.fromJson(json)).toList();
}
// TODO : Enregistre urlphotoprincipale sur le disque pour l'avoir en cache ?
Future<void> addVisites(List<dynamic> _listVisites) =>
Future<void> addVisits(List<dynamic> _listVisits) =>
store.runInTransactionAsync(
TxMode.write, _addVisitesInTx, parseVisites(_listVisites));
TxMode.write, _addVisitsInTx, parseVisit(_listVisits));
static void _addVisitesInTx(Store store, _Visites) {
store.box<Visite>().putMany(_Visites);
static void _addVisitsInTx(Store store, _Visits) {
store.box<Visit>().putMany(_Visits);
}
Future<void> addVisite(
Future<void> addVisit(
int _id_visite,
DateTime _date_visite,
DateTime _date_debut,
DateTime _date_fin,
DateTime _date_validation,
String _type_visite,
String _title,
bool _allDay,
@ -304,10 +350,13 @@ class ObjectBox {
String _langage) =>
store.runInTransactionAsync(
TxMode.write,
_addVisiteInTx,
Visite(
_addVisitInTx,
Visit(
id_visite: _id_visite,
date_visite: _date_visite,
date_debut: _date_debut,
date_fin: _date_fin,
date_validation: _date_validation,
type_visite: _type_visite,
title: _title,
allDay: _allDay,
@ -317,66 +366,93 @@ class ObjectBox {
url_photo_principale: _url_photo_principale,
langage: _langage));
static void _addVisiteInTx(Store store, _Visite) {
store.box<Visite>().put(_Visite);
static void _addVisitInTx(Store store, _Visite) {
store.box<Visit>().put(_Visite);
}
int getVisiteCount() {
Future<void> syncVisits(List<dynamic> _listVisits) async {
final toSyncId_visite =
_listVisits.map<int>((v) => v['id_visite']).toList();
final existingVisitsQuery =
visitBox.query(Visit_.id_visite.oneOf(toSyncId_visite));
final existingVisits = existingVisitsQuery.build().find();
final existingVisitIds =
existingVisits.map<int>((v) => v.id_visite).toList();
final newVisits = _listVisits
.where((v) => !existingVisitIds.contains(v['id_visite']))
.toList();
final updatedVisits = _listVisits
.where((v) => existingVisitIds.contains(v['id_visite']))
.toList();
newVisits.forEach((v) {
visitBox.put(Visit.fromJson(v));
});
updatedVisits.forEach((v) {
final existingVisit =
existingVisits.firstWhere((ev) => ev.id_visite == v['id_visite']);
final updatedVisit = Visit.fromJson(v)..id = existingVisit.id;
visitBox.put(updatedVisit);
});
}
int getVisitCount() {
return visitBox.count();
}
//TODO changer en PHOTO TAG / mettre dans l'ordre CRUD
/// PHOTO TAG ---------------------------------------------------------------
/// VISIT TAG ---------------------------------------------------------------
///
// converts a response body list into a List<VisiteTag>.
List<VisiteTag> parseVisiteTags(List responseDataList) {
// converts a response body list into a List<VisitTag>.
List<VisitTag> parseVisitTags(List responseDataList) {
final parsed = responseDataList.cast<Map<String, dynamic>>();
return parsed.map<VisiteTag>((json) => VisiteTag.fromJson(json)).toList();
return parsed.map<VisitTag>((json) => VisitTag.fromJson(json)).toList();
}
Future<void> addVisiteTags(List<dynamic> _listVisiteTags) =>
Future<void> addVisitTags(List<dynamic> _listVisitTags) =>
store.runInTransactionAsync(
TxMode.write, _addVisiteTagsInTx, parseVisiteTags(_listVisiteTags));
TxMode.write, _addVisitTagsInTx, parseVisitTags(_listVisitTags));
static void _addVisiteTagsInTx(Store store, _VisiteTags) {
store.box<VisiteTag>().putMany(_VisiteTags);
static void _addVisitTagsInTx(Store store, _VisitTags) {
store.box<VisitTag>().putMany(_VisitTags);
}
/// save new tag for a distributor / langage
Future<void> addVisiteTag(
int _id_visite_tag,
Future<void> addVisitTag(
int id_visite_tag,
int _id_distrib,
String _libelle,
String _langage,
) =>
store.runInTransactionAsync(
TxMode.write,
_addVisiteTagInTx,
VisiteTag(
id_visite_tag: _id_visite_tag,
_addVisitTagInTx,
VisitTag(
id_visite_tag: id_visite_tag,
id_distrib: _id_distrib,
libelle: _libelle,
langage: _langage,
));
static void _addVisiteTagInTx(Store store, _VisiteTag) {
store.box<VisiteTag>().put(_VisiteTag);
static void _addVisitTagInTx(Store store, _VisitTag) {
store.box<VisitTag>().put(_VisitTag);
}
List<String> getVisiteTagsLabels(int distribId, String langage) {
List<String> getVisitTagsLabels(int distribId, String langage) {
final query = visitTagBox
.query(VisiteTag_.id_distrib.equals(distribId) &
VisiteTag_.langage.equals(langage))
//.order(VisiteTag_.libelle)
.query(VisitTag_.id_distrib.equals(distribId) &
VisitTag_.langage.equals(langage))
//.order(VisitTag_.libelle)
.build();
PropertyQuery<String> pq = query.property(VisiteTag_.libelle);
PropertyQuery<String> pq = query.property(VisitTag_.libelle);
pq.distinct = true;
pq.caseSensitive = false;
return pq.find();
}
int getVisiteTagCount() {
int getVisitTagCount() {
return visitTagBox.count();
}
@ -498,7 +574,7 @@ class ObjectBox {
}
/* remettre les principal à zero
final queryBuilder = box.query(VisitPhoto_.visite_id.equals(idVisite) & VisitPhoto_.photo_principale.equals(1));
final queryBuilder = box.query(VisitPhoto_.Visit_id.equals(idVisite) & VisitPhoto_.photo_principale.equals(1));
final updatedPhotos = queryBuilder.build().find();
updatedPhotos.forEach((photo) {
photo.photo_principale = 0;

View File

@ -188,104 +188,6 @@ final _entities = <ModelEntity>[
],
relations: <ModelRelation>[],
backlinks: <ModelBacklink>[]),
ModelEntity(
id: const IdUid(7, 8290500625256822711),
name: 'Visite',
lastPropertyId: const IdUid(14, 5831680857919010234),
flags: 0,
properties: <ModelProperty>[
ModelProperty(
id: const IdUid(1, 4764888137112024855),
name: 'id',
type: 6,
flags: 1),
ModelProperty(
id: const IdUid(2, 5254234731633944539),
name: 'id_visite',
type: 6,
flags: 0),
ModelProperty(
id: const IdUid(3, 8500424631546195124),
name: 'type_visite',
type: 9,
flags: 0),
ModelProperty(
id: const IdUid(4, 307259370424642142),
name: 'title',
type: 9,
flags: 0),
ModelProperty(
id: const IdUid(5, 3383534011872507610),
name: 'allDay',
type: 1,
flags: 0),
ModelProperty(
id: const IdUid(7, 3559563062004847001),
name: 'id_distrib_visite',
type: 6,
flags: 0),
ModelProperty(
id: const IdUid(8, 702894233960499092),
name: 'id_etab',
type: 6,
flags: 0),
ModelProperty(
id: const IdUid(9, 5734787836187957444),
name: 'abandon',
type: 6,
flags: 0),
ModelProperty(
id: const IdUid(11, 3119168728902810585),
name: 'date_visite',
type: 10,
flags: 0),
ModelProperty(
id: const IdUid(13, 1900114397693432703),
name: 'url_photo_principale',
type: 9,
flags: 0),
ModelProperty(
id: const IdUid(14, 5831680857919010234),
name: 'langage',
type: 9,
flags: 0)
],
relations: <ModelRelation>[],
backlinks: <ModelBacklink>[]),
ModelEntity(
id: const IdUid(8, 637444607663700174),
name: 'VisiteTag',
lastPropertyId: const IdUid(5, 1603887098520719919),
flags: 0,
properties: <ModelProperty>[
ModelProperty(
id: const IdUid(1, 6166685814637290118),
name: 'id',
type: 6,
flags: 1),
ModelProperty(
id: const IdUid(2, 2059771745036116529),
name: 'id_visite_tag',
type: 6,
flags: 0),
ModelProperty(
id: const IdUid(3, 102253757473665009),
name: 'id_distrib',
type: 6,
flags: 0),
ModelProperty(
id: const IdUid(4, 1526411175344533047),
name: 'libelle',
type: 9,
flags: 0),
ModelProperty(
id: const IdUid(5, 1603887098520719919),
name: 'langage',
type: 9,
flags: 0)
],
relations: <ModelRelation>[],
backlinks: <ModelBacklink>[]),
ModelEntity(
id: const IdUid(10, 2779194860339140505),
name: 'PhotoTypology',
@ -402,6 +304,119 @@ final _entities = <ModelEntity>[
flags: 0)
],
relations: <ModelRelation>[],
backlinks: <ModelBacklink>[]),
ModelEntity(
id: const IdUid(14, 8708899666252263604),
name: 'Visit',
lastPropertyId: const IdUid(14, 2141854824886685065),
flags: 0,
properties: <ModelProperty>[
ModelProperty(
id: const IdUid(1, 1616706753952341931),
name: 'id',
type: 6,
flags: 1),
ModelProperty(
id: const IdUid(2, 481724387420447256),
name: 'id_visite',
type: 6,
flags: 0),
ModelProperty(
id: const IdUid(3, 4117089501376875705),
name: 'date_visite',
type: 10,
flags: 0),
ModelProperty(
id: const IdUid(4, 6960359036987777529),
name: 'date_debut',
type: 10,
flags: 0),
ModelProperty(
id: const IdUid(5, 2625279579039264654),
name: 'date_fin',
type: 10,
flags: 0),
ModelProperty(
id: const IdUid(6, 7413956781075545593),
name: 'date_validation',
type: 10,
flags: 0),
ModelProperty(
id: const IdUid(7, 1634711659019811476),
name: 'type_visite',
type: 9,
flags: 0),
ModelProperty(
id: const IdUid(8, 8990646204619539770),
name: 'title',
type: 9,
flags: 0),
ModelProperty(
id: const IdUid(9, 392889911199239462),
name: 'allDay',
type: 1,
flags: 0),
ModelProperty(
id: const IdUid(10, 7419826409064780644),
name: 'id_distrib_visite',
type: 6,
flags: 0),
ModelProperty(
id: const IdUid(11, 4334641330182955845),
name: 'id_etab',
type: 6,
flags: 0),
ModelProperty(
id: const IdUid(12, 9153440695191140990),
name: 'abandon',
type: 6,
flags: 0),
ModelProperty(
id: const IdUid(13, 2729810367696493366),
name: 'url_photo_principale',
type: 9,
flags: 0),
ModelProperty(
id: const IdUid(14, 2141854824886685065),
name: 'langage',
type: 9,
flags: 0)
],
relations: <ModelRelation>[],
backlinks: <ModelBacklink>[]),
ModelEntity(
id: const IdUid(15, 8818692504823914757),
name: 'VisitTag',
lastPropertyId: const IdUid(5, 7051299843455307303),
flags: 0,
properties: <ModelProperty>[
ModelProperty(
id: const IdUid(1, 43397073361653900),
name: 'id',
type: 6,
flags: 1),
ModelProperty(
id: const IdUid(2, 3130658169202818866),
name: 'id_visite_tag',
type: 6,
flags: 0),
ModelProperty(
id: const IdUid(3, 3266967171909331007),
name: 'id_distrib',
type: 6,
flags: 0),
ModelProperty(
id: const IdUid(4, 1055850760280831759),
name: 'libelle',
type: 9,
flags: 0),
ModelProperty(
id: const IdUid(5, 7051299843455307303),
name: 'langage',
type: 9,
flags: 0)
],
relations: <ModelRelation>[],
backlinks: <ModelBacklink>[])
];
@ -425,7 +440,7 @@ Future<Store> openStore(
ModelDefinition getObjectBoxModel() {
final model = ModelInfo(
entities: _entities,
lastEntityId: const IdUid(13, 6298506278273268036),
lastEntityId: const IdUid(15, 8818692504823914757),
lastIndexId: const IdUid(1, 7907819717055295102),
lastRelationId: const IdUid(0, 0),
lastSequenceId: const IdUid(0, 0),
@ -433,7 +448,9 @@ ModelDefinition getObjectBoxModel() {
7401686910042688313,
1805690312272107423,
6788844671665652158,
2910300629980903548
2910300629980903548,
8290500625256822711,
637444607663700174
],
retiredIndexUids: const [7907819717055295102],
retiredPropertyUids: const [
@ -467,7 +484,26 @@ ModelDefinition getObjectBoxModel() {
6313899520679425027,
4752064214129719799,
319372524127232986,
783761731187897018
783761731187897018,
4764888137112024855,
5254234731633944539,
8500424631546195124,
307259370424642142,
3383534011872507610,
3559563062004847001,
702894233960499092,
5734787836187957444,
3119168728902810585,
1900114397693432703,
5831680857919010234,
6072666250573656763,
138766887652455581,
4185186663484548877,
6166685814637290118,
2059771745036116529,
102253757473665009,
1526411175344533047,
1603887098520719919
],
retiredRelationUids: const [],
modelVersion: 5,
@ -645,105 +681,10 @@ ModelDefinition getObjectBoxModel() {
latitude: const fb.StringReader(asciiOptimization: true)
.vTableGet(buffer, rootOffset, 18, ''));
return object;
}),
Visite: EntityDefinition<Visite>(
model: _entities[4],
toOneRelations: (Visite object) => [],
toManyRelations: (Visite object) => {},
getId: (Visite object) => object.id,
setId: (Visite object, int id) {
object.id = id;
},
objectToFB: (Visite object, fb.Builder fbb) {
final type_visiteOffset = fbb.writeString(object.type_visite);
final titleOffset = fbb.writeString(object.title);
final url_photo_principaleOffset =
fbb.writeString(object.url_photo_principale);
final langageOffset = fbb.writeString(object.langage);
fbb.startTable(15);
fbb.addInt64(0, object.id);
fbb.addInt64(1, object.id_visite);
fbb.addOffset(2, type_visiteOffset);
fbb.addOffset(3, titleOffset);
fbb.addBool(4, object.allDay);
fbb.addInt64(6, object.id_distrib_visite);
fbb.addInt64(7, object.id_etab);
fbb.addInt64(8, object.abandon);
fbb.addInt64(10, object.date_visite.millisecondsSinceEpoch);
fbb.addOffset(12, url_photo_principaleOffset);
fbb.addOffset(13, langageOffset);
fbb.finish(fbb.endTable());
return object.id;
},
objectFromFB: (Store store, ByteData fbData) {
final buffer = fb.BufferContext(fbData);
final rootOffset = buffer.derefObject(0);
final object = Visite(
id: const fb.Int64Reader().vTableGet(buffer, rootOffset, 4, 0),
id_visite:
const fb.Int64Reader().vTableGet(buffer, rootOffset, 6, 0),
date_visite: DateTime.fromMillisecondsSinceEpoch(
const fb.Int64Reader().vTableGet(buffer, rootOffset, 24, 0)),
type_visite: const fb.StringReader(asciiOptimization: true)
.vTableGet(buffer, rootOffset, 8, ''),
title: const fb.StringReader(asciiOptimization: true)
.vTableGet(buffer, rootOffset, 10, ''),
allDay: const fb.BoolReader()
.vTableGet(buffer, rootOffset, 12, false),
id_distrib_visite:
const fb.Int64Reader().vTableGet(buffer, rootOffset, 16, 0),
id_etab:
const fb.Int64Reader().vTableGet(buffer, rootOffset, 18, 0),
abandon:
const fb.Int64Reader().vTableGet(buffer, rootOffset, 20, 0),
url_photo_principale: const fb.StringReader(asciiOptimization: true)
.vTableGet(buffer, rootOffset, 28, ''),
langage:
const fb.StringReader(asciiOptimization: true).vTableGet(buffer, rootOffset, 30, ''));
return object;
}),
VisiteTag: EntityDefinition<VisiteTag>(
model: _entities[5],
toOneRelations: (VisiteTag object) => [],
toManyRelations: (VisiteTag object) => {},
getId: (VisiteTag object) => object.id,
setId: (VisiteTag object, int id) {
object.id = id;
},
objectToFB: (VisiteTag object, fb.Builder fbb) {
final libelleOffset = fbb.writeString(object.libelle);
final langageOffset = fbb.writeString(object.langage);
fbb.startTable(6);
fbb.addInt64(0, object.id);
fbb.addInt64(1, object.id_visite_tag);
fbb.addInt64(2, object.id_distrib);
fbb.addOffset(3, libelleOffset);
fbb.addOffset(4, langageOffset);
fbb.finish(fbb.endTable());
return object.id;
},
objectFromFB: (Store store, ByteData fbData) {
final buffer = fb.BufferContext(fbData);
final rootOffset = buffer.derefObject(0);
final object = VisiteTag(
id: const fb.Int64Reader().vTableGet(buffer, rootOffset, 4, 0),
id_visite_tag:
const fb.Int64Reader().vTableGet(buffer, rootOffset, 6, 0),
id_distrib:
const fb.Int64Reader().vTableGet(buffer, rootOffset, 8, 0),
libelle: const fb.StringReader(asciiOptimization: true)
.vTableGet(buffer, rootOffset, 10, ''),
langage: const fb.StringReader(asciiOptimization: true)
.vTableGet(buffer, rootOffset, 12, ''));
return object;
}),
PhotoTypology: EntityDefinition<PhotoTypology>(
model: _entities[6],
model: _entities[4],
toOneRelations: (PhotoTypology object) => [],
toManyRelations: (PhotoTypology object) => {},
getId: (PhotoTypology object) => object.id,
@ -776,7 +717,7 @@ ModelDefinition getObjectBoxModel() {
return object;
}),
EtabCompetitor: EntityDefinition<EtabCompetitor>(
model: _entities[7],
model: _entities[5],
toOneRelations: (EtabCompetitor object) => [],
toManyRelations: (EtabCompetitor object) => {},
getId: (EtabCompetitor object) => object.id,
@ -809,7 +750,7 @@ ModelDefinition getObjectBoxModel() {
return object;
}),
VisitPhoto: EntityDefinition<VisitPhoto>(
model: _entities[8],
model: _entities[6],
toOneRelations: (VisitPhoto object) => [],
toManyRelations: (VisitPhoto object) => {},
getId: (VisitPhoto object) => object.id,
@ -858,6 +799,111 @@ ModelDefinition getObjectBoxModel() {
uploaded:
const fb.Int64Reader().vTableGet(buffer, rootOffset, 22, 0));
return object;
}),
Visit: EntityDefinition<Visit>(
model: _entities[7],
toOneRelations: (Visit object) => [],
toManyRelations: (Visit object) => {},
getId: (Visit object) => object.id,
setId: (Visit object, int id) {
object.id = id;
},
objectToFB: (Visit object, fb.Builder fbb) {
final type_visiteOffset = fbb.writeString(object.type_visite);
final titleOffset = fbb.writeString(object.title);
final url_photo_principaleOffset =
fbb.writeString(object.url_photo_principale);
final langageOffset = fbb.writeString(object.langage);
fbb.startTable(15);
fbb.addInt64(0, object.id);
fbb.addInt64(1, object.id_visite);
fbb.addInt64(2, object.date_visite.millisecondsSinceEpoch);
fbb.addInt64(3, object.date_debut.millisecondsSinceEpoch);
fbb.addInt64(4, object.date_fin?.millisecondsSinceEpoch);
fbb.addInt64(5, object.date_validation?.millisecondsSinceEpoch);
fbb.addOffset(6, type_visiteOffset);
fbb.addOffset(7, titleOffset);
fbb.addBool(8, object.allDay);
fbb.addInt64(9, object.id_distrib_visite);
fbb.addInt64(10, object.id_etab);
fbb.addInt64(11, object.abandon);
fbb.addOffset(12, url_photo_principaleOffset);
fbb.addOffset(13, langageOffset);
fbb.finish(fbb.endTable());
return object.id;
},
objectFromFB: (Store store, ByteData fbData) {
final buffer = fb.BufferContext(fbData);
final rootOffset = buffer.derefObject(0);
final date_finValue =
const fb.Int64Reader().vTableGetNullable(buffer, rootOffset, 12);
final date_validationValue =
const fb.Int64Reader().vTableGetNullable(buffer, rootOffset, 14);
final object = Visit(
id: const fb.Int64Reader().vTableGet(buffer, rootOffset, 4, 0),
id_visite:
const fb.Int64Reader().vTableGet(buffer, rootOffset, 6, 0),
date_visite: DateTime.fromMillisecondsSinceEpoch(
const fb.Int64Reader().vTableGet(buffer, rootOffset, 8, 0)),
date_debut: DateTime.fromMillisecondsSinceEpoch(
const fb.Int64Reader().vTableGet(buffer, rootOffset, 10, 0)),
date_fin: date_finValue == null
? null
: DateTime.fromMillisecondsSinceEpoch(date_finValue),
date_validation: date_validationValue == null
? null
: DateTime.fromMillisecondsSinceEpoch(date_validationValue),
type_visite: const fb.StringReader(asciiOptimization: true)
.vTableGet(buffer, rootOffset, 16, ''),
title: const fb.StringReader(asciiOptimization: true)
.vTableGet(buffer, rootOffset, 18, ''),
allDay: const fb.BoolReader()
.vTableGet(buffer, rootOffset, 20, false),
id_distrib_visite:
const fb.Int64Reader().vTableGet(buffer, rootOffset, 22, 0),
id_etab: const fb.Int64Reader().vTableGet(buffer, rootOffset, 24, 0),
abandon: const fb.Int64Reader().vTableGet(buffer, rootOffset, 26, 0),
url_photo_principale: const fb.StringReader(asciiOptimization: true).vTableGet(buffer, rootOffset, 28, ''),
langage: const fb.StringReader(asciiOptimization: true).vTableGet(buffer, rootOffset, 30, ''));
return object;
}),
VisitTag: EntityDefinition<VisitTag>(
model: _entities[8],
toOneRelations: (VisitTag object) => [],
toManyRelations: (VisitTag object) => {},
getId: (VisitTag object) => object.id,
setId: (VisitTag object, int id) {
object.id = id;
},
objectToFB: (VisitTag object, fb.Builder fbb) {
final libelleOffset = fbb.writeString(object.libelle);
final langageOffset = fbb.writeString(object.langage);
fbb.startTable(6);
fbb.addInt64(0, object.id);
fbb.addInt64(1, object.id_visite_tag);
fbb.addInt64(2, object.id_distrib);
fbb.addOffset(3, libelleOffset);
fbb.addOffset(4, langageOffset);
fbb.finish(fbb.endTable());
return object.id;
},
objectFromFB: (Store store, ByteData fbData) {
final buffer = fb.BufferContext(fbData);
final rootOffset = buffer.derefObject(0);
final object = VisitTag(
id: const fb.Int64Reader().vTableGet(buffer, rootOffset, 4, 0),
id_visite_tag:
const fb.Int64Reader().vTableGet(buffer, rootOffset, 6, 0),
id_distrib:
const fb.Int64Reader().vTableGet(buffer, rootOffset, 8, 0),
libelle: const fb.StringReader(asciiOptimization: true)
.vTableGet(buffer, rootOffset, 10, ''),
langage: const fb.StringReader(asciiOptimization: true)
.vTableGet(buffer, rootOffset, 12, ''));
return object;
})
};
@ -955,150 +1001,161 @@ class Etab_ {
QueryStringProperty<Etab>(_entities[3].properties[7]);
}
/// [Visite] entity fields to define ObjectBox queries.
class Visite_ {
/// see [Visite.id]
static final id = QueryIntegerProperty<Visite>(_entities[4].properties[0]);
/// see [Visite.id_visite]
static final id_visite =
QueryIntegerProperty<Visite>(_entities[4].properties[1]);
/// see [Visite.type_visite]
static final type_visite =
QueryStringProperty<Visite>(_entities[4].properties[2]);
/// see [Visite.title]
static final title = QueryStringProperty<Visite>(_entities[4].properties[3]);
/// see [Visite.allDay]
static final allDay =
QueryBooleanProperty<Visite>(_entities[4].properties[4]);
/// see [Visite.id_distrib_visite]
static final id_distrib_visite =
QueryIntegerProperty<Visite>(_entities[4].properties[5]);
/// see [Visite.id_etab]
static final id_etab =
QueryIntegerProperty<Visite>(_entities[4].properties[6]);
/// see [Visite.abandon]
static final abandon =
QueryIntegerProperty<Visite>(_entities[4].properties[7]);
/// see [Visite.date_visite]
static final date_visite =
QueryIntegerProperty<Visite>(_entities[4].properties[8]);
/// see [Visite.url_photo_principale]
static final url_photo_principale =
QueryStringProperty<Visite>(_entities[4].properties[9]);
/// see [Visite.langage]
static final langage =
QueryStringProperty<Visite>(_entities[4].properties[10]);
}
/// [VisiteTag] entity fields to define ObjectBox queries.
class VisiteTag_ {
/// see [VisiteTag.id]
static final id = QueryIntegerProperty<VisiteTag>(_entities[5].properties[0]);
/// see [VisiteTag.id_visite_tag]
static final id_visite_tag =
QueryIntegerProperty<VisiteTag>(_entities[5].properties[1]);
/// see [VisiteTag.id_distrib]
static final id_distrib =
QueryIntegerProperty<VisiteTag>(_entities[5].properties[2]);
/// see [VisiteTag.libelle]
static final libelle =
QueryStringProperty<VisiteTag>(_entities[5].properties[3]);
/// see [VisiteTag.langage]
static final langage =
QueryStringProperty<VisiteTag>(_entities[5].properties[4]);
}
/// [PhotoTypology] entity fields to define ObjectBox queries.
class PhotoTypology_ {
/// see [PhotoTypology.id]
static final id =
QueryIntegerProperty<PhotoTypology>(_entities[6].properties[0]);
QueryIntegerProperty<PhotoTypology>(_entities[4].properties[0]);
/// see [PhotoTypology.id_photo_typologie]
static final id_photo_typologie =
QueryIntegerProperty<PhotoTypology>(_entities[6].properties[1]);
QueryIntegerProperty<PhotoTypology>(_entities[4].properties[1]);
/// see [PhotoTypology.libelle]
static final libelle =
QueryStringProperty<PhotoTypology>(_entities[6].properties[2]);
QueryStringProperty<PhotoTypology>(_entities[4].properties[2]);
/// see [PhotoTypology.ordre]
static final ordre =
QueryIntegerProperty<PhotoTypology>(_entities[6].properties[3]);
QueryIntegerProperty<PhotoTypology>(_entities[4].properties[3]);
}
/// [EtabCompetitor] entity fields to define ObjectBox queries.
class EtabCompetitor_ {
/// see [EtabCompetitor.id]
static final id =
QueryIntegerProperty<EtabCompetitor>(_entities[7].properties[0]);
QueryIntegerProperty<EtabCompetitor>(_entities[5].properties[0]);
/// see [EtabCompetitor.id_concurrence_lien]
static final id_concurrence_lien =
QueryIntegerProperty<EtabCompetitor>(_entities[7].properties[1]);
QueryIntegerProperty<EtabCompetitor>(_entities[5].properties[1]);
/// see [EtabCompetitor.id_etab]
static final id_etab =
QueryIntegerProperty<EtabCompetitor>(_entities[7].properties[2]);
QueryIntegerProperty<EtabCompetitor>(_entities[5].properties[2]);
/// see [EtabCompetitor.nom]
static final nom =
QueryStringProperty<EtabCompetitor>(_entities[7].properties[3]);
QueryStringProperty<EtabCompetitor>(_entities[5].properties[3]);
}
/// [VisitPhoto] entity fields to define ObjectBox queries.
class VisitPhoto_ {
/// see [VisitPhoto.id]
static final id =
QueryIntegerProperty<VisitPhoto>(_entities[8].properties[0]);
QueryIntegerProperty<VisitPhoto>(_entities[6].properties[0]);
/// see [VisitPhoto.id_visite]
static final id_visite =
QueryIntegerProperty<VisitPhoto>(_entities[8].properties[1]);
QueryIntegerProperty<VisitPhoto>(_entities[6].properties[1]);
/// see [VisitPhoto.id_photo_typologie]
static final id_photo_typologie =
QueryIntegerProperty<VisitPhoto>(_entities[8].properties[2]);
QueryIntegerProperty<VisitPhoto>(_entities[6].properties[2]);
/// see [VisitPhoto.image_name]
static final image_name =
QueryStringProperty<VisitPhoto>(_entities[8].properties[3]);
QueryStringProperty<VisitPhoto>(_entities[6].properties[3]);
/// see [VisitPhoto.date_photo]
static final date_photo =
QueryIntegerProperty<VisitPhoto>(_entities[8].properties[4]);
QueryIntegerProperty<VisitPhoto>(_entities[6].properties[4]);
/// see [VisitPhoto.id_photo_mp4]
static final id_photo_mp4 =
QueryIntegerProperty<VisitPhoto>(_entities[8].properties[5]);
QueryIntegerProperty<VisitPhoto>(_entities[6].properties[5]);
/// see [VisitPhoto.photo_privee]
static final photo_privee =
QueryIntegerProperty<VisitPhoto>(_entities[8].properties[6]);
QueryIntegerProperty<VisitPhoto>(_entities[6].properties[6]);
/// see [VisitPhoto.photo_principale]
static final photo_principale =
QueryIntegerProperty<VisitPhoto>(_entities[8].properties[7]);
QueryIntegerProperty<VisitPhoto>(_entities[6].properties[7]);
/// see [VisitPhoto.tags]
static final tags =
QueryStringProperty<VisitPhoto>(_entities[8].properties[8]);
QueryStringProperty<VisitPhoto>(_entities[6].properties[8]);
/// see [VisitPhoto.uploaded]
static final uploaded =
QueryIntegerProperty<VisitPhoto>(_entities[8].properties[9]);
QueryIntegerProperty<VisitPhoto>(_entities[6].properties[9]);
}
/// [Visit] entity fields to define ObjectBox queries.
class Visit_ {
/// see [Visit.id]
static final id = QueryIntegerProperty<Visit>(_entities[7].properties[0]);
/// see [Visit.id_visite]
static final id_visite =
QueryIntegerProperty<Visit>(_entities[7].properties[1]);
/// see [Visit.date_visite]
static final date_visite =
QueryIntegerProperty<Visit>(_entities[7].properties[2]);
/// see [Visit.date_debut]
static final date_debut =
QueryIntegerProperty<Visit>(_entities[7].properties[3]);
/// see [Visit.date_fin]
static final date_fin =
QueryIntegerProperty<Visit>(_entities[7].properties[4]);
/// see [Visit.date_validation]
static final date_validation =
QueryIntegerProperty<Visit>(_entities[7].properties[5]);
/// see [Visit.type_visite]
static final type_visite =
QueryStringProperty<Visit>(_entities[7].properties[6]);
/// see [Visit.title]
static final title = QueryStringProperty<Visit>(_entities[7].properties[7]);
/// see [Visit.allDay]
static final allDay = QueryBooleanProperty<Visit>(_entities[7].properties[8]);
/// see [Visit.id_distrib_visite]
static final id_distrib_visite =
QueryIntegerProperty<Visit>(_entities[7].properties[9]);
/// see [Visit.id_etab]
static final id_etab =
QueryIntegerProperty<Visit>(_entities[7].properties[10]);
/// see [Visit.abandon]
static final abandon =
QueryIntegerProperty<Visit>(_entities[7].properties[11]);
/// see [Visit.url_photo_principale]
static final url_photo_principale =
QueryStringProperty<Visit>(_entities[7].properties[12]);
/// see [Visit.langage]
static final langage =
QueryStringProperty<Visit>(_entities[7].properties[13]);
}
/// [VisitTag] entity fields to define ObjectBox queries.
class VisitTag_ {
/// see [VisitTag.id]
static final id = QueryIntegerProperty<VisitTag>(_entities[8].properties[0]);
/// see [VisitTag.id_visite_tag]
static final id_visite_tag =
QueryIntegerProperty<VisitTag>(_entities[8].properties[1]);
/// see [VisitTag.id_distrib]
static final id_distrib =
QueryIntegerProperty<VisitTag>(_entities[8].properties[2]);
/// see [VisitTag.libelle]
static final libelle =
QueryStringProperty<VisitTag>(_entities[8].properties[3]);
/// see [VisitTag.langage]
static final langage =
QueryStringProperty<VisitTag>(_entities[8].properties[4]);
}

View File

@ -207,8 +207,8 @@ class _TabSyncPageState extends State<TabSyncPage>
child: Icon(Icons.chevron_right),
onPressed: () async {
var futures = [
_apiProvider.SyncEtablissements(),
_apiProvider.SyncVisites(),
//_apiProvider.SyncEtablissements(),
//_apiProvider.SyncVisites(),
_apiProvider.SyncPhotos(),
];

View File

@ -5,7 +5,7 @@ import 'package:mobdr/main.dart';
import 'package:mobdr/ui/account/tab_account.dart';
import 'package:mobdr/ui/home/tab_home.dart';
import 'package:mobdr/ui/mp4/tab_mp4.dart';
import 'package:mobdr/ui/sync/tab_sync.dart';
import 'package:mobdr/ui/visit/tab_visit.dart';
import 'package:mobdr/config/constant.dart';
import 'package:mobdr/events.dart';
@ -18,7 +18,7 @@ class HomePage extends StatefulWidget {
class _HomePageState extends State<HomePage>
with SingleTickerProviderStateMixin {
late PageController _pageController;
late StreamSubscription sub; // déclaration de la variable sub
late StreamSubscription subUrlEvent;
int _currentIndex = 0;
@ -28,7 +28,7 @@ class _HomePageState extends State<HomePage>
void initState() {
_contentPages = <Widget>[
TabHomePage(),
TabSyncPage(),
TabVisitListPage(),
TabMP4Page(),
TabAccountPage(),
];
@ -38,7 +38,7 @@ class _HomePageState extends State<HomePage>
_pageController.addListener(_handleTabSelection);
// Listen particular event
sub = eventBus.on<UrlEvent>().listen((e) {
subUrlEvent = eventBus.on<UrlEvent>().listen((e) {
setState(() {
_currentIndex = 2;
_pageController.jumpToPage(_currentIndex);
@ -55,7 +55,7 @@ class _HomePageState extends State<HomePage>
@override
void dispose() {
sub.cancel();
subUrlEvent.cancel();
_pageController.dispose();
super.dispose();
}
@ -95,7 +95,7 @@ class _HomePageState extends State<HomePage>
icon: Icon(Icons.home,
color: _currentIndex == 0 ? PRIMARY_COLOR : CHARCOAL)),
BottomNavigationBarItem(
label: 'Sync',
label: 'Visits',
icon: Icon(Icons.sync,
color: _currentIndex == 1 ? ASSENT_COLOR : CHARCOAL)),
BottomNavigationBarItem(

View File

@ -3,20 +3,27 @@ This is home page
we used AutomaticKeepAliveClientMixin to keep the state when moving from 1 navbar to another navbar, so the page is not refresh overtime
*/
import 'dart:async';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:badges/badges.dart' as badges;
import 'package:mobdr/main.dart';
import 'package:mobdr/config/constant.dart';
import 'package:mobdr/cubit/language/language_cubit.dart';
import 'package:mobdr/cubit/language/app_localizations.dart';
import 'package:mobdr/service/shared_prefs.dart';
import 'package:mobdr/config/global_style.dart';
import 'package:mobdr/events.dart';
import 'package:mobdr/ui/sync/sync_calendar.dart';
import 'package:mobdr/model/visite_model.dart';
import 'package:mobdr/ui/visit/visit_photo_typology.dart';
import 'package:mobdr/ui/general/chat_us.dart';
import 'package:mobdr/ui/general/notification.dart';
import 'package:mobdr/ui/reusable/reusable_widget.dart';
import 'package:mobdr/ui/reusable/cache_image_network.dart';
class TabHomePage extends StatefulWidget {
@override
@ -28,8 +35,7 @@ class _TabHomePageState extends State<TabHomePage>
// initialize global function and reusable widget
final _reusableWidget = ReusableWidget();
// _listKey is used for AnimatedList
final GlobalKey<AnimatedListState> _listKey = GlobalKey();
late StreamSubscription subVisitPhotoCountEvent;
// keep the state to do not refresh when switch navbar
@override
@ -42,8 +48,8 @@ class _TabHomePageState extends State<TabHomePage>
bool _isLoading = true;
String _errorMessage = '';
late List<VisiteModel> todayVisitsData = [];
late List<VisiteModel> previousVisitsData = [];
late List<VisiteModel> todayVisitData = [];
late List<VisiteModel> previousVisitData = [];
@override
void initState() {
@ -60,12 +66,32 @@ class _TabHomePageState extends State<TabHomePage>
loadData().then((_) {
setState(() {
_isLoading = false;
// Listen particular event
subVisitPhotoCountEvent =
eventBus.on<VisitPhotoCountEvent>().listen((e) {
setState(() {
for (int i = 0; i < todayVisitData.length; i++) {
if (todayVisitData[i].id_visite == e.id_visite) {
todayVisitData[i].photoCount = e.photoCount;
break;
}
}
for (int i = 0; i < previousVisitData.length; i++) {
if (previousVisitData[i].id_visite == e.id_visite) {
previousVisitData[i].photoCount = e.photoCount;
break;
}
}
});
});
});
});
}
@override
void dispose() {
subVisitPhotoCountEvent.cancel();
super.dispose();
}
@ -139,35 +165,48 @@ class _TabHomePageState extends State<TabHomePage>
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('Today Visits', style: GlobalStyle.horizontalTitle),
GestureDetector(
onTap: () {
//Navigator.push(context, MaterialPageRoute(builder: (context) => RestaurantListPage(title: 'Food Arround You')));
},
child: Text('View All',
style: GlobalStyle.viewAll, textAlign: TextAlign.end),
)
],
),
),
Container(
if (todayVisitData.length == 0)
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(height: 16), // Ajout de l'espace ici
Text('Aucune visite ce jour'),
ElevatedButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SyncCalendarPage()),
);
},
child: Text('Synchroniser'),
),
],
)
else
Container(
margin: EdgeInsets.only(top: 8),
height: boxImageSize * GlobalStyle.cardHeightMultiplication,
child: ListView.builder(
padding: EdgeInsets.symmetric(horizontal: 12),
scrollDirection: Axis.horizontal,
itemCount: todayVisitsData.length,
itemCount: todayVisitData.length,
itemBuilder: (BuildContext context, int index) {
return _reusableWidget.buildHorizontalVisitListCard(
context,
todayVisitsData[index],
);
return buildHorizontalVisitListCard(
context, todayVisitData[index]);
},
)),
),
),
],
);
}
Widget _builPreviousVisits(boxImageSize) {
if (previousVisitData.length == 0) {
return SizedBox.shrink(); // Rien ne sera affiché
}
return Column(
children: [
Container(
@ -176,38 +215,130 @@ class _TabHomePageState extends State<TabHomePage>
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('Previous Visits', style: GlobalStyle.horizontalTitle),
GestureDetector(
onTap: () {
//Navigator.push(context, MaterialPageRoute(builder: (context) => RestaurantListPage(title: 'Food Arround You')));
},
child: Text('View All',
style: GlobalStyle.viewAll, textAlign: TextAlign.end),
)
],
),
),
Container(
margin: EdgeInsets.only(top: 8),
height: boxImageSize * GlobalStyle.cardHeightMultiplication,
child: ListView.builder(
padding: EdgeInsets.symmetric(horizontal: 12),
scrollDirection: Axis.horizontal,
itemCount: previousVisitsData.length,
itemBuilder: (BuildContext context, int index) {
return _reusableWidget.buildHorizontalVisitListCard(
context, previousVisitsData[index]);
},
)),
margin: EdgeInsets.only(top: 8),
height: boxImageSize * GlobalStyle.cardHeightMultiplication,
child: ListView.builder(
padding: EdgeInsets.symmetric(horizontal: 12),
scrollDirection: Axis.horizontal,
itemCount: previousVisitData.length,
itemBuilder: (BuildContext context, int index) {
return buildHorizontalVisitListCard(
context, previousVisitData[index]);
},
),
),
],
);
}
Widget buildHorizontalVisitListCard(context, data) {
final double imageWidth = (MediaQuery.of(context).size.width / 2.3);
final double imageheight = (MediaQuery.of(context).size.width / 3.07);
return Container(
width: imageWidth,
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(6),
),
elevation: 2,
color: Colors.white,
child: GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: () {
Route route = MaterialPageRoute(
builder: (context) => VisitPhotoTypologyPage(
pp_id_distrib: data.id_distrib,
pp_langage: data.langage,
pp_id_visite: data.id_visite,
pp_name: data.name,
onRefreshVisit: (int photoCount) {},
),
);
Navigator.push(context, route);
},
child: Stack(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
ClipRRect(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(10),
topRight: Radius.circular(6)),
child: buildCacheNetworkImage(
width: imageWidth,
height: imageheight,
url: data.image)),
Container(
margin: EdgeInsets.all(8),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
height: 36,
child: Text(data.name,
style: GlobalStyle.cardTitle,
maxLines: 2,
overflow: TextOverflow.ellipsis),
),
],
),
),
],
),
Positioned(
bottom: 4,
right: 4, // alignement à droite
child: GestureDetector(
onTap: () {
// TODO si visite validée ce n'est pas la meme url (on il mettre date validation dans le json frederik
SharedPrefs().urlMP4 =
'${ApiConstants.baseUrl}/MobilePortal4/index.html#ajax/visite_modification.html?visite=${data.id_visite}';
eventBus.fire(UrlEvent(SharedPrefs().urlMP4));
},
child: Image.asset(
"assets/images/logo_mp4.png",
width: 24,
height: 24,
),
),
),
if (data.photoCount != 0)
Positioned(
bottom: 0,
left: 2, // alignement à gauche
child: Container(
margin: EdgeInsets.symmetric(vertical: 2),
child: badges.Badge(
badgeStyle: badges.BadgeStyle(
badgeColor: Colors.blue,
padding: EdgeInsets.all(data.photoCount >= 10 ? 2 : 6),
),
badgeContent: Text(data.photoCount.toString(),
style: TextStyle(color: Colors.white)),
child: Icon(Icons.camera_alt_sharp),
),
),
),
],
),
),
),
);
}
/// Initializes data when the page loads.
Future<void> loadData() async {
try {
// visite model initialisation
todayVisitsData = await VisiteModel.getAllVisites();
previousVisitsData = await VisiteModel.getAllVisites();
todayVisitData = await VisiteModel.getTodayVisit();
previousVisitData = await VisiteModel.getPreviousVisit();
} catch (e) {
// set errorMessage for debug
_errorMessage = 'Error loading visites : $e';

View File

@ -231,75 +231,4 @@ class ReusableWidget {
),
);
}
Widget buildHorizontalVisitListCard(context, data) {
final double imageWidth = (MediaQuery.of(context).size.width / 2.3);
final double imageheight = (MediaQuery.of(context).size.width / 3.07);
return Container(
width: imageWidth,
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(6),
),
elevation: 2,
color: Colors.white,
child: GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: () {
//Navigator.push(context, MaterialPageRoute(builder: (context) => DetailRestaurantPage()));
},
child: Stack(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
ClipRRect(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(10),
topRight: Radius.circular(6)),
child: buildCacheNetworkImage(
width: imageWidth,
height: imageheight,
url: data.image)),
Container(
margin: EdgeInsets.all(8),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
height: 36,
child: Text(data.name,
style: GlobalStyle.cardTitle,
maxLines: 2,
overflow: TextOverflow.ellipsis),
),
],
),
),
],
),
Positioned(
bottom: 4, //ajout de cette ligne pour placer l'icone en bas
right: 4, //ajout de cette ligne pour placer l'icone à droite
child: GestureDetector(
onTap: () {
// TODO si visite validée ce n'est pas la meme url (on il mettre date validation dans le json
SharedPrefs().urlMP4 =
'${ApiConstants.baseUrl}/MobilePortal4/index.html#ajax/visite_modification.html?visite=${data.id_visite}';
eventBus.fire(UrlEvent(SharedPrefs().urlMP4));
},
child: Image.asset(
"assets/images/logo_mp4.png",
width: 24,
height: 24,
),
),
),
],
),
),
),
);
}
}

View File

@ -0,0 +1,116 @@
import 'package:flutter/material.dart';
import 'package:mobdr/network/api_provider.dart';
class SyncCalendarPage extends StatefulWidget {
@override
_SyncCalendarPageState createState() => _SyncCalendarPageState();
}
class _SyncCalendarPageState extends State<SyncCalendarPage> {
bool _isSyncing = false;
bool _syncSuccessful = false;
String? _syncErrorMessage;
Future<void> _syncData() async {
setState(() {
_isSyncing = true;
});
final ApiProvider _apiProvider = ApiProvider();
final syncResult = await _apiProvider.SyncCalendar();
if (syncResult == 'OK') {
setState(() {
_isSyncing = false;
_syncSuccessful = true;
});
// Wait for 2 seconds before navigating back to the previous screen.
await Future.delayed(Duration(seconds: 2));
_popScreen();
} else {
setState(() {
_isSyncing = false;
_syncSuccessful = false;
_syncErrorMessage = syncResult;
});
}
}
void _popScreen() {
if (mounted) {
Navigator.of(context).pop();
}
}
@override
Widget build(BuildContext context) {
return WillPopScope(
// Disable the back button while the synchronization is in progress.
onWillPop: () async => !_isSyncing,
child: Scaffold(
appBar: AppBar(
title: Text('Synchronisation'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
if (!_isSyncing && !_syncSuccessful && _syncErrorMessage == null)
Text(
'Appuyez sur le bouton pour lancer la synchronisation.',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 18.0),
),
if (_isSyncing)
Text(
'Synchronisation en cours...',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 18.0),
),
if (_syncSuccessful)
Column(
children: [
Icon(Icons.check_circle, size: 100.0, color: Colors.green),
SizedBox(height: 16.0),
ElevatedButton(
onPressed: _popScreen,
child: Text('Synchronisation réussie'),
),
],
),
if (_syncErrorMessage != null)
Column(
children: [
Icon(Icons.error, size: 100.0, color: Colors.red),
SizedBox(height: 16.0),
Text(
_syncErrorMessage!,
textAlign: TextAlign.center,
style: TextStyle(fontSize: 18.0),
),
SizedBox(height: 16.0),
ElevatedButton(
onPressed: _isSyncing ? null : _syncData,
child: _isSyncing
? CircularProgressIndicator()
: Text('Relancer la synchronisation'),
),
],
),
if (!_isSyncing && !_syncSuccessful && _syncErrorMessage == null)
ElevatedButton(
onPressed: _isSyncing ? null : _syncData,
child: _isSyncing
? CircularProgressIndicator()
: Text('Lancer la synchronisation'),
),
],
),
),
),
);
}
}

332
lib/ui/visit/tab_visit.dart Normal file
View File

@ -0,0 +1,332 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:mobdr/main.dart';
import 'package:mobdr/config/constant.dart';
import 'package:mobdr/config/global_style.dart';
import 'package:mobdr/events.dart';
import 'package:mobdr/model/visite_model.dart';
import 'package:mobdr/ui/visit/visit_photo_typology.dart';
import 'package:mobdr/ui/reusable/cache_image_network.dart';
class TabVisitListPage extends StatefulWidget {
@override
_TabVisitListPageState createState() => _TabVisitListPageState();
}
class _TabVisitListPageState extends State<TabVisitListPage>
with AutomaticKeepAliveClientMixin {
// _listKey is used for AnimatedList
final GlobalKey<AnimatedListState> _listKey = GlobalKey();
// keep the state to do not refresh when switch navbar
@override
bool get wantKeepAlive => true;
bool _isLoading = true;
String _errorMessage = '';
late List<VisiteModel> modelData = [];
late StreamSubscription subVisitPhotoCountEvent;
@override
void initState() {
super.initState();
// Listen particular event
subVisitPhotoCountEvent = eventBus.on<VisitPhotoCountEvent>().listen((e) {
setState(() {
for (int i = 0; i < modelData.length; i++) {
if (modelData[i].id_visite == e.id_visite) {
modelData[i].photoCount = e.photoCount;
break;
}
}
});
});
loadData().then((_) {
setState(() {
_isLoading = false;
});
});
}
@override
void dispose() {
subVisitPhotoCountEvent.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
// if we used AutomaticKeepAliveClientMixin, we must call super.build(context);
super.build(context);
final double boxImageSize = (MediaQuery.of(context).size.width / 4);
if (_isLoading) {
return Center(child: CircularProgressIndicator());
} else if (modelData.isEmpty) {
return Center(
child: Text('Aucune visite trouvée.'),
);
}
return Scaffold(
appBar: AppBar(
iconTheme: IconThemeData(
color: GlobalStyle.appBarIconThemeColor,
),
elevation: GlobalStyle.appBarElevation,
title: Text(
'Visit List',
style: GlobalStyle.appBarTitle,
),
backgroundColor: GlobalStyle.appBarBackgroundColor,
systemOverlayStyle: GlobalStyle.appBarSystemOverlayStyle),
body: Column(children: [
Flexible(
child: AnimatedList(
key: _listKey,
initialItemCount: modelData.length,
physics: AlwaysScrollableScrollPhysics(),
itemBuilder: (context, index, animation) {
return _buildVisitelistCard(
modelData[index], boxImageSize, animation, index);
},
)),
Container(
padding: EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.grey,
offset: Offset(0.0, 1.0), //(x,y)
blurRadius: 2.0,
),
],
),
child: Row(
children: [
Container(
child: GestureDetector(
onTap: () {
// TODO functionality to be implemented
/*`
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ChatUsPage()));
*/
},
child: ClipOval(
child: Container(
color: SOFT_BLUE,
padding: EdgeInsets.all(9),
child: Icon(Icons.filter_list,
color: Colors.white, size: 16)),
),
),
),
SizedBox(
width: 10,
),
Expanded(
child: GestureDetector(
onTap: () {},
child: Container(
alignment: Alignment.center,
padding: EdgeInsets.fromLTRB(12, 8, 12, 8),
margin: EdgeInsets.only(right: 8),
decoration: BoxDecoration(
color: Colors.white,
border: Border.all(width: 1, color: SOFT_BLUE),
borderRadius: BorderRadius.all(Radius.circular(
10) // <--- border radius here
)),
child: Text('Synchronize ALL',
style: TextStyle(
color: SOFT_BLUE, fontWeight: FontWeight.bold)),
),
),
),
],
),
)
]));
}
Widget _buildVisitelistCard(
VisiteModel visiteData, boxImageSize, animation, index) {
return SizeTransition(
sizeFactor: animation,
child: GestureDetector(
onTap: () {
Route route = MaterialPageRoute(
builder: (context) => VisitPhotoTypologyPage(
pp_id_distrib: visiteData.id_distrib,
pp_langage: visiteData.langage,
pp_id_visite: visiteData.id_visite,
pp_name: visiteData.name,
onRefreshVisit: (int photoCount) {},
));
Navigator.push(context, route);
},
child: Container(
margin: EdgeInsets.fromLTRB(12, 6, 12, 0),
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
elevation: 2,
color: Colors.white,
child: Container(
margin: EdgeInsets.all(8),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(10)),
child: buildCacheNetworkImage(
width: boxImageSize,
height: boxImageSize,
url: visiteData.image,
),
),
SizedBox(
width: 10,
),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
margin: EdgeInsets.only(top: 5),
child: Row(
children: [
Text(visiteData.name,
style: TextStyle(
fontSize: 11, color: SOFT_GREY))
],
),
),
Container(height: 8),
Text(
visiteData.date,
style: GlobalStyle.productSale,
),
Container(
margin: EdgeInsets.only(top: 5),
child: Text(
'${visiteData.photoCount} Photo(s)',
style: GlobalStyle.productPrice,
),
),
Container(height: 8),
Container(
margin: EdgeInsets.only(top: 5),
child: Row(
children: [
Icon(
Icons.store,
color: SOFT_GREY,
size: 20,
),
Text(
' ' + visiteData.type_visite,
style: GlobalStyle.productName.copyWith(
fontSize: 13,
),
maxLines: 1,
overflow: TextOverflow.ellipsis,
)
],
),
),
],
),
)
],
),
Container(
margin: EdgeInsets.only(top: 12),
child: Row(
children: [
Expanded(
child: (visiteData.photoCount == 0)
? TextButton(
style: ButtonStyle(
minimumSize:
MaterialStateProperty.all(Size(0, 30)),
backgroundColor: MaterialStateProperty
.resolveWith<Color>(
(Set<MaterialState> states) =>
Colors.grey[300]!,
),
overlayColor: MaterialStateProperty.all(
Colors.transparent),
shape: MaterialStateProperty.all(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5.0),
)),
),
onPressed: null,
child: Text(
'Synchronize',
style: TextStyle(
color: Colors.grey[600],
fontWeight: FontWeight.bold,
fontSize: 13),
textAlign: TextAlign.center,
))
: OutlinedButton(
onPressed: () {},
style: ButtonStyle(
minimumSize: MaterialStateProperty.all(
Size(0, 30)),
overlayColor: MaterialStateProperty.all(
Colors.transparent),
shape: MaterialStateProperty.all(
RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(5.0),
)),
side: MaterialStateProperty.all(
BorderSide(
color: SOFT_BLUE, width: 1.0),
)),
child: Text(
'Synchronize',
style: TextStyle(
color: SOFT_BLUE,
fontWeight: FontWeight.bold,
fontSize: 13),
textAlign: TextAlign.center,
)),
),
],
),
)
],
),
),
),
),
),
);
}
/// Initializes data when the page loads.
Future<void> loadData() async {
try {
// data initialisation with today visits
modelData = await VisiteModel.getAllVisit();
} catch (e) {
// set errorMessage for debug
_errorMessage = 'Error loading visits : $e';
}
}
}

View File

@ -210,7 +210,7 @@ class _PhotoTagPageState extends State<PhotoTagPage> {
}
Future<void> loadData() async {
allTagsList = await objectbox.getVisiteTagsLabels(
allTagsList = await objectbox.getVisitTagsLabels(
widget.pp_id_distrib, widget.pp_langage);
_selectedTags = List<String>.from(widget.pp_currentTags);
}
@ -236,7 +236,7 @@ class _PhotoTagPageState extends State<PhotoTagPage> {
for (final tag in newTags) {
// insert new tag in the database
objectbox.addVisiteTag(0, distribId, tag, langage);
objectbox.addVisitTag(0, distribId, tag, langage);
}
}

View File

@ -1,11 +1,12 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:badges/badges.dart' as badges;
import 'package:mobdr/main.dart';
import 'package:mobdr/config/global_style.dart';
import 'package:mobdr/config/constant.dart';
import 'package:mobdr/db/box_photo_typology.dart';
import 'package:mobdr/ui/home/visit_photo_typology_list.dart';
import 'package:mobdr/ui/visit/visit_photo_typology_list.dart';
class VisitPhotoTypologyPage extends StatefulWidget {
final int pp_id_distrib;
@ -88,14 +89,15 @@ class _VisitPhotoTypologyPageState extends State<VisitPhotoTypologyPage> {
),
),
Container(
padding: EdgeInsets.symmetric(horizontal: 6, vertical: 4),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Colors.blue,
),
child: Text(
photoCount.toString(),
style: TextStyle(color: Colors.white),
margin: EdgeInsets.symmetric(vertical: 0, horizontal: 10),
child: badges.Badge(
badgeStyle: badges.BadgeStyle(
badgeColor: Colors.blue,
padding: EdgeInsets.all(photoCount >= 10 ? 2 : 6),
),
badgeContent: Text(photoCount.toString(),
style: TextStyle(color: Colors.white)),
child: Icon(Icons.camera_alt_sharp),
),
),
],

View File

@ -9,7 +9,7 @@ import 'package:mobdr/service/shared_prefs.dart';
import 'package:mobdr/config/global_style.dart';
import 'package:mobdr/main.dart';
import 'package:mobdr/ui/general/chat_us.dart';
import 'package:mobdr/ui/home/visit_photo_tag.dart';
import 'package:mobdr/ui/visit/visit_photo_tag.dart';
import 'package:mobdr/db/box_photo.dart';
import 'package:mobdr/db/box_photo_typology.dart';
@ -529,7 +529,7 @@ class _VisitPhotoTypologyDetailPageState
tagList = tags.isEmpty ? [] : _photo.tags.split(",");
// competitor initialization
_competitorsList = objectbox.getPhotoCompetitorList();
_competitorsList = objectbox.getEtabCompetitorList();
_competitor = "";
} catch (e) {
// set errorMessage for debug

View File

@ -17,8 +17,9 @@ import 'package:mobdr/service/shared_prefs.dart';
import 'package:mobdr/main.dart';
import 'package:mobdr/ui/reusable/global_widget.dart';
import 'package:mobdr/ui/home/photo_camera.dart';
import 'package:mobdr/ui/home/visite_photo_typology_detail.dart';
import 'package:mobdr/ui/visit/visit_photo_typology_detail.dart';
import 'package:mobdr/db/box_photo.dart';
import 'package:mobdr/events.dart';
// TODO Il faut supprimer les possibles photos du répertoire cache !
@ -59,6 +60,8 @@ class _VisitPhotoTypologyListPageState
Color _color1 = Color(0xff777777);
Color _color2 = Color(0xFF515151);
late int visitPhotoCount = 0;
// _listKey is used for AnimatedList
var _listKey = GlobalKey<AnimatedListState>();
@ -448,6 +451,9 @@ class _VisitPhotoTypologyListPageState
void loadData() {
_visitPhotoData = objectbox.getAllVisitTypologyPhotos(
widget.pp_id_visite, widget.pp_id_typologie);
// number of photos of the visit
visitPhotoCount = objectbox.getVisitPhotoCount(widget.pp_id_visite);
}
/// Removes the image at the specified [imageURL] from the cache of the [NetworkImage] provider.
@ -480,6 +486,14 @@ class _VisitPhotoTypologyListPageState
/// insert photo(s) in widget at the beginning (0)
_visitPhotoData.insertAll(0, addedPhotos);
/// if new photos are taken
if (addedPhotos.length > 0) {
visitPhotoCount += addedPhotos.length;
// a global refresh event is sent
eventBus
.fire(VisitPhotoCountEvent(widget.pp_id_visite, visitPhotoCount));
}
/// refresh widget
setState(() {
_listKey = GlobalKey();
@ -523,6 +537,11 @@ class _VisitPhotoTypologyListPageState
int removeIndex = index;
var removedItem = _visitPhotoData.removeAt(removeIndex);
// a global refresh event is sent
visitPhotoCount -= 1;
eventBus
.fire(VisitPhotoCountEvent(widget.pp_id_visite, visitPhotoCount));
// delete file on database
objectbox.delPhoto(removedItem.image_name);
@ -540,6 +559,7 @@ class _VisitPhotoTypologyListPageState
_listKey.currentState!.removeItem(removeIndex, builder);
Navigator.pop(context);
Fluttertoast.showToast(
msg: 'Photo has been deleted from your visit',
toastLength: Toast.LENGTH_SHORT);

View File

@ -41,6 +41,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.10.0"
badges:
dependency: "direct main"
description:
name: badges
sha256: "6e7f3ec561ec08f47f912cfe349d4a1707afdc8dda271e17b046aa6d42c89e77"
url: "https://pub.dev"
source: hosted
version: "3.1.1"
bloc:
dependency: transitive
description:

View File

@ -87,6 +87,9 @@ dependencies:
# https://pub.dev/packages/event_bus_plus/
event_bus_plus: ^0.6.1
# https://pub.dev/packages/badges
badges: ^3.1.1
dev_dependencies:
flutter_test:
sdk: flutter