diff --git a/assets/images/simulator.jpeg b/assets/images/simulator.jpeg
new file mode 100644
index 0000000..fb272dd
Binary files /dev/null and b/assets/images/simulator.jpeg differ
diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index a1618e5..8a9a4b2 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -1,4 +1,8 @@
PODS:
+ - camera_avfoundation (0.0.1):
+ - Flutter
+ - device_info_plus (0.0.1):
+ - Flutter
- Flutter (1.0.0)
- fluttertoast (0.0.2):
- Flutter
@@ -6,6 +10,8 @@ PODS:
- FMDB (2.7.5):
- FMDB/standard (= 2.7.5)
- FMDB/standard (2.7.5)
+ - image_picker_ios (0.0.1):
+ - Flutter
- ObjectBox (1.8.1)
- objectbox_flutter_libs (0.0.1):
- Flutter
@@ -15,6 +21,8 @@ PODS:
- path_provider_foundation (0.0.1):
- Flutter
- FlutterMacOS
+ - permission_handler_apple (9.0.4):
+ - Flutter
- shared_preferences_foundation (0.0.1):
- Flutter
- FlutterMacOS
@@ -22,15 +30,22 @@ PODS:
- Flutter
- FMDB (>= 2.7.5)
- Toast (4.0.0)
+ - wakelock (0.0.1):
+ - Flutter
DEPENDENCIES:
+ - camera_avfoundation (from `.symlinks/plugins/camera_avfoundation/ios`)
+ - device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
- Flutter (from `Flutter`)
- fluttertoast (from `.symlinks/plugins/fluttertoast/ios`)
+ - image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
- objectbox_flutter_libs (from `.symlinks/plugins/objectbox_flutter_libs/ios`)
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/ios`)
+ - permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/ios`)
- sqflite (from `.symlinks/plugins/sqflite/ios`)
+ - wakelock (from `.symlinks/plugins/wakelock/ios`)
SPEC REPOS:
trunk:
@@ -39,32 +54,47 @@ SPEC REPOS:
- Toast
EXTERNAL SOURCES:
+ camera_avfoundation:
+ :path: ".symlinks/plugins/camera_avfoundation/ios"
+ device_info_plus:
+ :path: ".symlinks/plugins/device_info_plus/ios"
Flutter:
:path: Flutter
fluttertoast:
:path: ".symlinks/plugins/fluttertoast/ios"
+ image_picker_ios:
+ :path: ".symlinks/plugins/image_picker_ios/ios"
objectbox_flutter_libs:
:path: ".symlinks/plugins/objectbox_flutter_libs/ios"
package_info_plus:
:path: ".symlinks/plugins/package_info_plus/ios"
path_provider_foundation:
:path: ".symlinks/plugins/path_provider_foundation/ios"
+ permission_handler_apple:
+ :path: ".symlinks/plugins/permission_handler_apple/ios"
shared_preferences_foundation:
:path: ".symlinks/plugins/shared_preferences_foundation/ios"
sqflite:
:path: ".symlinks/plugins/sqflite/ios"
+ wakelock:
+ :path: ".symlinks/plugins/wakelock/ios"
SPEC CHECKSUMS:
+ camera_avfoundation: 3125e8cd1a4387f6f31c6c63abb8a55892a9eeeb
+ device_info_plus: e5c5da33f982a436e103237c0c85f9031142abed
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
fluttertoast: eb263d302cc92e04176c053d2385237e9f43fad0
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
+ image_picker_ios: 4a8aadfbb6dc30ad5141a2ce3832af9214a705b5
ObjectBox: a7900d5335218cd437cbc080b7ccc38a5211f7b4
objectbox_flutter_libs: 61d74196d924fbc773da5f5757d1e9fab7b3cc78
package_info_plus: 6c92f08e1f853dc01228d6f553146438dafcd14e
path_provider_foundation: c68054786f1b4f3343858c1e1d0caaded73f0be9
+ permission_handler_apple: 44366e37eaf29454a1e7b1b7d736c2cceaeb17ce
shared_preferences_foundation: 986fc17f3d3251412d18b0265f9c64113a8c2472
sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904
Toast: 91b396c56ee72a5790816f40d3a94dd357abc196
+ wakelock: d0fc7c864128eac40eba1617cb5264d9c940b46f
PODFILE CHECKSUM: b634fd49380cdd3837626153fb977533b1916433
diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist
index 1974f7b..f34142f 100644
--- a/ios/Runner/Info.plist
+++ b/ios/Runner/Info.plist
@@ -48,7 +48,10 @@
UIApplicationSupportsIndirectInputEvents
NSPhotoLibraryUsageDescription
+ Cette application a besoin de votre autorisation pour accéder à votre galerie photo afin que vous puissiez sélectionner des photos pour votre profil.
NSCameraUsageDescription
+ Cette application a besoin de votre autorisation pour accéder à votre caméra afin que vous puissiez prendre des photos pour votre profil.
NSMicrophoneUsageDescription
+ Cette application a besoin de votre autorisation pour accéder à votre microphone afin que vous puissiez enregistrer des messages audio pour envoyer à vos amis.
diff --git a/lib/db/box_photo.dart b/lib/db/box_photo.dart
index 5b24a28..8fc6b16 100644
--- a/lib/db/box_photo.dart
+++ b/lib/db/box_photo.dart
@@ -1,7 +1,9 @@
import 'package:objectbox/objectbox.dart';
-import 'package:mobdr/objectbox.g.dart';
import 'package:intl/intl.dart';
+import 'package:mobdr/objectbox.g.dart';
+import 'package:mobdr/service/shared_prefs.dart';
+
// ignore_for_file: public_member_api_docs
@Entity()
@@ -12,7 +14,6 @@ class Photo {
int id_visite;
int id_photo_typologie;
- String image;
String image_name;
DateTime date_photo;
int id_photo_mp4;
@@ -25,7 +26,6 @@ class Photo {
{this.id = 0,
required this.id_visite,
required this.id_photo_typologie,
- required this.image,
required this.image_name,
this.id_photo_mp4 = 0,
this.photo_privee = 0,
@@ -35,6 +35,15 @@ class Photo {
this.uploaded = 0})
: date_photo = date_photo ?? DateTime.now();
+ static String? _photosDir = SharedPrefs().photosDir;
+
+ String getImage() {
+ if (_photosDir == null) {
+ throw Exception('Photos directory not initialized');
+ }
+ return '$_photosDir/$image_name';
+ }
+
String get dateFormat => DateFormat('dd.MM.yyyy hh:mm:ss').format(date_photo);
Photo copyWith({
@@ -54,7 +63,6 @@ class Photo {
id: id ?? this.id,
id_visite: id_visite ?? this.id_visite,
id_photo_typologie: id_photo_typologie ?? this.id_photo_typologie,
- image: image ?? this.image,
image_name: image_name ?? this.image_name,
date_photo: date_photo ?? this.date_photo,
id_photo_mp4: id_photo_mp4 ?? this.id_photo_mp4,
diff --git a/lib/db/box_visite.dart b/lib/db/box_visite.dart
index cec182f..59bc27e 100644
--- a/lib/db/box_visite.dart
+++ b/lib/db/box_visite.dart
@@ -1,4 +1,3 @@
-import 'package:intl/intl.dart';
import 'package:objectbox/objectbox.dart';
import 'package:mobdr/objectbox.g.dart';
import 'package:mobdr/config/constant.dart';
@@ -20,6 +19,7 @@ class Visite {
int id_etab;
int abandon;
String url_photo_principale;
+ String langage;
Visite(
{this.id = 0,
@@ -31,7 +31,8 @@ class Visite {
required this.id_distrib_visite,
required this.id_etab,
required this.abandon,
- required this.url_photo_principale});
+ required this.url_photo_principale,
+ required this.langage});
Visite.fromJson(Map json)
: id_visite = json['id_visite'],
@@ -43,5 +44,6 @@ class Visite {
id_etab = json['id_etab'],
abandon = json['abandon'],
url_photo_principale =
- ApiConstants.baseUrl + json['url_photo_principale'];
+ ApiConstants.baseUrl + json['url_photo_principale'],
+ langage = 'fr';
}
diff --git a/lib/main.dart b/lib/main.dart
index 3a6a67f..d879d1d 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -1,17 +1,11 @@
// ignore_for_file: prefer_const_constructors
import 'dart:ui';
+import 'dart:developer' as developer;
import 'dart:io';
-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/cubit/language/initial_language.dart';
-
-import 'package:mobdr/service/shared_prefs.dart';
-
-import 'package:mobdr/ui/splash_screen.dart';
+import 'package:device_info_plus/device_info_plus.dart';
+import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
@@ -22,9 +16,19 @@ import 'package:path_provider/path_provider.dart';
import 'objectbox.dart';
import 'package:wakelock/wakelock.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/cubit/language/initial_language.dart';
+import 'package:mobdr/service/shared_prefs.dart';
+import 'package:mobdr/ui/splash_screen.dart';
+
/// Provides access to the ObjectBox Store throughout the app.
late ObjectBox objectbox;
+final DeviceInfoPlugin deviceInfoPlugin = DeviceInfoPlugin();
+
Future main() async {
// This is required so ObjectBox can get the application directory
// to store the database in.
@@ -62,6 +66,7 @@ class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
initDirectories();
+ initPlatformState();
// Initialize all bloc provider used on this entire application here
return MultiBlocProvider(
@@ -139,5 +144,193 @@ class MyApp extends StatelessWidget {
print(
'The "photos" directory has been created in the documents directory.');
}
+
+ // save directories into shared Prefs
+ SharedPrefs().documentsDir = documentsDir.path;
+ SharedPrefs().photosDir = photosDir.path;
+
+ // Get a list of all files in the "photos" directory
+ final List files = await photosDir.list().toList();
+
+ // Print out the names of the files in the directory
+ for (FileSystemEntity file in files) {
+ print('File name: ${file.path.split('/').last}');
+ }
+ }
+
+ Future initPlatformState() async {
+ var deviceData = {};
+
+ try {
+ if (kIsWeb) {
+ deviceData = _readWebBrowserInfo(await deviceInfoPlugin.webBrowserInfo);
+ } else {
+ if (Platform.isAndroid) {
+ deviceData =
+ _readAndroidBuildData(await deviceInfoPlugin.androidInfo);
+ } else if (Platform.isIOS) {
+ deviceData = _readIosDeviceInfo(await deviceInfoPlugin.iosInfo);
+ } else if (Platform.isLinux) {
+ deviceData = _readLinuxDeviceInfo(await deviceInfoPlugin.linuxInfo);
+ } else if (Platform.isMacOS) {
+ deviceData = _readMacOsDeviceInfo(await deviceInfoPlugin.macOsInfo);
+ } else if (Platform.isWindows) {
+ deviceData =
+ _readWindowsDeviceInfo(await deviceInfoPlugin.windowsInfo);
+ }
+ }
+
+ // save if we are on a simulator
+ if (deviceData['isPhysicalDevice'] == false) {
+ SharedPrefs().isSimulator = true;
+ }
+
+ print(deviceData);
+ } on PlatformException {
+ deviceData = {
+ 'Error:': 'Failed to get platform version.'
+ };
+ }
+ }
+
+ Map _readAndroidBuildData(AndroidDeviceInfo build) {
+ return {
+ 'version.securityPatch': build.version.securityPatch,
+ 'version.sdkInt': build.version.sdkInt,
+ 'version.release': build.version.release,
+ 'version.previewSdkInt': build.version.previewSdkInt,
+ 'version.incremental': build.version.incremental,
+ 'version.codename': build.version.codename,
+ 'version.baseOS': build.version.baseOS,
+ 'board': build.board,
+ 'bootloader': build.bootloader,
+ 'brand': build.brand,
+ 'device': build.device,
+ 'display': build.display,
+ 'fingerprint': build.fingerprint,
+ 'hardware': build.hardware,
+ 'host': build.host,
+ 'id': build.id,
+ 'manufacturer': build.manufacturer,
+ 'model': build.model,
+ 'product': build.product,
+ 'supported32BitAbis': build.supported32BitAbis,
+ 'supported64BitAbis': build.supported64BitAbis,
+ 'supportedAbis': build.supportedAbis,
+ 'tags': build.tags,
+ 'type': build.type,
+ 'isPhysicalDevice': build.isPhysicalDevice,
+ 'systemFeatures': build.systemFeatures,
+ 'displaySizeInches':
+ ((build.displayMetrics.sizeInches * 10).roundToDouble() / 10),
+ 'displayWidthPixels': build.displayMetrics.widthPx,
+ 'displayWidthInches': build.displayMetrics.widthInches,
+ 'displayHeightPixels': build.displayMetrics.heightPx,
+ 'displayHeightInches': build.displayMetrics.heightInches,
+ 'displayXDpi': build.displayMetrics.xDpi,
+ 'displayYDpi': build.displayMetrics.yDpi,
+ 'serialNumber': build.serialNumber,
+ };
+ }
+
+ Map _readIosDeviceInfo(IosDeviceInfo data) {
+ return {
+ 'name': data.name,
+ 'systemName': data.systemName,
+ 'systemVersion': data.systemVersion,
+ 'model': data.model,
+ 'localizedModel': data.localizedModel,
+ 'identifierForVendor': data.identifierForVendor,
+ 'isPhysicalDevice': data.isPhysicalDevice,
+ 'utsname.sysname:': data.utsname.sysname,
+ 'utsname.nodename:': data.utsname.nodename,
+ 'utsname.release:': data.utsname.release,
+ 'utsname.version:': data.utsname.version,
+ 'utsname.machine:': data.utsname.machine,
+ };
+ }
+
+ Map _readLinuxDeviceInfo(LinuxDeviceInfo data) {
+ return {
+ 'name': data.name,
+ 'version': data.version,
+ 'id': data.id,
+ 'idLike': data.idLike,
+ 'versionCodename': data.versionCodename,
+ 'versionId': data.versionId,
+ 'prettyName': data.prettyName,
+ 'buildId': data.buildId,
+ 'variant': data.variant,
+ 'variantId': data.variantId,
+ 'machineId': data.machineId,
+ };
+ }
+
+ Map _readWebBrowserInfo(WebBrowserInfo data) {
+ return {
+ 'browserName': describeEnum(data.browserName),
+ 'appCodeName': data.appCodeName,
+ 'appName': data.appName,
+ 'appVersion': data.appVersion,
+ 'deviceMemory': data.deviceMemory,
+ 'language': data.language,
+ 'languages': data.languages,
+ 'platform': data.platform,
+ 'product': data.product,
+ 'productSub': data.productSub,
+ 'userAgent': data.userAgent,
+ 'vendor': data.vendor,
+ 'vendorSub': data.vendorSub,
+ 'hardwareConcurrency': data.hardwareConcurrency,
+ 'maxTouchPoints': data.maxTouchPoints,
+ };
+ }
+
+ Map _readMacOsDeviceInfo(MacOsDeviceInfo data) {
+ return {
+ 'computerName': data.computerName,
+ 'hostName': data.hostName,
+ 'arch': data.arch,
+ 'model': data.model,
+ 'kernelVersion': data.kernelVersion,
+ 'majorVersion': data.majorVersion,
+ 'minorVersion': data.minorVersion,
+ 'patchVersion': data.patchVersion,
+ 'osRelease': data.osRelease,
+ 'activeCPUs': data.activeCPUs,
+ 'memorySize': data.memorySize,
+ 'cpuFrequency': data.cpuFrequency,
+ 'systemGUID': data.systemGUID,
+ };
+ }
+
+ Map _readWindowsDeviceInfo(WindowsDeviceInfo data) {
+ return {
+ 'numberOfCores': data.numberOfCores,
+ 'computerName': data.computerName,
+ 'systemMemoryInMegabytes': data.systemMemoryInMegabytes,
+ 'userName': data.userName,
+ 'majorVersion': data.majorVersion,
+ 'minorVersion': data.minorVersion,
+ 'buildNumber': data.buildNumber,
+ 'platformId': data.platformId,
+ 'csdVersion': data.csdVersion,
+ 'servicePackMajor': data.servicePackMajor,
+ 'servicePackMinor': data.servicePackMinor,
+ 'suitMask': data.suitMask,
+ 'productType': data.productType,
+ 'reserved': data.reserved,
+ 'buildLab': data.buildLab,
+ 'buildLabEx': data.buildLabEx,
+ 'digitalProductId': data.digitalProductId,
+ 'displayVersion': data.displayVersion,
+ 'editionId': data.editionId,
+ 'installDate': data.installDate,
+ 'productId': data.productId,
+ 'productName': data.productName,
+ 'registeredOwner': data.registeredOwner,
+ 'releaseId': data.releaseId,
+ 'deviceId': data.deviceId,
+ };
}
}
diff --git a/lib/model/photo_model.dart b/lib/model/photo_model.dart
index 80b06cb..f59d486 100644
--- a/lib/model/photo_model.dart
+++ b/lib/model/photo_model.dart
@@ -2,13 +2,11 @@ class PhotoModel {
late int id;
late int id_visite;
late int id_photo_typologie;
- late String image;
late String image_name;
PhotoModel(
{required this.id,
required this.id_visite,
required this.id_photo_typologie,
- required this.image,
required this.image_name});
}
diff --git a/lib/model/visite_model.dart b/lib/model/visite_model.dart
index 1ae3425..f32a88b 100644
--- a/lib/model/visite_model.dart
+++ b/lib/model/visite_model.dart
@@ -2,32 +2,25 @@ import 'package:mobdr/main.dart';
class VisiteModel {
late int id;
+ late int id_distrib;
+ late int id_visite;
late String name;
- late int photo;
+ late int photoCount;
late String date;
late String image;
late String type_visite;
- late double price;
- late double rating;
- late int review;
- late int sale;
- late int stock;
- late String location;
+ late String langage;
- VisiteModel({
- required this.id,
- required this.name,
- required this.photo,
- required this.date,
- required this.image,
- required this.type_visite,
- required this.price,
- required this.rating,
- required this.review,
- required this.sale,
- required this.stock,
- required this.location,
- });
+ VisiteModel(
+ {required this.id,
+ required this.id_distrib,
+ required this.id_visite,
+ required this.name,
+ required this.photoCount,
+ required this.date,
+ required this.image,
+ required this.type_visite,
+ required this.langage});
static Future> getAllVisites() async {
// Retrieve all visits from the database using the getAllVisites() method
@@ -36,18 +29,15 @@ class VisiteModel {
// 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.title,
- photo: 1,
+ photoCount: objectbox.getVisitPhotoCount(visite.id_visite),
date: visite.date_visite.toString(),
image: visite.url_photo_principale,
type_visite: visite.type_visite,
- price: 0,
- rating: 0,
- review: 0,
- sale: 0,
- stock: 10,
- location: ""))
+ langage: visite.langage))
.toList();
// Return the list of VisiteModel
diff --git a/lib/objectbox-model.json b/lib/objectbox-model.json
index d6ef092..b98ec04 100644
--- a/lib/objectbox-model.json
+++ b/lib/objectbox-model.json
@@ -195,7 +195,7 @@
},
{
"id": "7:8290500625256822711",
- "lastPropertyId": "13:1900114397693432703",
+ "lastPropertyId": "14:5831680857919010234",
"name": "Visite",
"properties": [
{
@@ -248,6 +248,11 @@
"id": "13:1900114397693432703",
"name": "url_photo_principale",
"type": 9
+ },
+ {
+ "id": "14:5831680857919010234",
+ "name": "langage",
+ "type": 9
}
],
"relations": []
@@ -332,11 +337,6 @@
"name": "uploaded",
"type": 6
},
- {
- "id": "15:1865824860595482227",
- "name": "image",
- "type": 9
- },
{
"id": "16:539065583624712715",
"name": "image_name",
@@ -404,7 +404,8 @@
5293139139799032553,
2141346538986140281,
7877546811840884522,
- 3784190804330297742
+ 3784190804330297742,
+ 1865824860595482227
],
"retiredRelationUids": [],
"version": 1
diff --git a/lib/objectbox.dart b/lib/objectbox.dart
index e5c7b44..83db299 100644
--- a/lib/objectbox.dart
+++ b/lib/objectbox.dart
@@ -8,9 +8,6 @@ import 'package:mobdr/db/box_photo.dart';
import 'package:mobdr/db/box_photo_typology.dart';
import 'model.dart';
-import 'package:mobdr/model/visite_model.dart';
-import 'package:mobdr/model/photo_model.dart';
-
import 'objectbox.g.dart'; // created by `flutter pub run build_runner build`
/// Provides access to the ObjectBox Store throughout the app.
@@ -66,6 +63,7 @@ class ObjectBox {
userBox.removeAll();
etabBox.removeAll();
concurrentBox.removeAll();
+
//visiteBox.removeAll();
//visiteTagBox.removeAll();
//photoBox.removeAll();
@@ -289,7 +287,8 @@ class ObjectBox {
int _id_etab,
int _abandon,
String _end,
- String _url_photo_principale) =>
+ String _url_photo_principale,
+ String _langage) =>
store.runInTransactionAsync(
TxMode.write,
_addVisiteInTx,
@@ -302,7 +301,8 @@ class ObjectBox {
id_distrib_visite: _id_distrib_visite,
id_etab: _id_etab,
abandon: _abandon,
- url_photo_principale: _url_photo_principale));
+ url_photo_principale: _url_photo_principale,
+ langage: _langage));
static void _addVisiteInTx(Store store, _Visite) {
store.box().put(_Visite);
@@ -367,15 +367,6 @@ class ObjectBox {
return visiteTagBox.count();
}
- Future putPhotoTags(int photoId, List tags) async {
- final photo = photoBox.get(photoId);
-
- if (photo != null) {
- final updatedPhoto = photo.copyWith(tags: tags.join(","));
- await photoBox.putAsync(updatedPhoto);
- }
- }
-
/// PHOTO --------------------------------------------------------------------
///
///
@@ -385,15 +376,14 @@ class ObjectBox {
return addedPhotos;
}
- Future addPhoto(int id_visite, int id_photo_typologie, String image,
- String image_name) =>
+ Future addPhoto(
+ int id_visite, int id_photo_typologie, String image_name) =>
store.runInTransactionAsync(
TxMode.write,
_addPhotoInTx,
Photo(
id_visite: id_visite,
id_photo_typologie: id_photo_typologie,
- image: image,
image_name: image_name));
static void _addPhotoInTx(Store store, _Photo) {
@@ -402,11 +392,13 @@ class ObjectBox {
store.box().put(_Photo);
}
- List getAllPhotos() {
+ List getAllVisitTypologyPhotos(
+ int id_visite, int _id_photo_typologie) {
// Query for all photos, sorted by their date.
// https://docs.objectbox.io/queries
final query = photoBox
- .query()
+ .query(Photo_.id_visite.equals(id_visite) &
+ Photo_.id_photo_typologie.equals(_id_photo_typologie))
.order(Photo_.date_photo, flags: Order.descending)
.build();
return query.find();
@@ -446,14 +438,58 @@ class ObjectBox {
}
}
- int getVisitPhotoCount(int _id_visite, int _id_Photo_typologie) {
+ int getVisitPhotoCount(int _id_visite) {
+ final builder = photoBox.query(Photo_.id_visite.equals(_id_visite)).build();
+ return builder.count();
+ }
+
+ int getVisitTypologiePhotoCount(int _id_visite, int _id_photo_typologie) {
final builder = photoBox
.query(Photo_.id_visite.equals(_id_visite) &
- Photo_.id_photo_typologie.equals(_id_Photo_typologie))
+ Photo_.id_photo_typologie.equals(_id_photo_typologie))
.build();
return builder.count();
}
+ Future putPhotoTypologie(int photoId, int typologieId) async {
+ final photo = photoBox.get(photoId);
+
+ if (photo != null) {
+ final updatedPhoto = photo.copyWith(id_photo_typologie: typologieId);
+ await photoBox.putAsync(updatedPhoto);
+ }
+ }
+
+ Future putPhotoTags(int photoId, List tags) async {
+ final photo = photoBox.get(photoId);
+
+ if (photo != null) {
+ final updatedPhoto = photo.copyWith(tags: tags.join(","));
+ await photoBox.putAsync(updatedPhoto);
+ }
+ }
+
+ Future putPhotoVisibilities(
+ int photoId, List visibilities) async {
+ final photo = photoBox.get(photoId);
+
+ if (photo != null) {
+ final updatedPhoto = photo.copyWith(
+ photo_principale: visibilities.contains('principal') ? 1 : 0,
+ photo_privee: visibilities.contains('private') ? 1 : 0);
+ await photoBox.putAsync(updatedPhoto);
+ }
+ }
+
+ /* remettre les principal à zero
+ final queryBuilder = box.query(Photo_.visite_id.equals(idVisite) & Photo_.photo_principale.equals(1));
+ final updatedPhotos = queryBuilder.build().find();
+ updatedPhotos.forEach((photo) {
+ photo.photo_principale = 0;
+ });
+ box.putMany(updatedPhotos);
+ */
+
/// PHOTO TYPOLOGY -----------------------------------------------------------
///
@@ -496,6 +532,13 @@ class ObjectBox {
.toList();
}
+ List getPhotoTypologiesList() {
+ final query = photoTypologyBox.query().order(PhotoTypology_.ordre).build();
+ final photoTypologies = query.find();
+
+ return photoTypologies.toList();
+ }
+
Stream> getPhotoTypologies() {
// Query for all Typologies, sorted by their order.
// https://docs.objectbox.io/queries
diff --git a/lib/objectbox.g.dart b/lib/objectbox.g.dart
index 51a7dd0..2932a61 100644
--- a/lib/objectbox.g.dart
+++ b/lib/objectbox.g.dart
@@ -220,7 +220,7 @@ final _entities = [
ModelEntity(
id: const IdUid(7, 8290500625256822711),
name: 'Visite',
- lastPropertyId: const IdUid(13, 1900114397693432703),
+ lastPropertyId: const IdUid(14, 5831680857919010234),
flags: 0,
properties: [
ModelProperty(
@@ -272,6 +272,11 @@ final _entities = [
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: [],
@@ -356,11 +361,6 @@ final _entities = [
name: 'uploaded',
type: 6,
flags: 0),
- ModelProperty(
- id: const IdUid(15, 1865824860595482227),
- name: 'image',
- type: 9,
- flags: 0),
ModelProperty(
id: const IdUid(16, 539065583624712715),
name: 'image_name',
@@ -443,7 +443,8 @@ ModelDefinition getObjectBoxModel() {
5293139139799032553,
2141346538986140281,
7877546811840884522,
- 3784190804330297742
+ 3784190804330297742,
+ 1865824860595482227
],
retiredRelationUids: const [],
modelVersion: 5,
@@ -669,7 +670,8 @@ ModelDefinition getObjectBoxModel() {
final titleOffset = fbb.writeString(object.title);
final url_photo_principaleOffset =
fbb.writeString(object.url_photo_principale);
- fbb.startTable(14);
+ 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);
@@ -680,6 +682,7 @@ ModelDefinition getObjectBoxModel() {
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;
},
@@ -705,9 +708,10 @@ ModelDefinition getObjectBoxModel() {
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, ''));
+ url_photo_principale: const fb.StringReader(asciiOptimization: true)
+ .vTableGet(buffer, rootOffset, 28, ''),
+ langage:
+ const fb.StringReader(asciiOptimization: true).vTableGet(buffer, rootOffset, 30, ''));
return object;
}),
@@ -757,7 +761,6 @@ ModelDefinition getObjectBoxModel() {
object.id = id;
},
objectToFB: (Photo object, fb.Builder fbb) {
- final imageOffset = fbb.writeString(object.image);
final image_nameOffset = fbb.writeString(object.image_name);
final tagsOffset = fbb.writeString(object.tags);
fbb.startTable(18);
@@ -769,7 +772,6 @@ ModelDefinition getObjectBoxModel() {
fbb.addInt64(7, object.photo_privee);
fbb.addInt64(8, object.photo_principale);
fbb.addInt64(13, object.uploaded);
- fbb.addOffset(14, imageOffset);
fbb.addOffset(15, image_nameOffset);
fbb.addOffset(16, tagsOffset);
fbb.finish(fbb.endTable());
@@ -785,8 +787,6 @@ ModelDefinition getObjectBoxModel() {
const fb.Int64Reader().vTableGet(buffer, rootOffset, 8, 0),
id_photo_typologie:
const fb.Int64Reader().vTableGet(buffer, rootOffset, 10, 0),
- image: const fb.StringReader(asciiOptimization: true)
- .vTableGet(buffer, rootOffset, 32, ''),
image_name: const fb.StringReader(asciiOptimization: true)
.vTableGet(buffer, rootOffset, 34, ''),
id_photo_mp4:
@@ -990,6 +990,10 @@ class Visite_ {
/// see [Visite.url_photo_principale]
static final url_photo_principale =
QueryStringProperty(_entities[5].properties[9]);
+
+ /// see [Visite.langage]
+ static final langage =
+ QueryStringProperty(_entities[5].properties[10]);
}
/// [VisiteTag] entity fields to define ObjectBox queries.
@@ -1047,15 +1051,12 @@ class Photo_ {
static final uploaded =
QueryIntegerProperty(_entities[7].properties[7]);
- /// see [Photo.image]
- static final image = QueryStringProperty(_entities[7].properties[8]);
-
/// see [Photo.image_name]
static final image_name =
- QueryStringProperty(_entities[7].properties[9]);
+ QueryStringProperty(_entities[7].properties[8]);
/// see [Photo.tags]
- static final tags = QueryStringProperty(_entities[7].properties[10]);
+ static final tags = QueryStringProperty(_entities[7].properties[9]);
}
/// [PhotoTypology] entity fields to define ObjectBox queries.
diff --git a/lib/service/shared_prefs.dart b/lib/service/shared_prefs.dart
index a48a33c..1ccb2c6 100644
--- a/lib/service/shared_prefs.dart
+++ b/lib/service/shared_prefs.dart
@@ -102,4 +102,25 @@ class SharedPrefs {
set id_visite(int value) {
_sharedPrefs.setInt('key_id_visite', value);
}
+
+ /// get/set isSimulator
+ bool get isSimulator => _sharedPrefs.getBool('key_issimulator') ?? false;
+
+ set isSimulator(bool value) {
+ _sharedPrefs.setBool('key_issimulator', value);
+ }
+
+ /// get/set application's document directory
+ String get documentsDir => _sharedPrefs.getString('documentsDir') ?? "";
+
+ set documentsDir(String value) {
+ _sharedPrefs.setString('documentsDir', value);
+ }
+
+ /// get/set application's photo directory
+ String get photosDir => _sharedPrefs.getString('photosDir') ?? "";
+
+ set photosDir(String value) {
+ _sharedPrefs.setString('photosDir', value);
+ }
}
diff --git a/lib/ui/home/photo_typology.dart b/lib/ui/home/photo_typology.dart
deleted file mode 100644
index b71a078..0000000
--- a/lib/ui/home/photo_typology.dart
+++ /dev/null
@@ -1,102 +0,0 @@
-import 'dart:async';
-import 'package:mobdr/main.dart';
-import 'package:mobdr/config/global_style.dart';
-import 'package:mobdr/config/constant.dart';
-import 'package:flutter/material.dart';
-import 'package:mobdr/db/box_photo_typology.dart';
-import 'package:mobdr/ui/home/photo_list.dart';
-
-class PhotoTypologyPage extends StatefulWidget {
- @override
- _PhotoTypologyPageState createState() => _PhotoTypologyPageState();
-}
-
-class _PhotoTypologyPageState extends State {
- GestureDetector Function(BuildContext, int) _itemBuilder(
- List PhotoTypology) =>
- (BuildContext context, int index) => GestureDetector(
- onTap: () {
- Route route =
- MaterialPageRoute(builder: (context) => PhotoListPage());
- Navigator.push(context, route).then(onGoBack);
- },
-
- ///objectbox.noteBox.remove(PhotoTypology[index].id),
- child: Row(
- children: [
- Expanded(
- child: Container(
- decoration: const BoxDecoration(
- border:
- Border(bottom: BorderSide(color: Colors.black12))),
- child: Padding(
- padding: const EdgeInsets.symmetric(
- vertical: 15.0, horizontal: 10.0),
- child: Row(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
- children: [
- Text(
- PhotoTypology[index].libelle +
- " " +
- objectbox
- .getVisitPhotoCount(0,
- PhotoTypology[index].id_photo_typologie)
- .toString(),
- style: const TextStyle(
- fontSize: 15.0,
- ),
- // Provide a Key for the integration test
- key: Key('list_log_$index'),
- ),
- Icon(Icons.chevron_right, size: 20, color: SOFT_GREY),
- ],
- ),
- ),
- ),
- ),
- ],
- ),
- );
-
- @override
- void initState() {
- super.initState();
- }
-
- @override
- void dispose() {
- super.dispose();
- }
-
- FutureOr onGoBack(dynamic value) {
- //refreshData();
- setState(() {});
- }
-
- @override
- Widget build(BuildContext context) {
- return Scaffold(
- backgroundColor: Colors.white,
- appBar: AppBar(
- iconTheme: IconThemeData(
- color: GlobalStyle.appBarIconThemeColor,
- ),
- elevation: GlobalStyle.appBarElevation,
- title: Text(
- 'Visite de ...',
- style: GlobalStyle.appBarTitle,
- ),
- backgroundColor: GlobalStyle.appBarBackgroundColor,
- systemOverlayStyle: GlobalStyle.appBarSystemOverlayStyle),
- body: Column(children: [
- Expanded(
- child: StreamBuilder>(
- stream: objectbox.getPhotoTypologies(),
- builder: (context, snapshot) => ListView.builder(
- shrinkWrap: true,
- //padding: const EdgeInsets.symmetric(horizontal: 20.0),
- itemCount: snapshot.hasData ? snapshot.data!.length : 0,
- itemBuilder: _itemBuilder(snapshot.data ?? []))))
- ]));
- }
-}
diff --git a/lib/ui/home/tab_home.dart b/lib/ui/home/tab_home.dart
index ed8d123..3340acb 100644
--- a/lib/ui/home/tab_home.dart
+++ b/lib/ui/home/tab_home.dart
@@ -3,20 +3,20 @@ 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 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:flutter/material.dart';
+
+import 'package:shared_preferences/shared_preferences.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:flutter_bloc/flutter_bloc.dart';
-import 'package:flutter/material.dart';
-import 'package:shared_preferences/shared_preferences.dart';
-
import 'package:mobdr/service/shared_prefs.dart';
import 'package:mobdr/config/global_style.dart';
import 'package:mobdr/model/visite_model.dart';
import 'package:mobdr/ui/general/chat_us.dart';
import 'package:mobdr/ui/general/notification.dart';
-import 'package:mobdr/ui/home/photo_typology.dart';
-import 'package:mobdr/ui/general/product_detail/product_detail.dart';
+import 'package:mobdr/ui/home/visit_photo_typology.dart';
import 'package:mobdr/ui/reusable/reusable_widget.dart';
import 'package:mobdr/ui/reusable/cache_image_network.dart';
@@ -44,7 +44,7 @@ class _TabHomePageState extends State
bool _isLoading = true;
String _errorMessage = '';
- late List visiteData = [];
+ late List modelData = [];
@override
void initState() {
@@ -91,7 +91,7 @@ class _TabHomePageState extends State
final double boxImageSize = (MediaQuery.of(context).size.width / 4);
if (_isLoading) {
return Center(child: CircularProgressIndicator());
- } else if (visiteData.isEmpty) {
+ } else if (modelData.isEmpty) {
return Center(
child: Text('Aucune visite trouvée.'),
);
@@ -127,11 +127,11 @@ class _TabHomePageState extends State
),
body: AnimatedList(
key: _listKey,
- initialItemCount: visiteData.length,
+ initialItemCount: modelData.length,
physics: AlwaysScrollableScrollPhysics(),
itemBuilder: (context, index, animation) {
return _buildVisitelistCard(
- visiteData[index], boxImageSize, animation, index);
+ modelData[index], boxImageSize, animation, index);
},
));
}
@@ -142,41 +142,44 @@ class _TabHomePageState extends State
sizeFactor: animation,
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: [
- GestureDetector(
- onTap: () {
- Navigator.push(
- context,
- MaterialPageRoute(
- builder: (context) => ProductDetailPage(
- name: visiteData.name,
- image: visiteData.image,
- price: visiteData.price,
- photo: visiteData.photo,
- rating: visiteData.rating,
- review: visiteData.review,
- sale: visiteData.sale,
- date: visiteData.date)));
- },
- child: Row(
+ 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) {
+ setState(() {
+ modelData[index].photoCount = photoCount;
+ });
+ },
+ ));
+ Navigator.push(context, route);
+ },
+ 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: [
ClipRRect(
- borderRadius: BorderRadius.all(Radius.circular(10)),
- child: buildCacheNetworkImage(
- width: boxImageSize,
- height: boxImageSize,
- url: visiteData.image)),
+ borderRadius: BorderRadius.all(Radius.circular(10)),
+ child: buildCacheNetworkImage(
+ width: boxImageSize,
+ height: boxImageSize,
+ url: visiteData.image,
+ ),
+ ),
SizedBox(
width: 10,
),
@@ -187,34 +190,45 @@ class _TabHomePageState extends State
Container(height: 8),
Text(
visiteData.name,
- style: GlobalStyle.productName
- .copyWith(fontSize: 13),
+ style: GlobalStyle.productName.copyWith(
+ fontSize: 13,
+ ),
maxLines: 3,
overflow: TextOverflow.ellipsis,
),
Container(
margin: EdgeInsets.only(top: 5),
- child: Text(visiteData.date,
- style: GlobalStyle.productSale),
+ child: Text(
+ visiteData.date,
+ style: GlobalStyle.productSale,
+ ),
),
Container(height: 5),
Container(
margin: EdgeInsets.only(top: 5),
child: Text(
- visiteData.photo.toString() + ' Photo(s)',
- style: GlobalStyle.productPrice),
+ '${visiteData.photoCount} Photo(s)',
+ style: GlobalStyle.productPrice,
+ ),
),
Container(height: 5),
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)
+ Icon(
+ Icons.store,
+ color: SOFT_GREY,
+ size: 20,
+ ),
+ Text(
+ ' ' + visiteData.type_visite,
+ style: GlobalStyle.productName.copyWith(
+ fontSize: 13,
+ ),
+ maxLines: 1,
+ overflow: TextOverflow.ellipsis,
+ )
],
),
),
@@ -223,72 +237,8 @@ class _TabHomePageState extends State
)
],
),
- ),
- Container(
- margin: EdgeInsets.only(top: 12),
- child: Row(
- children: [
- Expanded(
- child: (visiteData.stock == 0)
- ? TextButton(
- style: ButtonStyle(
- minimumSize:
- MaterialStateProperty.all(Size(0, 30)),
- backgroundColor:
- MaterialStateProperty.resolveWith(
- (Set states) =>
- Colors.grey[300]!,
- ),
- overlayColor: MaterialStateProperty.all(
- Colors.transparent),
- shape: MaterialStateProperty.all(
- RoundedRectangleBorder(
- borderRadius: BorderRadius.circular(5.0),
- )),
- ),
- onPressed: null,
- child: Text(
- 'Out of Stock',
- style: TextStyle(
- color: Colors.grey[600],
- fontWeight: FontWeight.bold,
- fontSize: 13),
- textAlign: TextAlign.center,
- ))
- : OutlinedButton(
- onPressed: () {
- Navigator.push(
- context,
- MaterialPageRoute(
- builder: (context) =>
- PhotoTypologyPage()));
- },
- 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(
- AppLocalizations.of(context)!
- .translate('i18n_take_pictures')!,
- style: TextStyle(
- color: SOFT_BLUE,
- fontWeight: FontWeight.bold,
- fontSize: 13),
- textAlign: TextAlign.center,
- )),
- ),
- ],
- ),
- )
- ],
+ ],
+ ),
),
),
),
@@ -296,11 +246,21 @@ class _TabHomePageState extends State
);
}
- // data initialization on loading.
+ /// Called when a visit is refreshed with new photo count.
+ ///
+ /// [index]: The index of the visit being refreshed.
+ /// [newPhotoCount]: The new photo count for the visit.
+ void onRefreshVisit(int index, int newPhotoCount) {
+ setState(() {
+ modelData[index].photoCount = newPhotoCount;
+ });
+ }
+
+ /// Initializes data when the page loads.
Future loadData() async {
try {
- // visite initialisation
- visiteData = await VisiteModel.getAllVisites();
+ // visite model initialisation
+ modelData = await VisiteModel.getAllVisites();
} catch (e) {
// set errorMessage for debug
_errorMessage = 'Error loading visites : $e';
diff --git a/lib/ui/home/photo_tag.dart b/lib/ui/home/visit_photo_tag.dart
similarity index 88%
rename from lib/ui/home/photo_tag.dart
rename to lib/ui/home/visit_photo_tag.dart
index dad5b75..7c3edf9 100644
--- a/lib/ui/home/photo_tag.dart
+++ b/lib/ui/home/visit_photo_tag.dart
@@ -9,13 +9,19 @@ import 'package:super_tag_editor/widgets/rich_text_widget.dart';
class PhotoTagPage extends StatefulWidget {
// variables corresponding to the data parameters
- final int photoId;
- final List currentTags;
+ final int pp_id_distrib;
+ final String pp_langage;
+ final int pp_photoId;
+ final List pp_currentTags;
// Requiring data parameters
- const PhotoTagPage(
- {Key? key, required this.photoId, required this.currentTags})
- : super(key: key);
+ const PhotoTagPage({
+ Key? key,
+ required this.pp_id_distrib,
+ required this.pp_langage,
+ required this.pp_photoId,
+ required this.pp_currentTags,
+ }) : super(key: key);
@override
_PhotoTagPageState createState() => _PhotoTagPageState();
@@ -187,8 +193,9 @@ class _PhotoTagPageState extends State {
const Divider(),
ElevatedButton(
onPressed: () async {
- // Save the selected tags to the database //TODO 1,fr ===
- await saveSelectedTags(_selectedTags, 1, 'fr');
+ // Save the selected tags to the database
+ await saveSelectedTags(
+ _selectedTags, widget.pp_id_distrib, widget.pp_langage);
Navigator.pop(
context, _selectedTags.map((tag) => tag).toList());
@@ -203,9 +210,9 @@ class _PhotoTagPageState extends State {
}
Future loadData() async {
- // TODO 1,fr
- allTagsList = await objectbox.getVisiteTagsLabels(1, 'fr');
- _selectedTags = List.from(widget.currentTags);
+ allTagsList = await objectbox.getVisiteTagsLabels(
+ widget.pp_id_distrib, widget.pp_langage);
+ _selectedTags = List.from(widget.pp_currentTags);
}
/// Saves the selected tags for a photo to the ObjectBox database.
@@ -223,20 +230,18 @@ class _PhotoTagPageState extends State {
/// Nothing.
Future saveSelectedTags(
List tags, int distribId, String langage) async {
- if (tags.isEmpty) {
- return; // exit function without saving tags
- }
+ if (tags.isNotEmpty) {
+ // determines if there are any new tags
+ final newTags = tags.where((tag) => !allTagsList.contains(tag)).toList();
- // determines if there are any new tags
- final newTags = tags.where((tag) => !allTagsList.contains(tag)).toList();
-
- for (final tag in newTags) {
- // insert new tag in the database
- objectbox.addVisiteTag(0, distribId, tag, langage);
+ for (final tag in newTags) {
+ // insert new tag in the database
+ objectbox.addVisiteTag(0, distribId, tag, langage);
+ }
}
// save photo tag in the database
- objectbox.putPhotoTags(widget.photoId, tags);
+ objectbox.putPhotoTags(widget.pp_photoId, tags);
}
}
diff --git a/lib/ui/home/visit_photo_typology.dart b/lib/ui/home/visit_photo_typology.dart
new file mode 100644
index 0000000..2e00cd0
--- /dev/null
+++ b/lib/ui/home/visit_photo_typology.dart
@@ -0,0 +1,166 @@
+import 'dart:async';
+import 'package:flutter/material.dart';
+
+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';
+
+class VisitPhotoTypologyPage extends StatefulWidget {
+ final int pp_id_distrib;
+ final String pp_langage;
+ final int pp_id_visite;
+ final String pp_name;
+ final Function(int) onRefreshVisit;
+
+ VisitPhotoTypologyPage(
+ {Key? key,
+ required this.pp_id_distrib,
+ required this.pp_langage,
+ required this.pp_id_visite,
+ required this.pp_name,
+ required this.onRefreshVisit})
+ : super(key: key);
+
+ @override
+ _VisitPhotoTypologyPageState createState() => _VisitPhotoTypologyPageState();
+}
+
+class _VisitPhotoTypologyPageState extends State {
+ GestureDetector Function(BuildContext, int) _itemBuilder(
+ List PhotoTypology) =>
+ (BuildContext context, int index) => GestureDetector(
+ 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_id_typologie:
+ PhotoTypology[index].id_photo_typologie,
+ pp_libelle_typologie: PhotoTypology[index].libelle,
+ ));
+ Navigator.push(context, route).then(onGoBack);
+ },
+
+ /// TODO objectbox.noteBox.remove(PhotoTypology[index].id),
+ child: Container(
+ decoration: const BoxDecoration(
+ border: Border(bottom: BorderSide(color: Colors.black12)),
+ ),
+ child: Padding(
+ padding: const EdgeInsets.symmetric(
+ vertical: 15.0, horizontal: 10.0),
+ child: Row(
+ children: [
+ Expanded(
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ _buildBadge(
+ widget.pp_id_visite,
+ PhotoTypology[index].id_photo_typologie,
+ PhotoTypology[index].libelle),
+ Icon(Icons.chevron_right, size: 20, color: SOFT_GREY),
+ ],
+ ),
+ ),
+ ],
+ ),
+ ),
+ ),
+ );
+
+ Widget _buildBadge(int visitId, int photoTypologyId, String libelle) {
+ int photoCount =
+ objectbox.getVisitTypologiePhotoCount(visitId, photoTypologyId);
+ if (photoCount > 0) {
+ return Expanded(
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Text(
+ libelle,
+ style: const TextStyle(
+ fontSize: 15.0,
+ fontWeight: FontWeight.bold,
+ ),
+ ),
+ 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),
+ ),
+ ),
+ ],
+ ),
+ );
+ } else {
+ return Text(
+ libelle,
+ style: const TextStyle(
+ fontSize: 15.0,
+ ),
+ );
+ }
+ }
+
+ @override
+ void initState() {
+ super.initState();
+ }
+
+ @override
+ void dispose() {
+ super.dispose();
+ }
+
+ FutureOr onGoBack(dynamic value) {
+ setState(() {});
+ }
+
+ Future onBackPressed() async {
+ // Navigate back to the visits page and refresh the data
+ int newPhotoCount = objectbox.getVisitPhotoCount(widget.pp_id_visite);
+ widget.onRefreshVisit(newPhotoCount);
+ return true;
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return WillPopScope(
+ onWillPop: () async {
+ return onBackPressed();
+ },
+ child: Scaffold(
+ backgroundColor: Colors.white,
+ appBar: AppBar(
+ iconTheme: IconThemeData(
+ color: GlobalStyle.appBarIconThemeColor,
+ ),
+ elevation: GlobalStyle.appBarElevation,
+ title: Text(
+ widget.pp_name,
+ style: GlobalStyle.appBarTitle,
+ ),
+ backgroundColor: GlobalStyle.appBarBackgroundColor,
+ systemOverlayStyle: GlobalStyle.appBarSystemOverlayStyle),
+ body: Column(children: [
+ Expanded(
+ child: StreamBuilder>(
+ stream: objectbox.getPhotoTypologies(),
+ builder: (context, snapshot) => ListView.builder(
+ shrinkWrap: true,
+ //padding: const EdgeInsets.symmetric(horizontal: 20.0),
+ itemCount:
+ snapshot.hasData ? snapshot.data!.length : 0,
+ itemBuilder: _itemBuilder(snapshot.data ?? []))))
+ ])));
+ }
+}
diff --git a/lib/ui/home/photo_list.dart b/lib/ui/home/visit_photo_typology_list.dart
similarity index 59%
rename from lib/ui/home/photo_list.dart
rename to lib/ui/home/visit_photo_typology_list.dart
index 9292ebf..83bdb55 100644
--- a/lib/ui/home/photo_list.dart
+++ b/lib/ui/home/visit_photo_typology_list.dart
@@ -1,21 +1,24 @@
-import 'dart:developer' as developer;
import 'dart:async';
import 'dart:io';
+import 'package:intl/intl.dart';
+
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:image/image.dart' as img;
+
import 'package:path/path.dart' as path;
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/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/db/box_photo.dart';
-import 'package:mobdr/ui/home/photo_detail.dart';
// TODO Il faut supprimer les possibles photos du répertoire cache !
@@ -26,17 +29,32 @@ extension FileNameExtension on File {
}
}
-class PhotoListPage extends StatefulWidget {
+class VisitPhotoTypologyListPage extends StatefulWidget {
+ final int pp_id_distrib;
+ final String pp_langage;
+ final int pp_id_visite;
+ 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_id_typologie,
+ required this.pp_libelle_typologie});
+
@override
- _PhotoListPageState createState() => _PhotoListPageState();
+ _VisitPhotoTypologyListPageState createState() =>
+ _VisitPhotoTypologyListPageState();
}
-class _PhotoListPageState extends State {
+class _VisitPhotoTypologyListPageState
+ extends State {
final _globalWidget = GlobalWidget();
// initialize photos files list
- final List photoFiles = [];
- List _photoData = [];
+ final List _visitPhotoFiles = [];
+ List _visitPhotoData = [];
Color _color1 = Color(0xff777777);
Color _color2 = Color(0xFF515151);
@@ -47,7 +65,7 @@ class _PhotoListPageState extends State {
@override
void initState() {
super.initState();
- _loadData();
+ loadData();
}
@override
@@ -55,10 +73,6 @@ class _PhotoListPageState extends State {
super.dispose();
}
- void _loadData() {
- _photoData = objectbox.getAllPhotos();
- }
-
@override
Widget build(BuildContext context) {
final double boxImageSize = (MediaQuery.of(context).size.width / 4);
@@ -70,7 +84,7 @@ class _PhotoListPageState extends State {
systemOverlayStyle: SystemUiOverlayStyle.dark,
elevation: 0,
title: Text(
- 'Catégorie : A trier',
+ widget.pp_libelle_typologie,
style: TextStyle(fontSize: 18, color: Colors.black),
),
backgroundColor: Colors.white,
@@ -95,16 +109,107 @@ class _PhotoListPageState extends State {
}),
],
),
- body: AnimatedList(
- key: _listKey,
- initialItemCount: _photoData.length,
- physics: AlwaysScrollableScrollPhysics(),
- itemBuilder: (context, index, animation) {
- return _buildPhotolistCard(
- _photoData[index], boxImageSize, animation, index);
- },
- ),
- floatingActionButton: fabCart(context));
+ body: Column(children: [
+ Flexible(
+ child: AnimatedList(
+ key: _listKey,
+ initialItemCount: _visitPhotoData.length,
+ physics: AlwaysScrollableScrollPhysics(),
+ itemBuilder: (context, index, animation) {
+ return _buildPhotolistCard(
+ _visitPhotoData[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.chat, color: Colors.white, size: 16)),
+ ),
+ ),
+ ),
+ SizedBox(
+ width: 10,
+ ),
+ Expanded(
+ child: GestureDetector(
+ onTap: () async {
+ // clear photoFiles list before taking photos
+ _visitPhotoFiles.clear();
+
+ // if we are not on a simulator
+ if (SharedPrefs().isSimulator == false) {
+ Route route = MaterialPageRoute(
+ builder: (context) =>
+ CameraPage(photoFiles: _visitPhotoFiles));
+ Navigator.push(context, route).then((val) {
+ // Restore the constraint before navigating away
+ // DO await here to avoid any other screen in
+ // landscape mode
+ SystemChrome.setPreferredOrientations([
+ DeviceOrientation.portraitUp,
+ ]);
+
+ // if the user has validated photos
+ if (val == true) {
+ savePhotos();
+ }
+ });
+ } else {
+ // simulates the taking of a photo
+ final File imageFile =
+ await copyImageFromAssetsToTemporaryDirectory();
+ _visitPhotoFiles.add(imageFile);
+ savePhotos();
+ }
+ },
+ 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('Prendre des photos',
+ style: TextStyle(
+ color: SOFT_BLUE, fontWeight: FontWeight.bold)),
+ ),
+ ),
+ ),
+ ],
+ ),
+ )
+ ]));
}
Widget _buildPhotolistCard(Photo photoData, boxImageSize, animation, index) {
@@ -124,24 +229,31 @@ class _PhotoListPageState extends State {
children: [
GestureDetector(
onTap: () {
- Navigator.push(
- context,
- MaterialPageRoute(
- builder: (context) => PhotoDetailPage(
- id: _photoData[index].id,
- name: 'visiteData.name',
- image: _photoData[index].image,
- price: 0,
- photo: 1,
- rating: 0,
- review: 0,
- sale: 0,
- date: '')));
+ Route route = MaterialPageRoute(
+ builder: (context) => VisitPhotoTypologyDetailPage(
+ pp_id: _visitPhotoData[index].id,
+ pp_id_distrib: widget.pp_id_distrib,
+ pp_langage: widget.pp_langage,
+ pp_image: _visitPhotoData[index].getImage(),
+ pp_id_typologie: widget.pp_id_typologie,
+ ));
- // todo if qq chose à changé
- // ne raffraichir que le widget en cours ==
- setState(() {
- _listKey = GlobalKey();
+ Navigator.push(context, route).then((result) {
+ if (result['change_typologie']) {
+ // the photo must be removed
+ setState(() {
+ _visitPhotoData.removeAt(index);
+ _listKey = GlobalKey();
+ });
+ } else {
+ setState(() {
+ _visitPhotoData[index].tags = result['tags'];
+ _visitPhotoData[index].photo_principale =
+ result['photo_principale'];
+ _visitPhotoData[index].photo_privee =
+ result['photo_privee'];
+ });
+ }
});
},
child: Row(
@@ -150,7 +262,7 @@ class _PhotoListPageState extends State {
children: [
ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(10)),
- child: Image.file(File(photoData.image),
+ child: Image.file(File(photoData.getImage()),
fit: BoxFit.cover, height: 100, width: 150),
),
SizedBox(
@@ -160,54 +272,34 @@ class _PhotoListPageState extends State {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
+ Container(
+ margin: EdgeInsets.only(top: 5),
+ child: Row(
+ children: [
+ Text(
+ DateFormat('dd/MM/yyyy HH:mm:ss')
+ .format(photoData.date_photo),
+ style: TextStyle(
+ fontSize: 11, color: SOFT_GREY))
+ ],
+ ),
+ ),
+ Container(height: 8),
Text(
- photoData.id_photo_typologie.toString(),
+ "Private : ${photoData.photo_privee == 1 ? 'Yes' : 'No'}",
style: TextStyle(fontSize: 13, color: _color2),
maxLines: 3,
overflow: TextOverflow.ellipsis,
),
Container(
margin: EdgeInsets.only(top: 5),
- child: Text((index + 1).toString(),
+ child: Text(
+ '${photoData.tags.isNotEmpty ? (photoData.tags.length > 53 ? '${photoData.tags.substring(0, 50)}...' : photoData.tags) : "notag"}',
style: TextStyle(
fontSize: 13,
fontWeight: FontWeight.bold)),
),
- Container(
- margin: EdgeInsets.only(top: 5),
- child: Row(
- children: [
- Icon(Icons.location_on,
- color: SOFT_GREY, size: 12),
- Text(' ' + photoData.image_name,
- style: TextStyle(
- fontSize: 11, color: SOFT_GREY))
- ],
- ),
- ),
- Container(
- margin: EdgeInsets.only(top: 5),
- child: Row(
- children: [
- Text(
- '(' +
- photoData.id_photo_typologie
- .toString() +
- ')',
- style: TextStyle(
- fontSize: 11, color: SOFT_GREY))
- ],
- ),
- ),
- Container(
- margin: EdgeInsets.only(top: 5),
- child: Text(
- photoData.id_photo_typologie.toString() +
- ' ' +
- 'Sale',
- style: TextStyle(
- fontSize: 11, color: SOFT_GREY)),
- ),
+ Container(height: 8),
],
),
)
@@ -279,12 +371,12 @@ class _PhotoListPageState extends State {
borderRadius: BorderRadius.circular(5.0),
)),
side: MaterialStateProperty.all(
- BorderSide(color: SOFT_BLUE, width: 1.0),
+ BorderSide(color: SOFT_GREY, width: 1.0),
)),
child: Text(
'Copier dans galerie',
style: TextStyle(
- color: SOFT_BLUE,
+ color: SOFT_GREY,
fontWeight: FontWeight.bold,
fontSize: 13),
textAlign: TextAlign.center,
@@ -297,7 +389,7 @@ class _PhotoListPageState extends State {
behavior: HitTestBehavior.translucent,
onTap: () async {
await rotateAndReplaceImage(
- File(_photoData[index].image), 90);
+ File(_visitPhotoData[index].getImage()), 90);
setState(() {
_listKey = GlobalKey();
});
@@ -322,7 +414,7 @@ class _PhotoListPageState extends State {
behavior: HitTestBehavior.translucent,
onTap: () async {
await rotateAndReplaceImage(
- File(_photoData[index].image), -90);
+ File(_visitPhotoData[index].getImage()), -90);
setState(() {
_listKey = GlobalKey();
});
@@ -351,78 +443,33 @@ class _PhotoListPageState extends State {
);
}
- Widget fabCart(context) {
- return FloatingActionButton(
- onPressed: () {
- photoFiles.clear();
- Route route = MaterialPageRoute(
- builder: (context) => CameraPage(photoFiles: photoFiles));
- Navigator.push(context, route).then((val) {
- // Restore the constraint before navigating away
- // DO await here to avoid any other screen in
- // landscape mode
- SystemChrome.setPreferredOrientations([
- DeviceOrientation.portraitUp,
- ]);
-
- /// if the user has validated photos
- if (val == true) {
- savePhotos();
- }
- });
- },
- child: Stack(children: [
- Icon(Icons.add_a_photo, color: BLACK21, size: 42),
- Positioned(
- right: 0,
- bottom: 0,
- child: Container(
- padding: EdgeInsets.all(1),
- decoration: BoxDecoration(
- color: PRIMARY_COLOR,
- borderRadius: BorderRadius.circular(14),
- ),
- constraints: BoxConstraints(
- minWidth: 16,
- minHeight: 16,
- ),
- child: Center(
- child: Text(
- _photoData.length.toString(),
- style: TextStyle(
- color: Colors.white,
- fontSize: 8,
- ),
- textAlign: TextAlign.center,
- ),
- ),
- ),
- )
- ]),
- backgroundColor: Colors.white,
- shape: RoundedRectangleBorder(
- borderRadius: BorderRadius.all(Radius.circular(4.0))),
- );
+ // TODO ƒuture void ?
+ void loadData() {
+ _visitPhotoData = objectbox.getAllVisitTypologyPhotos(
+ widget.pp_id_visite, widget.pp_id_typologie);
}
+ /// Removes the image at the specified [imageURL] from the cache of the [NetworkImage] provider.
+ /// Returns a boolean indicating whether the image was successfully evicted.
Future evictImage(String imageURL) async {
final NetworkImage provider = NetworkImage(imageURL);
return await provider.evict();
}
+ /// Saves photos to the database and updates the widget with the new photos.
+ ///
void savePhotos() async {
- if (photoFiles.length > 0) {
+ if (_visitPhotoFiles.length > 0) {
final List _listPhotos = [];
- for (var myTmpPhoto in photoFiles) {
+ for (var myTmpPhoto in _visitPhotoFiles) {
/// move jpg file to photo directory
final myPhoto = await moveFileFromTempToPhotosDir(myTmpPhoto);
/// to insert into database
_listPhotos.add(Photo(
- id_visite: 0,
- id_photo_typologie: 0,
- image: myPhoto.path,
+ id_visite: widget.pp_id_visite,
+ id_photo_typologie: widget.pp_id_typologie,
image_name: myPhoto.path.split('/').last));
}
@@ -430,7 +477,7 @@ class _PhotoListPageState extends State {
final addedPhotos = await objectbox.addPhotos(_listPhotos);
/// insert photo(s) in widget at the beginning (0)
- _photoData.insertAll(0, addedPhotos);
+ _visitPhotoData.insertAll(0, addedPhotos);
/// refresh widget
setState(() {
@@ -439,6 +486,11 @@ class _PhotoListPageState extends State {
}
}
+ /// Deletes the given file if it exists.
+ ///
+ /// Returns nothing.
+ ///
+ /// Throws an error if there was an issue deleting the file.
Future deleteFile(File file) async {
try {
if (await file.exists()) {
@@ -451,6 +503,13 @@ class _PhotoListPageState extends State {
}
}
+ /// Shows an alert dialog to confirm the deletion of a photo from the visit and
+ /// removes it from the list of photos. Also deletes the photo file from the
+ /// database and local storage.
+ ///
+ /// Parameters:
+ /// - index : index of the photo in the list to be deleted.
+ /// - boxImageSize : size of the image to be displayed in the list.
void showPopupDeletePhoto(index, boxImageSize) {
// set up the buttons
Widget cancelButton = TextButton(
@@ -461,13 +520,13 @@ class _PhotoListPageState extends State {
Widget continueButton = TextButton(
onPressed: () {
int removeIndex = index;
- var removedItem = _photoData.removeAt(removeIndex);
+ var removedItem = _visitPhotoData.removeAt(removeIndex);
// delete file on database
objectbox.delPhoto(removedItem.image_name);
// delete file on local storage
- deleteFile(new File(removedItem.image));
+ deleteFile(new File(removedItem.getImage()));
// This builder is just so that the animation has something
// to work with before it disappears from view since the original
@@ -512,13 +571,18 @@ class _PhotoListPageState extends State {
);
}
+ // Moves a temporary file to the photos directory in the app's document directory.
+ ///
+ /// Returns a `File` object for the new file in the photos directory.
+ ///
+ /// Parameters:
+ /// * `tempFile`: The temporary `File` object to move to the photos directory.
+ ///
+ /// Throws a `FileSystemException` if there is an error renaming the file.
Future moveFileFromTempToPhotosDir(File tempFile) async {
- // Get the application's document directory
- final Directory documentsDir = await getApplicationDocumentsDirectory();
-
// Set the new file path with the original file name
final String newPath =
- '${documentsDir.path}/photos/${tempFile.path.split('/').last}';
+ '${SharedPrefs().photosDir}/${tempFile.path.split('/').last}';
// Rename the file to move it to the documents directory
await tempFile.rename(newPath);
@@ -527,6 +591,13 @@ class _PhotoListPageState extends State {
return File(newPath);
}
+ /// Rotates the image file clockwise by the specified angle (in degrees) and overwrites the original file with the rotated image.
+ ///
+ /// Parameters:
+ /// - `imageFile`: The image file to rotate and replace.
+ /// - `angle`: The angle (in degrees) by which to rotate the image. Valid values are 90, 180, and 270.
+ ///
+ /// Throws an exception if there is an error in the rotation process.
Future rotateAndReplaceImage(File imageFile, int angle) async {
// Read the image file into a Uint8List
Uint8List bytes = await imageFile.readAsBytes();
@@ -546,4 +617,19 @@ class _PhotoListPageState extends State {
// remove the flutter cache image
FileImage(imageFile).evict();
}
+
+ /// Copies the 'simulator.jpg' image file from the app's assets to a randomly named file in the app's temporary directory and returns the File object.
+ /// The temporary file name will start with 'sim_'.
+ Future copyImageFromAssetsToTemporaryDirectory() async {
+ final String randomName = 'sim_${DateTime.now().microsecondsSinceEpoch}';
+ final Directory tempDir = await getTemporaryDirectory();
+ final String tempPath = tempDir.path;
+ final String assetPath = 'assets/images/simulator.jpeg';
+
+ final ByteData data = await rootBundle.load(assetPath);
+ final File tempFile = File('$tempPath/$randomName.jpeg');
+ await tempFile.writeAsBytes(data.buffer.asUint8List(), flush: true);
+
+ return tempFile;
+ }
}
diff --git a/lib/ui/home/photo_detail.dart b/lib/ui/home/visite_photo_typology_detail.dart
similarity index 58%
rename from lib/ui/home/photo_detail.dart
rename to lib/ui/home/visite_photo_typology_detail.dart
index 32b8ac2..cb13d7e 100644
--- a/lib/ui/home/photo_detail.dart
+++ b/lib/ui/home/visite_photo_typology_detail.dart
@@ -5,79 +5,59 @@ 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/general/notification.dart';
-import 'package:mobdr/ui/home/product_category.dart';
-import 'package:mobdr/ui/home/photo_tag.dart';
-import 'package:mobdr/ui/home/search.dart';
-import 'package:mobdr/ui/reusable/reusable_widget.dart';
-import 'package:mobdr/ui/shopping_cart/tab_shopping_cart.dart';
-import 'package:mobdr/ui/reusable/global_function.dart';
+import 'package:mobdr/ui/home/visit_photo_tag.dart';
import 'package:mobdr/db/box_photo.dart';
+import 'package:mobdr/db/box_photo_typology.dart';
-class PhotoDetailPage extends StatefulWidget {
+//TODO : faire concurrents ===
+
+class VisitPhotoTypologyDetailPage extends StatefulWidget {
// variables corresponding to the data parameters
- final int id;
- final String name;
- final String image;
- final String tags;
- final double price;
- final int photo;
- final double rating;
- final int review;
- final int sale;
- final String date;
+ final int pp_id;
+ final int pp_id_distrib;
+ final String pp_langage;
+ final String pp_image;
+ final int pp_id_typologie;
// Requiring data parameters
- const PhotoDetailPage(
- {Key? key,
- this.id = 0,
- this.name = '',
- this.image = '',
- this.tags = '',
- this.price = 24,
- this.photo = 1,
- this.rating = 4,
- this.review = 45,
- this.sale = 63,
- this.date = ''})
- : super(key: key);
+ VisitPhotoTypologyDetailPage({
+ Key? key,
+ required this.pp_id,
+ required this.pp_id_distrib,
+ required this.pp_langage,
+ required this.pp_image,
+ required this.pp_id_typologie,
+ }) : super(key: key);
@override
- _PhotoDetailPageState createState() => _PhotoDetailPageState();
+ _VisitPhotoTypologyDetailPageState createState() =>
+ _VisitPhotoTypologyDetailPageState();
}
-class _PhotoDetailPageState extends State {
- // initialize global function and reusable widget
- final _globalFunction = GlobalFunction();
- final _reusableWidget = ReusableWidget();
-
+class _VisitPhotoTypologyDetailPageState
+ extends State {
bool _isLoading = true;
String _errorMessage = '';
// Typology list
- late List _typologyList = [];
+ late List _typologyList = [];
int _typologyIndex = 0;
- List _chickenParts = [];
- int _maxChickenParts = 2;
+ List _visibilities = [];
- // shopping cart count
- int _shoppingCartCount = 3;
-
- late String tags = "";
late List tagList = [];
-
late Photo _photo;
@override
void initState() {
super.initState();
- loadData(widget.id).then((_) {
+ loadData(widget.pp_id).then((_) {
setState(() {
_isLoading = false;
});
@@ -111,71 +91,31 @@ class _PhotoDetailPageState extends State {
}
return Scaffold(
appBar: AppBar(
- iconTheme: IconThemeData(
- color: GlobalStyle.appBarIconThemeColor,
- ),
- elevation: GlobalStyle.appBarElevation,
- titleSpacing: 0.0,
- // create search text field in the app bar
- title: Container(
- margin: EdgeInsets.only(right: 16),
- child: TextButton(
- style: ButtonStyle(
- backgroundColor: MaterialStateProperty.resolveWith(
- (Set states) => Colors.grey[100]!,
- ),
- overlayColor: MaterialStateProperty.all(Colors.transparent),
- shape: MaterialStateProperty.all(RoundedRectangleBorder(
- borderRadius: BorderRadius.circular(5.0),
- )),
- ),
- onPressed: () {
- Navigator.push(context,
- MaterialPageRoute(builder: (context) => SearchPage()));
- },
- child: Row(
- children: [
- SizedBox(width: 8),
- Icon(Icons.search, color: Colors.grey[500], size: 18),
- SizedBox(width: 8),
- Text(
- 'Search Product',
- style: TextStyle(
- fontSize: 13,
- color: Colors.grey[600],
- fontWeight: FontWeight.normal),
- )
- ],
- )),
- ),
- backgroundColor: GlobalStyle.appBarBackgroundColor,
- systemOverlayStyle: GlobalStyle.appBarSystemOverlayStyle,
- actions: [
- IconButton(
- padding: EdgeInsets.all(0),
- constraints: BoxConstraints(),
- icon: _customShoppingCart(_shoppingCartCount),
- onPressed: () {
- Navigator.push(
- context,
- MaterialPageRoute(
- builder: (context) => TabShoppingCartPage()));
- }),
- IconButton(
- icon: _reusableWidget.customNotifIcon(
- count: 8, notifColor: BLACK_GREY),
- onPressed: () {
- Navigator.push(
- context,
- MaterialPageRoute(
- builder: (context) => NotificationPage()));
- }),
- ],
- bottom: _reusableWidget.bottomAppBar(),
- ),
+ iconTheme: IconThemeData(
+ color: GlobalStyle.appBarIconThemeColor,
+ ),
+ elevation: GlobalStyle.appBarElevation,
+ title: Text(
+ 'Photo',
+ style: GlobalStyle.appBarTitle,
+ ),
+ backgroundColor: GlobalStyle.appBarBackgroundColor,
+ systemOverlayStyle: GlobalStyle.appBarSystemOverlayStyle),
body: WillPopScope(
onWillPop: () {
- Navigator.pop(context);
+ // fred
+ Map result = {
+ 'change_typologie': _typologyIndex !=
+ _typologyList.indexWhere((typology) =>
+ typology.id_photo_typologie == widget.pp_id_typologie),
+ 'tags': tagList.join(","),
+ 'photo_principale': _visibilities.contains('principal') ? 1 : 0,
+ 'photo_privee': _visibilities.contains('private') ? 1 : 0,
+ };
+
+ // return to the parent page fred
+ Navigator.pop(context, result);
+
return Future.value(true);
},
child: Column(
@@ -183,8 +123,7 @@ class _PhotoDetailPageState extends State {
Flexible(
child: ListView(
children: [
- Image.file(File(widget.image), fit: BoxFit.cover),
- //_createProductSlider(),
+ Image.file(File(widget.pp_image), fit: BoxFit.cover),
_buildPhotoTypology(),
_buildPhotoVisibility(),
_buildPhotoTag(context),
@@ -230,7 +169,7 @@ class _PhotoDetailPageState extends State {
child: GestureDetector(
onTap: () {
setState(() {
- _shoppingCartCount++;
+ //_shoppingCartCount++;
});
Fluttertoast.showToast(
msg: 'Item has been added to Shopping Cart',
@@ -246,7 +185,7 @@ class _PhotoDetailPageState extends State {
borderRadius: BorderRadius.all(Radius.circular(
10) // <--- border radius here
)),
- child: Text('Add to Shopping Cart',
+ child: Text('Copier dans galerie',
style: TextStyle(
color: SOFT_BLUE,
fontWeight: FontWeight.bold)),
@@ -261,38 +200,6 @@ class _PhotoDetailPageState extends State {
));
}
- Widget _customShoppingCart(int count) {
- return Stack(
- children: [
- Icon(Icons.shopping_cart, color: BLACK_GREY),
- Positioned(
- right: 0,
- child: Container(
- padding: EdgeInsets.all(1),
- decoration: BoxDecoration(
- color: ASSENT_COLOR,
- borderRadius: BorderRadius.circular(10),
- ),
- constraints: BoxConstraints(
- minWidth: 14,
- minHeight: 14,
- ),
- child: Center(
- child: Text(
- count.toString(),
- style: TextStyle(
- color: Colors.white,
- fontSize: 8,
- ),
- textAlign: TextAlign.center,
- ),
- ),
- ),
- )
- ],
- );
- }
-
Widget _buildPhotoTypology() {
return Container(
margin: EdgeInsets.only(top: 12),
@@ -307,7 +214,7 @@ class _PhotoDetailPageState extends State {
),
Wrap(
children: List.generate(_typologyList.length, (index) {
- return radioSize(_typologyList[index], index);
+ return radioSize(_typologyList[index].libelle, index);
}),
),
],
@@ -316,7 +223,11 @@ class _PhotoDetailPageState extends State {
Widget radioSize(String txt, int index) {
return GestureDetector(
- onTap: () {
+ onTap: () async {
+ // save photo typology in the database
+ objectbox.putPhotoTypologie(
+ widget.pp_id, _typologyList[index].id_photo_typologie);
+
setState(() {
_typologyIndex = index;
});
@@ -339,20 +250,20 @@ class _PhotoDetailPageState extends State {
);
}
- // TODO changer chicken
- Widget _checboxChicken({value = 'breast', primaryText = 'Chicken Breast'}) {
+ Widget _checkboxVisibility({value, primaryText}) {
return GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: () {
setState(() {
- if (_chickenParts.contains(value)) {
- _chickenParts.remove(value);
+ if (_visibilities.contains(value)) {
+ _visibilities.remove(value);
} else {
- if (_chickenParts.length < _maxChickenParts) {
- _chickenParts.add(value);
- }
+ _visibilities.add(value);
}
});
+
+ // save photo visibilities in the database
+ objectbox.putPhotoVisibilities(widget.pp_id, _visibilities);
},
child: Row(
children: [
@@ -360,14 +271,14 @@ class _PhotoDetailPageState extends State {
decoration: BoxDecoration(
border: Border.all(
width: 1,
- color: (_chickenParts.contains(value))
+ color: (_visibilities.contains(value))
? PRIMARY_COLOR
: BLACK77),
borderRadius: BorderRadius.all(Radius.circular(4.0)),
),
child: Padding(
padding: const EdgeInsets.all(2),
- child: (_chickenParts.contains(value))
+ child: (_visibilities.contains(value))
? Icon(
Icons.check,
size: 12.0,
@@ -385,7 +296,7 @@ class _PhotoDetailPageState extends State {
style: TextStyle(
fontSize: 13,
color: BLACK77,
- fontWeight: (_chickenParts.contains(value))
+ fontWeight: (_visibilities.contains(value))
? FontWeight.bold
: FontWeight.normal)),
],
@@ -406,12 +317,12 @@ class _PhotoDetailPageState extends State {
],
),
SizedBox(height: 16),
- _checboxChicken(value: 'public', primaryText: 'Public'),
+ _checkboxVisibility(value: 'private', primaryText: 'Privée'),
Divider(
height: 32,
color: Colors.grey[400],
),
- _checboxChicken(value: 'principal', primaryText: 'Principal')
+ _checkboxVisibility(value: 'principal', primaryText: 'Principale')
],
),
);
@@ -424,8 +335,11 @@ class _PhotoDetailPageState extends State {
final newTags = await Navigator.push>(
context,
MaterialPageRoute(
- builder: (context) =>
- PhotoTagPage(photoId: this._photo.id, currentTags: tagList),
+ builder: (context) => PhotoTagPage(
+ pp_langage: widget.pp_langage,
+ pp_id_distrib: widget.pp_id_distrib,
+ pp_photoId: this._photo.id,
+ pp_currentTags: tagList),
),
);
@@ -465,18 +379,27 @@ class _PhotoDetailPageState extends State {
);
}
- /// data initialization on loading.
+ /// Initializes data when the page loads.
Future loadData(int photoId) async {
+ String tags = "";
+
try {
// photo typologies initialization
- _typologyList = objectbox.getPhotoTypologiesLabels();
+ _typologyList = objectbox.getPhotoTypologiesList();
+
+ _typologyIndex = _typologyList.indexWhere(
+ (typology) => typology.id_photo_typologie == widget.pp_id_typologie);
// get photo object
_photo = objectbox.getPhotoById(photoId)!;
+ // visibilities initialization
+ if (_photo.photo_privee == 1) _visibilities.add('private');
+ if (_photo.photo_principale == 1) _visibilities.add('principal');
+
// photo tag initialization
tags = _photo.tags;
- tagList = tags.isEmpty ? [] : tags.split(",");
+ tagList = tags.isEmpty ? [] : _photo.tags.split(",");
} catch (e) {
// set errorMessage for debug
_errorMessage = 'Error loading photo: $e';
diff --git a/lib/ui/sync/tab_sync.dart b/lib/ui/sync/tab_sync.dart
index 40d2895..325ae86 100644
--- a/lib/ui/sync/tab_sync.dart
+++ b/lib/ui/sync/tab_sync.dart
@@ -4,7 +4,6 @@ we used AutomaticKeepAliveClientMixin to keep the state when moving from 1 navba
*/
import 'package:mobdr/config/global_style.dart';
-import 'package:mobdr/main.dart';
import 'package:mobdr/ui/reusable/reusable_widget.dart';
import 'package:mobdr/network/api_provider.dart';
import 'package:flutter/material.dart';
diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift
index 049788b..83c4826 100644
--- a/macos/Flutter/GeneratedPluginRegistrant.swift
+++ b/macos/Flutter/GeneratedPluginRegistrant.swift
@@ -5,6 +5,7 @@
import FlutterMacOS
import Foundation
+import device_info_plus
import objectbox_flutter_libs
import package_info_plus
import path_provider_foundation
@@ -13,6 +14,7 @@ import sqflite
import wakelock_macos
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
+ DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin"))
ObjectboxFlutterLibsPlugin.register(with: registry.registrar(forPlugin: "ObjectboxFlutterLibsPlugin"))
FLTPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlusPlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
diff --git a/pubspec.lock b/pubspec.lock
index 7e1f7a8..ce8e0ea 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -149,10 +149,10 @@ packages:
dependency: "direct main"
description:
name: camera
- sha256: ad1c53c554a2f3e5708f3b01eb738d60b902bb61f7f4ad420c65c715e65a7379
+ sha256: "7afc256902062cab191540c09908b98bc71e93d5e20b6486dbee51aa7731e9b2"
url: "https://pub.dev"
source: hosted
- version: "0.10.3+2"
+ version: "0.10.4"
camera_android:
dependency: transitive
description:
@@ -297,6 +297,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.0.0"
+ device_info_plus:
+ dependency: "direct main"
+ description:
+ name: device_info_plus
+ sha256: "435383ca05f212760b0a70426b5a90354fe6bd65992b3a5e27ab6ede74c02f5c"
+ url: "https://pub.dev"
+ source: hosted
+ version: "8.2.0"
+ device_info_plus_platform_interface:
+ dependency: transitive
+ description:
+ name: device_info_plus_platform_interface
+ sha256: d3b01d5868b50ae571cd1dc6e502fc94d956b665756180f7b16ead09e836fd64
+ url: "https://pub.dev"
+ source: hosted
+ version: "7.0.0"
dio:
dependency: "direct main"
description:
diff --git a/pubspec.yaml b/pubspec.yaml
index 64b04d0..2f0dd83 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -52,7 +52,10 @@ dependencies:
shimmer: 2.0.0
image_picker: ^0.8.7
- camera: ^0.10.3+2
+
+ # https://pub.dev/packages/camera
+ camera: ^0.10.4
+
permission_handler: 10.2.0
image: ^4.0.15
@@ -75,6 +78,9 @@ dependencies:
universal_io: 2.2.0
xml: ^6.2.2
+ # https://pub.dev/packages/device_info_plus/install
+ device_info_plus: ^8.2.0
+
dev_dependencies:
flutter_test:
sdk: flutter
@@ -148,6 +154,7 @@ flutter:
- assets/images/process_timeline/status3.png
- assets/images/process_timeline/status4.png
- assets/images/process_timeline/status5.png
+ - assets/images/simulator.jpeg
- assets/lang/fr.json
- assets/lang/en.json