Updates for photo model
parent
ee76c40294
commit
d76f037333
|
|
@ -10,7 +10,6 @@ class Photo {
|
|||
@Id()
|
||||
int id = 0;
|
||||
|
||||
int id_photo;
|
||||
int id_visite;
|
||||
int id_photo_typologie;
|
||||
String image;
|
||||
|
|
@ -19,10 +18,7 @@ class Photo {
|
|||
int id_photo_mp4;
|
||||
int photo_privee;
|
||||
int photo_principale;
|
||||
String photo_tag1;
|
||||
String photo_tag2;
|
||||
String photo_tag3;
|
||||
String photo_tag4;
|
||||
String tags;
|
||||
int uploaded;
|
||||
|
||||
Photo(
|
||||
|
|
@ -31,20 +27,43 @@ class Photo {
|
|||
required this.id_photo_typologie,
|
||||
required this.image,
|
||||
required this.image_name,
|
||||
this.id_photo = 0,
|
||||
this.id_photo_mp4 = 0,
|
||||
this.photo_privee = 0,
|
||||
this.photo_principale = 0,
|
||||
this.photo_tag1 = '',
|
||||
this.photo_tag2 = '',
|
||||
this.photo_tag3 = '',
|
||||
this.photo_tag4 = '',
|
||||
this.tags = '',
|
||||
DateTime? date_photo,
|
||||
this.uploaded = 0})
|
||||
: date_photo = date_photo ?? DateTime.now();
|
||||
|
||||
String get dateFormat => DateFormat('dd.MM.yyyy hh:mm:ss').format(date_photo);
|
||||
|
||||
Photo copyWith({
|
||||
int? id,
|
||||
int? id_visite,
|
||||
int? id_photo_typologie,
|
||||
String? image,
|
||||
String? image_name,
|
||||
DateTime? date_photo,
|
||||
int? id_photo_mp4,
|
||||
int? photo_privee,
|
||||
int? photo_principale,
|
||||
String? tags,
|
||||
int? uploaded,
|
||||
}) {
|
||||
return 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,
|
||||
photo_privee: photo_privee ?? this.photo_privee,
|
||||
photo_principale: photo_principale ?? this.photo_principale,
|
||||
tags: tags ?? this.tags,
|
||||
uploaded: uploaded ?? this.uploaded,
|
||||
);
|
||||
}
|
||||
/*
|
||||
Photo.fromJson(Map<String, dynamic> json)
|
||||
: id_visite = json['id_visite'],
|
||||
|
|
|
|||
|
|
@ -1,11 +1,13 @@
|
|||
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_visite,
|
||||
{required this.id,
|
||||
required this.id_visite,
|
||||
required this.id_photo_typologie,
|
||||
required this.image,
|
||||
required this.image_name});
|
||||
|
|
|
|||
|
|
@ -1,44 +1,56 @@
|
|||
import 'package:mobdr/config/constant.dart';
|
||||
import 'package:mobdr/main.dart';
|
||||
|
||||
class VisiteModel {
|
||||
late int id;
|
||||
late String name;
|
||||
late double price;
|
||||
late int photo;
|
||||
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 int photo;
|
||||
late String date;
|
||||
|
||||
VisiteModel(
|
||||
{required this.id,
|
||||
required this.name,
|
||||
required this.price,
|
||||
required this.photo,
|
||||
required this.image,
|
||||
required this.rating,
|
||||
required this.review,
|
||||
required this.sale,
|
||||
required this.stock,
|
||||
required this.location,
|
||||
required this.date});
|
||||
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,
|
||||
});
|
||||
|
||||
static Future<List<VisiteModel>> getAllVisites() async {
|
||||
// Retrieve all visits from the database using the getAllVisites() method
|
||||
final visites = await objectbox.getAllVisites();
|
||||
|
||||
// Map each retrieved visit to VisiteModel
|
||||
final visiteModels = visites
|
||||
.map((visite) => VisiteModel(
|
||||
id: visite.id,
|
||||
name: visite.title,
|
||||
photo: 1,
|
||||
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: ""))
|
||||
.toList();
|
||||
|
||||
// Return the list of VisiteModel
|
||||
return visiteModels;
|
||||
}
|
||||
}
|
||||
|
||||
List<VisiteModel> visiteData = [
|
||||
VisiteModel(
|
||||
id: 1,
|
||||
name: "Villeneuve d'asc ONE-STEP",
|
||||
price: 62,
|
||||
photo: 1,
|
||||
image:
|
||||
'https://mp4.ikksgroup.com/photos/1/0/1/8/4/4/101844-thumbnail.JPG',
|
||||
rating: 5,
|
||||
review: 42,
|
||||
sale: 4,
|
||||
stock: 5,
|
||||
location: "Villeneuve d'asc",
|
||||
date: 'Dimanche 26/02/2023 14:00')
|
||||
];
|
||||
|
|
|
|||
|
|
@ -256,7 +256,7 @@ class ApiProvider {
|
|||
ApiConstants.externalEndpoint +
|
||||
ApiConstants.restEndpoint +
|
||||
'/mobDR/visite/calendrier',
|
||||
{"id_utilisateur": 6, "start": 20230101, "end": 20230131});
|
||||
{"id_utilisateur": 6, "start": 20230101, "end": 20230501});
|
||||
|
||||
/// get "Visite tags" list
|
||||
response2 = await getCrud(
|
||||
|
|
@ -274,6 +274,9 @@ class ApiProvider {
|
|||
}
|
||||
|
||||
if (response2.statusCode == STATUS_OK) {
|
||||
// remove all objects
|
||||
objectbox.visiteTagBox.removeAll();
|
||||
|
||||
/// fill box "visiteTag"
|
||||
objectbox.addVisiteTags(response2.data['tags']);
|
||||
}
|
||||
|
|
@ -302,6 +305,9 @@ class ApiProvider {
|
|||
null);
|
||||
|
||||
if (response.statusCode == STATUS_OK) {
|
||||
// remove all objects
|
||||
objectbox.photoTypologyBox.removeAll();
|
||||
|
||||
/// fill box "Photo typologies"
|
||||
objectbox.addPhotoTypologies(response.data['typologies']);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -195,7 +195,7 @@
|
|||
},
|
||||
{
|
||||
"id": "7:8290500625256822711",
|
||||
"lastPropertyId": "11:3119168728902810585",
|
||||
"lastPropertyId": "13:1900114397693432703",
|
||||
"name": "Visite",
|
||||
"properties": [
|
||||
{
|
||||
|
|
@ -243,6 +243,11 @@
|
|||
"id": "11:3119168728902810585",
|
||||
"name": "date_visite",
|
||||
"type": 10
|
||||
},
|
||||
{
|
||||
"id": "13:1900114397693432703",
|
||||
"name": "url_photo_principale",
|
||||
"type": 9
|
||||
}
|
||||
],
|
||||
"relations": []
|
||||
|
|
@ -283,7 +288,7 @@
|
|||
},
|
||||
{
|
||||
"id": "9:6788844671665652158",
|
||||
"lastPropertyId": "16:539065583624712715",
|
||||
"lastPropertyId": "17:7248999677905103482",
|
||||
"name": "Photo",
|
||||
"properties": [
|
||||
{
|
||||
|
|
@ -292,11 +297,6 @@
|
|||
"type": 6,
|
||||
"flags": 1
|
||||
},
|
||||
{
|
||||
"id": "2:7877546811840884522",
|
||||
"name": "id_photo",
|
||||
"type": 6
|
||||
},
|
||||
{
|
||||
"id": "3:1374846727562410311",
|
||||
"name": "id_visite",
|
||||
|
|
@ -327,26 +327,6 @@
|
|||
"name": "photo_principale",
|
||||
"type": 6
|
||||
},
|
||||
{
|
||||
"id": "10:2757780641715705310",
|
||||
"name": "photo_tag1",
|
||||
"type": 9
|
||||
},
|
||||
{
|
||||
"id": "11:6494338359539955476",
|
||||
"name": "photo_tag2",
|
||||
"type": 9
|
||||
},
|
||||
{
|
||||
"id": "12:5293139139799032553",
|
||||
"name": "photo_tag3",
|
||||
"type": 9
|
||||
},
|
||||
{
|
||||
"id": "13:2141346538986140281",
|
||||
"name": "photo_tag4",
|
||||
"type": 9
|
||||
},
|
||||
{
|
||||
"id": "14:4568092734700892012",
|
||||
"name": "uploaded",
|
||||
|
|
@ -361,6 +341,11 @@
|
|||
"id": "16:539065583624712715",
|
||||
"name": "image_name",
|
||||
"type": 9
|
||||
},
|
||||
{
|
||||
"id": "17:7248999677905103482",
|
||||
"name": "tags",
|
||||
"type": 9
|
||||
}
|
||||
],
|
||||
"relations": []
|
||||
|
|
@ -396,7 +381,7 @@
|
|||
}
|
||||
],
|
||||
"lastEntityId": "10:2779194860339140505",
|
||||
"lastIndexId": "0:0",
|
||||
"lastIndexId": "1:7907819717055295102",
|
||||
"lastRelationId": "0:0",
|
||||
"lastSequenceId": "0:0",
|
||||
"modelVersion": 5,
|
||||
|
|
@ -404,14 +389,22 @@
|
|||
"retiredEntityUids": [
|
||||
7401686910042688313
|
||||
],
|
||||
"retiredIndexUids": [],
|
||||
"retiredIndexUids": [
|
||||
7907819717055295102
|
||||
],
|
||||
"retiredPropertyUids": [
|
||||
402019719780433349,
|
||||
2876428622751679696,
|
||||
6435857490868115471,
|
||||
4582947574501853036,
|
||||
103801570610300983,
|
||||
1940661113633121688
|
||||
1940661113633121688,
|
||||
2757780641715705310,
|
||||
6494338359539955476,
|
||||
5293139139799032553,
|
||||
2141346538986140281,
|
||||
7877546811840884522,
|
||||
3784190804330297742
|
||||
],
|
||||
"retiredRelationUids": [],
|
||||
"version": 1
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ class ObjectBox {
|
|||
userBox.removeAll();
|
||||
etabBox.removeAll();
|
||||
concurrentBox.removeAll();
|
||||
visiteBox.removeAll();
|
||||
//visiteBox.removeAll();
|
||||
//visiteTagBox.removeAll();
|
||||
//photoBox.removeAll();
|
||||
//photoTypologyBox.removeAll();
|
||||
|
|
@ -240,7 +240,7 @@ class ObjectBox {
|
|||
/// VISITE ------------------------------------------------------------------
|
||||
///
|
||||
|
||||
Stream<List<Visite>> getVisites() {
|
||||
Stream<List<Visite>> getVisitesStream() {
|
||||
// Query for all visites, sorted by their date.
|
||||
// https://docs.objectbox.io/queries
|
||||
final builder =
|
||||
|
|
@ -253,12 +253,23 @@ class ObjectBox {
|
|||
.map((query) => query.find());
|
||||
}
|
||||
|
||||
List<Visite> getAllVisites() {
|
||||
// Query for all visites, sorted by their date.
|
||||
final builder = visiteBox
|
||||
.query()
|
||||
.order(Visite_.date_visite, flags: Order.descending)
|
||||
.build();
|
||||
// Execute the query and return the result.
|
||||
return builder.find();
|
||||
}
|
||||
|
||||
// A function that converts a response body list into a List<Visite>.
|
||||
List<Visite> parseVisites(List responseDataList) {
|
||||
final parsed = responseDataList.cast<Map<String, dynamic>>();
|
||||
return parsed.map<Visite>((json) => Visite.fromJson(json)).toList();
|
||||
}
|
||||
|
||||
// TODO : Enregistre urlphotoprincipale sur le disque pour l'avoir en cache ?
|
||||
Future<void> addVisites(List<dynamic> _listVisites) =>
|
||||
store.runInTransactionAsync(
|
||||
TxMode.write, _addVisitesInTx, parseVisites(_listVisites));
|
||||
|
|
@ -277,7 +288,8 @@ class ObjectBox {
|
|||
int _id_distrib_visite,
|
||||
int _id_etab,
|
||||
int _abandon,
|
||||
String _end) =>
|
||||
String _end,
|
||||
String _url_photo_principale) =>
|
||||
store.runInTransactionAsync(
|
||||
TxMode.write,
|
||||
_addVisiteInTx,
|
||||
|
|
@ -289,7 +301,8 @@ class ObjectBox {
|
|||
allDay: _allDay,
|
||||
id_distrib_visite: _id_distrib_visite,
|
||||
id_etab: _id_etab,
|
||||
abandon: _abandon));
|
||||
abandon: _abandon,
|
||||
url_photo_principale: _url_photo_principale));
|
||||
|
||||
static void _addVisiteInTx(Store store, _Visite) {
|
||||
store.box<Visite>().put(_Visite);
|
||||
|
|
@ -299,10 +312,11 @@ class ObjectBox {
|
|||
return visiteBox.count();
|
||||
}
|
||||
|
||||
/// VISITE TAG ---------------------------------------------------------------
|
||||
//TODO changer en PHOTO TAG / mettre dans l'ordre CRUD
|
||||
/// PHOTO TAG ---------------------------------------------------------------
|
||||
///
|
||||
|
||||
// A function that converts a response body list into a List<VisiteTag>.
|
||||
// converts a response body list into a List<VisiteTag>.
|
||||
List<VisiteTag> parseVisiteTags(List responseDataList) {
|
||||
final parsed = responseDataList.cast<Map<String, dynamic>>();
|
||||
return parsed.map<VisiteTag>((json) => VisiteTag.fromJson(json)).toList();
|
||||
|
|
@ -316,6 +330,7 @@ class ObjectBox {
|
|||
store.box<VisiteTag>().putMany(_VisiteTags);
|
||||
}
|
||||
|
||||
/// save new tag for a distributor / langage
|
||||
Future<void> addVisiteTag(
|
||||
int _id_visite_tag,
|
||||
int _id_distrib,
|
||||
|
|
@ -336,23 +351,38 @@ class ObjectBox {
|
|||
store.box<VisiteTag>().put(_VisiteTag);
|
||||
}
|
||||
|
||||
List<String> getVisiteTagsLabels() {
|
||||
List<String> getVisiteTagsLabels(int distribId, String langage) {
|
||||
final query = visiteTagBox
|
||||
.query(VisiteTag_.langage.equals('fr'))
|
||||
.order(VisiteTag_.libelle)
|
||||
.query(VisiteTag_.id_distrib.equals(distribId) &
|
||||
VisiteTag_.langage.equals(langage))
|
||||
//.order(VisiteTag_.libelle)
|
||||
.build();
|
||||
final visiteTags = query.find();
|
||||
return visiteTags.map((VisiteTag) => VisiteTag.libelle).toList();
|
||||
PropertyQuery<String> pq = query.property(VisiteTag_.libelle);
|
||||
pq.distinct = true;
|
||||
pq.caseSensitive = false;
|
||||
return pq.find();
|
||||
}
|
||||
|
||||
int getVisiteTagCount() {
|
||||
return visiteTagBox.count();
|
||||
}
|
||||
|
||||
Future<void> putPhotoTags(int photoId, List<String> tags) async {
|
||||
final photo = photoBox.get(photoId);
|
||||
|
||||
if (photo != null) {
|
||||
final updatedPhoto = photo.copyWith(tags: tags.join(","));
|
||||
await photoBox.putAsync(updatedPhoto);
|
||||
}
|
||||
}
|
||||
|
||||
/// PHOTO --------------------------------------------------------------------
|
||||
///
|
||||
void addPhotos(List<Photo> _listPhotos) {
|
||||
store.box<Photo>().putManyAsync(_listPhotos);
|
||||
///
|
||||
|
||||
Future<List<Photo>> addPhotos(List<Photo> photos) async {
|
||||
final addedPhotos = await photoBox.putAndGetManyAsync(photos);
|
||||
return addedPhotos;
|
||||
}
|
||||
|
||||
Future<void> addPhoto(int id_visite, int id_photo_typologie, String image,
|
||||
|
|
@ -372,7 +402,7 @@ class ObjectBox {
|
|||
store.box<Photo>().put(_Photo);
|
||||
}
|
||||
|
||||
List<Photo> getPhotos2() {
|
||||
List<Photo> getAllPhotos() {
|
||||
// Query for all photos, sorted by their date.
|
||||
// https://docs.objectbox.io/queries
|
||||
final query = photoBox
|
||||
|
|
@ -382,6 +412,18 @@ class ObjectBox {
|
|||
return query.find();
|
||||
}
|
||||
|
||||
/// Retrieves a Photo object from the ObjectBox database with the specified ID.
|
||||
///
|
||||
/// Parameters:
|
||||
/// id_photo: The ID of the photo to retrieve.
|
||||
///
|
||||
/// Returns:
|
||||
/// A Photo object, or null if no object is found.
|
||||
Photo? getPhotoById(int id_photo) {
|
||||
final photo = photoBox.get(id_photo);
|
||||
return photo;
|
||||
}
|
||||
|
||||
Stream<List<Photo>> getPhotos() {
|
||||
// Query for all photos, sorted by their date.
|
||||
// https://docs.objectbox.io/queries
|
||||
|
|
|
|||
|
|
@ -220,7 +220,7 @@ final _entities = <ModelEntity>[
|
|||
ModelEntity(
|
||||
id: const IdUid(7, 8290500625256822711),
|
||||
name: 'Visite',
|
||||
lastPropertyId: const IdUid(11, 3119168728902810585),
|
||||
lastPropertyId: const IdUid(13, 1900114397693432703),
|
||||
flags: 0,
|
||||
properties: <ModelProperty>[
|
||||
ModelProperty(
|
||||
|
|
@ -267,6 +267,11 @@ final _entities = <ModelEntity>[
|
|||
id: const IdUid(11, 3119168728902810585),
|
||||
name: 'date_visite',
|
||||
type: 10,
|
||||
flags: 0),
|
||||
ModelProperty(
|
||||
id: const IdUid(13, 1900114397693432703),
|
||||
name: 'url_photo_principale',
|
||||
type: 9,
|
||||
flags: 0)
|
||||
],
|
||||
relations: <ModelRelation>[],
|
||||
|
|
@ -308,7 +313,7 @@ final _entities = <ModelEntity>[
|
|||
ModelEntity(
|
||||
id: const IdUid(9, 6788844671665652158),
|
||||
name: 'Photo',
|
||||
lastPropertyId: const IdUid(16, 539065583624712715),
|
||||
lastPropertyId: const IdUid(17, 7248999677905103482),
|
||||
flags: 0,
|
||||
properties: <ModelProperty>[
|
||||
ModelProperty(
|
||||
|
|
@ -316,11 +321,6 @@ final _entities = <ModelEntity>[
|
|||
name: 'id',
|
||||
type: 6,
|
||||
flags: 1),
|
||||
ModelProperty(
|
||||
id: const IdUid(2, 7877546811840884522),
|
||||
name: 'id_photo',
|
||||
type: 6,
|
||||
flags: 0),
|
||||
ModelProperty(
|
||||
id: const IdUid(3, 1374846727562410311),
|
||||
name: 'id_visite',
|
||||
|
|
@ -351,26 +351,6 @@ final _entities = <ModelEntity>[
|
|||
name: 'photo_principale',
|
||||
type: 6,
|
||||
flags: 0),
|
||||
ModelProperty(
|
||||
id: const IdUid(10, 2757780641715705310),
|
||||
name: 'photo_tag1',
|
||||
type: 9,
|
||||
flags: 0),
|
||||
ModelProperty(
|
||||
id: const IdUid(11, 6494338359539955476),
|
||||
name: 'photo_tag2',
|
||||
type: 9,
|
||||
flags: 0),
|
||||
ModelProperty(
|
||||
id: const IdUid(12, 5293139139799032553),
|
||||
name: 'photo_tag3',
|
||||
type: 9,
|
||||
flags: 0),
|
||||
ModelProperty(
|
||||
id: const IdUid(13, 2141346538986140281),
|
||||
name: 'photo_tag4',
|
||||
type: 9,
|
||||
flags: 0),
|
||||
ModelProperty(
|
||||
id: const IdUid(14, 4568092734700892012),
|
||||
name: 'uploaded',
|
||||
|
|
@ -385,6 +365,11 @@ final _entities = <ModelEntity>[
|
|||
id: const IdUid(16, 539065583624712715),
|
||||
name: 'image_name',
|
||||
type: 9,
|
||||
flags: 0),
|
||||
ModelProperty(
|
||||
id: const IdUid(17, 7248999677905103482),
|
||||
name: 'tags',
|
||||
type: 9,
|
||||
flags: 0)
|
||||
],
|
||||
relations: <ModelRelation>[],
|
||||
|
|
@ -441,18 +426,24 @@ ModelDefinition getObjectBoxModel() {
|
|||
final model = ModelInfo(
|
||||
entities: _entities,
|
||||
lastEntityId: const IdUid(10, 2779194860339140505),
|
||||
lastIndexId: const IdUid(0, 0),
|
||||
lastIndexId: const IdUid(1, 7907819717055295102),
|
||||
lastRelationId: const IdUid(0, 0),
|
||||
lastSequenceId: const IdUid(0, 0),
|
||||
retiredEntityUids: const [7401686910042688313],
|
||||
retiredIndexUids: const [],
|
||||
retiredIndexUids: const [7907819717055295102],
|
||||
retiredPropertyUids: const [
|
||||
402019719780433349,
|
||||
2876428622751679696,
|
||||
6435857490868115471,
|
||||
4582947574501853036,
|
||||
103801570610300983,
|
||||
1940661113633121688
|
||||
1940661113633121688,
|
||||
2757780641715705310,
|
||||
6494338359539955476,
|
||||
5293139139799032553,
|
||||
2141346538986140281,
|
||||
7877546811840884522,
|
||||
3784190804330297742
|
||||
],
|
||||
retiredRelationUids: const [],
|
||||
modelVersion: 5,
|
||||
|
|
@ -676,7 +667,9 @@ ModelDefinition getObjectBoxModel() {
|
|||
objectToFB: (Visite object, fb.Builder fbb) {
|
||||
final type_visiteOffset = fbb.writeString(object.type_visite);
|
||||
final titleOffset = fbb.writeString(object.title);
|
||||
fbb.startTable(12);
|
||||
final url_photo_principaleOffset =
|
||||
fbb.writeString(object.url_photo_principale);
|
||||
fbb.startTable(14);
|
||||
fbb.addInt64(0, object.id);
|
||||
fbb.addInt64(1, object.id_visite);
|
||||
fbb.addOffset(2, type_visiteOffset);
|
||||
|
|
@ -686,6 +679,7 @@ ModelDefinition getObjectBoxModel() {
|
|||
fbb.addInt64(7, object.id_etab);
|
||||
fbb.addInt64(8, object.abandon);
|
||||
fbb.addInt64(10, object.date_visite.millisecondsSinceEpoch);
|
||||
fbb.addOffset(12, url_photo_principaleOffset);
|
||||
fbb.finish(fbb.endTable());
|
||||
return object.id;
|
||||
},
|
||||
|
|
@ -710,7 +704,10 @@ ModelDefinition getObjectBoxModel() {
|
|||
id_etab:
|
||||
const fb.Int64Reader().vTableGet(buffer, rootOffset, 18, 0),
|
||||
abandon:
|
||||
const fb.Int64Reader().vTableGet(buffer, rootOffset, 20, 0));
|
||||
const fb.Int64Reader().vTableGet(buffer, rootOffset, 20, 0),
|
||||
url_photo_principale:
|
||||
const fb.StringReader(asciiOptimization: true)
|
||||
.vTableGet(buffer, rootOffset, 28, ''));
|
||||
|
||||
return object;
|
||||
}),
|
||||
|
|
@ -760,28 +757,21 @@ ModelDefinition getObjectBoxModel() {
|
|||
object.id = id;
|
||||
},
|
||||
objectToFB: (Photo object, fb.Builder fbb) {
|
||||
final photo_tag1Offset = fbb.writeString(object.photo_tag1);
|
||||
final photo_tag2Offset = fbb.writeString(object.photo_tag2);
|
||||
final photo_tag3Offset = fbb.writeString(object.photo_tag3);
|
||||
final photo_tag4Offset = fbb.writeString(object.photo_tag4);
|
||||
final imageOffset = fbb.writeString(object.image);
|
||||
final image_nameOffset = fbb.writeString(object.image_name);
|
||||
fbb.startTable(17);
|
||||
final tagsOffset = fbb.writeString(object.tags);
|
||||
fbb.startTable(18);
|
||||
fbb.addInt64(0, object.id);
|
||||
fbb.addInt64(1, object.id_photo);
|
||||
fbb.addInt64(2, object.id_visite);
|
||||
fbb.addInt64(3, object.id_photo_typologie);
|
||||
fbb.addInt64(5, object.date_photo.millisecondsSinceEpoch);
|
||||
fbb.addInt64(6, object.id_photo_mp4);
|
||||
fbb.addInt64(7, object.photo_privee);
|
||||
fbb.addInt64(8, object.photo_principale);
|
||||
fbb.addOffset(9, photo_tag1Offset);
|
||||
fbb.addOffset(10, photo_tag2Offset);
|
||||
fbb.addOffset(11, photo_tag3Offset);
|
||||
fbb.addOffset(12, photo_tag4Offset);
|
||||
fbb.addInt64(13, object.uploaded);
|
||||
fbb.addOffset(14, imageOffset);
|
||||
fbb.addOffset(15, image_nameOffset);
|
||||
fbb.addOffset(16, tagsOffset);
|
||||
fbb.finish(fbb.endTable());
|
||||
return object.id;
|
||||
},
|
||||
|
|
@ -799,23 +789,18 @@ ModelDefinition getObjectBoxModel() {
|
|||
.vTableGet(buffer, rootOffset, 32, ''),
|
||||
image_name: const fb.StringReader(asciiOptimization: true)
|
||||
.vTableGet(buffer, rootOffset, 34, ''),
|
||||
id_photo:
|
||||
const fb.Int64Reader().vTableGet(buffer, rootOffset, 6, 0),
|
||||
id_photo_mp4:
|
||||
const fb.Int64Reader().vTableGet(buffer, rootOffset, 16, 0),
|
||||
photo_privee:
|
||||
const fb.Int64Reader().vTableGet(buffer, rootOffset, 18, 0),
|
||||
photo_principale:
|
||||
const fb.Int64Reader().vTableGet(buffer, rootOffset, 20, 0),
|
||||
photo_tag1: const fb.StringReader(asciiOptimization: true)
|
||||
.vTableGet(buffer, rootOffset, 22, ''),
|
||||
photo_tag2: const fb.StringReader(asciiOptimization: true)
|
||||
.vTableGet(buffer, rootOffset, 24, ''),
|
||||
photo_tag3:
|
||||
const fb.StringReader(asciiOptimization: true).vTableGet(buffer, rootOffset, 26, ''),
|
||||
photo_tag4: const fb.StringReader(asciiOptimization: true).vTableGet(buffer, rootOffset, 28, ''),
|
||||
date_photo: DateTime.fromMillisecondsSinceEpoch(const fb.Int64Reader().vTableGet(buffer, rootOffset, 14, 0)),
|
||||
uploaded: const fb.Int64Reader().vTableGet(buffer, rootOffset, 30, 0));
|
||||
tags: const fb.StringReader(asciiOptimization: true)
|
||||
.vTableGet(buffer, rootOffset, 36, ''),
|
||||
date_photo: DateTime.fromMillisecondsSinceEpoch(
|
||||
const fb.Int64Reader().vTableGet(buffer, rootOffset, 14, 0)),
|
||||
uploaded:
|
||||
const fb.Int64Reader().vTableGet(buffer, rootOffset, 30, 0));
|
||||
|
||||
return object;
|
||||
}),
|
||||
|
|
@ -1001,6 +986,10 @@ class Visite_ {
|
|||
/// see [Visite.date_visite]
|
||||
static final date_visite =
|
||||
QueryIntegerProperty<Visite>(_entities[5].properties[8]);
|
||||
|
||||
/// see [Visite.url_photo_principale]
|
||||
static final url_photo_principale =
|
||||
QueryStringProperty<Visite>(_entities[5].properties[9]);
|
||||
}
|
||||
|
||||
/// [VisiteTag] entity fields to define ObjectBox queries.
|
||||
|
|
@ -1030,60 +1019,43 @@ class Photo_ {
|
|||
/// see [Photo.id]
|
||||
static final id = QueryIntegerProperty<Photo>(_entities[7].properties[0]);
|
||||
|
||||
/// see [Photo.id_photo]
|
||||
static final id_photo =
|
||||
QueryIntegerProperty<Photo>(_entities[7].properties[1]);
|
||||
|
||||
/// see [Photo.id_visite]
|
||||
static final id_visite =
|
||||
QueryIntegerProperty<Photo>(_entities[7].properties[2]);
|
||||
QueryIntegerProperty<Photo>(_entities[7].properties[1]);
|
||||
|
||||
/// see [Photo.id_photo_typologie]
|
||||
static final id_photo_typologie =
|
||||
QueryIntegerProperty<Photo>(_entities[7].properties[3]);
|
||||
QueryIntegerProperty<Photo>(_entities[7].properties[2]);
|
||||
|
||||
/// see [Photo.date_photo]
|
||||
static final date_photo =
|
||||
QueryIntegerProperty<Photo>(_entities[7].properties[4]);
|
||||
QueryIntegerProperty<Photo>(_entities[7].properties[3]);
|
||||
|
||||
/// see [Photo.id_photo_mp4]
|
||||
static final id_photo_mp4 =
|
||||
QueryIntegerProperty<Photo>(_entities[7].properties[5]);
|
||||
QueryIntegerProperty<Photo>(_entities[7].properties[4]);
|
||||
|
||||
/// see [Photo.photo_privee]
|
||||
static final photo_privee =
|
||||
QueryIntegerProperty<Photo>(_entities[7].properties[6]);
|
||||
QueryIntegerProperty<Photo>(_entities[7].properties[5]);
|
||||
|
||||
/// see [Photo.photo_principale]
|
||||
static final photo_principale =
|
||||
QueryIntegerProperty<Photo>(_entities[7].properties[7]);
|
||||
|
||||
/// see [Photo.photo_tag1]
|
||||
static final photo_tag1 =
|
||||
QueryStringProperty<Photo>(_entities[7].properties[8]);
|
||||
|
||||
/// see [Photo.photo_tag2]
|
||||
static final photo_tag2 =
|
||||
QueryStringProperty<Photo>(_entities[7].properties[9]);
|
||||
|
||||
/// see [Photo.photo_tag3]
|
||||
static final photo_tag3 =
|
||||
QueryStringProperty<Photo>(_entities[7].properties[10]);
|
||||
|
||||
/// see [Photo.photo_tag4]
|
||||
static final photo_tag4 =
|
||||
QueryStringProperty<Photo>(_entities[7].properties[11]);
|
||||
QueryIntegerProperty<Photo>(_entities[7].properties[6]);
|
||||
|
||||
/// see [Photo.uploaded]
|
||||
static final uploaded =
|
||||
QueryIntegerProperty<Photo>(_entities[7].properties[12]);
|
||||
QueryIntegerProperty<Photo>(_entities[7].properties[7]);
|
||||
|
||||
/// see [Photo.image]
|
||||
static final image = QueryStringProperty<Photo>(_entities[7].properties[13]);
|
||||
static final image = QueryStringProperty<Photo>(_entities[7].properties[8]);
|
||||
|
||||
/// see [Photo.image_name]
|
||||
static final image_name =
|
||||
QueryStringProperty<Photo>(_entities[7].properties[14]);
|
||||
QueryStringProperty<Photo>(_entities[7].properties[9]);
|
||||
|
||||
/// see [Photo.tags]
|
||||
static final tags = QueryStringProperty<Photo>(_entities[7].properties[10]);
|
||||
}
|
||||
|
||||
/// [PhotoTypology] entity fields to define ObjectBox queries.
|
||||
|
|
|
|||
|
|
@ -88,4 +88,18 @@ class SharedPrefs {
|
|||
set photo(String value) {
|
||||
_sharedPrefs.setString('key_photo', value);
|
||||
}
|
||||
|
||||
/// get/set id_distrib
|
||||
int get id_distrib => _sharedPrefs.getInt('key_id_distrib') ?? 0;
|
||||
|
||||
set id_distrib(int value) {
|
||||
_sharedPrefs.setInt('key_id_distrib', value);
|
||||
}
|
||||
|
||||
/// get/set id_visite
|
||||
int get id_visite => _sharedPrefs.getInt('key_id_visite') ?? 0;
|
||||
|
||||
set id_visite(int value) {
|
||||
_sharedPrefs.setInt('key_id_visite', value);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:fluttertoast/fluttertoast.dart';
|
||||
import 'package:filter_list/filter_list.dart';
|
||||
|
||||
import 'package:mobdr/config/constant.dart';
|
||||
import 'package:mobdr/config/global_style.dart';
|
||||
|
|
@ -10,14 +10,20 @@ 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/db/box_photo.dart';
|
||||
|
||||
class PhotoDetailPage 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;
|
||||
|
|
@ -25,10 +31,13 @@ class PhotoDetailPage extends StatefulWidget {
|
|||
final int sale;
|
||||
final String date;
|
||||
|
||||
// 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,
|
||||
|
|
@ -46,8 +55,11 @@ class _PhotoDetailPageState extends State<PhotoDetailPage> {
|
|||
final _globalFunction = GlobalFunction();
|
||||
final _reusableWidget = ReusableWidget();
|
||||
|
||||
bool _isLoading = true;
|
||||
String _errorMessage = '';
|
||||
|
||||
// Typology list
|
||||
List<String> _typologyList = objectbox.getPhotoTypologiesLabels();
|
||||
late List<String> _typologyList = [];
|
||||
int _typologyIndex = 0;
|
||||
|
||||
List<String> _chickenParts = [];
|
||||
|
|
@ -56,13 +68,20 @@ class _PhotoDetailPageState extends State<PhotoDetailPage> {
|
|||
// shopping cart count
|
||||
int _shoppingCartCount = 3;
|
||||
|
||||
// tag(s) list
|
||||
final List<String> tagsList = objectbox.getVisiteTagsLabels();
|
||||
List<String> selectedTagsList = [];
|
||||
late String tags = "";
|
||||
late List<String> tagList = [];
|
||||
|
||||
late Photo _photo;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
loadData(widget.id).then((_) {
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
@ -72,6 +91,24 @@ class _PhotoDetailPageState extends State<PhotoDetailPage> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (_isLoading) {
|
||||
return Center(child: CircularProgressIndicator());
|
||||
} else if (_errorMessage.isNotEmpty) {
|
||||
return Center(
|
||||
child: AlertDialog(
|
||||
title: Text("Erreur"),
|
||||
content: Text("La photo est introuvable"),
|
||||
actions: <Widget>[
|
||||
TextButton(
|
||||
child: Text("OK"),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
iconTheme: IconThemeData(
|
||||
|
|
@ -150,7 +187,7 @@ class _PhotoDetailPageState extends State<PhotoDetailPage> {
|
|||
//_createProductSlider(),
|
||||
_buildPhotoTypology(),
|
||||
_buildPhotoVisibility(),
|
||||
_buildPhotoTag(),
|
||||
_buildPhotoTag(context),
|
||||
SizedBox(height: 16)
|
||||
],
|
||||
),
|
||||
|
|
@ -302,6 +339,7 @@ class _PhotoDetailPageState extends State<PhotoDetailPage> {
|
|||
);
|
||||
}
|
||||
|
||||
// TODO changer chicken
|
||||
Widget _checboxChicken({value = 'breast', primaryText = 'Chicken Breast'}) {
|
||||
return GestureDetector(
|
||||
behavior: HitTestBehavior.translucent,
|
||||
|
|
@ -379,74 +417,69 @@ class _PhotoDetailPageState extends State<PhotoDetailPage> {
|
|||
);
|
||||
}
|
||||
|
||||
Widget _buildPhotoTag() {
|
||||
return Container(
|
||||
Widget _buildPhotoTag(BuildContext context) {
|
||||
return GestureDetector(
|
||||
onTap: () async {
|
||||
// Navigation to the PhotoTagPage
|
||||
final newTags = await Navigator.push<List<String>>(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) =>
|
||||
PhotoTagPage(photoId: this._photo.id, currentTags: tagList),
|
||||
),
|
||||
);
|
||||
|
||||
// Checking changes made to tags
|
||||
if (newTags != null && !listEquals(tagList, newTags)) {
|
||||
setState(() {
|
||||
tagList = newTags;
|
||||
});
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
margin: EdgeInsets.only(top: 12),
|
||||
padding: EdgeInsets.all(16),
|
||||
color: Colors.white,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text("Tags sélectionnés:"),
|
||||
SizedBox(height: 8),
|
||||
selectedTagsList.isEmpty
|
||||
? Text("Aucun tag sélectionné.")
|
||||
: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: tagsList.map((tag) => Text("- $tag")).toList(),
|
||||
),
|
||||
SizedBox(height: 16),
|
||||
ElevatedButton(
|
||||
onPressed: () => _openTagSelectionDialog(),
|
||||
child: Text("Modifier"),
|
||||
Row(
|
||||
children: [
|
||||
Text('Tags', style: GlobalStyle.sectionTitle),
|
||||
],
|
||||
),
|
||||
Wrap(
|
||||
spacing: 8.0,
|
||||
runSpacing: 8.0,
|
||||
alignment: WrapAlignment.start,
|
||||
children: tagList.map((tag) {
|
||||
return Chip(
|
||||
label: Text(tag),
|
||||
backgroundColor: Colors.grey[300],
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
],
|
||||
));
|
||||
}
|
||||
|
||||
Future<void> _openTagSelectionDialog() async {
|
||||
await FilterListDialog.display<String>(
|
||||
context,
|
||||
hideSelectedTextCount: true,
|
||||
themeData: FilterListThemeData(context),
|
||||
headlineText: 'Select Users',
|
||||
height: 500,
|
||||
listData: tagsList,
|
||||
selectedListData: selectedTagsList,
|
||||
choiceChipLabel: (item) => item,
|
||||
validateSelectedItem: (list, val) => list!.contains(val),
|
||||
controlButtons: [ControlButtonType.All, ControlButtonType.Reset],
|
||||
onItemSearch: (user, query) {
|
||||
/// When search query change in search bar then this method will be called
|
||||
///
|
||||
/// Check if items contains query
|
||||
return user.toLowerCase().contains(query.toLowerCase());
|
||||
},
|
||||
|
||||
onApplyButtonClick: (list) {
|
||||
setState(() {
|
||||
selectedTagsList = list!;
|
||||
});
|
||||
Navigator.pop(context);
|
||||
},
|
||||
|
||||
/// uncomment below code to create custom choice chip
|
||||
/*
|
||||
choiceChipBuilder: (context, item, isSelected) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
||||
margin: const EdgeInsets.symmetric(horizontal: 10, vertical: 10),
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(
|
||||
color: isSelected! ? Colors.blue[300]! : Colors.grey[300]!,
|
||||
)),
|
||||
child: Text(
|
||||
item,
|
||||
style: TextStyle(
|
||||
color: isSelected ? Colors.blue[300] : Colors.grey[500]),
|
||||
),
|
||||
);
|
||||
},*/
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// data initialization on loading.
|
||||
Future<void> loadData(int photoId) async {
|
||||
try {
|
||||
// photo typologies initialization
|
||||
_typologyList = objectbox.getPhotoTypologiesLabels();
|
||||
|
||||
// get photo object
|
||||
_photo = objectbox.getPhotoById(photoId)!;
|
||||
|
||||
// photo tag initialization
|
||||
tags = _photo.tags;
|
||||
tagList = tags.isEmpty ? [] : tags.split(",");
|
||||
} catch (e) {
|
||||
// set errorMessage for debug
|
||||
_errorMessage = 'Error loading photo: $e';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ import 'package:mobdr/config/constant.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/model/photo_model.dart';
|
||||
import 'package:mobdr/db/box_photo.dart';
|
||||
import 'package:mobdr/ui/home/photo_detail.dart';
|
||||
|
||||
|
|
@ -37,7 +36,7 @@ class _PhotoListPageState extends State<PhotoListPage> {
|
|||
|
||||
// initialize photos files list
|
||||
final List<File> photoFiles = [];
|
||||
List<PhotoModel> _photoData = [];
|
||||
List<Photo> _photoData = [];
|
||||
|
||||
Color _color1 = Color(0xff777777);
|
||||
Color _color2 = Color(0xFF515151);
|
||||
|
|
@ -57,13 +56,7 @@ class _PhotoListPageState extends State<PhotoListPage> {
|
|||
}
|
||||
|
||||
void _loadData() {
|
||||
for (Photo myPhoto in objectbox.getPhotos2()) {
|
||||
_photoData.add(PhotoModel(
|
||||
id_visite: myPhoto.id_visite,
|
||||
id_photo_typologie: myPhoto.id_photo_typologie,
|
||||
image: myPhoto.image,
|
||||
image_name: myPhoto.image_name));
|
||||
}
|
||||
_photoData = objectbox.getAllPhotos();
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
@ -114,8 +107,7 @@ class _PhotoListPageState extends State<PhotoListPage> {
|
|||
floatingActionButton: fabCart(context));
|
||||
}
|
||||
|
||||
Widget _buildPhotolistCard(
|
||||
PhotoModel photoData, boxImageSize, animation, index) {
|
||||
Widget _buildPhotolistCard(Photo photoData, boxImageSize, animation, index) {
|
||||
return SizeTransition(
|
||||
sizeFactor: animation,
|
||||
child: Container(
|
||||
|
|
@ -136,6 +128,7 @@ class _PhotoListPageState extends State<PhotoListPage> {
|
|||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => PhotoDetailPage(
|
||||
id: _photoData[index].id,
|
||||
name: 'visiteData.name',
|
||||
image: _photoData[index].image,
|
||||
price: 0,
|
||||
|
|
@ -144,6 +137,12 @@ class _PhotoListPageState extends State<PhotoListPage> {
|
|||
review: 0,
|
||||
sale: 0,
|
||||
date: '')));
|
||||
|
||||
// todo if qq chose à changé
|
||||
// ne raffraichir que le widget en cours ==
|
||||
setState(() {
|
||||
_listKey = GlobalKey();
|
||||
});
|
||||
},
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
|
|
@ -414,32 +413,24 @@ class _PhotoListPageState extends State<PhotoListPage> {
|
|||
void savePhotos() async {
|
||||
if (photoFiles.length > 0) {
|
||||
final List<Photo> _listPhotos = [];
|
||||
final List<PhotoModel> _listPhotosModel = [];
|
||||
|
||||
for (var myTmpPhoto in photoFiles) {
|
||||
/// move jpg file to photo directory
|
||||
final myPhoto = await moveFileFromTempToPhotosDir(myTmpPhoto);
|
||||
|
||||
/// database
|
||||
/// to insert into database
|
||||
_listPhotos.add(Photo(
|
||||
id_visite: 0,
|
||||
id_photo_typologie: 0,
|
||||
image: myPhoto.path,
|
||||
image_name: myPhoto.path.split('/').last));
|
||||
|
||||
/// widget
|
||||
_listPhotosModel.add(PhotoModel(
|
||||
id_visite: 0,
|
||||
id_photo_typologie: 0,
|
||||
image: myPhoto.path,
|
||||
image_name: myPhoto.path.split('/').last));
|
||||
}
|
||||
|
||||
/// insert photo(s) in database (async)
|
||||
objectbox.addPhotos(_listPhotos);
|
||||
final addedPhotos = await objectbox.addPhotos(_listPhotos);
|
||||
|
||||
/// insert photo(s) in widget
|
||||
_photoData.insertAll(0, _listPhotosModel);
|
||||
/// insert photo(s) in widget at the beginning (0)
|
||||
_photoData.insertAll(0, addedPhotos);
|
||||
|
||||
/// refresh widget
|
||||
setState(() {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,268 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
import 'package:mobdr/main.dart';
|
||||
import 'package:mobdr/config/global_style.dart';
|
||||
|
||||
import 'package:super_tag_editor/tag_editor.dart';
|
||||
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<String> currentTags;
|
||||
|
||||
// Requiring data parameters
|
||||
const PhotoTagPage(
|
||||
{Key? key, required this.photoId, required this.currentTags})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
_PhotoTagPageState createState() => _PhotoTagPageState();
|
||||
}
|
||||
|
||||
class _PhotoTagPageState extends State<PhotoTagPage> {
|
||||
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
|
||||
|
||||
late List<String> allTagsList = [];
|
||||
late List<String> _selectedTags = [];
|
||||
bool isLoading = true;
|
||||
|
||||
final FocusNode _focusNode = FocusNode();
|
||||
final TextEditingController _textEditingController = TextEditingController();
|
||||
bool focusTagEnabled = false;
|
||||
|
||||
_onDelete(index) {
|
||||
setState(() {
|
||||
_selectedTags.removeAt(index);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
loadData().then((_) {
|
||||
setState(() {
|
||||
isLoading = false;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (isLoading) {
|
||||
return Center(child: CircularProgressIndicator());
|
||||
}
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.white,
|
||||
appBar: AppBar(
|
||||
iconTheme: IconThemeData(
|
||||
color: GlobalStyle.appBarIconThemeColor,
|
||||
),
|
||||
elevation: GlobalStyle.appBarElevation,
|
||||
title: Text(
|
||||
'Edit tags ...',
|
||||
style: GlobalStyle.appBarTitle,
|
||||
),
|
||||
backgroundColor: GlobalStyle.appBarBackgroundColor,
|
||||
systemOverlayStyle: GlobalStyle.appBarSystemOverlayStyle),
|
||||
body: Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: ListView(
|
||||
children: <Widget>[
|
||||
TagEditor<String>(
|
||||
length: _selectedTags.length,
|
||||
controller: _textEditingController,
|
||||
focusNode: _focusNode,
|
||||
delimiters: [',', ' '],
|
||||
hasAddButton: true,
|
||||
resetTextOnSubmitted: true,
|
||||
// This is set to grey just to illustrate the `textStyle` prop
|
||||
textStyle: const TextStyle(color: Colors.grey),
|
||||
onSubmitted: (outstandingValue) {
|
||||
setState(() {
|
||||
_selectedTags.add(outstandingValue);
|
||||
});
|
||||
},
|
||||
inputDecoration: const InputDecoration(
|
||||
border: InputBorder.none,
|
||||
hintText: 'Enter tag ...',
|
||||
),
|
||||
onTagChanged: (newValue) {
|
||||
setState(() {
|
||||
_selectedTags.add(newValue);
|
||||
});
|
||||
},
|
||||
tagBuilder: (context, index) => Container(
|
||||
color: focusTagEnabled && index == _selectedTags.length - 1
|
||||
? Colors.redAccent
|
||||
: Colors.white,
|
||||
child: _Chip(
|
||||
index: index,
|
||||
label: _selectedTags[index],
|
||||
onDeleted: _onDelete,
|
||||
),
|
||||
),
|
||||
// InputFormatters example, this disallow \ and /
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.deny(RegExp(r'[/\\]'))
|
||||
],
|
||||
useDefaultHighlight: false,
|
||||
suggestionBuilder: (context, state, data, index, length,
|
||||
highlight, suggestionValid) {
|
||||
var borderRadius =
|
||||
const BorderRadius.all(Radius.circular(20));
|
||||
if (index == 0) {
|
||||
borderRadius = const BorderRadius.only(
|
||||
topLeft: Radius.circular(20),
|
||||
topRight: Radius.circular(20),
|
||||
);
|
||||
} else if (index == length - 1) {
|
||||
borderRadius = const BorderRadius.only(
|
||||
bottomRight: Radius.circular(20),
|
||||
bottomLeft: Radius.circular(20),
|
||||
);
|
||||
}
|
||||
return InkWell(
|
||||
onTap: () {
|
||||
setState(() {
|
||||
_selectedTags.add(data);
|
||||
});
|
||||
state.resetTextField();
|
||||
state.closeSuggestionBox();
|
||||
},
|
||||
child: Container(
|
||||
decoration: highlight
|
||||
? BoxDecoration(
|
||||
color: Theme.of(context).focusColor,
|
||||
borderRadius: borderRadius)
|
||||
: null,
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: RichTextWidget(
|
||||
wordSearched: suggestionValid ?? '',
|
||||
textOrigin: data,
|
||||
)),
|
||||
);
|
||||
},
|
||||
onFocusTagAction: (focused) {
|
||||
setState(() {
|
||||
focusTagEnabled = focused;
|
||||
});
|
||||
},
|
||||
onDeleteTagAction: () {
|
||||
if (_selectedTags.isNotEmpty) {
|
||||
setState(() {
|
||||
_selectedTags.removeLast();
|
||||
});
|
||||
}
|
||||
},
|
||||
onSelectOptionAction: (item) {
|
||||
setState(() {
|
||||
_selectedTags.add(item);
|
||||
});
|
||||
},
|
||||
suggestionsBoxElevation: 10,
|
||||
findSuggestions: (String query) {
|
||||
if (query.isNotEmpty) {
|
||||
var lowercaseQuery = query.toLowerCase();
|
||||
var filteredList = allTagsList
|
||||
.where((tag) =>
|
||||
!_selectedTags.contains(tag) &&
|
||||
(tag.toLowerCase().startsWith(lowercaseQuery) ||
|
||||
tag.toLowerCase().contains(lowercaseQuery)))
|
||||
.toList(growable: false);
|
||||
|
||||
filteredList.sort((a, b) => a
|
||||
.toLowerCase()
|
||||
.indexOf(lowercaseQuery)
|
||||
.compareTo(b.toLowerCase().indexOf(lowercaseQuery)));
|
||||
|
||||
return filteredList;
|
||||
}
|
||||
return [];
|
||||
},
|
||||
),
|
||||
const Divider(),
|
||||
ElevatedButton(
|
||||
onPressed: () async {
|
||||
// Save the selected tags to the database //TODO 1,fr ===
|
||||
await saveSelectedTags(_selectedTags, 1, 'fr');
|
||||
|
||||
Navigator.pop(
|
||||
context, _selectedTags.map((tag) => tag).toList());
|
||||
},
|
||||
child: const Text('Save'),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> loadData() async {
|
||||
// TODO 1,fr
|
||||
allTagsList = await objectbox.getVisiteTagsLabels(1, 'fr');
|
||||
_selectedTags = List<String>.from(widget.currentTags);
|
||||
}
|
||||
|
||||
/// Saves the selected tags for a photo to the ObjectBox database.
|
||||
///
|
||||
/// Parameters:
|
||||
/// tags: The list of tags to save.
|
||||
/// distribId: The ID of the distribution associated with the photo.
|
||||
/// langage: The language code for the tags.
|
||||
///
|
||||
/// If the list of tags is empty, the function will exit without saving any tags.
|
||||
/// Otherwise, any new tags that are not already in the database will be added,
|
||||
/// and the photo's tags will be saved to the database.
|
||||
///
|
||||
/// Returns:
|
||||
/// Nothing.
|
||||
Future<void> saveSelectedTags(
|
||||
List<String> tags, int distribId, String langage) async {
|
||||
if (tags.isEmpty) {
|
||||
return; // exit function without saving tags
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
// save photo tag in the database
|
||||
objectbox.putPhotoTags(widget.photoId, tags);
|
||||
}
|
||||
}
|
||||
|
||||
class _Chip extends StatelessWidget {
|
||||
const _Chip({
|
||||
required this.label,
|
||||
required this.onDeleted,
|
||||
required this.index,
|
||||
});
|
||||
|
||||
final String label;
|
||||
final ValueChanged<int> onDeleted;
|
||||
final int index;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Chip(
|
||||
labelPadding: const EdgeInsets.only(left: 8.0),
|
||||
label: Text(label),
|
||||
deleteIcon: const Icon(
|
||||
Icons.close,
|
||||
size: 18,
|
||||
),
|
||||
onDeleted: () {
|
||||
onDeleted(index);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -7,6 +7,9 @@ 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';
|
||||
|
|
@ -16,8 +19,6 @@ import 'package:mobdr/ui/home/photo_typology.dart';
|
|||
import 'package:mobdr/ui/general/product_detail/product_detail.dart';
|
||||
import 'package:mobdr/ui/reusable/reusable_widget.dart';
|
||||
import 'package:mobdr/ui/reusable/cache_image_network.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
class TabHomePage extends StatefulWidget {
|
||||
@override
|
||||
|
|
@ -40,8 +41,15 @@ class _TabHomePageState extends State<TabHomePage>
|
|||
|
||||
late LanguageCubit _languageCubit;
|
||||
|
||||
bool _isLoading = true;
|
||||
String _errorMessage = '';
|
||||
|
||||
late List<VisiteModel> visiteData = [];
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
_languageCubit = BlocProvider.of<LanguageCubit>(context);
|
||||
|
||||
_getLocale().then((val) {
|
||||
|
|
@ -50,7 +58,11 @@ class _TabHomePageState extends State<TabHomePage>
|
|||
});
|
||||
});
|
||||
|
||||
super.initState();
|
||||
loadData().then((_) {
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
@ -77,6 +89,13 @@ class _TabHomePageState extends State<TabHomePage>
|
|||
// if we used AutomaticKeepAliveClientMixin, we must call super.build(context);
|
||||
super.build(context);
|
||||
final double boxImageSize = (MediaQuery.of(context).size.width / 4);
|
||||
if (_isLoading) {
|
||||
return Center(child: CircularProgressIndicator());
|
||||
} else if (visiteData.isEmpty) {
|
||||
return Center(
|
||||
child: Text('Aucune visite trouvée.'),
|
||||
);
|
||||
}
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
automaticallyImplyLeading: false,
|
||||
|
|
@ -165,6 +184,7 @@ class _TabHomePageState extends State<TabHomePage>
|
|||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Container(height: 8),
|
||||
Text(
|
||||
visiteData.name,
|
||||
style: GlobalStyle.productName
|
||||
|
|
@ -172,39 +192,32 @@ class _TabHomePageState extends State<TabHomePage>
|
|||
maxLines: 3,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
Container(
|
||||
margin: EdgeInsets.only(top: 5),
|
||||
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),
|
||||
),
|
||||
Container(height: 5),
|
||||
Container(
|
||||
margin: EdgeInsets.only(top: 5),
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(Icons.location_on,
|
||||
color: SOFT_GREY, size: 12),
|
||||
Text(' ' + visiteData.location,
|
||||
style: GlobalStyle.productLocation)
|
||||
Icon(Icons.store, color: SOFT_GREY, size: 20),
|
||||
Text(' ' + visiteData.type_visite,
|
||||
style: GlobalStyle.productName
|
||||
.copyWith(fontSize: 13),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis)
|
||||
],
|
||||
),
|
||||
),
|
||||
Container(
|
||||
margin: EdgeInsets.only(top: 5),
|
||||
child: Row(
|
||||
children: [
|
||||
_reusableWidget.createRatingBar(
|
||||
rating: visiteData.rating, size: 12),
|
||||
Text('(' + visiteData.review.toString() + ')',
|
||||
style: GlobalStyle.productTotalReview)
|
||||
],
|
||||
),
|
||||
),
|
||||
Container(
|
||||
margin: EdgeInsets.only(top: 5),
|
||||
child: Text(visiteData.date,
|
||||
style: GlobalStyle.productSale),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
|
|
@ -282,4 +295,15 @@ class _TabHomePageState extends State<TabHomePage>
|
|||
),
|
||||
);
|
||||
}
|
||||
|
||||
// data initialization on loading.
|
||||
Future<void> loadData() async {
|
||||
try {
|
||||
// visite initialisation
|
||||
visiteData = await VisiteModel.getAllVisites();
|
||||
} catch (e) {
|
||||
// set errorMessage for debug
|
||||
_errorMessage = 'Error loading visites : $e';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
74
pubspec.lock
74
pubspec.lock
|
|
@ -289,14 +289,22 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.4"
|
||||
debounce_throttle:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: debounce_throttle
|
||||
sha256: c95cf47afda975fc507794a52040a16756fb2f31ad3027d4e691c41862ff5692
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
dio:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: dio
|
||||
sha256: "2644a9e0965a7aa3deb09cb8ce4081db4450c178f472818c8cd34216a3070d7b"
|
||||
sha256: "0894a098594263fe1caaba3520e3016d8a855caeb010a882273189cca10f11e9"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.0.2"
|
||||
version: "5.1.1"
|
||||
fake_async:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -321,14 +329,6 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.1.4"
|
||||
filter_list:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: filter_list
|
||||
sha256: "2d80d6d19beb7847c1176e8bf6fe06d302b23eb7d1bf48c231dd730409ff9b4d"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.2"
|
||||
fixnum:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -805,6 +805,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.4"
|
||||
pointer_interceptor:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pointer_interceptor
|
||||
sha256: "6aa680b30d96dccef496933d00208ad25f07e047f644dc98ce03ec6141633a9a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.9.3+4"
|
||||
pointycastle:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -873,58 +881,58 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: shared_preferences
|
||||
sha256: ee6257848f822b8481691f20c3e6d2bfee2e9eccb2a3d249907fcfb198c55b41
|
||||
sha256: "858aaa72d8f61637d64e776aca82e1c67e6d9ee07979123c5d17115031c1b13b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.18"
|
||||
version: "2.1.0"
|
||||
shared_preferences_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_android
|
||||
sha256: a51a4f9375097f94df1c6e0a49c0374440d31ab026b59d58a7e7660675879db4
|
||||
sha256: "7fa90471a6875d26ad78c7e4a675874b2043874586891128dc5899662c97db46"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.16"
|
||||
version: "2.1.2"
|
||||
shared_preferences_foundation:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_foundation
|
||||
sha256: "6b84fdf06b32bb336f972d373cd38b63734f3461ba56ac2ba01b56d052796259"
|
||||
sha256: "0c1c16c56c9708aa9c361541a6f0e5cc6fc12a3232d866a687a7b7db30032b07"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.4"
|
||||
version: "2.2.1"
|
||||
shared_preferences_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_linux
|
||||
sha256: d7fb71e6e20cd3dfffcc823a28da3539b392e53ed5fc5c2b90b55fdaa8a7e8fa
|
||||
sha256: "9d387433ca65717bbf1be88f4d5bb18f10508917a8fa2fb02e0fd0d7479a9afa"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.4"
|
||||
version: "2.2.0"
|
||||
shared_preferences_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_platform_interface
|
||||
sha256: "824bfd02713e37603b2bdade0842e47d56e7db32b1dcdd1cae533fb88e2913fc"
|
||||
sha256: fb5cf25c0235df2d0640ac1b1174f6466bd311f621574997ac59018a6664548d
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
version: "2.2.0"
|
||||
shared_preferences_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_web
|
||||
sha256: "6737b757e49ba93de2a233df229d0b6a87728cea1684da828cbc718b65dcf9d7"
|
||||
sha256: "74083203a8eae241e0de4a0d597dbedab3b8fef5563f33cf3c12d7e93c655ca5"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.5"
|
||||
version: "2.1.0"
|
||||
shared_preferences_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_windows
|
||||
sha256: bd014168e8484837c39ef21065b78f305810ceabc1d4f90be6e3b392ce81b46d
|
||||
sha256: "5e588e2efef56916a3b229c3bfe81e6a525665a454519ca51dbcc4236a274173"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.4"
|
||||
version: "2.2.0"
|
||||
shelf:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -949,6 +957,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
simple_observable:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: simple_observable
|
||||
sha256: b392795c48f8b5f301b4c8f73e15f56e38fe70f42278c649d8325e859a783301
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
sky_engine:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
|
|
@ -1018,6 +1034,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
super_tag_editor:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: super_tag_editor
|
||||
sha256: "0888ef22d5a1485baeb628892de449e03af4b6f901ac7f7c9ddd2f44f6199e22"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.1.1"
|
||||
synchronized:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -1179,5 +1203,5 @@ packages:
|
|||
source: hosted
|
||||
version: "3.1.1"
|
||||
sdks:
|
||||
dart: ">=2.19.0 <3.0.0"
|
||||
dart: ">=2.19.2 <3.0.0"
|
||||
flutter: ">=3.3.0"
|
||||
|
|
|
|||
12
pubspec.yaml
12
pubspec.yaml
|
|
@ -31,7 +31,8 @@ dependencies:
|
|||
flutter:
|
||||
sdk: flutter
|
||||
|
||||
dio: 5.0.2
|
||||
# https://pub.dev/packages/dio
|
||||
dio: 5.1.1
|
||||
objectbox: ^2.0.0
|
||||
objectbox_flutter_libs: any
|
||||
pin_code_fields: 7.4.0
|
||||
|
|
@ -55,8 +56,8 @@ dependencies:
|
|||
permission_handler: 10.2.0
|
||||
image: ^4.0.15
|
||||
|
||||
# https://pub.dev/packages/filter_list/install
|
||||
filter_list: ^1.0.2
|
||||
# https://pub.dev/packages/super_tag_editor
|
||||
super_tag_editor: ^0.1.1
|
||||
|
||||
flutter_cache_manager: ^3.3.0
|
||||
|
||||
|
|
@ -66,7 +67,10 @@ dependencies:
|
|||
carousel_slider: 4.2.1
|
||||
cached_network_image: 3.2.3
|
||||
get_it: ^7.2.0
|
||||
shared_preferences: 2.0.18
|
||||
|
||||
# https://pub.dev/packages/shared_preferences
|
||||
shared_preferences: ^2.1.0
|
||||
|
||||
timelines: ^0.1.0
|
||||
universal_io: 2.2.0
|
||||
xml: ^6.2.2
|
||||
|
|
|
|||
Loading…
Reference in New Issue