refactor: visit synchronisation
parent
f2f3bf22fa
commit
a42c0847b8
|
|
@ -1,3 +0,0 @@
|
|||
export 'example_bloc.dart';
|
||||
export 'example_event.dart';
|
||||
export 'example_state.dart';
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
import 'package:bloc/bloc.dart';
|
||||
import 'package:mobdr/network/api_provider.dart';
|
||||
import './bloc.dart';
|
||||
|
||||
class ExampleBloc extends Bloc<ExampleEvent, ExampleState> {
|
||||
ExampleBloc() : super(InitialExampleState()) {
|
||||
on<GetExample>(_getExample);
|
||||
on<PostExample>(_postExample);
|
||||
}
|
||||
}
|
||||
|
||||
void _getExample(GetExample event, Emitter<ExampleState> emit) async {
|
||||
ApiProvider _apiProvider = ApiProvider();
|
||||
|
||||
emit(ExampleWaiting());
|
||||
try {
|
||||
String data = await _apiProvider.getExample(event.apiToken);
|
||||
emit(GetExampleSuccess(exampleData: data));
|
||||
} catch (ex) {
|
||||
if (ex != 'cancel') {
|
||||
emit(ExampleError(errorMessage: ex.toString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _postExample(PostExample event, Emitter<ExampleState> emit) async {
|
||||
ApiProvider _apiProvider = ApiProvider();
|
||||
|
||||
emit(ExampleWaiting());
|
||||
try {
|
||||
String data = await _apiProvider.postExample(event.id, event.apiToken);
|
||||
emit(PostExampleSuccess(exampleData: data));
|
||||
} catch (ex) {
|
||||
if (ex != 'cancel') {
|
||||
emit(ExampleError(errorMessage: ex.toString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
import 'package:meta/meta.dart';
|
||||
|
||||
@immutable
|
||||
abstract class ExampleEvent {}
|
||||
|
||||
class GetExample extends ExampleEvent {
|
||||
final apiToken;
|
||||
GetExample({@required this.apiToken});
|
||||
}
|
||||
|
||||
class PostExample extends ExampleEvent {
|
||||
final String id;
|
||||
final apiToken;
|
||||
PostExample({required this.id, required this.apiToken});
|
||||
}
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
import 'package:meta/meta.dart';
|
||||
|
||||
@immutable
|
||||
abstract class ExampleState {}
|
||||
|
||||
class InitialExampleState extends ExampleState {}
|
||||
|
||||
class ExampleError extends ExampleState {
|
||||
final String errorMessage;
|
||||
|
||||
ExampleError({
|
||||
required this.errorMessage,
|
||||
});
|
||||
}
|
||||
|
||||
class ExampleWaiting extends ExampleState {}
|
||||
|
||||
class GetExampleSuccess extends ExampleState {
|
||||
final String exampleData;
|
||||
GetExampleSuccess({required this.exampleData});
|
||||
}
|
||||
|
||||
class PostExampleSuccess extends ExampleState {
|
||||
final String exampleData;
|
||||
PostExampleSuccess({required this.exampleData});
|
||||
}
|
||||
|
|
@ -71,7 +71,9 @@ Future<void> main() async {
|
|||
Wakelock.enable();
|
||||
|
||||
eventBus.on().listen((event) {
|
||||
LoggerUtil.logVerbose('${DateTime.now()} Event: $event');
|
||||
if (!(event is EmptyEvent)) {
|
||||
LoggerUtil.logNStackInfo('${DateTime.now()} Event: $event');
|
||||
}
|
||||
});
|
||||
|
||||
runApp(MyApp());
|
||||
|
|
|
|||
|
|
@ -54,8 +54,8 @@ class VisitModel {
|
|||
}
|
||||
|
||||
static Future<List<VisitModel>> getPreviousVisits() async {
|
||||
// Retrieve all previsous visits from the database
|
||||
final visits = await objectbox.getPreviousVisit();
|
||||
// Retrieve all previous visits from the database
|
||||
final visits = await objectbox.getActivePreviousVisit();
|
||||
|
||||
// Map each retrieved visit to VisiteModel
|
||||
final visitModelList = visits
|
||||
|
|
|
|||
|
|
@ -1,8 +1,3 @@
|
|||
/*
|
||||
This is api provider
|
||||
This page is used to get data from API
|
||||
*/
|
||||
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:dio/dio.dart';
|
||||
|
|
@ -11,10 +6,12 @@ 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:intl/intl.dart';
|
||||
|
||||
import 'package:mobdr/config/constant.dart';
|
||||
import 'package:mobdr/main.dart';
|
||||
import 'package:mobdr/service/shared_prefs.dart';
|
||||
import 'package:mobdr/service/logger_util.dart';
|
||||
|
||||
class ApiProvider {
|
||||
Dio dio = Dio();
|
||||
|
|
@ -210,6 +207,12 @@ class ApiProvider {
|
|||
|
||||
/// Synchronize all informations about store, competitor, calendar
|
||||
Future<String> SyncCalendar() async {
|
||||
DateTime now = DateTime.now();
|
||||
DateTime end = now.add(Duration(days: 7));
|
||||
|
||||
String formattedStartDate = DateFormat('yyyyMMdd').format(now);
|
||||
String formattedEndDate = DateFormat('yyyyMMdd').format(end);
|
||||
|
||||
try {
|
||||
final responseFutures = Future.wait([
|
||||
getCrud(
|
||||
|
|
@ -231,7 +234,11 @@ class ApiProvider {
|
|||
ApiConstants.externalEndpoint +
|
||||
ApiConstants.restEndpoint +
|
||||
'/mobDR/visite/calendrier',
|
||||
{"id_utilisateur": 6, "start": 20230101, "end": 20230531},
|
||||
{
|
||||
"id_utilisateur": SharedPrefs().id_utilisateur,
|
||||
"start": formattedStartDate,
|
||||
"end": formattedEndDate
|
||||
},
|
||||
),
|
||||
getCrud(
|
||||
ApiConstants.baseUrl +
|
||||
|
|
@ -313,38 +320,6 @@ class ApiProvider {
|
|||
}
|
||||
}
|
||||
|
||||
/// Synchronize "Photos"
|
||||
Future<String> SyncPhotos() async {
|
||||
Response response;
|
||||
|
||||
try {
|
||||
/// get "Photo typologies"
|
||||
response = await getCrud(
|
||||
ApiConstants.baseUrl +
|
||||
ApiConstants.externalEndpoint +
|
||||
ApiConstants.restEndpoint +
|
||||
'/mobDR/visite/typologie',
|
||||
null);
|
||||
|
||||
if (response.statusCode == STATUS_OK) {
|
||||
// remove all objects
|
||||
objectbox.PhotoTypologyBox.removeAll();
|
||||
|
||||
/// fill box "Photo typologies"
|
||||
objectbox.addPhotoTypologies(response.data['typologies']);
|
||||
}
|
||||
|
||||
/// all ok
|
||||
if (response.statusCode == STATUS_OK) {
|
||||
return 'OK';
|
||||
} else {
|
||||
return response.statusMessage ?? 'Unknow error ...';
|
||||
}
|
||||
} catch (ex) {
|
||||
return ex.toString(); // return ex.response!.data;
|
||||
}
|
||||
}
|
||||
|
||||
Future<int> uploadPhotoServlet(int id_visite, String photoPath) async {
|
||||
try {
|
||||
final url = Uri.parse(SERVLET_API);
|
||||
|
|
@ -476,161 +451,13 @@ class ApiProvider {
|
|||
}
|
||||
}
|
||||
|
||||
Future<String> getExample(apiToken) async {
|
||||
Response response;
|
||||
|
||||
response =
|
||||
await getConnect(ApiConstants.baseUrl + '/example/getData', apiToken);
|
||||
print('res : ' + response.toString());
|
||||
return response.data.toString();
|
||||
}
|
||||
|
||||
Future<String> postExample(String id, apiToken) async {
|
||||
Response response;
|
||||
|
||||
var postData = {'id': id};
|
||||
response = await postConnect(
|
||||
ApiConstants.baseUrl + '/example/postData', postData, apiToken);
|
||||
print('res : ' + response.toString());
|
||||
return response.data.toString();
|
||||
}
|
||||
/*
|
||||
Future<List<StudentModel>> getStudent(String sessionId, apiToken) async {
|
||||
var postData = {'session_id': sessionId};
|
||||
response = await postConnect(
|
||||
ApiConstants.baseUrl + '/student/getStudent', postData, apiToken);
|
||||
if (response.data['status'] == STATUS_OK) {
|
||||
List responseList = response.data['data'];
|
||||
List<StudentModel> listData =
|
||||
responseList.map((f) => StudentModel.fromJson(f)).toList();
|
||||
return listData;
|
||||
} else {
|
||||
throw response.data['msg'];
|
||||
/// Synchronize all informations about store, competitor, calendar
|
||||
Future<String> SyncLog() async {
|
||||
try {
|
||||
LoggerUtil.logNStacktackDebug("Synchronisation LOG à implementer !!");
|
||||
return 'OK';
|
||||
} catch (ex) {
|
||||
return ex.toString();
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
Future<List<dynamic>> addStudent(
|
||||
String sessionId,
|
||||
String studentName,
|
||||
String studentPhoneNumber,
|
||||
String studentGender,
|
||||
String studentAddress,
|
||||
apiToken) async {
|
||||
var postData = {
|
||||
'session_id': sessionId,
|
||||
'student_name': studentName,
|
||||
'student_phone_number': studentPhoneNumber,
|
||||
'student_gender': studentGender,
|
||||
'student_address': studentAddress,
|
||||
};
|
||||
Response response;
|
||||
|
||||
response = await postConnect(
|
||||
ApiConstants.baseUrl + '/student/addStudent', postData, apiToken);
|
||||
if (response.data['status'] == STATUS_OK) {
|
||||
List<dynamic> respList = [];
|
||||
respList.add(response.data['msg']);
|
||||
respList.add(response.data['data']['id']);
|
||||
return respList;
|
||||
} else {
|
||||
throw response.data['msg'];
|
||||
}
|
||||
}
|
||||
|
||||
Future<String> editStudent(
|
||||
String sessionId,
|
||||
int studentId,
|
||||
String studentName,
|
||||
String studentPhoneNumber,
|
||||
String studentGender,
|
||||
String studentAddress,
|
||||
apiToken) async {
|
||||
var postData = {
|
||||
'session_id': sessionId,
|
||||
'student_id': studentId,
|
||||
'student_name': studentName,
|
||||
'student_phone_number': studentPhoneNumber,
|
||||
'student_gender': studentGender,
|
||||
'student_address': studentAddress,
|
||||
};
|
||||
Response response;
|
||||
|
||||
response = await postConnect(
|
||||
ApiConstants.baseUrl + '/student/editStudent', postData, apiToken);
|
||||
if (response.data['status'] == STATUS_OK) {
|
||||
return response.data['msg'];
|
||||
} else {
|
||||
throw response.data['msg'];
|
||||
}
|
||||
}
|
||||
|
||||
Future<String> deleteStudent(
|
||||
String sessionId, int studentId, apiToken) async {
|
||||
var postData = {
|
||||
'session_id': sessionId,
|
||||
'student_id': studentId,
|
||||
};
|
||||
Response response;
|
||||
response = await postConnect(
|
||||
ApiConstants.baseUrl + '/student/deleteStudent', postData, apiToken);
|
||||
if (response.data['status'] == STATUS_OK) {
|
||||
return response.data['msg'];
|
||||
} else {
|
||||
throw response.data['msg'];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Future<List<LoginModel>> login2(
|
||||
String email, String password, apiToken) async {
|
||||
var postData = {
|
||||
'email': email,
|
||||
'password': password,
|
||||
};
|
||||
response = await postConnect(LOGIN_API, postData, apiToken);
|
||||
if (response.data['status'] == STATUS_OK) {
|
||||
List responseList = response.data['data'];
|
||||
List<LoginModel> listData =
|
||||
responseList.map((f) => LoginModel.fromJson(f)).toList();
|
||||
return listData;
|
||||
} else {
|
||||
throw response.data['msg'];
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
Future<List<ProductGridModel>> getProductGrid(
|
||||
String sessionId, String skip, String limit, apiToken) async {
|
||||
var postData = {'session_id': sessionId, 'skip': skip, 'limit': limit};
|
||||
response = await postConnect(PRODUCT_API, postData, apiToken);
|
||||
if (response.data['status'] == STATUS_OK) {
|
||||
List responseList = response.data['data'];
|
||||
//print('data : '+responseList.toString());
|
||||
List<ProductGridModel> listData =
|
||||
responseList.map((f) => ProductGridModel.fromJson(f)).toList();
|
||||
return listData;
|
||||
} else {
|
||||
throw response.data['msg'];
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
Future<List<ProductListviewModel>> getProductListview(
|
||||
String sessionId, String skip, String limit, apiToken) async {
|
||||
var postData = {'session_id': sessionId, 'skip': skip, 'limit': limit};
|
||||
response = await postConnect(PRODUCT_API, postData, apiToken);
|
||||
if (response.data['status'] == STATUS_OK) {
|
||||
List responseList = response.data['data'];
|
||||
//print('data : '+responseList.toString());
|
||||
List<ProductListviewModel> listData =
|
||||
responseList.map((f) => ProductListviewModel.fromJson(f)).toList();
|
||||
return listData;
|
||||
} else {
|
||||
throw response.data['msg'];
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ import 'package:mobdr/db/box_visit_tag.dart';
|
|||
import 'package:mobdr/db/box_visit_photo.dart';
|
||||
import 'package:mobdr/db/box_photo_typology.dart';
|
||||
|
||||
import 'package:mobdr/service/logger_util.dart';
|
||||
|
||||
import 'model.dart';
|
||||
import 'objectbox.g.dart'; // created by `flutter pub run build_runner build`
|
||||
|
||||
|
|
@ -270,7 +272,7 @@ class ObjectBox {
|
|||
return builder.find();
|
||||
}
|
||||
|
||||
List<Visit> getPreviousVisit() {
|
||||
List<Visit> getActivePreviousVisit() {
|
||||
// Get the previous date at midnight.
|
||||
final now = DateTime.now();
|
||||
final midnight = DateTime(now.year, now.month, now.day);
|
||||
|
|
@ -291,6 +293,24 @@ class ObjectBox {
|
|||
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 criteria, sorted by their date.
|
||||
final builder = visitBox
|
||||
.query(Visit_.date_visite.lessThan(millisecondsSinceEpoch))
|
||||
.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<Visit> parseVisit(List responseDataList) {
|
||||
final parsed = responseDataList.cast<Map<String, dynamic>>();
|
||||
|
|
@ -372,6 +392,33 @@ class ObjectBox {
|
|||
});
|
||||
}
|
||||
|
||||
Future<void> DeletePreviousVisitWithoutPhoto() async {
|
||||
final visits = getPreviousVisit();
|
||||
|
||||
for (final visit in visits) {
|
||||
final photoCount = getVisitPhotoCount(visit.id_visite);
|
||||
|
||||
if (photoCount == 0) {
|
||||
// Delete the visit
|
||||
delVisitById(visit.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Removes a Visito object from the ObjectBox database with the specified ID.
|
||||
///
|
||||
/// Parameters:
|
||||
/// id: The ID of the Visit object to remove.
|
||||
///
|
||||
/// Returns:
|
||||
/// None.
|
||||
void delVisitById(int id) {
|
||||
if (visitBox.remove(id)) {
|
||||
LoggerUtil.logNStacktackDebug("delete visit:${id}");
|
||||
} else
|
||||
LoggerUtil.logNStackError("delete visit:${id} KO");
|
||||
}
|
||||
|
||||
int getVisitCount() {
|
||||
return visitBox.count();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,319 +0,0 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:timelines/timelines.dart';
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:mobdr/config/global_style.dart';
|
||||
import 'package:mobdr/ui/reusable/reusable_widget.dart';
|
||||
import 'package:mobdr/network/api_provider.dart';
|
||||
import 'package:mobdr/main.dart';
|
||||
|
||||
const completeColor = Color(0xff5e6172);
|
||||
const inProgressColor = Color(0xff5ec792);
|
||||
const todoColor = Color(0xffd1d2d7);
|
||||
const failedColor = Colors.red;
|
||||
|
||||
class TabSyncPage extends StatefulWidget {
|
||||
@override
|
||||
_TabSyncPageState createState() => _TabSyncPageState();
|
||||
}
|
||||
|
||||
class _TabSyncPageState extends State<TabSyncPage>
|
||||
with AutomaticKeepAliveClientMixin {
|
||||
// initialize global function and reusable widget
|
||||
//final _globalFunction = GlobalFunction();
|
||||
final _reusableWidget = ReusableWidget();
|
||||
|
||||
final _processes = ['Btqs', 'Params', 'Visites', 'Photos', 'Logs'];
|
||||
|
||||
final ApiProvider _apiProvider =
|
||||
ApiProvider(); // TODO: A voir si bien positionné
|
||||
|
||||
// _listKey is used for AnimatedList
|
||||
//final GlobalKey<AnimatedListState> _listKey = GlobalKey();
|
||||
|
||||
int _processIndex = 1;
|
||||
|
||||
Color getColor(int index) {
|
||||
if (index == _processIndex) {
|
||||
return inProgressColor;
|
||||
} else if (index < _processIndex) {
|
||||
return completeColor;
|
||||
} else {
|
||||
return todoColor;
|
||||
}
|
||||
}
|
||||
|
||||
// keep the state to do not refresh when switch navbar
|
||||
@override
|
||||
bool get wantKeepAlive => true;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// if we used AutomaticKeepAliveClientMixin, we must call super.build(context);
|
||||
super.build(context);
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.white,
|
||||
appBar: AppBar(
|
||||
iconTheme: IconThemeData(
|
||||
color: GlobalStyle.appBarIconThemeColor,
|
||||
),
|
||||
elevation: GlobalStyle.appBarElevation,
|
||||
title: Text(
|
||||
'Synchronisation',
|
||||
style: GlobalStyle.appBarTitle,
|
||||
),
|
||||
backgroundColor: GlobalStyle.appBarBackgroundColor,
|
||||
systemOverlayStyle: GlobalStyle.appBarSystemOverlayStyle,
|
||||
bottom: _reusableWidget.bottomAppBar(),
|
||||
),
|
||||
body: Timeline.tileBuilder(
|
||||
theme: TimelineThemeData(
|
||||
direction: Axis.horizontal,
|
||||
connectorTheme: ConnectorThemeData(
|
||||
space: 30.0,
|
||||
thickness: 5.0,
|
||||
),
|
||||
),
|
||||
builder: TimelineTileBuilder.connected(
|
||||
connectionDirection: ConnectionDirection.before,
|
||||
itemExtentBuilder: (_, __) =>
|
||||
MediaQuery.of(context).size.width / _processes.length,
|
||||
oppositeContentsBuilder: (context, index) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(bottom: 15.0),
|
||||
child: Image.asset(
|
||||
'assets/images/process_timeline/status${index + 1}.png',
|
||||
width: 50.0,
|
||||
color: getColor(index),
|
||||
),
|
||||
);
|
||||
},
|
||||
contentsBuilder: (context, index) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(top: 15.0),
|
||||
child: Text(
|
||||
_processes[index],
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: getColor(index),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
indicatorBuilder: (_, index) {
|
||||
var color;
|
||||
var child;
|
||||
if (index == _processIndex) {
|
||||
color = inProgressColor;
|
||||
child = Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: CircularProgressIndicator(
|
||||
strokeWidth: 3.0,
|
||||
valueColor: AlwaysStoppedAnimation(Colors.white),
|
||||
),
|
||||
);
|
||||
} else if (index < _processIndex) {
|
||||
color = failedColor;
|
||||
child = Icon(
|
||||
Icons.cancel,
|
||||
color: Colors.white,
|
||||
size: 20.0,
|
||||
);
|
||||
} else {
|
||||
color = todoColor;
|
||||
}
|
||||
|
||||
if (index <= _processIndex) {
|
||||
return Stack(
|
||||
children: [
|
||||
CustomPaint(
|
||||
size: Size(30.0, 30.0),
|
||||
painter: _BezierPainter(
|
||||
color: color,
|
||||
drawStart: index > 0,
|
||||
drawEnd: index < _processIndex,
|
||||
),
|
||||
),
|
||||
DotIndicator(
|
||||
size: 30.0,
|
||||
color: color,
|
||||
child: child,
|
||||
),
|
||||
],
|
||||
);
|
||||
} else {
|
||||
return Stack(
|
||||
children: [
|
||||
CustomPaint(
|
||||
size: Size(15.0, 15.0),
|
||||
painter: _BezierPainter(
|
||||
color: color,
|
||||
drawEnd: index < _processes.length - 1,
|
||||
),
|
||||
),
|
||||
OutlinedDotIndicator(
|
||||
borderWidth: 4.0,
|
||||
color: color,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
},
|
||||
connectorBuilder: (_, index, type) {
|
||||
if (index > 0) {
|
||||
if (index == _processIndex) {
|
||||
final prevColor = getColor(index - 1);
|
||||
final color = getColor(index);
|
||||
List<Color> gradientColors;
|
||||
if (type == ConnectorType.start) {
|
||||
gradientColors = [Color.lerp(prevColor, color, 0.5)!, color];
|
||||
} else {
|
||||
gradientColors = [
|
||||
prevColor,
|
||||
Color.lerp(prevColor, color, 0.5)!
|
||||
];
|
||||
}
|
||||
return DecoratedLineConnector(
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
colors: gradientColors,
|
||||
),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return SolidLineConnector(
|
||||
color: getColor(index),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
itemCount: _processes.length,
|
||||
),
|
||||
),
|
||||
floatingActionButton: FloatingActionButton(
|
||||
child: Icon(Icons.chevron_right),
|
||||
onPressed: () async {
|
||||
var futures = [
|
||||
//_apiProvider.SyncEtablissements(),
|
||||
//_apiProvider.SyncVisites(),
|
||||
_apiProvider.SyncPhotos(),
|
||||
];
|
||||
|
||||
objectbox.etabBox.removeAll();
|
||||
objectbox.etabCompetitorBox.removeAll();
|
||||
objectbox.visitBox.removeAll();
|
||||
objectbox.visitTagBox.removeAll();
|
||||
objectbox.visitPhotoBox.removeAll();
|
||||
objectbox.PhotoTypologyBox.removeAll();
|
||||
|
||||
var results = await Future.wait(futures);
|
||||
|
||||
if (results[0] == 'OK') {
|
||||
print("SyncEtablissements OK");
|
||||
} else {
|
||||
print("SyncEtablissements Error:" + results[0]);
|
||||
}
|
||||
|
||||
if (results[1] == 'OK') {
|
||||
print("SyncVisites OK");
|
||||
} else {
|
||||
print("SyncVisites Error:" + results[1]);
|
||||
}
|
||||
|
||||
if (results[0] == 'OK') {
|
||||
print("SyncPhotos OK");
|
||||
} else {
|
||||
print("SyncPhotos Error:" + results[0]);
|
||||
}
|
||||
|
||||
///
|
||||
setState(() {
|
||||
_processIndex = (_processIndex + 1) % _processes.length;
|
||||
});
|
||||
},
|
||||
backgroundColor: inProgressColor,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// hardcoded bezier painter
|
||||
class _BezierPainter extends CustomPainter {
|
||||
const _BezierPainter({
|
||||
required this.color,
|
||||
this.drawStart = true,
|
||||
this.drawEnd = true,
|
||||
});
|
||||
|
||||
final Color color;
|
||||
final bool drawStart;
|
||||
final bool drawEnd;
|
||||
|
||||
Offset _offset(double radius, double angle) {
|
||||
return Offset(
|
||||
radius * cos(angle) + radius,
|
||||
radius * sin(angle) + radius,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void paint(Canvas canvas, Size size) {
|
||||
final paint = Paint()
|
||||
..style = PaintingStyle.fill
|
||||
..color = color;
|
||||
|
||||
final radius = size.width / 2;
|
||||
|
||||
var angle;
|
||||
var offset1;
|
||||
var offset2;
|
||||
|
||||
var path;
|
||||
|
||||
if (drawStart) {
|
||||
angle = 3 * pi / 4;
|
||||
offset1 = _offset(radius, angle);
|
||||
offset2 = _offset(radius, -angle);
|
||||
path = Path()
|
||||
..moveTo(offset1.dx, offset1.dy)
|
||||
..quadraticBezierTo(0.0, size.height / 2, -radius, radius)
|
||||
..quadraticBezierTo(0.0, size.height / 2, offset2.dx, offset2.dy)
|
||||
..close();
|
||||
|
||||
canvas.drawPath(path, paint);
|
||||
}
|
||||
if (drawEnd) {
|
||||
angle = -pi / 4;
|
||||
offset1 = _offset(radius, angle);
|
||||
offset2 = _offset(radius, -angle);
|
||||
|
||||
path = Path()
|
||||
..moveTo(offset1.dx, offset1.dy)
|
||||
..quadraticBezierTo(
|
||||
size.width, size.height / 2, size.width + radius, radius)
|
||||
..quadraticBezierTo(size.width, size.height / 2, offset2.dx, offset2.dy)
|
||||
..close();
|
||||
|
||||
canvas.drawPath(path, paint);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldRepaint(_BezierPainter oldDelegate) {
|
||||
return oldDelegate.color != color ||
|
||||
oldDelegate.drawStart != drawStart ||
|
||||
oldDelegate.drawEnd != drawEnd;
|
||||
}
|
||||
}
|
||||
|
|
@ -25,6 +25,7 @@ class _SynchronizationPageState extends State<SynchronizationPage>
|
|||
bool _backofficeSyncCompleted = false;
|
||||
bool _photosSyncCompleted = false;
|
||||
bool _logSyncCompleted = false;
|
||||
bool _syncLog = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
|
|
@ -134,16 +135,6 @@ class _SynchronizationPageState extends State<SynchronizationPage>
|
|||
}
|
||||
|
||||
_photosSyncCompleted = (_totalUploaded == _visitPhotosList.length);
|
||||
|
||||
// Get unique id_visite values from _photosList
|
||||
Set<int> uniqueIds =
|
||||
_visitPhotosList.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)));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _cleanVisitPhotoDir() async {
|
||||
|
|
@ -221,8 +212,15 @@ class _SynchronizationPageState extends State<SynchronizationPage>
|
|||
// upload photo to server
|
||||
await _uploadVisitPhotos(_apiProvider);
|
||||
|
||||
// TODO:
|
||||
// supprimer les visites "ancienne" sans photo !!
|
||||
final syncLogResult = _syncLog ? await _apiProvider.SyncCalendar() : 'OK';
|
||||
|
||||
// log synchronization OK ?
|
||||
if (syncLogResult == 'OK') {
|
||||
_logSyncCompleted = true;
|
||||
}
|
||||
|
||||
// delete visits without a photo!
|
||||
await objectbox.DeletePreviousVisitWithoutPhoto();
|
||||
|
||||
// deletes photos that are no longer in any visits
|
||||
await _cleanVisitPhotoDir();
|
||||
|
|
@ -234,10 +232,7 @@ class _SynchronizationPageState extends State<SynchronizationPage>
|
|||
SharedPrefs().lastCalendarRefresh =
|
||||
DateFormat('dd/MM/yyyy HH:mm').format(DateTime.now());
|
||||
|
||||
// TODO: je pense que comme il y a cet event (qui reload tout) on est plus obligé
|
||||
// de lancer l'autre évent pour les count() de photo.
|
||||
//
|
||||
// de plus il faut supprimer les visites qui n'ont plus de photo !!!
|
||||
// send global event to refresh calendar
|
||||
eventBus.fire(RefreshCalendarEvent(SharedPrefs().lastCalendarRefresh));
|
||||
|
||||
setState(() {
|
||||
|
|
@ -312,7 +307,25 @@ class _SynchronizationPageState extends State<SynchronizationPage>
|
|||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
SizedBox(height: 30),
|
||||
SizedBox(height: 10),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
Text(
|
||||
'Sync Logs',
|
||||
style: TextStyle(fontSize: 16),
|
||||
),
|
||||
Switch(
|
||||
value: _syncLog,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
_syncLog = value;
|
||||
});
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 20),
|
||||
SyncItem(
|
||||
icon: Icons.business,
|
||||
title: 'Backoffice',
|
||||
|
|
|
|||
Loading…
Reference in New Issue