Bug: Resfres VisitCount

release/mobdr-v0.0.1
Frédérik Benoist 2023-05-07 23:19:39 +02:00
parent 492851ffc9
commit 662838c8ec
17 changed files with 464 additions and 195 deletions

View File

@ -19,19 +19,19 @@ class VisitPhoto {
int photo_privee;
int photo_principale;
String tags;
int uploaded;
int id_concurrence_lien;
VisitPhoto(
{this.id = 0,
required this.id_visite,
required this.id_photo_typologie,
required this.image_name,
this.id_photo_mp4 = 0,
this.id_photo_mp4 = -1,
this.photo_privee = 0,
this.photo_principale = 0,
this.tags = '',
DateTime? date_photo,
this.uploaded = 0})
this.id_concurrence_lien = 0})
: date_photo = date_photo ?? DateTime.now();
static String? _photosDir = SharedPrefs().photosDir;
@ -56,7 +56,7 @@ class VisitPhoto {
int? photo_privee,
int? photo_principale,
String? tags,
int? uploaded,
int? id_concurrence_lien,
}) {
return VisitPhoto(
id: id ?? this.id,
@ -68,7 +68,7 @@ class VisitPhoto {
photo_privee: photo_privee ?? this.photo_privee,
photo_principale: photo_principale ?? this.photo_principale,
tags: tags ?? this.tags,
uploaded: uploaded ?? this.uploaded,
id_concurrence_lien: id_concurrence_lien ?? this.id_concurrence_lien,
);
}
/*

View File

@ -1,7 +1,7 @@
// ignore_for_file: prefer_const_constructors
import 'dart:ui';
import 'dart:developer' as developer;
//import 'dart:developer' as developer;
import 'dart:io';
import 'package:device_info_plus/device_info_plus.dart';
@ -43,6 +43,9 @@ Future<void> main() async {
objectbox = await ObjectBox.create();
int objectboxAddress = identityHashCode(objectbox);
print(objectboxAddress);
/// Log
objectbox.addLog('LOG', 'MOBDR', 'Ouverture application ', 0);

View File

@ -1,9 +1,10 @@
import 'package:intl/intl.dart';
import 'package:mobdr/main.dart';
class VisiteModel {
class VisitModel {
late int id;
late int id_distrib;
late int id_etab;
late int id_visite;
late String name;
late int photoCount;
@ -12,9 +13,10 @@ class VisiteModel {
late String type_visite;
late String langage;
VisiteModel(
VisitModel(
{required this.id,
required this.id_distrib,
required this.id_etab,
required this.id_visite,
required this.name,
required this.photoCount,
@ -23,14 +25,15 @@ class VisiteModel {
required this.type_visite,
required this.langage});
static Future<List<VisiteModel>> getTodayVisit() async {
static Future<List<VisitModel>> getTodayVisit() async {
// Retrieve all today visits from the database
final visites = await objectbox.getTodayVisit();
final visits = await objectbox.getTodayVisit();
// Map each retrieved visit to VisiteModel
final visiteModels = visites
.map((visite) => VisiteModel(
final visitModelList = visits
.map((visite) => VisitModel(
id_distrib: visite.id_distrib_visite,
id_etab: visite.id_etab,
id: visite.id,
id_visite: visite.id_visite,
name: visite.id_etab.toString() + ' - ' + visite.title,
@ -43,17 +46,18 @@ class VisiteModel {
.toList();
// Return the list of VisiteModel
return visiteModels;
return visitModelList;
}
static Future<List<VisiteModel>> getPreviousVisit() async {
static Future<List<VisitModel>> getPreviousVisit() async {
// Retrieve all previsous visits from the database
final visites = await objectbox.getPreviousVisit();
final visits = await objectbox.getPreviousVisit();
// Map each retrieved visit to VisiteModel
final visiteModels = visites
.map((visite) => VisiteModel(
final visitModelList = visits
.map((visite) => VisitModel(
id_distrib: visite.id_distrib_visite,
id_etab: visite.id_etab,
id: visite.id,
id_visite: visite.id_visite,
name: visite.id_etab.toString() + ' - ' + visite.title,
@ -66,17 +70,18 @@ class VisiteModel {
.toList();
// Return the list of VisiteModel
return visiteModels;
return visitModelList;
}
static Future<List<VisiteModel>> getAllVisit() async {
static Future<List<VisitModel>> getAllVisit() async {
// Retrieve all visits from the database
final visites = await objectbox.getAllVisit();
final visits = await objectbox.getAllVisit();
// Map each retrieved visit to VisiteModel
final visiteModels = visites
.map((visite) => VisiteModel(
final visitModelList = visits
.map((visite) => VisitModel(
id_distrib: visite.id_distrib_visite,
id_etab: visite.id_etab,
id: visite.id,
id_visite: visite.id_visite,
name: visite.id_etab.toString() + ' - ' + visite.title,
@ -89,6 +94,6 @@ class VisiteModel {
.toList();
// Return the list of VisiteModel
return visiteModels;
return visitModelList;
}
}

View File

@ -3,12 +3,18 @@ This is api provider
This page is used to get data from API
*/
import 'package:mobdr/config/constant.dart';
import 'package:mobdr/main.dart';
import 'package:mobdr/service/shared_prefs.dart';
import 'dart:io';
import 'package:dio/dio.dart';
import 'dart:convert';
import 'package:crypto/crypto.dart';
import 'package:path/path.dart' as path;
import 'package:http/http.dart' as http;
import 'package:http_parser/http_parser.dart';
import 'package:mobdr/config/constant.dart';
import 'package:mobdr/main.dart';
import 'package:mobdr/service/shared_prefs.dart';
class ApiProvider {
Dio dio = Dio();
@ -224,7 +230,7 @@ class ApiProvider {
ApiConstants.externalEndpoint +
ApiConstants.restEndpoint +
'/mobDR/visite/calendrier',
{"id_utilisateur": 6, "start": 20230101, "end": 20230501},
{"id_utilisateur": 6, "start": 20230101, "end": 20230531},
),
getCrud(
ApiConstants.baseUrl +
@ -338,6 +344,137 @@ class ApiProvider {
}
}
Future<int> uploadPhotoServlet(int id_visite, String photoPath) async {
try {
final url = Uri.parse(SERVLET_API);
final file = File(photoPath);
final bytes = await file.readAsBytes();
final multipartRequest = http.MultipartRequest('POST', url)
..fields['id_visite'] = id_visite.toString()
..files.add(http.MultipartFile.fromBytes(
'photo',
bytes,
filename: path.basename(photoPath),
contentType: MediaType('image', 'jpeg'),
));
final headers = {'Cookie': "pguid=${SharedPrefs().guid};"};
multipartRequest.headers.addAll(headers);
final response = await multipartRequest.send();
final responseString = await response.stream.bytesToString();
final jsonResponse = jsonDecode(responseString);
final idPhotoString = jsonResponse[0]['id_photo'];
final idPhoto = int.parse(idPhotoString);
return idPhoto;
} catch (e) {
print('Error uploading photo: $e');
return -1;
}
}
Future<bool> updatePhotoTypology(
int id_visite, int id_photo_mp4, int id_photo_typologie) async {
final url =
'${ApiConstants.baseUrl}${ApiConstants.mp4Endpoint}${ApiConstants.restEndpoint}/visite/$id_visite/photo/$id_photo_mp4/tri/typo';
final headers = {
'Content-Type': 'application/x-www-form-urlencoded',
'Accept': 'application/json',
'Cookie': 'pguid=${SharedPrefs().guid};',
};
final params = {
'id_typologie': id_photo_typologie.toString(),
};
final response =
await http.put(Uri.parse(url), headers: headers, body: params);
if (response.statusCode == 200) {
return true;
} else {
return false;
}
}
Future<bool> updatePhotoVisibility(int id_visite, int id_photo_mp4,
int photo_principale, int photo_privee) async {
final url =
'${ApiConstants.baseUrl}${ApiConstants.mp4Endpoint}${ApiConstants.restEndpoint}/visite/$id_visite/photo/$id_photo_mp4/tri/visibilite';
final headers = {
'Content-Type': 'application/x-www-form-urlencoded',
'Accept': 'application/json',
'Cookie': 'pguid=${SharedPrefs().guid};',
};
final params = {
'principale': photo_principale.toString(),
'privee': photo_privee.toString(),
};
final response =
await http.put(Uri.parse(url), headers: headers, body: params);
if (response.statusCode == 200) {
return true;
} else {
return false;
}
}
Future<bool> updatePhotoTags(
int id_visite, int id_photo_mp4, String tags) async {
final url =
'${ApiConstants.baseUrl}${ApiConstants.mp4Endpoint}${ApiConstants.restEndpoint}/visite/$id_visite/photo/$id_photo_mp4/tri/tags';
final headers = {
'Content-Type': 'application/x-www-form-urlencoded',
'Accept': 'application/json',
'Cookie': 'pguid=${SharedPrefs().guid};',
};
final params = {'tags': tags};
final response =
await http.put(Uri.parse(url), headers: headers, body: params);
if (response.statusCode == 200) {
return true;
} else {
return false;
}
}
Future<bool> updatePhotoConpetitor(
int id_visite, int id_photo_mp4, int id_concurrence_lien) async {
final url =
'${ApiConstants.baseUrl}${ApiConstants.mp4Endpoint}${ApiConstants.restEndpoint}/visite/$id_visite/photo/$id_photo_mp4/tri/concurrence';
final headers = {
'Content-Type': 'application/x-www-form-urlencoded',
'Accept': 'application/json',
'Cookie': 'pguid=${SharedPrefs().guid};',
};
final params = {
'id_concurrence_lien': id_concurrence_lien.toString(),
};
final response =
await http.put(Uri.parse(url), headers: headers, body: params);
if (response.statusCode == 200) {
return true;
} else {
return false;
}
}
Future<String> getExample(apiToken) async {
Response response;

View File

@ -224,7 +224,7 @@
},
{
"id": "13:6298506278273268036",
"lastPropertyId": "10:427077651567855068",
"lastPropertyId": "11:7594245284938827569",
"name": "VisitPhoto",
"properties": [
{
@ -274,8 +274,8 @@
"type": 9
},
{
"id": "10:427077651567855068",
"name": "uploaded",
"id": "11:7594245284938827569",
"name": "id_concurrence_lien",
"type": 6
}
],
@ -462,7 +462,8 @@
2059771745036116529,
102253757473665009,
1526411175344533047,
1603887098520719919
1603887098520719919,
427077651567855068
],
"retiredRelationUids": [],
"version": 1

View File

@ -4,7 +4,7 @@ import 'package:mobdr/db/box_etab.dart';
import 'package:mobdr/db/box_photo_competitor.dart';
import 'package:mobdr/db/box_visit.dart';
import 'package:mobdr/db/box_visit_tag.dart';
import 'package:mobdr/db/box_photo.dart';
import 'package:mobdr/db/box_visit_photo.dart';
import 'package:mobdr/db/box_photo_typology.dart';
import 'model.dart';
@ -236,9 +236,9 @@ class ObjectBox {
store.box<EtabCompetitor>().put(_Competitor);
}
List<EtabCompetitor> getEtabCompetitorList() {
List<EtabCompetitor> getEtabCompetitorList(int _id_etab) {
final query = etabCompetitorBox
.query(EtabCompetitor_.id_etab.equals(1417))
.query(EtabCompetitor_.id_etab.equals(_id_etab))
.order(EtabCompetitor_.nom)
.build();
final photoCompetitors = query.find();
@ -493,6 +493,31 @@ class ObjectBox {
return query.find();
}
// Retrieves a VisitPhoto object from the ObjectBox database with the specified visit ID.
///
/// Parameters:
/// _id_visite: The ID of the visit the photo belongs to.
///
/// Returns:
/// A VisitPhoto object, or null if no object is found.
List<VisitPhoto> getAllVisitPhotosByVisit(int id_visite) {
final query =
visitPhotoBox.query(VisitPhoto_.id_visite.equals(id_visite)).build();
return query.find();
}
/// Retrieves all VisitPhoto objects from the ObjectBox database.
///
/// Parameters:
/// None.
///
/// Returns:
/// A list of VisitPhoto objects, or an empty list if no objects are found.
List<VisitPhoto> getAllVisitPhotos() {
final query = visitPhotoBox.query().build();
return query.find();
}
/// Retrieves a Photo object from the ObjectBox database with the specified ID.
///
/// Parameters:
@ -500,8 +525,8 @@ class ObjectBox {
///
/// Returns:
/// A Photo object, or null if no object is found.
VisitPhoto? getPhotoById(int id_photo) {
final photo = visitPhotoBox.get(id_photo);
VisitPhoto? getPhotoById(int _id) {
final photo = visitPhotoBox.get(_id);
return photo;
}
@ -519,7 +544,28 @@ class ObjectBox {
.map((query) => query.find());
}
void delPhoto(String _name) {
/// Removes a VisitPhoto object from the ObjectBox database with the specified ID.
///
/// Parameters:
/// id: The ID of the VisitPhoto object to remove.
///
/// Returns:
/// None.
void delPhotoById(int id) {
if (visitPhotoBox.remove(id)) {
print("Supression photo :${id}");
} else
print("Supression photo :${id} KO");
}
/// Removes a VisitPhoto object from the ObjectBox database with the specified ID.
///
/// Parameters:
/// id: The NAME of the VisitPhoto object to remove.
///
/// Returns:
/// None.
void delPhotoByName(String _name) {
final query =
visitPhotoBox.query(VisitPhoto_.image_name.equals(_name)).build();
final results = query.find();
@ -543,6 +589,15 @@ class ObjectBox {
return builder.count();
}
void putPhotoIdMP4(int photoId, int id_photo_mp4) {
final photo = visitPhotoBox.get(photoId);
if (photo != null) {
final updatedPhoto = photo.copyWith(id_photo_mp4: id_photo_mp4);
visitPhotoBox.put(updatedPhoto);
}
}
Future<void> putPhotoTypologie(int photoId, int typologieId) async {
final photo = visitPhotoBox.get(photoId);
@ -573,6 +628,15 @@ class ObjectBox {
}
}
Future<void> putPhotoCompetitor(int photoId, int competitorId) async {
final photo = visitPhotoBox.get(photoId);
if (photo != null) {
final updatedPhoto = photo.copyWith(id_concurrence_lien: competitorId);
await visitPhotoBox.putAsync(updatedPhoto);
}
}
/* remettre les principal à zero
final queryBuilder = box.query(VisitPhoto_.Visit_id.equals(idVisite) & VisitPhoto_.photo_principale.equals(1));
final updatedPhotos = queryBuilder.build().find();

View File

@ -16,11 +16,11 @@ import 'package:objectbox_flutter_libs/objectbox_flutter_libs.dart';
import 'db/box_etab.dart';
import 'db/box_log.dart';
import 'db/box_photo.dart';
import 'db/box_photo_competitor.dart';
import 'db/box_photo_typology.dart';
import 'db/box_user.dart';
import 'db/box_visit.dart';
import 'db/box_visit_photo.dart';
import 'db/box_visit_tag.dart';
import 'model.dart';
@ -249,7 +249,7 @@ final _entities = <ModelEntity>[
ModelEntity(
id: const IdUid(13, 6298506278273268036),
name: 'VisitPhoto',
lastPropertyId: const IdUid(10, 427077651567855068),
lastPropertyId: const IdUid(11, 7594245284938827569),
flags: 0,
properties: <ModelProperty>[
ModelProperty(
@ -298,8 +298,8 @@ final _entities = <ModelEntity>[
type: 9,
flags: 0),
ModelProperty(
id: const IdUid(10, 427077651567855068),
name: 'uploaded',
id: const IdUid(11, 7594245284938827569),
name: 'id_concurrence_lien',
type: 6,
flags: 0)
],
@ -503,7 +503,8 @@ ModelDefinition getObjectBoxModel() {
2059771745036116529,
102253757473665009,
1526411175344533047,
1603887098520719919
1603887098520719919,
427077651567855068
],
retiredRelationUids: const [],
modelVersion: 5,
@ -760,7 +761,7 @@ ModelDefinition getObjectBoxModel() {
objectToFB: (VisitPhoto object, fb.Builder fbb) {
final image_nameOffset = fbb.writeString(object.image_name);
final tagsOffset = fbb.writeString(object.tags);
fbb.startTable(11);
fbb.startTable(12);
fbb.addInt64(0, object.id);
fbb.addInt64(1, object.id_visite);
fbb.addInt64(2, object.id_photo_typologie);
@ -770,7 +771,7 @@ ModelDefinition getObjectBoxModel() {
fbb.addInt64(6, object.photo_privee);
fbb.addInt64(7, object.photo_principale);
fbb.addOffset(8, tagsOffset);
fbb.addInt64(9, object.uploaded);
fbb.addInt64(10, object.id_concurrence_lien);
fbb.finish(fbb.endTable());
return object.id;
},
@ -796,8 +797,8 @@ ModelDefinition getObjectBoxModel() {
.vTableGet(buffer, rootOffset, 20, ''),
date_photo: DateTime.fromMillisecondsSinceEpoch(
const fb.Int64Reader().vTableGet(buffer, rootOffset, 12, 0)),
uploaded:
const fb.Int64Reader().vTableGet(buffer, rootOffset, 22, 0));
id_concurrence_lien:
const fb.Int64Reader().vTableGet(buffer, rootOffset, 24, 0));
return object;
}),
@ -1077,8 +1078,8 @@ class VisitPhoto_ {
static final tags =
QueryStringProperty<VisitPhoto>(_entities[6].properties[8]);
/// see [VisitPhoto.uploaded]
static final uploaded =
/// see [VisitPhoto.id_concurrence_lien]
static final id_concurrence_lien =
QueryIntegerProperty<VisitPhoto>(_entities[6].properties[9]);
}

View File

@ -130,4 +130,11 @@ class SharedPrefs {
set urlMP4(String value) {
_sharedPrefs.setString('urlMP4', value);
}
/// get/set onboarding visualizaton
int get onboarding => _sharedPrefs.getInt('key_onboarding') ?? 0;
set onboarding(int value) {
_sharedPrefs.setInt('key_onboarding', value);
}
}

View File

@ -50,7 +50,11 @@ class _HomePageState extends State<HomePage>
}
void _handleTabSelection() {
setState(() {});
// TODO a voir si on laisse setState ??
/*
setState(() {
});
*/
}
@override

View File

@ -18,7 +18,7 @@ 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/model/visit_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';
@ -48,8 +48,8 @@ class _TabHomePageState extends State<TabHomePage>
bool _isLoading = true;
String _errorMessage = '';
late List<VisiteModel> todayVisitData = [];
late List<VisiteModel> previousVisitData = [];
late List<VisitModel> todayVisitData = [];
late List<VisitModel> previousVisitData = [];
@override
void initState() {
@ -251,12 +251,7 @@ class _TabHomePageState extends State<TabHomePage>
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,
),
builder: (context) => VisitPhotoTypologyPage(pp_visitModel: data),
);
Navigator.push(context, route);
},
@ -336,8 +331,8 @@ class _TabHomePageState extends State<TabHomePage>
Future<void> loadData() async {
try {
// visite model initialisation
todayVisitData = await VisiteModel.getTodayVisit();
previousVisitData = await VisiteModel.getPreviousVisit();
todayVisitData = await VisitModel.getTodayVisit();
previousVisitData = await VisitModel.getPreviousVisit();
} catch (e) {
// set errorMessage for debug
_errorMessage = 'Error loading visites : $e';

View File

@ -1,5 +1,6 @@
import 'package:mobdr/ui/authentication/signin.dart';
import 'package:flutter/material.dart';
import 'package:mobdr/ui/authentication/signin.dart';
import 'package:mobdr/config/constant.dart';
import 'package:mobdr/library/flutter_overboard/overboard.dart';
import 'package:mobdr/library/flutter_overboard/page_model.dart';

View File

@ -1,10 +1,13 @@
import 'dart:async';
import 'package:mobdr/config/constant.dart';
import 'package:mobdr/ui/onboarding.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:mobdr/service/shared_prefs.dart';
import 'package:mobdr/config/constant.dart';
import 'package:mobdr/ui/onboarding.dart';
import 'package:mobdr/ui/authentication/signin.dart';
class SplashScreenPage extends StatefulWidget {
@override
_SplashScreenPageState createState() => _SplashScreenPageState();
@ -12,7 +15,7 @@ class SplashScreenPage extends StatefulWidget {
class _SplashScreenPageState extends State<SplashScreenPage> {
Timer? _timer;
int _second = 3; // set timer for 3 second and then direct to next page
int _second = 2; // set timer for 3 second and then direct to next page
void _startTimer() {
const period = const Duration(seconds: 1);
@ -22,10 +25,18 @@ class _SplashScreenPageState extends State<SplashScreenPage> {
});
if (_second == 0) {
_cancelFlashsaleTimer();
// for this example we will use pushReplacement because we want to go back to the list
Navigator.pushReplacement(
context, MaterialPageRoute(builder: (context) => OnBoardingPage()));
if (SharedPrefs().onboarding == 0) {
SharedPrefs().onboarding = 1;
// for this example we will use pushReplacement because we want to go back to the list
Navigator.pushReplacement(context,
MaterialPageRoute(builder: (context) => OnBoardingPage()));
} else {
// for this example we will use pushReplacement because we want to go back to the list
Navigator.pushReplacement(
context, MaterialPageRoute(builder: (context) => SigninPage()));
}
// if you use this splash screen on the very first time when you open the page, use below code
//Navigator.of(context).pushAndRemoveUntil(MaterialPageRoute(builder: (context) => OnBoardingPage()), (Route<dynamic> route) => false);
}

View File

@ -1,19 +1,16 @@
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:path/path.dart' as path;
import 'package:http/http.dart' as http;
import 'package:http_parser/http_parser.dart';
import 'package:mobdr/service/shared_prefs.dart';
import 'package:mobdr/config/constant.dart';
import 'package:mobdr/main.dart';
import 'package:mobdr/events.dart';
import 'package:mobdr/db/box_visit_photo.dart';
import 'package:mobdr/network/api_provider.dart';
class UploadPhotosPage extends StatefulWidget {
final int id_visite;
final List<String> photoPaths;
final int pp_id_visite;
UploadPhotosPage({required this.id_visite, required this.photoPaths});
UploadPhotosPage({required this.pp_id_visite});
@override
_UploadPhotosPageState createState() => _UploadPhotosPageState();
@ -25,29 +22,110 @@ class _UploadPhotosPageState extends State<UploadPhotosPage> {
int _totalUploaded = 0;
int _totalPhotos = 0;
late List<VisitPhoto> _photosList;
ApiProvider _apiProvider = ApiProvider();
@override
void initState() {
super.initState();
_totalPhotos = widget.photoPaths.length;
// "visit" mode
if (widget.pp_id_visite > 0) {
_photosList = objectbox.getAllVisitPhotosByVisit(widget.pp_id_visite);
_totalPhotos = _photosList.length;
// "all" mode
} else {
_photosList = objectbox.getAllVisitPhotos();
_totalPhotos = _photosList.length;
}
}
Future<void> _uploadPhotos() async {
void _uploadPhotos() async {
setState(() {
_isUploading = true;
_isFinished = false;
});
for (int i = 0; i < widget.photoPaths.length; i++) {
String photoPath = SharedPrefs().photosDir + "/" + widget.photoPaths[i];
//String filename = path.basename(photoPath);
// parse all photos
for (var photo in _photosList) {
int id_photo_mp4 = -1;
bool isUpdatePhotoTypologie = true;
bool isUpdatePhotoVisibility = true;
bool isUpdatePhotoCompetitor = true;
bool isUpdatePhotoTags = true;
// Upload the photo
int photoId = await uploadPhoto(photoPath);
// if photo not already uploaded
if (photo.id_photo_mp4 <= 0) {
// try upload the photo
id_photo_mp4 = await _apiProvider.uploadPhotoServlet(
photo.id_visite, photo.getImage());
} else
id_photo_mp4 = photo.id_photo_mp4;
if (photoId != -1) {
_totalUploaded++;
// the photo is saved in MP4
if (id_photo_mp4 > 0) {
// update photo typology
isUpdatePhotoTypologie = await _apiProvider.updatePhotoTypology(
photo.id_visite, id_photo_mp4, photo.id_photo_typologie);
// update photo visibility
if (photo.photo_principale == 1 || photo.photo_privee == 1) {
isUpdatePhotoVisibility = await _apiProvider.updatePhotoVisibility(
photo.id_visite,
id_photo_mp4,
photo.photo_principale,
photo.photo_privee);
}
// update photo tags
if (photo.tags.isNotEmpty) {
isUpdatePhotoTags = await _apiProvider.updatePhotoTags(
photo.id_visite, id_photo_mp4, photo.tags);
}
// update photo competitor
if (photo.id_concurrence_lien > 0) {
isUpdatePhotoCompetitor = await _apiProvider.updatePhotoConpetitor(
photo.id_visite, id_photo_mp4, photo.id_concurrence_lien);
}
}
if (id_photo_mp4 > 0 &&
isUpdatePhotoTypologie == true &&
isUpdatePhotoVisibility == true &&
isUpdatePhotoTags == true &&
isUpdatePhotoCompetitor == true) {
// delete photo in database
objectbox.delPhotoById(photo.id);
// delete the file
File file = File(photo.getImage());
if (await file.exists()) {
await file.delete();
}
_totalUploaded++;
} else {
// if successful upload
if (id_photo_mp4 != -1) {
photo.id_photo_mp4 = id_photo_mp4;
// save MP4 id in database
objectbox.putPhotoIdMP4(photo.id, id_photo_mp4);
}
}
//await Future.delayed(Duration(seconds: 5));
}
// Get unique id_visite values from _photosList
Set<int> uniqueIds = _photosList.map((photo) => photo.id_visite).toSet();
// Send VisitPhotoCountEvent for each unique id_visite
for (int id_visite in uniqueIds) {
eventBus.fire(VisitPhotoCountEvent(
id_visite, objectbox.getVisitPhotoCount(id_visite)));
}
setState(() {
@ -56,38 +134,6 @@ class _UploadPhotosPageState extends State<UploadPhotosPage> {
});
}
Future<int> uploadPhoto(String photoPath) async {
try {
final url = Uri.parse(SERVLET_API);
final file = File(photoPath);
final bytes = await file.readAsBytes();
final multipartRequest = http.MultipartRequest('POST', url)
..fields['id_visite'] = widget.id_visite.toString()
..files.add(http.MultipartFile.fromBytes(
'photo',
bytes,
filename: path.basename(photoPath),
contentType: MediaType('image', 'jpeg'),
));
final headers = {'Cookie': "pguid=${SharedPrefs().guid};"};
multipartRequest.headers.addAll(headers);
final response = await multipartRequest.send();
final responseString = await response.stream.bytesToString();
final jsonResponse = jsonDecode(responseString);
final idPhotoString = jsonResponse[0]['id_photo'];
final idPhoto = int.parse(idPhotoString);
return idPhoto;
} catch (e) {
print('Error uploading photo: $e');
return -1;
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
@ -175,9 +221,15 @@ class _UploadPhotosPageState extends State<UploadPhotosPage> {
Visibility(
visible: !_isUploading,
child: ElevatedButton(
child: Text('Upload Photos ($_totalUploaded / $_totalPhotos)'),
onPressed: _isFinished ? null : _uploadPhotos,
),
child:
Text('Upload Photos ($_totalUploaded / $_totalPhotos)'),
onPressed: _isFinished
? null
: () {
_uploadPhotos();
}
//,
),
),
],
),

View File

@ -5,7 +5,7 @@ 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/model/visit_model.dart';
import 'package:mobdr/ui/visit/visit_photo_typology.dart';
import 'package:mobdr/ui/reusable/cache_image_network.dart';
import 'package:mobdr/ui/sync/upload_photos.dart';
@ -27,7 +27,7 @@ class _TabVisitListPageState extends State<TabVisitListPage>
bool _isLoading = true;
String _errorMessage = '';
late List<VisiteModel> modelData = [];
late List<VisitModel> modelData = [];
late StreamSubscription subVisitPhotoCountEvent;
@ -134,7 +134,12 @@ class _TabVisitListPageState extends State<TabVisitListPage>
),
Expanded(
child: GestureDetector(
onTap: () {},
onTap: () {
Route route = MaterialPageRoute(
builder: (context) => UploadPhotosPage(pp_id_visite: 0),
);
Navigator.push(context, route);
},
child: Container(
alignment: Alignment.center,
padding: EdgeInsets.fromLTRB(12, 8, 12, 8),
@ -157,18 +162,14 @@ class _TabVisitListPageState extends State<TabVisitListPage>
]));
}
Widget _buildVisitelistCard(
VisiteModel visiteData, boxImageSize, animation, index) {
Widget _buildVisitelistCard(VisitModel data, 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));
builder: (context) =>
VisitPhotoTypologyPage(pp_visitModel: data));
Navigator.push(context, route);
},
child: Container(
@ -192,7 +193,7 @@ class _TabVisitListPageState extends State<TabVisitListPage>
child: buildCacheNetworkImage(
width: boxImageSize,
height: boxImageSize,
url: visiteData.image,
url: data.image,
),
),
SizedBox(
@ -206,20 +207,20 @@ class _TabVisitListPageState extends State<TabVisitListPage>
margin: EdgeInsets.only(top: 5),
child: Row(
children: [
Text(visiteData.name,
Text(data.name,
style: GlobalStyle.productPrice)
],
),
),
Container(height: 8),
Text(
visiteData.date,
data.date,
style: GlobalStyle.productSale,
),
Container(
margin: EdgeInsets.only(top: 5),
child: Text(
'${visiteData.photoCount} Photo(s)',
'${data.photoCount} Photo(s)',
style: GlobalStyle.productPrice,
),
),
@ -234,7 +235,7 @@ class _TabVisitListPageState extends State<TabVisitListPage>
size: 20,
),
Text(
' ' + visiteData.type_visite,
' ' + data.type_visite,
style: GlobalStyle.productName.copyWith(
fontSize: 13,
),
@ -254,7 +255,7 @@ class _TabVisitListPageState extends State<TabVisitListPage>
child: Row(
children: [
Expanded(
child: (visiteData.photoCount == 0)
child: (data.photoCount == 0)
? TextButton(
style: ButtonStyle(
minimumSize:
@ -284,11 +285,7 @@ class _TabVisitListPageState extends State<TabVisitListPage>
onPressed: () {
Route route = MaterialPageRoute(
builder: (context) => UploadPhotosPage(
id_visite: visiteData.id_visite,
photoPaths: [
'sim_1682957196322406.jpeg',
],
),
pp_id_visite: data.id_visite),
);
Navigator.push(context, route);
},
@ -331,7 +328,7 @@ class _TabVisitListPageState extends State<TabVisitListPage>
Future<void> loadData() async {
try {
// data initialisation with today visits
modelData = await VisiteModel.getAllVisit();
modelData = await VisitModel.getAllVisit();
} catch (e) {
// set errorMessage for debug
_errorMessage = 'Error loading visits : $e';

View File

@ -6,21 +6,15 @@ 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/model/visit_model.dart';
import 'package:mobdr/ui/visit/visit_photo_typology_list.dart';
class VisitPhotoTypologyPage extends StatefulWidget {
final int pp_id_distrib;
final String pp_langage;
final int pp_id_visite;
final String pp_name;
final VisitModel pp_visitModel;
VisitPhotoTypologyPage({
Key? key,
required this.pp_id_distrib,
required this.pp_langage,
required this.pp_id_visite,
required this.pp_name,
}) : super(key: key);
required this.pp_visitModel,
});
@override
_VisitPhotoTypologyPageState createState() => _VisitPhotoTypologyPageState();
@ -33,9 +27,7 @@ class _VisitPhotoTypologyPageState extends State<VisitPhotoTypologyPage> {
onTap: () {
Route route = MaterialPageRoute(
builder: (context) => VisitPhotoTypologyListPage(
pp_id_distrib: widget.pp_id_distrib,
pp_langage: widget.pp_langage,
pp_id_visite: widget.pp_id_visite,
pp_visitModel: widget.pp_visitModel,
pp_id_typologie:
PhotoTypology[index].id_photo_typologie,
pp_libelle_typologie: PhotoTypology[index].libelle,
@ -58,7 +50,7 @@ class _VisitPhotoTypologyPageState extends State<VisitPhotoTypologyPage> {
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
_buildBadge(
widget.pp_id_visite,
widget.pp_visitModel.id_visite,
PhotoTypology[index].id_photo_typologie,
PhotoTypology[index].libelle),
Icon(Icons.chevron_right, size: 20, color: SOFT_GREY),
@ -135,7 +127,7 @@ class _VisitPhotoTypologyPageState extends State<VisitPhotoTypologyPage> {
),
elevation: GlobalStyle.appBarElevation,
title: Text(
widget.pp_name,
widget.pp_visitModel.name,
style: GlobalStyle.appBarTitle,
),
backgroundColor: GlobalStyle.appBarBackgroundColor,

View File

@ -5,33 +5,29 @@ import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:mobdr/config/constant.dart';
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/visit/visit_photo_tag.dart';
import 'package:mobdr/db/box_photo.dart';
import 'package:mobdr/db/box_visit_photo.dart';
import 'package:mobdr/db/box_photo_typology.dart';
import 'package:mobdr/db/box_photo_competitor.dart';
import 'package:mobdr/model/visit_model.dart';
class VisitPhotoTypologyDetailPage extends StatefulWidget {
// variables corresponding to the data parameters
final int pp_id;
final int pp_id_distrib;
final String pp_langage;
final VisitModel pp_visitModel;
final int pp_imageId;
final String pp_image;
final int pp_id_typologie;
// Requiring data parameters
VisitPhotoTypologyDetailPage({
Key? key,
required this.pp_id,
required this.pp_id_distrib,
required this.pp_langage,
required this.pp_visitModel,
required this.pp_imageId,
required this.pp_image,
required this.pp_id_typologie,
}) : super(key: key);
});
@override
_VisitPhotoTypologyDetailPageState createState() =>
@ -60,7 +56,7 @@ class _VisitPhotoTypologyDetailPageState
void initState() {
super.initState();
loadData(widget.pp_id).then((_) {
loadData(widget.pp_imageId).then((_) {
setState(() {
_isLoading = false;
});
@ -228,13 +224,13 @@ class _VisitPhotoTypologyDetailPageState
Widget radioSize(String txt, int index) {
return GestureDetector(
onTap: () async {
// save photo typology in the database
objectbox.putPhotoTypologie(
widget.pp_id, _typologiesList[index].id_photo_typologie);
setState(() {
_typologyIndex = index;
});
// save photo typology in the database
objectbox.putPhotoTypologie(
widget.pp_imageId, _typologiesList[index].id_photo_typologie);
},
child: Container(
padding: EdgeInsets.fromLTRB(12, 8, 12, 8),
@ -267,7 +263,7 @@ class _VisitPhotoTypologyDetailPageState
});
// save photo visibilities in the database
objectbox.putPhotoVisibilities(widget.pp_id, _visibilities);
objectbox.putPhotoVisibilities(widget.pp_imageId, _visibilities);
},
child: Row(
children: [
@ -340,8 +336,8 @@ class _VisitPhotoTypologyDetailPageState
context,
MaterialPageRoute(
builder: (context) => PhotoTagPage(
pp_langage: widget.pp_langage,
pp_id_distrib: widget.pp_id_distrib,
pp_langage: widget.pp_visitModel.langage,
pp_id_distrib: widget.pp_visitModel.id_distrib,
pp_photoId: this._photo.id,
pp_currentTags: tagList),
),
@ -486,6 +482,11 @@ class _VisitPhotoTypologyDetailPageState
setState(() {
_competitor = competitor.nom;
});
// save photo competitor in the database
objectbox.putPhotoCompetitor(widget.pp_visitModel.id,
competitor.id_concurrence_lien);
Navigator.pop(context);
},
child: Container(
@ -529,7 +530,8 @@ class _VisitPhotoTypologyDetailPageState
tagList = tags.isEmpty ? [] : _photo.tags.split(",");
// competitor initialization
_competitorsList = objectbox.getEtabCompetitorList();
_competitorsList =
objectbox.getEtabCompetitorList(widget.pp_visitModel.id_etab);
_competitor = "";
} catch (e) {
// set errorMessage for debug

View File

@ -15,10 +15,11 @@ import 'package:path_provider/path_provider.dart';
import 'package:mobdr/config/constant.dart';
import 'package:mobdr/service/shared_prefs.dart';
import 'package:mobdr/main.dart';
import 'package:mobdr/db/box_visit_photo.dart';
import 'package:mobdr/model/visit_model.dart';
import 'package:mobdr/ui/reusable/global_widget.dart';
import 'package:mobdr/ui/home/photo_camera.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 !
@ -31,16 +32,12 @@ extension FileNameExtension on File {
}
class VisitPhotoTypologyListPage extends StatefulWidget {
final int pp_id_distrib;
final String pp_langage;
final int pp_id_visite;
final VisitModel pp_visitModel;
final int pp_id_typologie;
final String pp_libelle_typologie;
VisitPhotoTypologyListPage(
{required this.pp_id_distrib,
required this.pp_langage,
required this.pp_id_visite,
{required this.pp_visitModel,
required this.pp_id_typologie,
required this.pp_libelle_typologie});
@ -235,9 +232,8 @@ class _VisitPhotoTypologyListPageState
onTap: () {
Route route = MaterialPageRoute(
builder: (context) => VisitPhotoTypologyDetailPage(
pp_id: _visitPhotoData[index].id,
pp_id_distrib: widget.pp_id_distrib,
pp_langage: widget.pp_langage,
pp_imageId: _visitPhotoData[index].id,
pp_visitModel: widget.pp_visitModel,
pp_image: _visitPhotoData[index].getImage(),
pp_id_typologie: widget.pp_id_typologie,
));
@ -450,10 +446,11 @@ class _VisitPhotoTypologyListPageState
// TODO ƒuture void ?
void loadData() {
_visitPhotoData = objectbox.getAllVisitTypologyPhotos(
widget.pp_id_visite, widget.pp_id_typologie);
widget.pp_visitModel.id_visite, widget.pp_id_typologie);
// number of photos of the visit
visitPhotoCount = objectbox.getVisitPhotoCount(widget.pp_id_visite);
visitPhotoCount =
objectbox.getVisitPhotoCount(widget.pp_visitModel.id_visite);
}
/// Removes the image at the specified [imageURL] from the cache of the [NetworkImage] provider.
@ -475,7 +472,7 @@ class _VisitPhotoTypologyListPageState
/// to insert into database
_listPhotos.add(VisitPhoto(
id_visite: widget.pp_id_visite,
id_visite: widget.pp_visitModel.id_visite,
id_photo_typologie: widget.pp_id_typologie,
image_name: myPhoto.path.split('/').last));
}
@ -490,8 +487,8 @@ class _VisitPhotoTypologyListPageState
if (addedPhotos.length > 0) {
visitPhotoCount += addedPhotos.length;
// a global refresh event is sent
eventBus
.fire(VisitPhotoCountEvent(widget.pp_id_visite, visitPhotoCount));
eventBus.fire(VisitPhotoCountEvent(
widget.pp_visitModel.id_visite, visitPhotoCount));
}
/// refresh widget
@ -539,11 +536,11 @@ class _VisitPhotoTypologyListPageState
// a global refresh event is sent
visitPhotoCount -= 1;
eventBus
.fire(VisitPhotoCountEvent(widget.pp_id_visite, visitPhotoCount));
eventBus.fire(VisitPhotoCountEvent(
widget.pp_visitModel.id_visite, visitPhotoCount));
// delete file on database
objectbox.delPhoto(removedItem.image_name);
objectbox.delPhotoByName(removedItem.image_name);
// delete file on local storage
deleteFile(new File(removedItem.getImage()));