Amélioration de la splash_page et du login
This commit is contained in:
23
app/.cline
23
app/.cline
@@ -1,23 +0,0 @@
|
||||
{
|
||||
"memoryBank": {
|
||||
"enabled": true,
|
||||
"path": "./docs",
|
||||
"maxContextSize": 100000
|
||||
},
|
||||
"contextSettings": {
|
||||
"maxTokens": 100000,
|
||||
"cline.maxAutoApprovedRequests": 100,
|
||||
"cline.enableMemoryBank": true,
|
||||
"cline.includeSnippetsFromMemory": true,
|
||||
"cline.contextLength": 10000,
|
||||
"cline.autoFormat": true
|
||||
},
|
||||
"mcpServers": {
|
||||
"github.com/modelcontextprotocol/servers/tree/main/src/git": {
|
||||
"command": "python",
|
||||
"args": ["-m", "mcp_server_git"],
|
||||
"disabled": false,
|
||||
"autoApprove": []
|
||||
}
|
||||
}
|
||||
}
|
||||
2
app/.dart_tool/build/entrypoint/.packageLocations
Normal file
2
app/.dart_tool/build/entrypoint/.packageLocations
Normal file
@@ -0,0 +1,2 @@
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/build_daemon-4.0.4/lib/fake.dart
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/build_runner-2.4.15/lib/fake.dart
|
||||
54
app/.dart_tool/build/entrypoint/build.dart
Normal file
54
app/.dart_tool/build/entrypoint/build.dart
Normal file
@@ -0,0 +1,54 @@
|
||||
// @dart=3.6
|
||||
// ignore_for_file: directives_ordering
|
||||
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||
import 'package:build_runner_core/build_runner_core.dart' as _i1;
|
||||
import 'package:hive_generator/hive_generator.dart' as _i2;
|
||||
import 'package:source_gen/builder.dart' as _i3;
|
||||
import 'package:build_resolvers/builder.dart' as _i4;
|
||||
import 'dart:isolate' as _i5;
|
||||
import 'package:build_runner/build_runner.dart' as _i6;
|
||||
import 'dart:io' as _i7;
|
||||
|
||||
final _builders = <_i1.BuilderApplication>[
|
||||
_i1.apply(
|
||||
r'hive_generator:hive_generator',
|
||||
[_i2.getBuilder],
|
||||
_i1.toDependentsOf(r'hive_generator'),
|
||||
hideOutput: true,
|
||||
appliesBuilders: const [r'source_gen:combining_builder'],
|
||||
),
|
||||
_i1.apply(
|
||||
r'source_gen:combining_builder',
|
||||
[_i3.combiningBuilder],
|
||||
_i1.toNoneByDefault(),
|
||||
hideOutput: false,
|
||||
appliesBuilders: const [r'source_gen:part_cleanup'],
|
||||
),
|
||||
_i1.apply(
|
||||
r'build_resolvers:transitive_digests',
|
||||
[_i4.transitiveDigestsBuilder],
|
||||
_i1.toAllPackages(),
|
||||
isOptional: true,
|
||||
hideOutput: true,
|
||||
appliesBuilders: const [r'build_resolvers:transitive_digest_cleanup'],
|
||||
),
|
||||
_i1.applyPostProcess(
|
||||
r'build_resolvers:transitive_digest_cleanup',
|
||||
_i4.transitiveDigestCleanup,
|
||||
),
|
||||
_i1.applyPostProcess(
|
||||
r'source_gen:part_cleanup',
|
||||
_i3.partCleanup,
|
||||
),
|
||||
];
|
||||
void main(
|
||||
List<String> args, [
|
||||
_i5.SendPort? sendPort,
|
||||
]) async {
|
||||
var result = await _i6.run(
|
||||
args,
|
||||
_builders,
|
||||
);
|
||||
sendPort?.send(result);
|
||||
_i7.exitCode = result;
|
||||
}
|
||||
BIN
app/.dart_tool/build/entrypoint/build.dart.dill
Normal file
BIN
app/.dart_tool/build/entrypoint/build.dart.dill
Normal file
Binary file not shown.
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
<EFBFBD>
|
||||
@@ -0,0 +1 @@
|
||||
<EFBFBD>C><3E>N<EFBFBD>a<EFBFBD><61><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"<22>
|
||||
@@ -0,0 +1 @@
|
||||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>5z<EFBFBD><EFBFBD><EFBFBD>k<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
@@ -0,0 +1 @@
|
||||
<EFBFBD>ũ<EFBFBD><EFBFBD><0C><><EFBFBD>U/!<21><>W<EFBFBD>
|
||||
@@ -0,0 +1 @@
|
||||
<EFBFBD> n<><6E>A<EFBFBD><41><08><13>+<2B><><EFBFBD>
|
||||
@@ -0,0 +1 @@
|
||||
X<EFBFBD>͊?<3F>sSφ?/^<5E>-k
|
||||
@@ -0,0 +1 @@
|
||||
<EFBFBD><EFBFBD><EFBFBD>0)9#<23>D<EFBFBD><<3C>Ѹ#
|
||||
@@ -0,0 +1 @@
|
||||
!iT<69>IeS<65> 2d<32>.<2E>n
|
||||
@@ -0,0 +1 @@
|
||||
<05><><EFBFBD>[<5B><>,<2C><><EFBFBD><EFBFBD><18><><EFBFBD>
|
||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1 @@
|
||||
e<EFBFBD>v<EFBFBD><EFBFBD><EFBFBD>K4I<34>]Ĕ<>:
|
||||
@@ -0,0 +1,55 @@
|
||||
// **************************************************************************
|
||||
// TypeAdapterGenerator
|
||||
// **************************************************************************
|
||||
|
||||
class AnonymousUserModelAdapter extends TypeAdapter<AnonymousUserModel> {
|
||||
@override
|
||||
final int typeId = 24;
|
||||
|
||||
@override
|
||||
AnonymousUserModel read(BinaryReader reader) {
|
||||
final numOfFields = reader.readByte();
|
||||
final fields = <int, dynamic>{
|
||||
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
|
||||
};
|
||||
return AnonymousUserModel(
|
||||
id: fields[0] as String,
|
||||
deviceId: fields[1] as String,
|
||||
name: fields[2] as String?,
|
||||
email: fields[3] as String?,
|
||||
createdAt: fields[4] as DateTime,
|
||||
convertedToUserId: fields[5] as String?,
|
||||
metadata: (fields[6] as Map?)?.cast<String, dynamic>(),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void write(BinaryWriter writer, AnonymousUserModel obj) {
|
||||
writer
|
||||
..writeByte(7)
|
||||
..writeByte(0)
|
||||
..write(obj.id)
|
||||
..writeByte(1)
|
||||
..write(obj.deviceId)
|
||||
..writeByte(2)
|
||||
..write(obj.name)
|
||||
..writeByte(3)
|
||||
..write(obj.email)
|
||||
..writeByte(4)
|
||||
..write(obj.createdAt)
|
||||
..writeByte(5)
|
||||
..write(obj.convertedToUserId)
|
||||
..writeByte(6)
|
||||
..write(obj.metadata);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => typeId.hashCode;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is AnonymousUserModelAdapter &&
|
||||
runtimeType == other.runtimeType &&
|
||||
typeId == other.typeId;
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
// **************************************************************************
|
||||
// TypeAdapterGenerator
|
||||
// **************************************************************************
|
||||
|
||||
class AudienceTargetModelAdapter extends TypeAdapter<AudienceTargetModel> {
|
||||
@override
|
||||
final int typeId = 23;
|
||||
|
||||
@override
|
||||
AudienceTargetModel read(BinaryReader reader) {
|
||||
final numOfFields = reader.readByte();
|
||||
final fields = <int, dynamic>{
|
||||
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
|
||||
};
|
||||
return AudienceTargetModel(
|
||||
id: fields[0] as String,
|
||||
conversationId: fields[1] as String,
|
||||
targetType: fields[2] as String,
|
||||
targetId: fields[3] as String?,
|
||||
createdAt: fields[4] as DateTime,
|
||||
roleFilter: fields[5] as String?,
|
||||
entityFilter: fields[6] as String?,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void write(BinaryWriter writer, AudienceTargetModel obj) {
|
||||
writer
|
||||
..writeByte(7)
|
||||
..writeByte(0)
|
||||
..write(obj.id)
|
||||
..writeByte(1)
|
||||
..write(obj.conversationId)
|
||||
..writeByte(2)
|
||||
..write(obj.targetType)
|
||||
..writeByte(3)
|
||||
..write(obj.targetId)
|
||||
..writeByte(4)
|
||||
..write(obj.createdAt)
|
||||
..writeByte(5)
|
||||
..write(obj.roleFilter)
|
||||
..writeByte(6)
|
||||
..write(obj.entityFilter);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => typeId.hashCode;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is AudienceTargetModelAdapter &&
|
||||
runtimeType == other.runtimeType &&
|
||||
typeId == other.typeId;
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
// **************************************************************************
|
||||
// TypeAdapterGenerator
|
||||
// **************************************************************************
|
||||
|
||||
class ConversationModelAdapter extends TypeAdapter<ConversationModel> {
|
||||
@override
|
||||
final int typeId = 20;
|
||||
|
||||
@override
|
||||
ConversationModel read(BinaryReader reader) {
|
||||
final numOfFields = reader.readByte();
|
||||
final fields = <int, dynamic>{
|
||||
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
|
||||
};
|
||||
return ConversationModel(
|
||||
id: fields[0] as String,
|
||||
type: fields[1] as String,
|
||||
title: fields[2] as String?,
|
||||
createdAt: fields[3] as DateTime,
|
||||
updatedAt: fields[4] as DateTime,
|
||||
participants: (fields[5] as List).cast<ParticipantModel>(),
|
||||
isSynced: fields[6] as bool,
|
||||
replyPermission: fields[7] as String,
|
||||
isPinned: fields[8] as bool,
|
||||
expiryDate: fields[9] as DateTime?,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void write(BinaryWriter writer, ConversationModel obj) {
|
||||
writer
|
||||
..writeByte(10)
|
||||
..writeByte(0)
|
||||
..write(obj.id)
|
||||
..writeByte(1)
|
||||
..write(obj.type)
|
||||
..writeByte(2)
|
||||
..write(obj.title)
|
||||
..writeByte(3)
|
||||
..write(obj.createdAt)
|
||||
..writeByte(4)
|
||||
..write(obj.updatedAt)
|
||||
..writeByte(5)
|
||||
..write(obj.participants)
|
||||
..writeByte(6)
|
||||
..write(obj.isSynced)
|
||||
..writeByte(7)
|
||||
..write(obj.replyPermission)
|
||||
..writeByte(8)
|
||||
..write(obj.isPinned)
|
||||
..writeByte(9)
|
||||
..write(obj.expiryDate);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => typeId.hashCode;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is ConversationModelAdapter &&
|
||||
runtimeType == other.runtimeType &&
|
||||
typeId == other.typeId;
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
// **************************************************************************
|
||||
// TypeAdapterGenerator
|
||||
// **************************************************************************
|
||||
|
||||
class MessageModelAdapter extends TypeAdapter<MessageModel> {
|
||||
@override
|
||||
final int typeId = 21;
|
||||
|
||||
@override
|
||||
MessageModel read(BinaryReader reader) {
|
||||
final numOfFields = reader.readByte();
|
||||
final fields = <int, dynamic>{
|
||||
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
|
||||
};
|
||||
return MessageModel(
|
||||
id: fields[0] as String,
|
||||
conversationId: fields[1] as String,
|
||||
senderId: fields[2] as String?,
|
||||
senderType: fields[3] as String,
|
||||
content: fields[4] as String,
|
||||
contentType: fields[5] as String,
|
||||
createdAt: fields[6] as DateTime,
|
||||
deliveredAt: fields[7] as DateTime?,
|
||||
readAt: fields[8] as DateTime?,
|
||||
status: fields[9] as String,
|
||||
isAnnouncement: fields[10] as bool,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void write(BinaryWriter writer, MessageModel obj) {
|
||||
writer
|
||||
..writeByte(11)
|
||||
..writeByte(0)
|
||||
..write(obj.id)
|
||||
..writeByte(1)
|
||||
..write(obj.conversationId)
|
||||
..writeByte(2)
|
||||
..write(obj.senderId)
|
||||
..writeByte(3)
|
||||
..write(obj.senderType)
|
||||
..writeByte(4)
|
||||
..write(obj.content)
|
||||
..writeByte(5)
|
||||
..write(obj.contentType)
|
||||
..writeByte(6)
|
||||
..write(obj.createdAt)
|
||||
..writeByte(7)
|
||||
..write(obj.deliveredAt)
|
||||
..writeByte(8)
|
||||
..write(obj.readAt)
|
||||
..writeByte(9)
|
||||
..write(obj.status)
|
||||
..writeByte(10)
|
||||
..write(obj.isAnnouncement);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => typeId.hashCode;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is MessageModelAdapter &&
|
||||
runtimeType == other.runtimeType &&
|
||||
typeId == other.typeId;
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
// **************************************************************************
|
||||
// TypeAdapterGenerator
|
||||
// **************************************************************************
|
||||
|
||||
class NotificationSettingsAdapter extends TypeAdapter<NotificationSettings> {
|
||||
@override
|
||||
final int typeId = 25;
|
||||
|
||||
@override
|
||||
NotificationSettings read(BinaryReader reader) {
|
||||
final numOfFields = reader.readByte();
|
||||
final fields = <int, dynamic>{
|
||||
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
|
||||
};
|
||||
return NotificationSettings(
|
||||
enableNotifications: fields[0] as bool,
|
||||
soundEnabled: fields[1] as bool,
|
||||
vibrationEnabled: fields[2] as bool,
|
||||
mutedConversations: (fields[3] as List).cast<String>(),
|
||||
showPreview: fields[4] as bool,
|
||||
conversationNotifications: (fields[5] as Map).cast<String, bool>(),
|
||||
doNotDisturb: fields[6] as bool,
|
||||
doNotDisturbStart: fields[7] as DateTime?,
|
||||
doNotDisturbEnd: fields[8] as DateTime?,
|
||||
deviceToken: fields[9] as String?,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void write(BinaryWriter writer, NotificationSettings obj) {
|
||||
writer
|
||||
..writeByte(10)
|
||||
..writeByte(0)
|
||||
..write(obj.enableNotifications)
|
||||
..writeByte(1)
|
||||
..write(obj.soundEnabled)
|
||||
..writeByte(2)
|
||||
..write(obj.vibrationEnabled)
|
||||
..writeByte(3)
|
||||
..write(obj.mutedConversations)
|
||||
..writeByte(4)
|
||||
..write(obj.showPreview)
|
||||
..writeByte(5)
|
||||
..write(obj.conversationNotifications)
|
||||
..writeByte(6)
|
||||
..write(obj.doNotDisturb)
|
||||
..writeByte(7)
|
||||
..write(obj.doNotDisturbStart)
|
||||
..writeByte(8)
|
||||
..write(obj.doNotDisturbEnd)
|
||||
..writeByte(9)
|
||||
..write(obj.deviceToken);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => typeId.hashCode;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is NotificationSettingsAdapter &&
|
||||
runtimeType == other.runtimeType &&
|
||||
typeId == other.typeId;
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
// **************************************************************************
|
||||
// TypeAdapterGenerator
|
||||
// **************************************************************************
|
||||
|
||||
class ParticipantModelAdapter extends TypeAdapter<ParticipantModel> {
|
||||
@override
|
||||
final int typeId = 22;
|
||||
|
||||
@override
|
||||
ParticipantModel read(BinaryReader reader) {
|
||||
final numOfFields = reader.readByte();
|
||||
final fields = <int, dynamic>{
|
||||
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
|
||||
};
|
||||
return ParticipantModel(
|
||||
id: fields[0] as String,
|
||||
conversationId: fields[1] as String,
|
||||
userId: fields[2] as String?,
|
||||
anonymousId: fields[3] as String?,
|
||||
role: fields[4] as String,
|
||||
joinedAt: fields[5] as DateTime,
|
||||
lastReadMessageId: fields[6] as String?,
|
||||
viaTarget: fields[7] as bool,
|
||||
canReply: fields[8] as bool?,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void write(BinaryWriter writer, ParticipantModel obj) {
|
||||
writer
|
||||
..writeByte(9)
|
||||
..writeByte(0)
|
||||
..write(obj.id)
|
||||
..writeByte(1)
|
||||
..write(obj.conversationId)
|
||||
..writeByte(2)
|
||||
..write(obj.userId)
|
||||
..writeByte(3)
|
||||
..write(obj.anonymousId)
|
||||
..writeByte(4)
|
||||
..write(obj.role)
|
||||
..writeByte(5)
|
||||
..write(obj.joinedAt)
|
||||
..writeByte(6)
|
||||
..write(obj.lastReadMessageId)
|
||||
..writeByte(7)
|
||||
..write(obj.viaTarget)
|
||||
..writeByte(8)
|
||||
..write(obj.canReply);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => typeId.hashCode;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is ParticipantModelAdapter &&
|
||||
runtimeType == other.runtimeType &&
|
||||
typeId == other.typeId;
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
// **************************************************************************
|
||||
// TypeAdapterGenerator
|
||||
// **************************************************************************
|
||||
|
||||
class AmicaleModelAdapter extends TypeAdapter<AmicaleModel> {
|
||||
@override
|
||||
final int typeId = 11;
|
||||
|
||||
@override
|
||||
AmicaleModel read(BinaryReader reader) {
|
||||
final numOfFields = reader.readByte();
|
||||
final fields = <int, dynamic>{
|
||||
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
|
||||
};
|
||||
return AmicaleModel(
|
||||
id: fields[0] as int,
|
||||
name: fields[1] as String,
|
||||
adresse1: fields[2] as String,
|
||||
adresse2: fields[3] as String,
|
||||
codePostal: fields[4] as String,
|
||||
ville: fields[5] as String,
|
||||
fkRegion: fields[6] as int?,
|
||||
libRegion: fields[7] as String?,
|
||||
fkType: fields[8] as int?,
|
||||
phone: fields[9] as String,
|
||||
mobile: fields[10] as String,
|
||||
email: fields[11] as String,
|
||||
gpsLat: fields[12] as String,
|
||||
gpsLng: fields[13] as String,
|
||||
stripeId: fields[14] as String,
|
||||
chkDemo: fields[15] as bool,
|
||||
chkCopieMailRecu: fields[16] as bool,
|
||||
chkAcceptSms: fields[17] as bool,
|
||||
chkActive: fields[18] as bool,
|
||||
chkStripe: fields[19] as bool,
|
||||
createdAt: fields[20] as DateTime?,
|
||||
updatedAt: fields[21] as DateTime?,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void write(BinaryWriter writer, AmicaleModel obj) {
|
||||
writer
|
||||
..writeByte(22)
|
||||
..writeByte(0)
|
||||
..write(obj.id)
|
||||
..writeByte(1)
|
||||
..write(obj.name)
|
||||
..writeByte(2)
|
||||
..write(obj.adresse1)
|
||||
..writeByte(3)
|
||||
..write(obj.adresse2)
|
||||
..writeByte(4)
|
||||
..write(obj.codePostal)
|
||||
..writeByte(5)
|
||||
..write(obj.ville)
|
||||
..writeByte(6)
|
||||
..write(obj.fkRegion)
|
||||
..writeByte(7)
|
||||
..write(obj.libRegion)
|
||||
..writeByte(8)
|
||||
..write(obj.fkType)
|
||||
..writeByte(9)
|
||||
..write(obj.phone)
|
||||
..writeByte(10)
|
||||
..write(obj.mobile)
|
||||
..writeByte(11)
|
||||
..write(obj.email)
|
||||
..writeByte(12)
|
||||
..write(obj.gpsLat)
|
||||
..writeByte(13)
|
||||
..write(obj.gpsLng)
|
||||
..writeByte(14)
|
||||
..write(obj.stripeId)
|
||||
..writeByte(15)
|
||||
..write(obj.chkDemo)
|
||||
..writeByte(16)
|
||||
..write(obj.chkCopieMailRecu)
|
||||
..writeByte(17)
|
||||
..write(obj.chkAcceptSms)
|
||||
..writeByte(18)
|
||||
..write(obj.chkActive)
|
||||
..writeByte(19)
|
||||
..write(obj.chkStripe)
|
||||
..writeByte(20)
|
||||
..write(obj.createdAt)
|
||||
..writeByte(21)
|
||||
..write(obj.updatedAt);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => typeId.hashCode;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is AmicaleModelAdapter &&
|
||||
runtimeType == other.runtimeType &&
|
||||
typeId == other.typeId;
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
// **************************************************************************
|
||||
// TypeAdapterGenerator
|
||||
// **************************************************************************
|
||||
|
||||
class ClientModelAdapter extends TypeAdapter<ClientModel> {
|
||||
@override
|
||||
final int typeId = 10;
|
||||
|
||||
@override
|
||||
ClientModel read(BinaryReader reader) {
|
||||
final numOfFields = reader.readByte();
|
||||
final fields = <int, dynamic>{
|
||||
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
|
||||
};
|
||||
return ClientModel(
|
||||
id: fields[0] as int,
|
||||
name: fields[1] as String,
|
||||
adresse1: fields[2] as String?,
|
||||
adresse2: fields[3] as String?,
|
||||
codePostal: fields[4] as String?,
|
||||
ville: fields[5] as String?,
|
||||
fkRegion: fields[6] as int?,
|
||||
libRegion: fields[7] as String?,
|
||||
fkType: fields[8] as int?,
|
||||
phone: fields[9] as String?,
|
||||
mobile: fields[10] as String?,
|
||||
email: fields[11] as String?,
|
||||
gpsLat: fields[12] as String?,
|
||||
gpsLng: fields[13] as String?,
|
||||
stripeId: fields[14] as String?,
|
||||
chkDemo: fields[15] as bool?,
|
||||
chkCopieMailRecu: fields[16] as bool?,
|
||||
chkAcceptSms: fields[17] as bool?,
|
||||
chkActive: fields[18] as bool?,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void write(BinaryWriter writer, ClientModel obj) {
|
||||
writer
|
||||
..writeByte(19)
|
||||
..writeByte(0)
|
||||
..write(obj.id)
|
||||
..writeByte(1)
|
||||
..write(obj.name)
|
||||
..writeByte(2)
|
||||
..write(obj.adresse1)
|
||||
..writeByte(3)
|
||||
..write(obj.adresse2)
|
||||
..writeByte(4)
|
||||
..write(obj.codePostal)
|
||||
..writeByte(5)
|
||||
..write(obj.ville)
|
||||
..writeByte(6)
|
||||
..write(obj.fkRegion)
|
||||
..writeByte(7)
|
||||
..write(obj.libRegion)
|
||||
..writeByte(8)
|
||||
..write(obj.fkType)
|
||||
..writeByte(9)
|
||||
..write(obj.phone)
|
||||
..writeByte(10)
|
||||
..write(obj.mobile)
|
||||
..writeByte(11)
|
||||
..write(obj.email)
|
||||
..writeByte(12)
|
||||
..write(obj.gpsLat)
|
||||
..writeByte(13)
|
||||
..write(obj.gpsLng)
|
||||
..writeByte(14)
|
||||
..write(obj.stripeId)
|
||||
..writeByte(15)
|
||||
..write(obj.chkDemo)
|
||||
..writeByte(16)
|
||||
..write(obj.chkCopieMailRecu)
|
||||
..writeByte(17)
|
||||
..write(obj.chkAcceptSms)
|
||||
..writeByte(18)
|
||||
..write(obj.chkActive);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => typeId.hashCode;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is ClientModelAdapter &&
|
||||
runtimeType == other.runtimeType &&
|
||||
typeId == other.typeId;
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
// **************************************************************************
|
||||
// TypeAdapterGenerator
|
||||
// **************************************************************************
|
||||
|
||||
class MembreModelAdapter extends TypeAdapter<MembreModel> {
|
||||
@override
|
||||
final int typeId = 5;
|
||||
|
||||
@override
|
||||
MembreModel read(BinaryReader reader) {
|
||||
final numOfFields = reader.readByte();
|
||||
final fields = <int, dynamic>{
|
||||
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
|
||||
};
|
||||
return MembreModel(
|
||||
id: fields[0] as int,
|
||||
fkRole: fields[1] as int,
|
||||
fkTitre: fields[2] as int,
|
||||
firstName: fields[3] as String,
|
||||
sectName: fields[4] as String?,
|
||||
dateNaissance: fields[5] as DateTime?,
|
||||
dateEmbauche: fields[6] as DateTime?,
|
||||
chkActive: fields[7] as int,
|
||||
name: fields[8] as String,
|
||||
username: fields[9] as String,
|
||||
email: fields[10] as String,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void write(BinaryWriter writer, MembreModel obj) {
|
||||
writer
|
||||
..writeByte(11)
|
||||
..writeByte(0)
|
||||
..write(obj.id)
|
||||
..writeByte(1)
|
||||
..write(obj.fkRole)
|
||||
..writeByte(2)
|
||||
..write(obj.fkTitre)
|
||||
..writeByte(3)
|
||||
..write(obj.firstName)
|
||||
..writeByte(4)
|
||||
..write(obj.sectName)
|
||||
..writeByte(5)
|
||||
..write(obj.dateNaissance)
|
||||
..writeByte(6)
|
||||
..write(obj.dateEmbauche)
|
||||
..writeByte(7)
|
||||
..write(obj.chkActive)
|
||||
..writeByte(8)
|
||||
..write(obj.name)
|
||||
..writeByte(9)
|
||||
..write(obj.username)
|
||||
..writeByte(10)
|
||||
..write(obj.email);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => typeId.hashCode;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is MembreModelAdapter &&
|
||||
runtimeType == other.runtimeType &&
|
||||
typeId == other.typeId;
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
// **************************************************************************
|
||||
// TypeAdapterGenerator
|
||||
// **************************************************************************
|
||||
|
||||
class OperationModelAdapter extends TypeAdapter<OperationModel> {
|
||||
@override
|
||||
final int typeId = 1;
|
||||
|
||||
@override
|
||||
OperationModel read(BinaryReader reader) {
|
||||
final numOfFields = reader.readByte();
|
||||
final fields = <int, dynamic>{
|
||||
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
|
||||
};
|
||||
return OperationModel(
|
||||
id: fields[0] as int,
|
||||
name: fields[1] as String,
|
||||
dateDebut: fields[2] as DateTime,
|
||||
dateFin: fields[3] as DateTime,
|
||||
lastSyncedAt: fields[4] as DateTime,
|
||||
isActive: fields[5] as bool,
|
||||
isSynced: fields[6] as bool,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void write(BinaryWriter writer, OperationModel obj) {
|
||||
writer
|
||||
..writeByte(7)
|
||||
..writeByte(0)
|
||||
..write(obj.id)
|
||||
..writeByte(1)
|
||||
..write(obj.name)
|
||||
..writeByte(2)
|
||||
..write(obj.dateDebut)
|
||||
..writeByte(3)
|
||||
..write(obj.dateFin)
|
||||
..writeByte(4)
|
||||
..write(obj.lastSyncedAt)
|
||||
..writeByte(5)
|
||||
..write(obj.isActive)
|
||||
..writeByte(6)
|
||||
..write(obj.isSynced);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => typeId.hashCode;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is OperationModelAdapter &&
|
||||
runtimeType == other.runtimeType &&
|
||||
typeId == other.typeId;
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
// **************************************************************************
|
||||
// TypeAdapterGenerator
|
||||
// **************************************************************************
|
||||
|
||||
class PassageModelAdapter extends TypeAdapter<PassageModel> {
|
||||
@override
|
||||
final int typeId = 4;
|
||||
|
||||
@override
|
||||
PassageModel read(BinaryReader reader) {
|
||||
final numOfFields = reader.readByte();
|
||||
final fields = <int, dynamic>{
|
||||
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
|
||||
};
|
||||
return PassageModel(
|
||||
id: fields[0] as int,
|
||||
fkOperation: fields[1] as int,
|
||||
fkSector: fields[2] as int,
|
||||
fkUser: fields[3] as int,
|
||||
fkType: fields[4] as int,
|
||||
fkAdresse: fields[5] as String,
|
||||
passedAt: fields[6] as DateTime,
|
||||
numero: fields[7] as String,
|
||||
rue: fields[8] as String,
|
||||
rueBis: fields[9] as String,
|
||||
ville: fields[10] as String,
|
||||
residence: fields[11] as String,
|
||||
fkHabitat: fields[12] as int,
|
||||
appt: fields[13] as String,
|
||||
niveau: fields[14] as String,
|
||||
gpsLat: fields[15] as String,
|
||||
gpsLng: fields[16] as String,
|
||||
nomRecu: fields[17] as String,
|
||||
remarque: fields[18] as String,
|
||||
montant: fields[19] as String,
|
||||
fkTypeReglement: fields[20] as int,
|
||||
emailErreur: fields[21] as String,
|
||||
nbPassages: fields[22] as int,
|
||||
name: fields[23] as String,
|
||||
email: fields[24] as String,
|
||||
phone: fields[25] as String,
|
||||
lastSyncedAt: fields[26] as DateTime,
|
||||
isActive: fields[27] as bool,
|
||||
isSynced: fields[28] as bool,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void write(BinaryWriter writer, PassageModel obj) {
|
||||
writer
|
||||
..writeByte(29)
|
||||
..writeByte(0)
|
||||
..write(obj.id)
|
||||
..writeByte(1)
|
||||
..write(obj.fkOperation)
|
||||
..writeByte(2)
|
||||
..write(obj.fkSector)
|
||||
..writeByte(3)
|
||||
..write(obj.fkUser)
|
||||
..writeByte(4)
|
||||
..write(obj.fkType)
|
||||
..writeByte(5)
|
||||
..write(obj.fkAdresse)
|
||||
..writeByte(6)
|
||||
..write(obj.passedAt)
|
||||
..writeByte(7)
|
||||
..write(obj.numero)
|
||||
..writeByte(8)
|
||||
..write(obj.rue)
|
||||
..writeByte(9)
|
||||
..write(obj.rueBis)
|
||||
..writeByte(10)
|
||||
..write(obj.ville)
|
||||
..writeByte(11)
|
||||
..write(obj.residence)
|
||||
..writeByte(12)
|
||||
..write(obj.fkHabitat)
|
||||
..writeByte(13)
|
||||
..write(obj.appt)
|
||||
..writeByte(14)
|
||||
..write(obj.niveau)
|
||||
..writeByte(15)
|
||||
..write(obj.gpsLat)
|
||||
..writeByte(16)
|
||||
..write(obj.gpsLng)
|
||||
..writeByte(17)
|
||||
..write(obj.nomRecu)
|
||||
..writeByte(18)
|
||||
..write(obj.remarque)
|
||||
..writeByte(19)
|
||||
..write(obj.montant)
|
||||
..writeByte(20)
|
||||
..write(obj.fkTypeReglement)
|
||||
..writeByte(21)
|
||||
..write(obj.emailErreur)
|
||||
..writeByte(22)
|
||||
..write(obj.nbPassages)
|
||||
..writeByte(23)
|
||||
..write(obj.name)
|
||||
..writeByte(24)
|
||||
..write(obj.email)
|
||||
..writeByte(25)
|
||||
..write(obj.phone)
|
||||
..writeByte(26)
|
||||
..write(obj.lastSyncedAt)
|
||||
..writeByte(27)
|
||||
..write(obj.isActive)
|
||||
..writeByte(28)
|
||||
..write(obj.isSynced);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => typeId.hashCode;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is PassageModelAdapter &&
|
||||
runtimeType == other.runtimeType &&
|
||||
typeId == other.typeId;
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
// **************************************************************************
|
||||
// TypeAdapterGenerator
|
||||
// **************************************************************************
|
||||
|
||||
class RegionModelAdapter extends TypeAdapter<RegionModel> {
|
||||
@override
|
||||
final int typeId = 7;
|
||||
|
||||
@override
|
||||
RegionModel read(BinaryReader reader) {
|
||||
final numOfFields = reader.readByte();
|
||||
final fields = <int, dynamic>{
|
||||
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
|
||||
};
|
||||
return RegionModel(
|
||||
id: fields[0] as int,
|
||||
fkPays: fields[1] as int,
|
||||
libelle: fields[2] as String,
|
||||
libelleLong: fields[3] as String?,
|
||||
tableOsm: fields[4] as String?,
|
||||
departements: fields[5] as String?,
|
||||
chkActive: fields[6] as bool,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void write(BinaryWriter writer, RegionModel obj) {
|
||||
writer
|
||||
..writeByte(7)
|
||||
..writeByte(0)
|
||||
..write(obj.id)
|
||||
..writeByte(1)
|
||||
..write(obj.fkPays)
|
||||
..writeByte(2)
|
||||
..write(obj.libelle)
|
||||
..writeByte(3)
|
||||
..write(obj.libelleLong)
|
||||
..writeByte(4)
|
||||
..write(obj.tableOsm)
|
||||
..writeByte(5)
|
||||
..write(obj.departements)
|
||||
..writeByte(6)
|
||||
..write(obj.chkActive);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => typeId.hashCode;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is RegionModelAdapter &&
|
||||
runtimeType == other.runtimeType &&
|
||||
typeId == other.typeId;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
// **************************************************************************
|
||||
// TypeAdapterGenerator
|
||||
// **************************************************************************
|
||||
|
||||
class SectorModelAdapter extends TypeAdapter<SectorModel> {
|
||||
@override
|
||||
final int typeId = 3;
|
||||
|
||||
@override
|
||||
SectorModel read(BinaryReader reader) {
|
||||
final numOfFields = reader.readByte();
|
||||
final fields = <int, dynamic>{
|
||||
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
|
||||
};
|
||||
return SectorModel(
|
||||
id: fields[0] as int,
|
||||
libelle: fields[1] as String,
|
||||
color: fields[2] as String,
|
||||
sector: fields[3] as String,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void write(BinaryWriter writer, SectorModel obj) {
|
||||
writer
|
||||
..writeByte(4)
|
||||
..writeByte(0)
|
||||
..write(obj.id)
|
||||
..writeByte(1)
|
||||
..write(obj.libelle)
|
||||
..writeByte(2)
|
||||
..write(obj.color)
|
||||
..writeByte(3)
|
||||
..write(obj.sector);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => typeId.hashCode;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is SectorModelAdapter &&
|
||||
runtimeType == other.runtimeType &&
|
||||
typeId == other.typeId;
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
// **************************************************************************
|
||||
// TypeAdapterGenerator
|
||||
// **************************************************************************
|
||||
|
||||
class UserModelAdapter extends TypeAdapter<UserModel> {
|
||||
@override
|
||||
final int typeId = 0;
|
||||
|
||||
@override
|
||||
UserModel read(BinaryReader reader) {
|
||||
final numOfFields = reader.readByte();
|
||||
final fields = <int, dynamic>{
|
||||
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
|
||||
};
|
||||
return UserModel(
|
||||
id: fields[0] as int,
|
||||
email: fields[1] as String,
|
||||
name: fields[2] as String?,
|
||||
username: fields[11] as String?,
|
||||
firstName: fields[10] as String?,
|
||||
role: fields[3] as int,
|
||||
createdAt: fields[4] as DateTime,
|
||||
lastSyncedAt: fields[5] as DateTime,
|
||||
isActive: fields[6] as bool,
|
||||
isSynced: fields[7] as bool,
|
||||
sessionId: fields[8] as String?,
|
||||
sessionExpiry: fields[9] as DateTime?,
|
||||
lastPath: fields[12] as String?,
|
||||
sectName: fields[13] as String?,
|
||||
fkEntite: fields[14] as int?,
|
||||
fkTitre: fields[15] as int?,
|
||||
phone: fields[16] as String?,
|
||||
mobile: fields[17] as String?,
|
||||
dateNaissance: fields[18] as DateTime?,
|
||||
dateEmbauche: fields[19] as DateTime?,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void write(BinaryWriter writer, UserModel obj) {
|
||||
writer
|
||||
..writeByte(20)
|
||||
..writeByte(0)
|
||||
..write(obj.id)
|
||||
..writeByte(1)
|
||||
..write(obj.email)
|
||||
..writeByte(2)
|
||||
..write(obj.name)
|
||||
..writeByte(11)
|
||||
..write(obj.username)
|
||||
..writeByte(10)
|
||||
..write(obj.firstName)
|
||||
..writeByte(3)
|
||||
..write(obj.role)
|
||||
..writeByte(4)
|
||||
..write(obj.createdAt)
|
||||
..writeByte(5)
|
||||
..write(obj.lastSyncedAt)
|
||||
..writeByte(6)
|
||||
..write(obj.isActive)
|
||||
..writeByte(7)
|
||||
..write(obj.isSynced)
|
||||
..writeByte(8)
|
||||
..write(obj.sessionId)
|
||||
..writeByte(9)
|
||||
..write(obj.sessionExpiry)
|
||||
..writeByte(12)
|
||||
..write(obj.lastPath)
|
||||
..writeByte(13)
|
||||
..write(obj.sectName)
|
||||
..writeByte(14)
|
||||
..write(obj.fkEntite)
|
||||
..writeByte(15)
|
||||
..write(obj.fkTitre)
|
||||
..writeByte(16)
|
||||
..write(obj.phone)
|
||||
..writeByte(17)
|
||||
..write(obj.mobile)
|
||||
..writeByte(18)
|
||||
..write(obj.dateNaissance)
|
||||
..writeByte(19)
|
||||
..write(obj.dateEmbauche);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => typeId.hashCode;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is UserModelAdapter &&
|
||||
runtimeType == other.runtimeType &&
|
||||
typeId == other.typeId;
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
// **************************************************************************
|
||||
// TypeAdapterGenerator
|
||||
// **************************************************************************
|
||||
|
||||
class UserSectorModelAdapter extends TypeAdapter<UserSectorModel> {
|
||||
@override
|
||||
final int typeId = 7;
|
||||
|
||||
@override
|
||||
UserSectorModel read(BinaryReader reader) {
|
||||
final numOfFields = reader.readByte();
|
||||
final fields = <int, dynamic>{
|
||||
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
|
||||
};
|
||||
return UserSectorModel(
|
||||
id: fields[0] as int,
|
||||
firstName: fields[1] as String?,
|
||||
sectName: fields[2] as String?,
|
||||
fkSector: fields[3] as int,
|
||||
name: fields[4] as String?,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void write(BinaryWriter writer, UserSectorModel obj) {
|
||||
writer
|
||||
..writeByte(5)
|
||||
..writeByte(0)
|
||||
..write(obj.id)
|
||||
..writeByte(1)
|
||||
..write(obj.firstName)
|
||||
..writeByte(2)
|
||||
..write(obj.sectName)
|
||||
..writeByte(3)
|
||||
..write(obj.fkSector)
|
||||
..writeByte(4)
|
||||
..write(obj.name);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => typeId.hashCode;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is UserSectorModelAdapter &&
|
||||
runtimeType == other.runtimeType &&
|
||||
typeId == other.typeId;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
C<EFBFBD><EFBFBD><EFBFBD>F}<7D><EFBFBD>7<><37><EFBFBD><EFBFBD>9
|
||||
@@ -0,0 +1 @@
|
||||
<EFBFBD><EFBFBD>E>`<60>e0<65>sl<73><6C><0C>
|
||||
@@ -0,0 +1 @@
|
||||
<EFBFBD>FJ6<EFBFBD><EFBFBD>6<EFBFBD><EFBFBD><EFBFBD><EFBFBD>e<EFBFBD><EFBFBD>-b
|
||||
@@ -0,0 +1 @@
|
||||
<EFBFBD>[ڀJ<DA80>n<EFBFBD><6E>(<28>v/<2F>~<7E>
|
||||
@@ -0,0 +1 @@
|
||||
<EFBFBD><EFBFBD><EFBFBD>ulM<6C>L<EFBFBD><4C><EFBFBD><EFBFBD>M
|
||||
@@ -0,0 +1 @@
|
||||
<11><><1D>;<3B><><0B><>^<5E>:p
|
||||
@@ -0,0 +1 @@
|
||||
o~<7E>+x<>\6<1B><><EFBFBD>o<EFBFBD><6F>a
|
||||
@@ -0,0 +1,2 @@
|
||||
Q<EFBFBD>;<14><><EFBFBD><EFBFBD><EFBFBD>
|
||||
<EFBFBD>)<29>j<EFBFBD>
|
||||
@@ -0,0 +1 @@
|
||||
<EFBFBD>I<EFBFBD>4<EFBFBD><17>]7<12>{Rf<52>
|
||||
@@ -0,0 +1 @@
|
||||
<EFBFBD><EFBFBD><EFBFBD>ve<EFBFBD>wz<EFBFBD>z::O<><4F><EFBFBD>
|
||||
BIN
app/.dart_tool/build_resolvers/sdk.sum
Normal file
BIN
app/.dart_tool/build_resolvers/sdk.sum
Normal file
Binary file not shown.
1
app/.dart_tool/build_resolvers/sdk.sum.deps
Normal file
1
app/.dart_tool/build_resolvers/sdk.sum.deps
Normal file
@@ -0,0 +1 @@
|
||||
{"sdk":"3.8.1 (stable) (Wed May 28 00:47:25 2025 -0700) on \"macos_arm64\"","analyzer":"/Users/pierre/.pub-cache/hosted/pub.dev/analyzer-6.11.0","build_resolvers":"/Users/pierre/.pub-cache/hosted/pub.dev/build_resolvers-2.4.4"}
|
||||
22
app/.dart_tool/dartpad/web_plugin_registrant.dart
Normal file
22
app/.dart_tool/dartpad/web_plugin_registrant.dart
Normal file
@@ -0,0 +1,22 @@
|
||||
// Flutter web plugin registrant file.
|
||||
//
|
||||
// Generated file. Do not edit.
|
||||
//
|
||||
|
||||
// @dart = 2.13
|
||||
// ignore_for_file: type=lint
|
||||
|
||||
import 'package:connectivity_plus/src/connectivity_plus_web.dart';
|
||||
import 'package:geolocator_web/geolocator_web.dart';
|
||||
import 'package:package_info_plus/src/package_info_plus_web.dart';
|
||||
import 'package:url_launcher_web/url_launcher_web.dart';
|
||||
import 'package:flutter_web_plugins/flutter_web_plugins.dart';
|
||||
|
||||
void registerPlugins([final Registrar? pluginRegistrar]) {
|
||||
final Registrar registrar = pluginRegistrar ?? webPluginRegistrar;
|
||||
ConnectivityPlusWebPlugin.registerWith(registrar);
|
||||
GeolocatorPlugin.registerWith(registrar);
|
||||
PackageInfoPlusWebPlugin.registerWith(registrar);
|
||||
UrlLauncherPlugin.registerWith(registrar);
|
||||
registrar.registerMessageHandler();
|
||||
}
|
||||
31
app/.dart_tool/extension_discovery/README.md
Normal file
31
app/.dart_tool/extension_discovery/README.md
Normal file
@@ -0,0 +1,31 @@
|
||||
Extension Discovery Cache
|
||||
=========================
|
||||
|
||||
This folder is used by `package:extension_discovery` to cache lists of
|
||||
packages that contains extensions for other packages.
|
||||
|
||||
DO NOT USE THIS FOLDER
|
||||
----------------------
|
||||
|
||||
* Do not read (or rely) the contents of this folder.
|
||||
* Do write to this folder.
|
||||
|
||||
If you're interested in the lists of extensions stored in this folder use the
|
||||
API offered by package `extension_discovery` to get this information.
|
||||
|
||||
If this package doesn't work for your use-case, then don't try to read the
|
||||
contents of this folder. It may change, and will not remain stable.
|
||||
|
||||
Use package `extension_discovery`
|
||||
---------------------------------
|
||||
|
||||
If you want to access information from this folder.
|
||||
|
||||
Feel free to delete this folder
|
||||
-------------------------------
|
||||
|
||||
Files in this folder act as a cache, and the cache is discarded if the files
|
||||
are older than the modification time of `.dart_tool/package_config.json`.
|
||||
|
||||
Hence, it should never be necessary to clear this cache manually, if you find a
|
||||
need to do please file a bug.
|
||||
1
app/.dart_tool/extension_discovery/vs_code.json
Normal file
1
app/.dart_tool/extension_discovery/vs_code.json
Normal file
@@ -0,0 +1 @@
|
||||
{"version":2,"entries":[{"package":"geosector_app","rootUri":"../","packageUri":"lib/"}]}
|
||||
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
{"inputs":[],"outputs":[]}
|
||||
@@ -0,0 +1,30 @@
|
||||
// @dart=3.0
|
||||
// Flutter web bootstrap script for package:geosector_app/main.dart.
|
||||
//
|
||||
// Generated file. Do not edit.
|
||||
//
|
||||
|
||||
// ignore_for_file: type=lint
|
||||
|
||||
import 'dart:ui_web' as ui_web;
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:geosector_app/main.dart' as entrypoint;
|
||||
import 'web_plugin_registrant.dart' as pluginRegistrant;
|
||||
|
||||
typedef _UnaryFunction = dynamic Function(List<String> args);
|
||||
typedef _NullaryFunction = dynamic Function();
|
||||
|
||||
Future<void> main() async {
|
||||
await ui_web.bootstrapEngine(
|
||||
runApp: () {
|
||||
if (entrypoint.main is _UnaryFunction) {
|
||||
return (entrypoint.main as _UnaryFunction)(<String>[]);
|
||||
}
|
||||
return (entrypoint.main as _NullaryFunction)();
|
||||
},
|
||||
registerPlugins: () {
|
||||
pluginRegistrant.registerPlugins();
|
||||
},
|
||||
);
|
||||
}
|
||||
139345
app/.dart_tool/flutter_build/41acb28aedc1da36af63ba5cb8859018/main.dart.js
Normal file
139345
app/.dart_tool/flutter_build/41acb28aedc1da36af63ba5cb8859018/main.dart.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1 @@
|
||||
["/Users/pierre/dev/geosector/app/build/web/*/index.html","/Users/pierre/dev/geosector/app/build/web/flutter_bootstrap.js","/Users/pierre/dev/geosector/app/build/web/main.dart.js","/Users/pierre/dev/geosector/app/build/web/assets/assets/images/geosector-logo.png","/Users/pierre/dev/geosector/app/build/web/assets/assets/images/logo-geosector-1024.png","/Users/pierre/dev/geosector/app/build/web/assets/assets/images/icon-geosector.svg","/Users/pierre/dev/geosector/app/build/web/assets/assets/images/logo_recu.png","/Users/pierre/dev/geosector/app/build/web/assets/assets/animations/geo_main.json","/Users/pierre/dev/geosector/app/build/web/assets/assets/fonts/Figtree-VariableFont_wght.ttf","/Users/pierre/dev/geosector/app/build/web/assets/packages/cupertino_icons/assets/CupertinoIcons.ttf","/Users/pierre/dev/geosector/app/build/web/assets/packages/flutter_map/lib/assets/flutter_map_logo.png","/Users/pierre/dev/geosector/app/build/web/assets/fonts/MaterialIcons-Regular.otf","/Users/pierre/dev/geosector/app/build/web/assets/shaders/ink_sparkle.frag","/Users/pierre/dev/geosector/app/build/web/assets/AssetManifest.json","/Users/pierre/dev/geosector/app/build/web/assets/AssetManifest.bin","/Users/pierre/dev/geosector/app/build/web/assets/AssetManifest.bin.json","/Users/pierre/dev/geosector/app/build/web/assets/FontManifest.json","/Users/pierre/dev/geosector/app/build/web/assets/NOTICES","/Users/pierre/dev/geosector/app/build/web/.DS_Store","/Users/pierre/dev/geosector/app/build/web/favicon-64.png","/Users/pierre/dev/geosector/app/build/web/favicon-16.png","/Users/pierre/dev/geosector/app/build/web/favicon.png","/Users/pierre/dev/geosector/app/build/web/icons/Icon-192.png","/Users/pierre/dev/geosector/app/build/web/icons/Icon-maskable-192.png","/Users/pierre/dev/geosector/app/build/web/icons/Icon-152.png","/Users/pierre/dev/geosector/app/build/web/icons/Icon-180.png","/Users/pierre/dev/geosector/app/build/web/icons/Icon-167.png","/Users/pierre/dev/geosector/app/build/web/icons/Icon-maskable-512.png","/Users/pierre/dev/geosector/app/build/web/icons/Icon-512.png","/Users/pierre/dev/geosector/app/build/web/manifest.json","/Users/pierre/dev/geosector/app/build/web/favicon-32.png","/Users/pierre/dev/geosector/app/build/web/flutter_service_worker.js"]
|
||||
@@ -0,0 +1 @@
|
||||
/Users/pierre/dev/geosector/app/build/web/flutter_service_worker.js: /Users/pierre/dev/geosector/app/build/web/flutter_bootstrap.js /Users/pierre/dev/geosector/app/build/web/version.json /Users/pierre/dev/geosector/app/build/web/index.html /Users/pierre/dev/geosector/app/build/web/favicon-64.png /Users/pierre/dev/geosector/app/build/web/favicon-16.png /Users/pierre/dev/geosector/app/build/web/main.dart.js /Users/pierre/dev/geosector/app/build/web/flutter.js /Users/pierre/dev/geosector/app/build/web/favicon.png /Users/pierre/dev/geosector/app/build/web/icons/Icon-192.png /Users/pierre/dev/geosector/app/build/web/icons/Icon-maskable-192.png /Users/pierre/dev/geosector/app/build/web/icons/Icon-152.png /Users/pierre/dev/geosector/app/build/web/icons/Icon-180.png /Users/pierre/dev/geosector/app/build/web/icons/Icon-167.png /Users/pierre/dev/geosector/app/build/web/icons/Icon-maskable-512.png /Users/pierre/dev/geosector/app/build/web/icons/Icon-512.png /Users/pierre/dev/geosector/app/build/web/manifest.json /Users/pierre/dev/geosector/app/build/web/favicon-32.png /Users/pierre/dev/geosector/app/build/web/assets/AssetManifest.json /Users/pierre/dev/geosector/app/build/web/assets/NOTICES /Users/pierre/dev/geosector/app/build/web/assets/FontManifest.json /Users/pierre/dev/geosector/app/build/web/assets/AssetManifest.bin.json /Users/pierre/dev/geosector/app/build/web/assets/packages/cupertino_icons/assets/CupertinoIcons.ttf /Users/pierre/dev/geosector/app/build/web/assets/packages/flutter_map/lib/assets/flutter_map_logo.png /Users/pierre/dev/geosector/app/build/web/assets/shaders/ink_sparkle.frag /Users/pierre/dev/geosector/app/build/web/assets/AssetManifest.bin /Users/pierre/dev/geosector/app/build/web/assets/fonts/MaterialIcons-Regular.otf /Users/pierre/dev/geosector/app/build/web/assets/assets/images/geosector-logo.png /Users/pierre/dev/geosector/app/build/web/assets/assets/images/logo-geosector-1024.png /Users/pierre/dev/geosector/app/build/web/assets/assets/images/icon-geosector.svg /Users/pierre/dev/geosector/app/build/web/assets/assets/images/logo_recu.png /Users/pierre/dev/geosector/app/build/web/assets/assets/fonts/Figtree-VariableFont_wght.ttf /Users/pierre/dev/geosector/app/build/web/assets/assets/animations/geo_main.json /Users/pierre/dev/geosector/app/build/web/canvaskit/skwasm.js /Users/pierre/dev/geosector/app/build/web/canvaskit/skwasm.js.symbols /Users/pierre/dev/geosector/app/build/web/canvaskit/canvaskit.js.symbols /Users/pierre/dev/geosector/app/build/web/canvaskit/skwasm.wasm /Users/pierre/dev/geosector/app/build/web/canvaskit/chromium/canvaskit.js.symbols /Users/pierre/dev/geosector/app/build/web/canvaskit/chromium/canvaskit.js /Users/pierre/dev/geosector/app/build/web/canvaskit/chromium/canvaskit.wasm /Users/pierre/dev/geosector/app/build/web/canvaskit/canvaskit.js /Users/pierre/dev/geosector/app/build/web/canvaskit/canvaskit.wasm
|
||||
@@ -0,0 +1 @@
|
||||
{"inputs":["/Users/pierre/dev/flutter/packages/flutter_tools/lib/src/build_system/targets/web.dart"],"outputs":["/Users/pierre/dev/geosector/app/.dart_tool/flutter_build/41acb28aedc1da36af63ba5cb8859018/main.dart"]}
|
||||
@@ -0,0 +1,22 @@
|
||||
// Flutter web plugin registrant file.
|
||||
//
|
||||
// Generated file. Do not edit.
|
||||
//
|
||||
|
||||
// @dart = 2.13
|
||||
// ignore_for_file: type=lint
|
||||
|
||||
import 'package:connectivity_plus/src/connectivity_plus_web.dart';
|
||||
import 'package:geolocator_web/geolocator_web.dart';
|
||||
import 'package:package_info_plus/src/package_info_plus_web.dart';
|
||||
import 'package:url_launcher_web/url_launcher_web.dart';
|
||||
import 'package:flutter_web_plugins/flutter_web_plugins.dart';
|
||||
|
||||
void registerPlugins([final Registrar? pluginRegistrar]) {
|
||||
final Registrar registrar = pluginRegistrar ?? webPluginRegistrar;
|
||||
ConnectivityPlusWebPlugin.registerWith(registrar);
|
||||
GeolocatorPlugin.registerWith(registrar);
|
||||
PackageInfoPlusWebPlugin.registerWith(registrar);
|
||||
UrlLauncherPlugin.registerWith(registrar);
|
||||
registrar.registerMessageHandler();
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
/Users/pierre/dev/geosector/app/build/web/.DS_Store /Users/pierre/dev/geosector/app/build/web/favicon-64.png /Users/pierre/dev/geosector/app/build/web/favicon-16.png /Users/pierre/dev/geosector/app/build/web/favicon.png /Users/pierre/dev/geosector/app/build/web/icons/Icon-192.png /Users/pierre/dev/geosector/app/build/web/icons/Icon-maskable-192.png /Users/pierre/dev/geosector/app/build/web/icons/Icon-152.png /Users/pierre/dev/geosector/app/build/web/icons/Icon-180.png /Users/pierre/dev/geosector/app/build/web/icons/Icon-167.png /Users/pierre/dev/geosector/app/build/web/icons/Icon-maskable-512.png /Users/pierre/dev/geosector/app/build/web/icons/Icon-512.png /Users/pierre/dev/geosector/app/build/web/manifest.json /Users/pierre/dev/geosector/app/build/web/favicon-32.png: /Users/pierre/dev/geosector/app/web/index.html /Users/pierre/dev/geosector/app/web/.DS_Store /Users/pierre/dev/geosector/app/web/favicon-64.png /Users/pierre/dev/geosector/app/web/favicon-16.png /Users/pierre/dev/geosector/app/web/favicon.png /Users/pierre/dev/geosector/app/web/icons/Icon-192.png /Users/pierre/dev/geosector/app/web/icons/Icon-maskable-192.png /Users/pierre/dev/geosector/app/web/icons/Icon-152.png /Users/pierre/dev/geosector/app/web/icons/Icon-180.png /Users/pierre/dev/geosector/app/web/icons/Icon-167.png /Users/pierre/dev/geosector/app/web/icons/Icon-maskable-512.png /Users/pierre/dev/geosector/app/web/icons/Icon-512.png /Users/pierre/dev/geosector/app/web/manifest.json /Users/pierre/dev/geosector/app/web/favicon-32.png
|
||||
@@ -0,0 +1 @@
|
||||
{"inputs":["/Users/pierre/dev/geosector/app/build/web/flutter_bootstrap.js","/Users/pierre/dev/geosector/app/build/web/version.json","/Users/pierre/dev/geosector/app/build/web/index.html","/Users/pierre/dev/geosector/app/build/web/favicon-64.png","/Users/pierre/dev/geosector/app/build/web/favicon-16.png","/Users/pierre/dev/geosector/app/build/web/main.dart.js","/Users/pierre/dev/geosector/app/build/web/flutter.js","/Users/pierre/dev/geosector/app/build/web/favicon.png","/Users/pierre/dev/geosector/app/build/web/icons/Icon-192.png","/Users/pierre/dev/geosector/app/build/web/icons/Icon-maskable-192.png","/Users/pierre/dev/geosector/app/build/web/icons/Icon-152.png","/Users/pierre/dev/geosector/app/build/web/icons/Icon-180.png","/Users/pierre/dev/geosector/app/build/web/icons/Icon-167.png","/Users/pierre/dev/geosector/app/build/web/icons/Icon-maskable-512.png","/Users/pierre/dev/geosector/app/build/web/icons/Icon-512.png","/Users/pierre/dev/geosector/app/build/web/manifest.json","/Users/pierre/dev/geosector/app/build/web/favicon-32.png","/Users/pierre/dev/geosector/app/build/web/assets/AssetManifest.json","/Users/pierre/dev/geosector/app/build/web/assets/NOTICES","/Users/pierre/dev/geosector/app/build/web/assets/FontManifest.json","/Users/pierre/dev/geosector/app/build/web/assets/AssetManifest.bin.json","/Users/pierre/dev/geosector/app/build/web/assets/packages/cupertino_icons/assets/CupertinoIcons.ttf","/Users/pierre/dev/geosector/app/build/web/assets/packages/flutter_map/lib/assets/flutter_map_logo.png","/Users/pierre/dev/geosector/app/build/web/assets/shaders/ink_sparkle.frag","/Users/pierre/dev/geosector/app/build/web/assets/AssetManifest.bin","/Users/pierre/dev/geosector/app/build/web/assets/fonts/MaterialIcons-Regular.otf","/Users/pierre/dev/geosector/app/build/web/assets/assets/images/geosector-logo.png","/Users/pierre/dev/geosector/app/build/web/assets/assets/images/logo-geosector-1024.png","/Users/pierre/dev/geosector/app/build/web/assets/assets/images/icon-geosector.svg","/Users/pierre/dev/geosector/app/build/web/assets/assets/images/logo_recu.png","/Users/pierre/dev/geosector/app/build/web/assets/assets/fonts/Figtree-VariableFont_wght.ttf","/Users/pierre/dev/geosector/app/build/web/assets/assets/animations/geo_main.json","/Users/pierre/dev/geosector/app/build/web/canvaskit/skwasm.js","/Users/pierre/dev/geosector/app/build/web/canvaskit/skwasm.js.symbols","/Users/pierre/dev/geosector/app/build/web/canvaskit/canvaskit.js.symbols","/Users/pierre/dev/geosector/app/build/web/canvaskit/skwasm.wasm","/Users/pierre/dev/geosector/app/build/web/canvaskit/chromium/canvaskit.js.symbols","/Users/pierre/dev/geosector/app/build/web/canvaskit/chromium/canvaskit.js","/Users/pierre/dev/geosector/app/build/web/canvaskit/chromium/canvaskit.wasm","/Users/pierre/dev/geosector/app/build/web/canvaskit/canvaskit.js","/Users/pierre/dev/geosector/app/build/web/canvaskit/canvaskit.wasm"],"outputs":["/Users/pierre/dev/geosector/app/build/web/flutter_service_worker.js"]}
|
||||
@@ -0,0 +1 @@
|
||||
{"inputs":["/Users/pierre/dev/flutter/bin/cache/engine.stamp"],"outputs":["/Users/pierre/dev/geosector/app/.dart_tool/flutter_build/41acb28aedc1da36af63ba5cb8859018/flutter.js","/Users/pierre/dev/geosector/app/.dart_tool/flutter_build/41acb28aedc1da36af63ba5cb8859018/canvaskit/skwasm.js","/Users/pierre/dev/geosector/app/.dart_tool/flutter_build/41acb28aedc1da36af63ba5cb8859018/canvaskit/skwasm.js.symbols","/Users/pierre/dev/geosector/app/.dart_tool/flutter_build/41acb28aedc1da36af63ba5cb8859018/canvaskit/canvaskit.js.symbols","/Users/pierre/dev/geosector/app/.dart_tool/flutter_build/41acb28aedc1da36af63ba5cb8859018/canvaskit/skwasm.wasm","/Users/pierre/dev/geosector/app/.dart_tool/flutter_build/41acb28aedc1da36af63ba5cb8859018/canvaskit/chromium/canvaskit.js.symbols","/Users/pierre/dev/geosector/app/.dart_tool/flutter_build/41acb28aedc1da36af63ba5cb8859018/canvaskit/chromium/canvaskit.js","/Users/pierre/dev/geosector/app/.dart_tool/flutter_build/41acb28aedc1da36af63ba5cb8859018/canvaskit/chromium/canvaskit.wasm","/Users/pierre/dev/geosector/app/.dart_tool/flutter_build/41acb28aedc1da36af63ba5cb8859018/canvaskit/canvaskit.js","/Users/pierre/dev/geosector/app/.dart_tool/flutter_build/41acb28aedc1da36af63ba5cb8859018/canvaskit/canvaskit.wasm"]}
|
||||
@@ -0,0 +1 @@
|
||||
{"inputs":["/Users/pierre/dev/geosector/app/web/*/index.html","/Users/pierre/dev/geosector/app/web/flutter_bootstrap.js","/Users/pierre/dev/flutter/bin/cache/engine.stamp"],"outputs":["/Users/pierre/dev/geosector/app/build/web/*/index.html","/Users/pierre/dev/geosector/app/build/web/flutter_bootstrap.js"],"buildKey":"[{\"compileTarget\":\"dart2js\",\"renderer\":\"canvaskit\",\"mainJsPath\":\"main.dart.js\"}]"}
|
||||
958
app/.dart_tool/package_config.json
Normal file
958
app/.dart_tool/package_config.json
Normal file
@@ -0,0 +1,958 @@
|
||||
{
|
||||
"configVersion": 2,
|
||||
"packages": [
|
||||
{
|
||||
"name": "_fe_analyzer_shared",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/_fe_analyzer_shared-76.0.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.3"
|
||||
},
|
||||
{
|
||||
"name": "_macros",
|
||||
"rootUri": "file:///Users/pierre/dev/flutter/bin/cache/dart-sdk/pkg/_macros",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.5"
|
||||
},
|
||||
{
|
||||
"name": "analyzer",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/analyzer-6.11.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.3"
|
||||
},
|
||||
{
|
||||
"name": "archive",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/archive-4.0.5",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.0"
|
||||
},
|
||||
{
|
||||
"name": "args",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/args-2.7.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.3"
|
||||
},
|
||||
{
|
||||
"name": "async",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/async-2.13.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "boolean_selector",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/boolean_selector-2.1.2",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.1"
|
||||
},
|
||||
{
|
||||
"name": "build",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/build-2.4.2",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.6"
|
||||
},
|
||||
{
|
||||
"name": "build_config",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/build_config-1.1.2",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.6"
|
||||
},
|
||||
{
|
||||
"name": "build_daemon",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/build_daemon-4.0.4",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.6"
|
||||
},
|
||||
{
|
||||
"name": "build_resolvers",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/build_resolvers-2.4.4",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.6"
|
||||
},
|
||||
{
|
||||
"name": "build_runner",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/build_runner-2.4.15",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.6"
|
||||
},
|
||||
{
|
||||
"name": "build_runner_core",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/build_runner_core-8.0.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.6"
|
||||
},
|
||||
{
|
||||
"name": "built_collection",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/built_collection-5.1.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.12"
|
||||
},
|
||||
{
|
||||
"name": "built_value",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/built_value-8.9.5",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.0"
|
||||
},
|
||||
{
|
||||
"name": "characters",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/characters-1.4.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "charcode",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/charcode-1.4.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.0"
|
||||
},
|
||||
{
|
||||
"name": "checked_yaml",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/checked_yaml-2.0.3",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.19"
|
||||
},
|
||||
{
|
||||
"name": "cli_util",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/cli_util-0.4.2",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "clock",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/clock-1.1.2",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "code_builder",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/code_builder-4.10.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.5"
|
||||
},
|
||||
{
|
||||
"name": "collection",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/collection-1.19.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "connectivity_plus",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/connectivity_plus-6.1.3",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.2"
|
||||
},
|
||||
{
|
||||
"name": "connectivity_plus_platform_interface",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/connectivity_plus_platform_interface-2.0.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.18"
|
||||
},
|
||||
{
|
||||
"name": "convert",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/convert-3.1.2",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "crypto",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/crypto-3.0.6",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "csslib",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/csslib-1.0.2",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.1"
|
||||
},
|
||||
{
|
||||
"name": "cupertino_icons",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/cupertino_icons-1.0.8",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.1"
|
||||
},
|
||||
{
|
||||
"name": "dart_earcut",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/dart_earcut-1.2.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.0"
|
||||
},
|
||||
{
|
||||
"name": "dart_style",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/dart_style-2.3.8",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.0"
|
||||
},
|
||||
{
|
||||
"name": "dbus",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/dbus-0.7.11",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.17"
|
||||
},
|
||||
{
|
||||
"name": "dio",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/dio-5.8.0+1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.18"
|
||||
},
|
||||
{
|
||||
"name": "dio_web_adapter",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/dio_web_adapter-2.1.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.3"
|
||||
},
|
||||
{
|
||||
"name": "equatable",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/equatable-2.0.7",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.12"
|
||||
},
|
||||
{
|
||||
"name": "event_bus",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/event_bus-2.0.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.12"
|
||||
},
|
||||
{
|
||||
"name": "fake_async",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/fake_async-1.3.3",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.3"
|
||||
},
|
||||
{
|
||||
"name": "ffi",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/ffi-2.1.4",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.7"
|
||||
},
|
||||
{
|
||||
"name": "file",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/file-7.0.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.0"
|
||||
},
|
||||
{
|
||||
"name": "fixnum",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/fixnum-1.1.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.1"
|
||||
},
|
||||
{
|
||||
"name": "fl_chart",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/fl_chart-0.70.2",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.2"
|
||||
},
|
||||
{
|
||||
"name": "flutter",
|
||||
"rootUri": "file:///Users/pierre/dev/flutter/packages/flutter",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.7"
|
||||
},
|
||||
{
|
||||
"name": "flutter_launcher_icons",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/flutter_launcher_icons-0.13.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.18"
|
||||
},
|
||||
{
|
||||
"name": "flutter_lints",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/flutter_lints-3.0.2",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.1"
|
||||
},
|
||||
{
|
||||
"name": "flutter_local_notifications",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/flutter_local_notifications-19.1.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "flutter_local_notifications_linux",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/flutter_local_notifications_linux-6.0.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "flutter_local_notifications_platform_interface",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/flutter_local_notifications_platform_interface-9.0.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "flutter_local_notifications_windows",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/flutter_local_notifications_windows-1.0.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "flutter_map",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/flutter_map-8.1.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.6"
|
||||
},
|
||||
{
|
||||
"name": "flutter_svg",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/flutter_svg-2.0.17",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "flutter_test",
|
||||
"rootUri": "file:///Users/pierre/dev/flutter/packages/flutter_test",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.7"
|
||||
},
|
||||
{
|
||||
"name": "flutter_web_plugins",
|
||||
"rootUri": "file:///Users/pierre/dev/flutter/packages/flutter_web_plugins",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.7"
|
||||
},
|
||||
{
|
||||
"name": "frontend_server_client",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/frontend_server_client-4.0.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.0"
|
||||
},
|
||||
{
|
||||
"name": "geolocator",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/geolocator-13.0.4",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.5"
|
||||
},
|
||||
{
|
||||
"name": "geolocator_android",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/geolocator_android-4.6.2",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.5"
|
||||
},
|
||||
{
|
||||
"name": "geolocator_apple",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/geolocator_apple-2.3.13",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.5"
|
||||
},
|
||||
{
|
||||
"name": "geolocator_platform_interface",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/geolocator_platform_interface-4.2.6",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.5"
|
||||
},
|
||||
{
|
||||
"name": "geolocator_web",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/geolocator_web-4.1.3",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.5"
|
||||
},
|
||||
{
|
||||
"name": "geolocator_windows",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/geolocator_windows-0.2.5",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.5"
|
||||
},
|
||||
{
|
||||
"name": "glob",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/glob-2.1.3",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.3"
|
||||
},
|
||||
{
|
||||
"name": "go_router",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/go_router-14.8.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "google_fonts",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/google_fonts-6.2.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.14"
|
||||
},
|
||||
{
|
||||
"name": "graphs",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/graphs-2.3.2",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "hive",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/hive-2.2.3",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.12"
|
||||
},
|
||||
{
|
||||
"name": "hive_flutter",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/hive_flutter-1.1.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.12"
|
||||
},
|
||||
{
|
||||
"name": "hive_generator",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/hive_generator-2.0.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.12"
|
||||
},
|
||||
{
|
||||
"name": "html",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/html-0.15.6",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.2"
|
||||
},
|
||||
{
|
||||
"name": "http",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/http-1.3.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "http_multi_server",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/http_multi_server-3.2.2",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.2"
|
||||
},
|
||||
{
|
||||
"name": "http_parser",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/http_parser-4.1.2",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "image",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/image-4.5.4",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.0"
|
||||
},
|
||||
{
|
||||
"name": "intl",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/intl-0.20.2",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.3"
|
||||
},
|
||||
{
|
||||
"name": "io",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/io-1.0.5",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "js",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/js-0.6.7",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.19"
|
||||
},
|
||||
{
|
||||
"name": "json_annotation",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/json_annotation-4.9.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.0"
|
||||
},
|
||||
{
|
||||
"name": "latlong2",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/latlong2-0.9.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.0"
|
||||
},
|
||||
{
|
||||
"name": "leak_tracker",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/leak_tracker-10.0.9",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.2"
|
||||
},
|
||||
{
|
||||
"name": "leak_tracker_flutter_testing",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/leak_tracker_flutter_testing-3.0.9",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.2"
|
||||
},
|
||||
{
|
||||
"name": "leak_tracker_testing",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/leak_tracker_testing-3.0.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.2"
|
||||
},
|
||||
{
|
||||
"name": "lints",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/lints-3.0.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.0"
|
||||
},
|
||||
{
|
||||
"name": "lists",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/lists-1.0.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.12"
|
||||
},
|
||||
{
|
||||
"name": "logger",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/logger-2.5.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.17"
|
||||
},
|
||||
{
|
||||
"name": "logging",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/logging-1.3.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "macros",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/macros-0.1.3-main.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "matcher",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/matcher-0.12.17",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "material_color_utilities",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/material_color_utilities-0.11.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.17"
|
||||
},
|
||||
{
|
||||
"name": "meta",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/meta-1.16.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.12"
|
||||
},
|
||||
{
|
||||
"name": "mgrs_dart",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/mgrs_dart-2.0.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.12"
|
||||
},
|
||||
{
|
||||
"name": "mime",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/mime-2.0.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.2"
|
||||
},
|
||||
{
|
||||
"name": "mqtt5_client",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/mqtt5_client-4.11.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.0"
|
||||
},
|
||||
{
|
||||
"name": "nested",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/nested-1.0.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.12"
|
||||
},
|
||||
{
|
||||
"name": "nm",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/nm-0.5.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.12"
|
||||
},
|
||||
{
|
||||
"name": "package_config",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/package_config-2.2.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "package_info_plus",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/package_info_plus-8.3.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.3"
|
||||
},
|
||||
{
|
||||
"name": "package_info_plus_platform_interface",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/package_info_plus_platform_interface-3.2.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.18"
|
||||
},
|
||||
{
|
||||
"name": "path",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/path-1.9.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "path_parsing",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/path_parsing-1.1.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.3"
|
||||
},
|
||||
{
|
||||
"name": "path_provider",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/path_provider-2.1.5",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "path_provider_android",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/path_provider_android-2.2.16",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.6"
|
||||
},
|
||||
{
|
||||
"name": "path_provider_foundation",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/path_provider_foundation-2.4.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.3"
|
||||
},
|
||||
{
|
||||
"name": "path_provider_linux",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.19"
|
||||
},
|
||||
{
|
||||
"name": "path_provider_platform_interface",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/path_provider_platform_interface-2.1.2",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.0"
|
||||
},
|
||||
{
|
||||
"name": "path_provider_windows",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/path_provider_windows-2.3.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.2"
|
||||
},
|
||||
{
|
||||
"name": "petitparser",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/petitparser-6.1.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.5"
|
||||
},
|
||||
{
|
||||
"name": "platform",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/platform-3.1.6",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.2"
|
||||
},
|
||||
{
|
||||
"name": "plugin_platform_interface",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/plugin_platform_interface-2.1.8",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.0"
|
||||
},
|
||||
{
|
||||
"name": "polylabel",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/polylabel-1.0.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.13"
|
||||
},
|
||||
{
|
||||
"name": "pool",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/pool-1.5.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.12"
|
||||
},
|
||||
{
|
||||
"name": "posix",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/posix-6.0.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.0"
|
||||
},
|
||||
{
|
||||
"name": "proj4dart",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/proj4dart-2.1.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.12"
|
||||
},
|
||||
{
|
||||
"name": "provider",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/provider-6.1.5",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.12"
|
||||
},
|
||||
{
|
||||
"name": "pub_semver",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/pub_semver-2.2.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "pubspec_parse",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/pubspec_parse-1.5.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.6"
|
||||
},
|
||||
{
|
||||
"name": "retry",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/retry-3.1.2",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.0"
|
||||
},
|
||||
{
|
||||
"name": "shelf",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/shelf-1.4.2",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "shelf_web_socket",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/shelf_web_socket-3.0.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.5"
|
||||
},
|
||||
{
|
||||
"name": "sky_engine",
|
||||
"rootUri": "file:///Users/pierre/dev/flutter/bin/cache/pkg/sky_engine",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.7"
|
||||
},
|
||||
{
|
||||
"name": "source_gen",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/source_gen-1.5.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.0"
|
||||
},
|
||||
{
|
||||
"name": "source_helper",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/source_helper-1.3.5",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "source_span",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/source_span-1.10.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.1"
|
||||
},
|
||||
{
|
||||
"name": "sprintf",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/sprintf-7.0.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.12"
|
||||
},
|
||||
{
|
||||
"name": "stack_trace",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/stack_trace-1.12.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "stream_channel",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/stream_channel-2.1.4",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.3"
|
||||
},
|
||||
{
|
||||
"name": "stream_transform",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/stream_transform-2.1.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.1"
|
||||
},
|
||||
{
|
||||
"name": "string_scanner",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/string_scanner-1.4.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.1"
|
||||
},
|
||||
{
|
||||
"name": "syncfusion_flutter_charts",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/syncfusion_flutter_charts-29.1.35",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "syncfusion_flutter_core",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/syncfusion_flutter_core-29.1.35",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "term_glyph",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/term_glyph-1.2.2",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.1"
|
||||
},
|
||||
{
|
||||
"name": "test_api",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/test_api-0.7.4",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.5"
|
||||
},
|
||||
{
|
||||
"name": "timezone",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/timezone-0.10.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.19"
|
||||
},
|
||||
{
|
||||
"name": "timing",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/timing-1.0.2",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "typed_data",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/typed_data-1.4.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.5"
|
||||
},
|
||||
{
|
||||
"name": "unicode",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/unicode-0.3.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.12"
|
||||
},
|
||||
{
|
||||
"name": "universal_html",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/universal_html-2.2.4",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.17"
|
||||
},
|
||||
{
|
||||
"name": "universal_io",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/universal_io-2.2.2",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.17"
|
||||
},
|
||||
{
|
||||
"name": "url_launcher",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/url_launcher-6.3.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.3"
|
||||
},
|
||||
{
|
||||
"name": "url_launcher_android",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/url_launcher_android-6.3.15",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.6"
|
||||
},
|
||||
{
|
||||
"name": "url_launcher_ios",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/url_launcher_ios-6.3.2",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.3"
|
||||
},
|
||||
{
|
||||
"name": "url_launcher_linux",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/url_launcher_linux-3.2.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.3"
|
||||
},
|
||||
{
|
||||
"name": "url_launcher_macos",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/url_launcher_macos-3.2.2",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.3"
|
||||
},
|
||||
{
|
||||
"name": "url_launcher_platform_interface",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/url_launcher_platform_interface-2.3.2",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.1"
|
||||
},
|
||||
{
|
||||
"name": "url_launcher_web",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/url_launcher_web-2.4.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.6"
|
||||
},
|
||||
{
|
||||
"name": "url_launcher_windows",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/url_launcher_windows-3.1.4",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "uuid",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/uuid-4.5.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.0"
|
||||
},
|
||||
{
|
||||
"name": "vector_graphics",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/vector_graphics-1.1.18",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "vector_graphics_codec",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/vector_graphics_codec-1.1.13",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "vector_graphics_compiler",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/vector_graphics_compiler-1.1.16",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "vector_math",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/vector_math-2.1.4",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.14"
|
||||
},
|
||||
{
|
||||
"name": "vm_service",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/vm_service-15.0.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.3"
|
||||
},
|
||||
{
|
||||
"name": "watcher",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/watcher-1.1.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.1"
|
||||
},
|
||||
{
|
||||
"name": "web",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/web-1.1.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "web_socket",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/web_socket-0.1.6",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.3"
|
||||
},
|
||||
{
|
||||
"name": "web_socket_channel",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/web_socket_channel-3.0.2",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.3"
|
||||
},
|
||||
{
|
||||
"name": "win32",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/win32-5.13.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.7"
|
||||
},
|
||||
{
|
||||
"name": "wkt_parser",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/wkt_parser-2.0.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.12"
|
||||
},
|
||||
{
|
||||
"name": "xdg_directories",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/xdg_directories-1.1.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.3"
|
||||
},
|
||||
{
|
||||
"name": "xml",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/xml-6.5.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.2"
|
||||
},
|
||||
{
|
||||
"name": "yaml",
|
||||
"rootUri": "file:///Users/pierre/.pub-cache/hosted/pub.dev/yaml-3.1.3",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "geosector_app",
|
||||
"rootUri": "../",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.0"
|
||||
}
|
||||
],
|
||||
"generator": "pub",
|
||||
"generatorVersion": "3.8.1",
|
||||
"flutterRoot": "file:///Users/pierre/dev/flutter",
|
||||
"flutterVersion": "3.32.1",
|
||||
"pubCache": "file:///Users/pierre/.pub-cache"
|
||||
}
|
||||
633
app/.dart_tool/package_config_subset
Normal file
633
app/.dart_tool/package_config_subset
Normal file
@@ -0,0 +1,633 @@
|
||||
_fe_analyzer_shared
|
||||
3.3
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/_fe_analyzer_shared-76.0.0/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/_fe_analyzer_shared-76.0.0/lib/
|
||||
analyzer
|
||||
3.3
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/analyzer-6.11.0/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/analyzer-6.11.0/lib/
|
||||
archive
|
||||
3.0
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/archive-4.0.5/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/archive-4.0.5/lib/
|
||||
args
|
||||
3.3
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/args-2.7.0/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/args-2.7.0/lib/
|
||||
async
|
||||
3.4
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/async-2.13.0/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/async-2.13.0/lib/
|
||||
boolean_selector
|
||||
3.1
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/boolean_selector-2.1.2/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/boolean_selector-2.1.2/lib/
|
||||
build
|
||||
3.6
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/build-2.4.2/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/build-2.4.2/lib/
|
||||
build_config
|
||||
3.6
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/build_config-1.1.2/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/build_config-1.1.2/lib/
|
||||
build_daemon
|
||||
3.6
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/build_daemon-4.0.4/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/build_daemon-4.0.4/lib/
|
||||
build_resolvers
|
||||
3.6
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/build_resolvers-2.4.4/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/build_resolvers-2.4.4/lib/
|
||||
build_runner
|
||||
3.6
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/build_runner-2.4.15/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/build_runner-2.4.15/lib/
|
||||
build_runner_core
|
||||
3.6
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/build_runner_core-8.0.0/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/build_runner_core-8.0.0/lib/
|
||||
built_collection
|
||||
2.12
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/built_collection-5.1.1/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/built_collection-5.1.1/lib/
|
||||
built_value
|
||||
3.0
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/built_value-8.9.5/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/built_value-8.9.5/lib/
|
||||
characters
|
||||
3.4
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/characters-1.4.0/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/characters-1.4.0/lib/
|
||||
charcode
|
||||
3.0
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/charcode-1.4.0/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/charcode-1.4.0/lib/
|
||||
checked_yaml
|
||||
2.19
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/checked_yaml-2.0.3/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/checked_yaml-2.0.3/lib/
|
||||
cli_util
|
||||
3.4
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/cli_util-0.4.2/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/cli_util-0.4.2/lib/
|
||||
clock
|
||||
3.4
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/clock-1.1.2/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/clock-1.1.2/lib/
|
||||
code_builder
|
||||
3.5
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/code_builder-4.10.1/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/code_builder-4.10.1/lib/
|
||||
collection
|
||||
3.4
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/collection-1.19.1/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/collection-1.19.1/lib/
|
||||
connectivity_plus
|
||||
3.2
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/connectivity_plus-6.1.3/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/connectivity_plus-6.1.3/lib/
|
||||
connectivity_plus_platform_interface
|
||||
2.18
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/connectivity_plus_platform_interface-2.0.1/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/connectivity_plus_platform_interface-2.0.1/lib/
|
||||
convert
|
||||
3.4
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/convert-3.1.2/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/convert-3.1.2/lib/
|
||||
crypto
|
||||
3.4
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/crypto-3.0.6/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/crypto-3.0.6/lib/
|
||||
csslib
|
||||
3.1
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/csslib-1.0.2/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/csslib-1.0.2/lib/
|
||||
cupertino_icons
|
||||
3.1
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/cupertino_icons-1.0.8/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/cupertino_icons-1.0.8/lib/
|
||||
dart_earcut
|
||||
3.0
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/dart_earcut-1.2.0/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/dart_earcut-1.2.0/lib/
|
||||
dart_style
|
||||
3.0
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/dart_style-2.3.8/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/dart_style-2.3.8/lib/
|
||||
dbus
|
||||
2.17
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/dbus-0.7.11/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/dbus-0.7.11/lib/
|
||||
dio
|
||||
2.18
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/dio-5.8.0+1/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/dio-5.8.0+1/lib/
|
||||
dio_web_adapter
|
||||
3.3
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/dio_web_adapter-2.1.1/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/dio_web_adapter-2.1.1/lib/
|
||||
equatable
|
||||
2.12
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/equatable-2.0.7/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/equatable-2.0.7/lib/
|
||||
event_bus
|
||||
2.12
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/event_bus-2.0.1/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/event_bus-2.0.1/lib/
|
||||
fake_async
|
||||
3.3
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/fake_async-1.3.3/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/fake_async-1.3.3/lib/
|
||||
ffi
|
||||
3.7
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/ffi-2.1.4/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/ffi-2.1.4/lib/
|
||||
file
|
||||
3.0
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/file-7.0.1/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/file-7.0.1/lib/
|
||||
fixnum
|
||||
3.1
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/fixnum-1.1.1/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/fixnum-1.1.1/lib/
|
||||
fl_chart
|
||||
3.2
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/fl_chart-0.70.2/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/fl_chart-0.70.2/lib/
|
||||
flutter_launcher_icons
|
||||
2.18
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/flutter_launcher_icons-0.13.1/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/flutter_launcher_icons-0.13.1/lib/
|
||||
flutter_lints
|
||||
3.1
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/flutter_lints-3.0.2/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/flutter_lints-3.0.2/lib/
|
||||
flutter_local_notifications
|
||||
3.4
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/flutter_local_notifications-19.1.0/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/flutter_local_notifications-19.1.0/lib/
|
||||
flutter_local_notifications_linux
|
||||
3.4
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/flutter_local_notifications_linux-6.0.0/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/flutter_local_notifications_linux-6.0.0/lib/
|
||||
flutter_local_notifications_platform_interface
|
||||
3.4
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/flutter_local_notifications_platform_interface-9.0.0/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/flutter_local_notifications_platform_interface-9.0.0/lib/
|
||||
flutter_local_notifications_windows
|
||||
3.4
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/flutter_local_notifications_windows-1.0.0/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/flutter_local_notifications_windows-1.0.0/lib/
|
||||
flutter_map
|
||||
3.6
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/flutter_map-8.1.1/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/flutter_map-8.1.1/lib/
|
||||
flutter_svg
|
||||
3.4
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/flutter_svg-2.0.17/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/flutter_svg-2.0.17/lib/
|
||||
frontend_server_client
|
||||
3.0
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/frontend_server_client-4.0.0/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/frontend_server_client-4.0.0/lib/
|
||||
geolocator
|
||||
3.5
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/geolocator-13.0.4/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/geolocator-13.0.4/lib/
|
||||
geolocator_android
|
||||
3.5
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/geolocator_android-4.6.2/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/geolocator_android-4.6.2/lib/
|
||||
geolocator_apple
|
||||
3.5
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/geolocator_apple-2.3.13/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/geolocator_apple-2.3.13/lib/
|
||||
geolocator_platform_interface
|
||||
3.5
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/geolocator_platform_interface-4.2.6/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/geolocator_platform_interface-4.2.6/lib/
|
||||
geolocator_web
|
||||
3.5
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/geolocator_web-4.1.3/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/geolocator_web-4.1.3/lib/
|
||||
geolocator_windows
|
||||
3.5
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/geolocator_windows-0.2.5/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/geolocator_windows-0.2.5/lib/
|
||||
glob
|
||||
3.3
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/glob-2.1.3/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/glob-2.1.3/lib/
|
||||
go_router
|
||||
3.4
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/go_router-14.8.1/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/go_router-14.8.1/lib/
|
||||
google_fonts
|
||||
2.14
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/google_fonts-6.2.1/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/google_fonts-6.2.1/lib/
|
||||
graphs
|
||||
3.4
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/graphs-2.3.2/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/graphs-2.3.2/lib/
|
||||
hive
|
||||
2.12
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/hive-2.2.3/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/hive-2.2.3/lib/
|
||||
hive_flutter
|
||||
2.12
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/hive_flutter-1.1.0/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/hive_flutter-1.1.0/lib/
|
||||
hive_generator
|
||||
2.12
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/hive_generator-2.0.1/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/hive_generator-2.0.1/lib/
|
||||
html
|
||||
3.2
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/html-0.15.6/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/html-0.15.6/lib/
|
||||
http
|
||||
3.4
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/http-1.3.0/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/http-1.3.0/lib/
|
||||
http_multi_server
|
||||
3.2
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/http_multi_server-3.2.2/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/http_multi_server-3.2.2/lib/
|
||||
http_parser
|
||||
3.4
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/http_parser-4.1.2/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/http_parser-4.1.2/lib/
|
||||
image
|
||||
3.0
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/image-4.5.4/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/image-4.5.4/lib/
|
||||
intl
|
||||
3.3
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/intl-0.20.2/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/intl-0.20.2/lib/
|
||||
io
|
||||
3.4
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/io-1.0.5/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/io-1.0.5/lib/
|
||||
js
|
||||
2.19
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/js-0.6.7/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/js-0.6.7/lib/
|
||||
json_annotation
|
||||
3.0
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/json_annotation-4.9.0/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/json_annotation-4.9.0/lib/
|
||||
latlong2
|
||||
3.0
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/latlong2-0.9.1/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/latlong2-0.9.1/lib/
|
||||
leak_tracker
|
||||
3.2
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/leak_tracker-10.0.9/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/leak_tracker-10.0.9/lib/
|
||||
leak_tracker_flutter_testing
|
||||
3.2
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/leak_tracker_flutter_testing-3.0.9/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/leak_tracker_flutter_testing-3.0.9/lib/
|
||||
leak_tracker_testing
|
||||
3.2
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/leak_tracker_testing-3.0.1/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/leak_tracker_testing-3.0.1/lib/
|
||||
lints
|
||||
3.0
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/lints-3.0.0/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/lints-3.0.0/lib/
|
||||
lists
|
||||
2.12
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/lists-1.0.1/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/lists-1.0.1/lib/
|
||||
logger
|
||||
2.17
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/logger-2.5.0/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/logger-2.5.0/lib/
|
||||
logging
|
||||
3.4
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/logging-1.3.0/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/logging-1.3.0/lib/
|
||||
macros
|
||||
3.4
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/macros-0.1.3-main.0/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/macros-0.1.3-main.0/lib/
|
||||
matcher
|
||||
3.4
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/matcher-0.12.17/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/matcher-0.12.17/lib/
|
||||
material_color_utilities
|
||||
2.17
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/material_color_utilities-0.11.1/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/material_color_utilities-0.11.1/lib/
|
||||
meta
|
||||
2.12
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/meta-1.16.0/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/meta-1.16.0/lib/
|
||||
mgrs_dart
|
||||
2.12
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/mgrs_dart-2.0.0/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/mgrs_dart-2.0.0/lib/
|
||||
mime
|
||||
3.2
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/mime-2.0.0/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/mime-2.0.0/lib/
|
||||
mqtt5_client
|
||||
3.0
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/mqtt5_client-4.11.0/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/mqtt5_client-4.11.0/lib/
|
||||
nested
|
||||
2.12
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/nested-1.0.0/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/nested-1.0.0/lib/
|
||||
nm
|
||||
2.12
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/nm-0.5.0/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/nm-0.5.0/lib/
|
||||
package_config
|
||||
3.4
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/package_config-2.2.0/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/package_config-2.2.0/lib/
|
||||
package_info_plus
|
||||
3.3
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/package_info_plus-8.3.0/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/package_info_plus-8.3.0/lib/
|
||||
package_info_plus_platform_interface
|
||||
2.18
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/package_info_plus_platform_interface-3.2.0/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/package_info_plus_platform_interface-3.2.0/lib/
|
||||
path
|
||||
3.4
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/path-1.9.1/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/path-1.9.1/lib/
|
||||
path_parsing
|
||||
3.3
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/path_parsing-1.1.0/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/path_parsing-1.1.0/lib/
|
||||
path_provider
|
||||
3.4
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/path_provider-2.1.5/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/path_provider-2.1.5/lib/
|
||||
path_provider_android
|
||||
3.6
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/path_provider_android-2.2.16/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/path_provider_android-2.2.16/lib/
|
||||
path_provider_foundation
|
||||
3.3
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/path_provider_foundation-2.4.1/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/path_provider_foundation-2.4.1/lib/
|
||||
path_provider_linux
|
||||
2.19
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/lib/
|
||||
path_provider_platform_interface
|
||||
3.0
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/path_provider_platform_interface-2.1.2/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/path_provider_platform_interface-2.1.2/lib/
|
||||
path_provider_windows
|
||||
3.2
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/path_provider_windows-2.3.0/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/path_provider_windows-2.3.0/lib/
|
||||
petitparser
|
||||
3.5
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/petitparser-6.1.0/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/petitparser-6.1.0/lib/
|
||||
platform
|
||||
3.2
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/platform-3.1.6/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/platform-3.1.6/lib/
|
||||
plugin_platform_interface
|
||||
3.0
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/plugin_platform_interface-2.1.8/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/plugin_platform_interface-2.1.8/lib/
|
||||
polylabel
|
||||
2.13
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/polylabel-1.0.1/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/polylabel-1.0.1/lib/
|
||||
pool
|
||||
2.12
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/pool-1.5.1/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/pool-1.5.1/lib/
|
||||
posix
|
||||
3.0
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/posix-6.0.1/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/posix-6.0.1/lib/
|
||||
proj4dart
|
||||
2.12
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/proj4dart-2.1.0/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/proj4dart-2.1.0/lib/
|
||||
provider
|
||||
2.12
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/provider-6.1.5/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/provider-6.1.5/lib/
|
||||
pub_semver
|
||||
3.4
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/pub_semver-2.2.0/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/pub_semver-2.2.0/lib/
|
||||
pubspec_parse
|
||||
3.6
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/pubspec_parse-1.5.0/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/pubspec_parse-1.5.0/lib/
|
||||
retry
|
||||
3.0
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/retry-3.1.2/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/retry-3.1.2/lib/
|
||||
shelf
|
||||
3.4
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/shelf-1.4.2/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/shelf-1.4.2/lib/
|
||||
shelf_web_socket
|
||||
3.5
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/shelf_web_socket-3.0.0/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/shelf_web_socket-3.0.0/lib/
|
||||
source_gen
|
||||
3.0
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/source_gen-1.5.0/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/source_gen-1.5.0/lib/
|
||||
source_helper
|
||||
3.4
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/source_helper-1.3.5/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/source_helper-1.3.5/lib/
|
||||
source_span
|
||||
3.1
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/source_span-1.10.1/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/source_span-1.10.1/lib/
|
||||
sprintf
|
||||
2.12
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/sprintf-7.0.0/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/sprintf-7.0.0/lib/
|
||||
stack_trace
|
||||
3.4
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/stack_trace-1.12.1/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/stack_trace-1.12.1/lib/
|
||||
stream_channel
|
||||
3.3
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/stream_channel-2.1.4/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/stream_channel-2.1.4/lib/
|
||||
stream_transform
|
||||
3.1
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/stream_transform-2.1.1/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/stream_transform-2.1.1/lib/
|
||||
string_scanner
|
||||
3.1
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/string_scanner-1.4.1/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/string_scanner-1.4.1/lib/
|
||||
syncfusion_flutter_charts
|
||||
3.4
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/syncfusion_flutter_charts-29.1.35/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/syncfusion_flutter_charts-29.1.35/lib/
|
||||
syncfusion_flutter_core
|
||||
3.4
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/syncfusion_flutter_core-29.1.35/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/syncfusion_flutter_core-29.1.35/lib/
|
||||
term_glyph
|
||||
3.1
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/term_glyph-1.2.2/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/term_glyph-1.2.2/lib/
|
||||
test_api
|
||||
3.5
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/test_api-0.7.4/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/test_api-0.7.4/lib/
|
||||
timezone
|
||||
2.19
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/timezone-0.10.1/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/timezone-0.10.1/lib/
|
||||
timing
|
||||
3.4
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/timing-1.0.2/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/timing-1.0.2/lib/
|
||||
typed_data
|
||||
3.5
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/typed_data-1.4.0/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/typed_data-1.4.0/lib/
|
||||
unicode
|
||||
2.12
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/unicode-0.3.1/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/unicode-0.3.1/lib/
|
||||
universal_html
|
||||
2.17
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/universal_html-2.2.4/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/universal_html-2.2.4/lib/
|
||||
universal_io
|
||||
2.17
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/universal_io-2.2.2/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/universal_io-2.2.2/lib/
|
||||
url_launcher
|
||||
3.3
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/url_launcher-6.3.1/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/url_launcher-6.3.1/lib/
|
||||
url_launcher_android
|
||||
3.6
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/url_launcher_android-6.3.15/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/url_launcher_android-6.3.15/lib/
|
||||
url_launcher_ios
|
||||
3.3
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/url_launcher_ios-6.3.2/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/url_launcher_ios-6.3.2/lib/
|
||||
url_launcher_linux
|
||||
3.3
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/url_launcher_linux-3.2.1/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/url_launcher_linux-3.2.1/lib/
|
||||
url_launcher_macos
|
||||
3.3
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/url_launcher_macos-3.2.2/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/url_launcher_macos-3.2.2/lib/
|
||||
url_launcher_platform_interface
|
||||
3.1
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/url_launcher_platform_interface-2.3.2/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/url_launcher_platform_interface-2.3.2/lib/
|
||||
url_launcher_web
|
||||
3.6
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/url_launcher_web-2.4.0/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/url_launcher_web-2.4.0/lib/
|
||||
url_launcher_windows
|
||||
3.4
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/url_launcher_windows-3.1.4/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/url_launcher_windows-3.1.4/lib/
|
||||
uuid
|
||||
3.0
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/uuid-4.5.1/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/uuid-4.5.1/lib/
|
||||
vector_graphics
|
||||
3.4
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/vector_graphics-1.1.18/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/vector_graphics-1.1.18/lib/
|
||||
vector_graphics_codec
|
||||
3.4
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/vector_graphics_codec-1.1.13/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/vector_graphics_codec-1.1.13/lib/
|
||||
vector_graphics_compiler
|
||||
3.4
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/vector_graphics_compiler-1.1.16/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/vector_graphics_compiler-1.1.16/lib/
|
||||
vector_math
|
||||
2.14
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/vector_math-2.1.4/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/vector_math-2.1.4/lib/
|
||||
vm_service
|
||||
3.3
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/vm_service-15.0.0/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/vm_service-15.0.0/lib/
|
||||
watcher
|
||||
3.1
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/watcher-1.1.1/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/watcher-1.1.1/lib/
|
||||
web
|
||||
3.4
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/web-1.1.1/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/web-1.1.1/lib/
|
||||
web_socket
|
||||
3.3
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/web_socket-0.1.6/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/web_socket-0.1.6/lib/
|
||||
web_socket_channel
|
||||
3.3
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/web_socket_channel-3.0.2/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/web_socket_channel-3.0.2/lib/
|
||||
win32
|
||||
3.7
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/win32-5.13.0/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/win32-5.13.0/lib/
|
||||
wkt_parser
|
||||
2.12
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/wkt_parser-2.0.0/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/wkt_parser-2.0.0/lib/
|
||||
xdg_directories
|
||||
3.3
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/xdg_directories-1.1.0/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/xdg_directories-1.1.0/lib/
|
||||
xml
|
||||
3.2
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/xml-6.5.0/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/xml-6.5.0/lib/
|
||||
yaml
|
||||
3.4
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/yaml-3.1.3/
|
||||
file:///Users/pierre/.pub-cache/hosted/pub.dev/yaml-3.1.3/lib/
|
||||
_macros
|
||||
3.5
|
||||
file:///Users/pierre/dev/flutter/bin/cache/dart-sdk/pkg/_macros/
|
||||
file:///Users/pierre/dev/flutter/bin/cache/dart-sdk/pkg/_macros/lib/
|
||||
sky_engine
|
||||
3.7
|
||||
file:///Users/pierre/dev/flutter/bin/cache/pkg/sky_engine/
|
||||
file:///Users/pierre/dev/flutter/bin/cache/pkg/sky_engine/lib/
|
||||
flutter
|
||||
3.7
|
||||
file:///Users/pierre/dev/flutter/packages/flutter/
|
||||
file:///Users/pierre/dev/flutter/packages/flutter/lib/
|
||||
flutter_test
|
||||
3.7
|
||||
file:///Users/pierre/dev/flutter/packages/flutter_test/
|
||||
file:///Users/pierre/dev/flutter/packages/flutter_test/lib/
|
||||
flutter_web_plugins
|
||||
3.7
|
||||
file:///Users/pierre/dev/flutter/packages/flutter_web_plugins/
|
||||
file:///Users/pierre/dev/flutter/packages/flutter_web_plugins/lib/
|
||||
geosector_app
|
||||
3.0
|
||||
file:///Users/pierre/dev/geosector/app/
|
||||
file:///Users/pierre/dev/geosector/app/lib/
|
||||
2
|
||||
1482
app/.dart_tool/package_graph.json
Normal file
1482
app/.dart_tool/package_graph.json
Normal file
File diff suppressed because it is too large
Load Diff
Binary file not shown.
1
app/.dart_tool/version
Normal file
1
app/.dart_tool/version
Normal file
@@ -0,0 +1 @@
|
||||
3.32.1
|
||||
1
app/.flutter-plugins-dependencies
Normal file
1
app/.flutter-plugins-dependencies
Normal file
File diff suppressed because one or more lines are too long
47
app/.gitignore
vendored
47
app/.gitignore
vendored
@@ -1,47 +0,0 @@
|
||||
# Miscellaneous
|
||||
*.class
|
||||
*.log
|
||||
*.pyc
|
||||
*.swp
|
||||
.DS_Store
|
||||
.atom/
|
||||
.build/
|
||||
.buildlog/
|
||||
.history
|
||||
.svn/
|
||||
.swiftpm/
|
||||
migrate_working_dir/
|
||||
|
||||
# IntelliJ related
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
.idea/
|
||||
|
||||
# The .vscode folder contains launch configuration and tasks you configure in
|
||||
# VS Code which you may wish to be included in version control, so this line
|
||||
# is commented out by default.
|
||||
#.vscode/
|
||||
|
||||
# Flutter/Dart/Pub related
|
||||
**/doc/api/
|
||||
**/ios/Flutter/.last_build_id
|
||||
.dart_tool/
|
||||
.flutter-plugins
|
||||
.flutter-plugins-dependencies
|
||||
.pub-cache/
|
||||
.pub/
|
||||
/build/
|
||||
|
||||
# Symbolication related
|
||||
app.*.symbols
|
||||
|
||||
# Obfuscation related
|
||||
app.*.map.json
|
||||
|
||||
# Android Studio will place build artifacts here
|
||||
/android/app/debug
|
||||
/android/app/profile
|
||||
/android/app/release
|
||||
|
||||
sync_config.jsonc
|
||||
94
app/.vscode/settings.json
vendored
94
app/.vscode/settings.json
vendored
@@ -6,7 +6,7 @@
|
||||
"editor.minimap.enabled": true, // On veut voir la minimap
|
||||
"editor.minimap.showSlider": "always", // On veut voir la minimap
|
||||
"editor.minimap.size": "fill", // On veut voir la minimap
|
||||
"editor.minimap.scale": 2,
|
||||
"editor.minimap.scale": 1,
|
||||
"editor.tokenColorCustomizations": {
|
||||
"textMateRules": [
|
||||
{
|
||||
@@ -23,12 +23,14 @@
|
||||
},
|
||||
"editor.minimap.renderCharacters": true,
|
||||
"editor.minimap.maxColumn": 120,
|
||||
"breadcrumbs.enabled": false,
|
||||
"breadcrumbs.enabled": true,
|
||||
|
||||
// -- Tabs
|
||||
"workbench.editor.wrapTabs": true, // On veut voir les tabs
|
||||
"workbench.editor.tabSizing": "shrink", // On veut voir les tabs
|
||||
"workbench.editor.pinnedTabSizing": "compact",
|
||||
"workbench.editor.enablePreview": false, // Un clic sur un fichier l'ouvre
|
||||
|
||||
// -- Sidebar
|
||||
"workbench.tree.indent": 15, // Indente plus pour plus de clarté dans la sidebar
|
||||
"workbench.tree.renderIndentGuides": "always",
|
||||
@@ -44,7 +46,8 @@
|
||||
"editor.guides.bracketPairs": "active",
|
||||
// Ergonomie
|
||||
"editor.wordWrap": "off",
|
||||
"editor.rulers": [],
|
||||
"editor.rulers": [300],
|
||||
"editor.wordWrapColumn": 300,
|
||||
"editor.suggest.insertMode": "replace", // L'autocomplétion remplace le mot en cours
|
||||
"editor.acceptSuggestionOnCommitCharacter": false, // Evite que l'autocomplétion soit accepté lors d'un . par exemple
|
||||
"editor.formatOnSave": true,
|
||||
@@ -59,21 +62,13 @@
|
||||
},
|
||||
"intelephense.format.braces": "k&r",
|
||||
"intelephense.format.enable": true,
|
||||
"php.validate.executablePath": "/opt/homebrew/opt/php@8.3/bin/php",
|
||||
"php.executablePath": "/opt/homebrew/opt/php@8.3/bin/php",
|
||||
"[javascript]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.formatOnSave": true,
|
||||
"editor.formatOnPaste": true
|
||||
},
|
||||
"[dart]": {
|
||||
"editor.formatOnSave": true,
|
||||
"editor.formatOnType": true,
|
||||
"editor.rulers": [
|
||||
80
|
||||
],
|
||||
"editor.selectionHighlight": false,
|
||||
"editor.tabCompletion": "onlySnippets",
|
||||
"editor.wordBasedSuggestions": "off"
|
||||
},
|
||||
"prettier.printWidth": 360,
|
||||
"prettier.semi": true,
|
||||
"prettier.singleQuote": true,
|
||||
@@ -82,6 +77,19 @@
|
||||
"explorer.autoReveal": false,
|
||||
"explorer.confirmDragAndDrop": false,
|
||||
"emmet.triggerExpansionOnTab": true,
|
||||
"emmet.includeLanguages": {
|
||||
"javascript": "javascript",
|
||||
"php": "php",
|
||||
"svelte": "html",
|
||||
"dart": "dart"
|
||||
},
|
||||
"problems.decorations.enabled": true,
|
||||
"explorer.decorations.colors": true,
|
||||
"explorer.decorations.badges": true,
|
||||
"php.validate.enable": true,
|
||||
"php.suggest.basic": false,
|
||||
"dart.analysisExcludedFolders": [],
|
||||
"dart.enableSdkFormatter": true,
|
||||
// Fichiers
|
||||
"files.defaultLanguage": "markdown",
|
||||
"files.autoSaveWorkspaceFilesOnly": true,
|
||||
@@ -92,7 +100,7 @@
|
||||
"javascript.preferences.importModuleSpecifierEnding": "js",
|
||||
"typescript.preferences.importModuleSpecifierEnding": "js",
|
||||
// Extensions
|
||||
"tailwindCSS.experimental.configFile": "frontend/tailwind.config.js",
|
||||
"tailwindCSS.experimental.configFile": "web/tailwind.config.js",
|
||||
"editor.quickSuggestions": {
|
||||
"strings": true
|
||||
},
|
||||
@@ -104,27 +112,45 @@
|
||||
"**/*.svelte"
|
||||
],
|
||||
"svelte.plugin.svelte.diagnostics.enable": false,
|
||||
"problems.decorations.enabled": false,
|
||||
"js/ts.implicitProjectConfig.checkJs": false,
|
||||
"svelte.enable-ts-plugin": false,
|
||||
"workbench.colorCustomizations": {
|
||||
"activityBar.activeBackground": "#405978",
|
||||
"activityBar.background": "#405978",
|
||||
"activityBar.foreground": "#e7e7e7",
|
||||
"activityBar.inactiveForeground": "#e7e7e799",
|
||||
"activityBarBadge.background": "#bc829c",
|
||||
"activityBarBadge.foreground": "#15202b",
|
||||
"commandCenter.border": "#e7e7e799",
|
||||
"sash.hoverBorder": "#405978",
|
||||
"statusBar.background": "#2e4057",
|
||||
"statusBar.foreground": "#e7e7e7",
|
||||
"statusBarItem.hoverBackground": "#405978",
|
||||
"statusBarItem.remoteBackground": "#2e4057",
|
||||
"statusBarItem.remoteForeground": "#e7e7e7",
|
||||
"titleBar.activeBackground": "#2e4057",
|
||||
"titleBar.activeForeground": "#e7e7e7",
|
||||
"titleBar.inactiveBackground": "#2e405799",
|
||||
"titleBar.inactiveForeground": "#e7e7e799"
|
||||
"cline.autoApproveLimit": 100,
|
||||
"cline.autoApproveRequests": true,
|
||||
"cline.enableMemoryBank": true,
|
||||
"cline.includeSnippetsFromMemory": true,
|
||||
"cline.contextLength": 10000,
|
||||
"cline.autoFormat": true,
|
||||
"cline.primaryDocumentationFile": ".cline",
|
||||
"cline.gitIntegration": true,
|
||||
"cline.projectStructure": {
|
||||
"api": "php",
|
||||
"app": "flutter",
|
||||
"web": "svelte"
|
||||
},
|
||||
"peacock.color": "#2E4057",
|
||||
"cline.referenceFiles": {
|
||||
"database": "docs/db-resalice.dump",
|
||||
"apiEndpoints": "docs/api_endpoints.md",
|
||||
"architecture": "docs/architecture.md"
|
||||
},
|
||||
"cline.databaseSchema": "docs/db-resalice.dump",
|
||||
"peacock.color": "#42b883",
|
||||
"workbench.colorCustomizations": {
|
||||
"activityBar.activeBackground": "#65c89b",
|
||||
"activityBar.background": "#65c89b",
|
||||
"activityBar.foreground": "#15202b",
|
||||
"activityBar.inactiveForeground": "#15202b99",
|
||||
"activityBarBadge.background": "#945bc4",
|
||||
"activityBarBadge.foreground": "#e7e7e7",
|
||||
"commandCenter.border": "#15202b99",
|
||||
"sash.hoverBorder": "#65c89b",
|
||||
"statusBar.background": "#42b883",
|
||||
"statusBar.foreground": "#15202b",
|
||||
"statusBarItem.hoverBackground": "#359268",
|
||||
"statusBarItem.remoteBackground": "#42b883",
|
||||
"statusBarItem.remoteForeground": "#15202b",
|
||||
"titleBar.activeBackground": "#42b883",
|
||||
"titleBar.activeForeground": "#15202b",
|
||||
"titleBar.inactiveBackground": "#42b88399",
|
||||
"titleBar.inactiveForeground": "#15202b99"
|
||||
}
|
||||
}
|
||||
428
app/README-APP.md
Normal file
428
app/README-APP.md
Normal file
@@ -0,0 +1,428 @@
|
||||
# GEOSECTOR
|
||||
|
||||
Une application puissante et intuitive de gestion de vos distributions de calendriers par secteurs géographiques pour les amicales de pompiers.
|
||||
|
||||
## 📱 Présentation
|
||||
|
||||
GEOSECTOR est une application Flutter qui permet aux amicales de pompiers de gérer efficacement la distribution de calendriers par secteurs géographiques.
|
||||
|
||||
### Fonctionnalités principales
|
||||
|
||||
- **Gestion des secteurs géographiques** avec cartes interactives (Flutter Map)
|
||||
- **Suivi des passages** avec géolocalisation
|
||||
- **Interface différenciée** : utilisateur et administrateur
|
||||
- **Authentification sécurisée** avec gestion des rôles@
|
||||
- **Chat intégré** avec système de notifications
|
||||
- **Stockage local** avec synchronisation en ligne
|
||||
- **Support multi-plateforme** : Web, iOS, Android
|
||||
|
||||
## 🏗️ Architecture
|
||||
|
||||
### Stack technique
|
||||
|
||||
- **Framework** : Flutter 3.32
|
||||
- **Routing** : Go Router
|
||||
- **Base de données locale** : Hive
|
||||
- **Gestion d'état** : Provider + Repository Pattern
|
||||
- **Cartes** : Flutter Map avec Mapbox
|
||||
- **API** : Dio pour les requêtes HTTP
|
||||
- **Chat** : MQTT5 Client
|
||||
|
||||
### Architecture de données : Hive + Provider + Repository
|
||||
|
||||
L'application utilise une architecture en couches pour la gestion des données :
|
||||
|
||||
```
|
||||
UI Layer (Widgets)
|
||||
↓
|
||||
Provider Layer (State Management)
|
||||
↓
|
||||
Repository Layer (Business Logic)
|
||||
↓
|
||||
Data Layer (Hive + API)
|
||||
```
|
||||
|
||||
#### Couches de l'architecture
|
||||
|
||||
1. **UI Layer** : Widgets Flutter qui affichent les données
|
||||
2. **Provider Layer** : Gestion d'état avec ChangeNotifier
|
||||
3. **Repository Layer** : Logique métier et orchestration des sources de données
|
||||
4. **Data Layer** : Stockage local (Hive) et API distante
|
||||
|
||||
### Structure des dossiers
|
||||
|
||||
```
|
||||
lib/
|
||||
├── core/
|
||||
│ ├── config/
|
||||
│ ├── constants/
|
||||
│ ├── errors/
|
||||
│ ├── network/
|
||||
│ └── utils/
|
||||
├── data/
|
||||
│ ├── datasources/
|
||||
│ ├── models/
|
||||
│ └── repositories/
|
||||
├── domain/
|
||||
│ ├── entities/
|
||||
│ ├── repositories/
|
||||
│ └── usecases/
|
||||
├── presentation/
|
||||
│ ├── pages/
|
||||
│ ├── providers/
|
||||
│ ├── widgets/
|
||||
│ └── theme/
|
||||
└── main.dart
|
||||
```
|
||||
|
||||
## 🚀 Installation et configuration
|
||||
|
||||
### Prérequis
|
||||
|
||||
- Flutter 3.x
|
||||
- Dart SDK
|
||||
- Android Studio / VS Code
|
||||
- Émulateur ou appareil physique
|
||||
|
||||
### Installation
|
||||
|
||||
1. **Cloner le repository**
|
||||
```bash
|
||||
git clone https://github.com/votre-repo/geosector.git
|
||||
cd geosector
|
||||
```
|
||||
|
||||
2. **Installer les dépendances**
|
||||
```bash
|
||||
flutter pub get
|
||||
```
|
||||
|
||||
3. **Configuration des clés API**
|
||||
|
||||
Créer un fichier `.env` à la racine :
|
||||
```env
|
||||
MAPBOX_ACCESS_TOKEN=your_mapbox_token
|
||||
API_BASE_URL=https://your-api.com
|
||||
MQTT_BROKER_URL=your-mqtt-broker
|
||||
```
|
||||
|
||||
4. **Lancer l'application**
|
||||
```bash
|
||||
flutter run
|
||||
```
|
||||
|
||||
## 📦 Dépendances principales
|
||||
|
||||
```yaml
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
|
||||
# État et navigation
|
||||
provider: ^6.1.1
|
||||
go_router: ^12.1.3
|
||||
|
||||
# Stockage local
|
||||
hive: ^2.2.3
|
||||
hive_flutter: ^1.1.0
|
||||
|
||||
# Réseau
|
||||
dio: ^5.4.0
|
||||
|
||||
# Cartes
|
||||
flutter_map: ^6.1.0
|
||||
geolocator: ^10.1.0
|
||||
|
||||
# Chat
|
||||
mqtt5_client: ^4.2.0
|
||||
|
||||
# UI
|
||||
flutter_screenutil: ^5.9.0
|
||||
cached_network_image: ^3.3.0
|
||||
|
||||
dev_dependencies:
|
||||
hive_generator: ^2.0.1
|
||||
build_runner: ^2.4.7
|
||||
```
|
||||
|
||||
## 🗄️ Modèles de données
|
||||
|
||||
### Secteur
|
||||
|
||||
```dart
|
||||
@HiveType(typeId: 0)
|
||||
class Secteur extends HiveObject {
|
||||
@HiveField(0)
|
||||
String id;
|
||||
|
||||
@HiveField(1)
|
||||
String nom;
|
||||
|
||||
@HiveField(2)
|
||||
List<LatLng> polygone;
|
||||
|
||||
@HiveField(3)
|
||||
String couleur;
|
||||
|
||||
@HiveField(4)
|
||||
int nombreCalendriers;
|
||||
|
||||
@HiveField(5)
|
||||
DateTime dateCreation;
|
||||
}
|
||||
```
|
||||
|
||||
### Passage
|
||||
|
||||
```dart
|
||||
@HiveType(typeId: 1)
|
||||
class Passage extends HiveObject {
|
||||
@HiveField(0)
|
||||
String id;
|
||||
|
||||
@HiveField(1)
|
||||
String secteurId;
|
||||
|
||||
@HiveField(2)
|
||||
String utilisateurId;
|
||||
|
||||
@HiveField(3)
|
||||
DateTime datePassage;
|
||||
|
||||
@HiveField(4)
|
||||
LatLng position;
|
||||
|
||||
@HiveField(5)
|
||||
int calendriersDistribues;
|
||||
|
||||
@HiveField(6)
|
||||
String commentaire;
|
||||
|
||||
@HiveField(7)
|
||||
List<String> photos;
|
||||
}
|
||||
```
|
||||
|
||||
### Utilisateur
|
||||
|
||||
```dart
|
||||
@HiveType(typeId: 2)
|
||||
class Utilisateur extends HiveObject {
|
||||
@HiveField(0)
|
||||
String id;
|
||||
|
||||
@HiveField(1)
|
||||
String nom;
|
||||
|
||||
@HiveField(2)
|
||||
String email;
|
||||
|
||||
@HiveField(3)
|
||||
String role; // 'admin' ou 'user'
|
||||
|
||||
@HiveField(4)
|
||||
List<String> secteursAssignes;
|
||||
|
||||
@HiveField(5)
|
||||
DateTime dernierLogin;
|
||||
}
|
||||
```
|
||||
|
||||
## 🔧 Gestion d'état avec Provider
|
||||
|
||||
### SecteurProvider
|
||||
|
||||
```dart
|
||||
class SecteurProvider extends ChangeNotifier {
|
||||
final SecteurRepository _repository;
|
||||
|
||||
List<Secteur> _secteurs = [];
|
||||
bool _isLoading = false;
|
||||
|
||||
List<Secteur> get secteurs => _secteurs;
|
||||
bool get isLoading => _isLoading;
|
||||
|
||||
Future<void> loadSecteurs() async {
|
||||
_isLoading = true;
|
||||
notifyListeners();
|
||||
|
||||
try {
|
||||
_secteurs = await _repository.getAllSecteurs();
|
||||
} catch (e) {
|
||||
// Gestion d'erreur
|
||||
} finally {
|
||||
_isLoading = false;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🗺️ Cartes et géolocalisation
|
||||
|
||||
### Configuration Flutter Map
|
||||
|
||||
```dart
|
||||
FlutterMap(
|
||||
options: MapOptions(
|
||||
center: LatLng(46.2276, 2.2137), // Centre de la France
|
||||
zoom: 6.0,
|
||||
),
|
||||
children: [
|
||||
TileLayer(
|
||||
urlTemplate: 'https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token={accessToken}',
|
||||
additionalOptions: {
|
||||
'accessToken': mapboxToken,
|
||||
'id': 'mapbox/streets-v11',
|
||||
},
|
||||
),
|
||||
PolygonLayer(
|
||||
polygons: secteurs.map((secteur) => Polygon(
|
||||
points: secteur.polygone,
|
||||
color: Color(int.parse(secteur.couleur)),
|
||||
borderColor: Colors.black,
|
||||
borderStrokeWidth: 2.0,
|
||||
)).toList(),
|
||||
),
|
||||
],
|
||||
)
|
||||
```
|
||||
|
||||
## 💬 Chat intégré
|
||||
|
||||
### Configuration MQTT
|
||||
|
||||
```dart
|
||||
class ChatService {
|
||||
late MqttClient client;
|
||||
|
||||
Future<void> connect() async {
|
||||
client = MqttClient('mqtt://broker-url', 'client-id');
|
||||
await client.connect();
|
||||
|
||||
client.subscribe('geosector/chat', MqttQos.atLeastOnce);
|
||||
client.updates!.listen((messages) {
|
||||
// Traitement des messages
|
||||
});
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🔐 Authentification
|
||||
|
||||
### Gestion des rôles
|
||||
|
||||
```dart
|
||||
class AuthProvider extends ChangeNotifier {
|
||||
Utilisateur? _currentUser;
|
||||
|
||||
bool get isAdmin => _currentUser?.role == 'admin';
|
||||
bool get isAuthenticated => _currentUser != null;
|
||||
|
||||
Future<void> login(String email, String password) async {
|
||||
// Logique d'authentification
|
||||
}
|
||||
|
||||
void logout() {
|
||||
_currentUser = null;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 📱 Interface utilisateur
|
||||
|
||||
### Thème de l'application
|
||||
|
||||
```dart
|
||||
class AppTheme {
|
||||
static ThemeData get lightTheme => ThemeData(
|
||||
primarySwatch: Colors.red,
|
||||
appBarTheme: AppBarTheme(
|
||||
backgroundColor: Colors.red[700],
|
||||
elevation: 0,
|
||||
),
|
||||
elevatedButtonTheme: ElevatedButtonThemeData(
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Colors.red[700],
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## 🔄 Synchronisation des données
|
||||
|
||||
### Repository Pattern
|
||||
|
||||
```dart
|
||||
class SecteurRepository {
|
||||
final SecteurLocalDataSource _localDataSource;
|
||||
final SecteurRemoteDataSource _remoteDataSource;
|
||||
|
||||
Future<List<Secteur>> getAllSecteurs() async {
|
||||
try {
|
||||
// Essayer de récupérer depuis l'API
|
||||
final remoteSecteurs = await _remoteDataSource.getAllSecteurs();
|
||||
await _localDataSource.cacheSecteurs(remoteSecteurs);
|
||||
return remoteSecteurs;
|
||||
} catch (e) {
|
||||
// Fallback sur le cache local
|
||||
return await _localDataSource.getAllSecteurs();
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🧪 Tests
|
||||
|
||||
### Tests unitaires
|
||||
|
||||
```bash
|
||||
flutter test
|
||||
```
|
||||
|
||||
### Tests d'intégration
|
||||
|
||||
```bash
|
||||
flutter test integration_test/
|
||||
```
|
||||
|
||||
## 📚 Documentation
|
||||
|
||||
- [Guide d'utilisation](docs/guide-utilisation.md)
|
||||
- [API Reference](docs/api-reference.md)
|
||||
- [Architecture détaillée](docs/architecture.md)
|
||||
- [Contribution](docs/contributing.md)
|
||||
|
||||
## 🤝 Contribution
|
||||
|
||||
1. Fork le projet
|
||||
2. Créer une branche feature (`git checkout -b feature/AmazingFeature`)
|
||||
3. Commit vos changements (`git commit -m 'Add some AmazingFeature'`)
|
||||
4. Push vers la branche (`git push origin feature/AmazingFeature`)
|
||||
5. Ouvrir une Pull Request
|
||||
|
||||
## 📄 Licence
|
||||
|
||||
Distribué sous la licence MIT. Voir `LICENSE` pour plus d'informations.
|
||||
|
||||
## 👥 Équipe
|
||||
|
||||
- **Développeur Principal** - [@votre-username](https://github.com/votre-username)
|
||||
- **Designer UI/UX** - [@designer-username](https://github.com/designer-username)
|
||||
|
||||
## 📞 Support
|
||||
|
||||
Pour toute question ou problème :
|
||||
|
||||
- 📧 Email : support@geosector.com
|
||||
- 🐛 Issues : [GitHub Issues](https://github.com/votre-repo/geosector/issues)
|
||||
- 📖 Documentation : [Wiki](https://github.com/votre-repo/geosector/wiki)
|
||||
|
||||
---
|
||||
|
||||
**GEOSECTOR** - Simplifiant la gestion des distributions de calendriers pour les amicales de pompiers 🚒
|
||||
@@ -1,16 +0,0 @@
|
||||
# geosector_app
|
||||
|
||||
A new Flutter project.
|
||||
|
||||
## Getting Started
|
||||
|
||||
This project is a starting point for a Flutter application.
|
||||
|
||||
A few resources to get you started if this is your first Flutter project:
|
||||
|
||||
- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
|
||||
- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)
|
||||
|
||||
For help getting started with Flutter development, view the
|
||||
[online documentation](https://docs.flutter.dev/), which offers tutorials,
|
||||
samples, guidance on mobile development, and a full API reference.
|
||||
29
app/android/geosector_app_android.iml
Normal file
29
app/android/geosector_app_android.iml
Normal file
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="FacetManager">
|
||||
<facet type="android" name="Android">
|
||||
<configuration>
|
||||
<option name="ALLOW_USER_CONFIGURATION" value="false" />
|
||||
<option name="GEN_FOLDER_RELATIVE_PATH_APT" value="/gen" />
|
||||
<option name="GEN_FOLDER_RELATIVE_PATH_AIDL" value="/gen" />
|
||||
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/app/src/main/AndroidManifest.xml" />
|
||||
<option name="RES_FOLDER_RELATIVE_PATH" value="/app/src/main/res" />
|
||||
<option name="ASSETS_FOLDER_RELATIVE_PATH" value="/app/src/main/assets" />
|
||||
<option name="LIBS_FOLDER_RELATIVE_PATH" value="/app/src/main/libs" />
|
||||
<option name="PROGUARD_LOGS_FOLDER_RELATIVE_PATH" value="/app/src/main/proguard_logs" />
|
||||
</configuration>
|
||||
</facet>
|
||||
</component>
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/app/src/main/java" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/app/src/main/kotlin" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/gen" isTestSource="false" generated="true" />
|
||||
</content>
|
||||
<orderEntry type="jdk" jdkName="Android API 29 Platform" jdkType="Android SDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="Flutter for Android" level="project" />
|
||||
<orderEntry type="library" name="KotlinJavaRuntime" level="project" />
|
||||
</component>
|
||||
</module>
|
||||
BIN
app/assets/images/logo_recu.png
Normal file
BIN
app/assets/images/logo_recu.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 99 KiB |
36
app/geosector_app.iml
Normal file
36
app/geosector_app.iml
Normal file
@@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/lib" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/.dart_tool" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/.idea" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/.pub" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/ios/.symlinks/plugins/connectivity_plus/.dart_tool" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/ios/.symlinks/plugins/connectivity_plus/.pub" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/ios/.symlinks/plugins/connectivity_plus/build" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/ios/.symlinks/plugins/connectivity_plus/example/.dart_tool" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/ios/.symlinks/plugins/connectivity_plus/example/.pub" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/ios/.symlinks/plugins/connectivity_plus/example/build" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/ios/.symlinks/plugins/path_provider_foundation/.dart_tool" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/ios/.symlinks/plugins/path_provider_foundation/.pub" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/ios/.symlinks/plugins/path_provider_foundation/build" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/ios/.symlinks/plugins/path_provider_foundation/example/.dart_tool" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/ios/.symlinks/plugins/path_provider_foundation/example/.pub" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/ios/.symlinks/plugins/path_provider_foundation/example/build" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/ios/.symlinks/plugins/url_launcher_ios/.dart_tool" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/ios/.symlinks/plugins/url_launcher_ios/.pub" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/ios/.symlinks/plugins/url_launcher_ios/build" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/ios/.symlinks/plugins/url_launcher_ios/example/.dart_tool" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/ios/.symlinks/plugins/url_launcher_ios/example/.pub" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/ios/.symlinks/plugins/url_launcher_ios/example/build" />
|
||||
</content>
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="Dart SDK" level="project" />
|
||||
<orderEntry type="library" name="Flutter Plugins" level="project" />
|
||||
<orderEntry type="library" name="Dart Packages" level="project" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -1,67 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Script to create a new branch from main/origin
|
||||
|
||||
# Check if branch name is provided
|
||||
if [ $# -eq 0 ]; then
|
||||
echo "Error: Branch name is required"
|
||||
echo "Usage: $0 <branch-name>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Store branch name from parameter
|
||||
BRANCH_NAME=$1
|
||||
|
||||
# Ensure we have the latest from origin
|
||||
echo "Fetching latest changes from origin..."
|
||||
git fetch origin
|
||||
|
||||
# Check if we're already on main, if not switch to it
|
||||
CURRENT_BRANCH=$(git symbolic-ref --short HEAD)
|
||||
if [ "$CURRENT_BRANCH" != "main" ]; then
|
||||
echo "Switching to main branch..."
|
||||
git checkout main
|
||||
fi
|
||||
|
||||
# Pull latest changes from main
|
||||
echo "Pulling latest changes from main..."
|
||||
git pull origin main
|
||||
|
||||
# Create and checkout the new branch
|
||||
echo "Creating and checking out new branch: $BRANCH_NAME"
|
||||
git checkout -b "$BRANCH_NAME"
|
||||
|
||||
# Stage all changes
|
||||
echo "Staging all changes..."
|
||||
git add .
|
||||
|
||||
# Ask if user wants to make an initial commit
|
||||
read -p "Do you want to make an initial commit? (Y/n): " COMMIT_CHOICE
|
||||
|
||||
# Default to Yes if Enter is pressed without input
|
||||
COMMIT_CHOICE=${COMMIT_CHOICE:-Y}
|
||||
|
||||
if [[ $COMMIT_CHOICE =~ ^[Yy]$ ]]; then
|
||||
# Ask for commit message
|
||||
read -p "Enter commit message: " COMMIT_MESSAGE
|
||||
|
||||
# Check if commit message is provided
|
||||
if [ -n "$COMMIT_MESSAGE" ]; then
|
||||
# Make the commit
|
||||
echo "Creating commit with message: '$COMMIT_MESSAGE'"
|
||||
git commit -m "$COMMIT_MESSAGE"
|
||||
|
||||
# Push to remote with upstream tracking
|
||||
echo "Pushing to origin and setting upstream tracking..."
|
||||
git push -u origin "$BRANCH_NAME"
|
||||
|
||||
echo "Branch '$BRANCH_NAME' has been pushed to origin with tracking."
|
||||
else
|
||||
echo "No commit message provided. Skipping commit."
|
||||
fi
|
||||
else
|
||||
echo "Skipping initial commit. You can commit changes later."
|
||||
fi
|
||||
|
||||
echo "Success! You are now on branch: $BRANCH_NAME"
|
||||
echo "Ready to start working!"
|
||||
@@ -1,76 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Check if a branch name was provided
|
||||
if [ -z "$1" ]; then
|
||||
echo "Error: Please provide the name of the branch to merge"
|
||||
echo "Usage: ./git-merge.sh branch_name"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
BRANCH_NAME=$1
|
||||
|
||||
# Check if the branch exists
|
||||
if ! git show-ref --verify --quiet refs/heads/$BRANCH_NAME; then
|
||||
echo "Error: Branch '$BRANCH_NAME' does not exist"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Display the steps that will be executed
|
||||
echo "=== Starting merge process ==="
|
||||
echo "1. Checkout to main"
|
||||
echo "2. Pull latest changes"
|
||||
echo "3. Merge branch $BRANCH_NAME"
|
||||
echo "4. Push to origin"
|
||||
echo "5. Delete local and remote branches"
|
||||
|
||||
# Ask for confirmation
|
||||
read -p "Do you want to continue? (y/n) " -n 1 -r
|
||||
echo
|
||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||
echo "Operation cancelled"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Execute commands
|
||||
echo -e "\n=== Checking out to main ==="
|
||||
git checkout main
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Error during checkout to main"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo -e "\n=== Pulling latest changes ==="
|
||||
git pull origin main
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Error during pull"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo -e "\n=== Merging branch $BRANCH_NAME ==="
|
||||
git merge $BRANCH_NAME
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Error during merge. Please resolve conflicts manually"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo -e "\n=== Pushing to origin ==="
|
||||
git push origin main
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Error during push"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo -e "\n=== Deleting local branch ==="
|
||||
git branch -d $BRANCH_NAME
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Warning: Unable to delete local branch"
|
||||
echo "If you are sure everything is properly merged, use: git branch -D $BRANCH_NAME"
|
||||
fi
|
||||
|
||||
echo -e "\n=== Deleting remote branch ==="
|
||||
git push origin --delete $BRANCH_NAME
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Warning: Unable to delete remote branch"
|
||||
fi
|
||||
|
||||
echo -e "\n=== Merge process completed successfully ==="
|
||||
384
app/lib/app.dart
384
app/lib/app.dart
@@ -1,7 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/foundation.dart' show kIsWeb;
|
||||
import 'package:geosector_app/core/theme/app_theme.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
import 'package:geosector_app/core/services/api_service.dart';
|
||||
import 'package:geosector_app/core/repositories/user_repository.dart';
|
||||
import 'package:geosector_app/core/repositories/operation_repository.dart';
|
||||
@@ -13,7 +13,6 @@ import 'package:geosector_app/core/services/sync_service.dart';
|
||||
import 'package:geosector_app/core/services/connectivity_service.dart';
|
||||
import 'package:geosector_app/presentation/auth/splash_page.dart';
|
||||
import 'package:geosector_app/presentation/auth/login_page.dart';
|
||||
import 'package:geosector_app/presentation/auth/register_page.dart';
|
||||
import 'package:geosector_app/presentation/admin/admin_dashboard_page.dart';
|
||||
import 'package:geosector_app/presentation/user/user_dashboard_page.dart';
|
||||
|
||||
@@ -28,239 +27,202 @@ final amicaleRepository = AmicaleRepository(apiService);
|
||||
final syncService = SyncService(userRepository: userRepository);
|
||||
final connectivityService = ConnectivityService();
|
||||
|
||||
class GeoSectorApp extends StatelessWidget {
|
||||
const GeoSectorApp({super.key});
|
||||
class GeosectorApp extends StatelessWidget {
|
||||
const GeosectorApp({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// Utiliser directement le router sans provider
|
||||
final router = GoRouter(
|
||||
return MaterialApp.router(
|
||||
title: 'GeoSector',
|
||||
theme: AppTheme.lightTheme,
|
||||
darkTheme: AppTheme.darkTheme,
|
||||
themeMode: ThemeMode.system,
|
||||
routerConfig: _createRouter(),
|
||||
debugShowCheckedModeBanner: false,
|
||||
);
|
||||
}
|
||||
|
||||
/// Création du routeur avec configuration pour URLs propres
|
||||
GoRouter _createRouter() {
|
||||
return GoRouter(
|
||||
initialLocation: '/',
|
||||
debugLogDiagnostics: true,
|
||||
refreshListenable:
|
||||
userRepository, // Écouter les changements d'état d'authentification
|
||||
// Gestionnaire de redirection global - intercepte toutes les navigations
|
||||
redirect: (context, state) {
|
||||
// Détection manuelle des paramètres d'URL pour le Web
|
||||
if (kIsWeb && state.uri.path == '/login') {
|
||||
try {
|
||||
// Obtenir le paramètre 'type' de l'URL actuelle
|
||||
final typeParam = state.uri.queryParameters['type'];
|
||||
|
||||
// Obtenir l'URL brute du navigateur pour comparer
|
||||
final rawUri = Uri.parse(Uri.base.toString());
|
||||
final rawTypeParam = rawUri.queryParameters['type'];
|
||||
|
||||
print('APP ROUTER: state.uri = ${state.uri}, type = $typeParam');
|
||||
print('APP ROUTER: rawUri = $rawUri, type = $rawTypeParam');
|
||||
|
||||
// Pas de redirection si on a déjà le paramètre type
|
||||
if (typeParam != null) {
|
||||
print('APP ROUTER: Param type déjà présent, pas de redirection');
|
||||
return null; // Pas de redirection
|
||||
}
|
||||
|
||||
// Si un paramètre type=user est présent dans l'URL brute mais pas dans l'état
|
||||
if (rawTypeParam == 'user' && typeParam == null) {
|
||||
print(
|
||||
'APP ROUTER: Paramètre détecté dans l\'URL brute, redirection vers /login?type=user');
|
||||
return '/login?type=user';
|
||||
}
|
||||
} catch (e) {
|
||||
print('Erreur lors de la récupération des paramètres d\'URL: $e');
|
||||
}
|
||||
}
|
||||
// Sauvegarder le chemin actuel pour l'utilisateur connecté, sauf pour la page de splash
|
||||
if (state.uri.toString() != '/' && userRepository.isLoggedIn) {
|
||||
// Ne pas sauvegarder les chemins de login/register
|
||||
if (!state.uri.toString().startsWith('/login') &&
|
||||
!state.uri.toString().startsWith('/register')) {
|
||||
userRepository.updateLastPath(state.uri.toString());
|
||||
}
|
||||
}
|
||||
|
||||
// Vérifier si l'utilisateur est sur la page de splash
|
||||
if (state.uri.toString() == '/') {
|
||||
// Laisser l'utilisateur sur la page de splash, la redirection sera gérée par SplashPage
|
||||
return null;
|
||||
}
|
||||
|
||||
// Vérifier si l'utilisateur est sur une page d'authentification
|
||||
final isLoggedIn = userRepository.isLoggedIn;
|
||||
final isOnLoginPage = state.uri.toString().startsWith('/login');
|
||||
final isOnRegisterPage = state.uri.toString() == '/register';
|
||||
final isOnAdminRegisterPage = state.uri.toString() == '/admin-register';
|
||||
|
||||
// Si l'utilisateur n'est pas connecté et n'est pas sur une page d'authentification, rediriger vers la page de connexion
|
||||
if (!isLoggedIn &&
|
||||
!isOnLoginPage &&
|
||||
!isOnRegisterPage &&
|
||||
!isOnAdminRegisterPage) {
|
||||
return '/login';
|
||||
}
|
||||
|
||||
// Si l'utilisateur est connecté et se trouve sur une page d'authentification, rediriger vers le tableau de bord approprié
|
||||
if (isLoggedIn &&
|
||||
(isOnLoginPage || isOnRegisterPage || isOnAdminRegisterPage)) {
|
||||
// Récupérer le rôle de l'utilisateur directement
|
||||
final user = userRepository.getCurrentUser();
|
||||
if (user != null) {
|
||||
// Convertir le rôle en int si nécessaire
|
||||
int roleValue;
|
||||
if (user.role is String) {
|
||||
roleValue = int.tryParse(user.role as String) ?? 1;
|
||||
} else {
|
||||
roleValue = user.role as int;
|
||||
}
|
||||
|
||||
// Redirection simple basée sur le rôle
|
||||
if (roleValue > 1) {
|
||||
debugPrint(
|
||||
'Router: Redirection vers /admin (rôle $roleValue > 1)');
|
||||
return '/admin';
|
||||
} else {
|
||||
debugPrint(
|
||||
'Router: Redirection vers /user (rôle $roleValue = 1)');
|
||||
return '/user';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Si l'utilisateur est connecté mais essaie d'accéder à la mauvaise page selon son rôle
|
||||
if (isLoggedIn) {
|
||||
final user = userRepository.getCurrentUser();
|
||||
if (user != null) {
|
||||
// Convertir le rôle en int si nécessaire
|
||||
int roleValue;
|
||||
if (user.role is String) {
|
||||
roleValue = int.tryParse(user.role as String) ?? 1;
|
||||
} else {
|
||||
roleValue = user.role as int;
|
||||
}
|
||||
|
||||
// Vérifier si l'utilisateur est sur la bonne page en fonction de son rôle
|
||||
final isOnUserPage = state.uri.toString().startsWith('/user');
|
||||
final isOnAdminPage = state.uri.toString().startsWith('/admin');
|
||||
|
||||
// Admin (rôle > 1) essayant d'accéder à une page utilisateur
|
||||
if (roleValue > 1 && isOnUserPage) {
|
||||
debugPrint(
|
||||
'Router: Redirection d\'admin (rôle $roleValue) vers /admin');
|
||||
return '/admin';
|
||||
}
|
||||
|
||||
// Utilisateur standard (rôle = 1) essayant d'accéder à une page admin
|
||||
if (roleValue == 1 && isOnAdminPage) {
|
||||
debugPrint(
|
||||
'Router: Redirection d\'utilisateur (rôle $roleValue) vers /user');
|
||||
return '/user';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
routes: [
|
||||
// Splash screen
|
||||
GoRoute(
|
||||
path: '/',
|
||||
builder: (context, state) => const SplashPage(),
|
||||
),
|
||||
|
||||
// Page de connexion utilisateur dédiée
|
||||
GoRoute(
|
||||
path: '/login/user',
|
||||
name: 'splash',
|
||||
builder: (context, state) {
|
||||
print('ROUTER: Accès direct à la route login user');
|
||||
return const LoginPage(
|
||||
key: Key('login_page_user'),
|
||||
loginType: 'user',
|
||||
);
|
||||
debugPrint('GoRoute: Affichage de SplashPage');
|
||||
return const SplashPage();
|
||||
},
|
||||
),
|
||||
|
||||
// Pages d'authentification standard
|
||||
GoRoute(
|
||||
path: '/login',
|
||||
name: 'login',
|
||||
builder: (context, state) {
|
||||
// Ajouter des logs de débogage détaillés pour comprendre les paramètres
|
||||
print('ROUTER DEBUG: Uri complète = ${state.uri}');
|
||||
print('ROUTER DEBUG: Path = ${state.uri.path}');
|
||||
print('ROUTER DEBUG: Query params = ${state.uri.queryParameters}');
|
||||
print(
|
||||
'ROUTER DEBUG: Has type? ${state.uri.queryParameters.containsKey("type")}');
|
||||
// Récupérer le type depuis les query parameters ou extra data
|
||||
final type = state.uri.queryParameters['type'] ??
|
||||
(state.extra as Map<String, dynamic>?)?['type'] as String?;
|
||||
|
||||
// Donner la priorité aux paramètres d'URL puis aux extras
|
||||
String? loginType;
|
||||
|
||||
// 1. Essayer d'abord les paramètres d'URL (pour les liens externes)
|
||||
final queryParams = state.uri.queryParameters;
|
||||
loginType = queryParams['type'];
|
||||
print('ROUTER DEBUG: Type from query params = $loginType');
|
||||
|
||||
// 2. Si aucun type dans les paramètres d'URL, vérifier les extras (pour la navigation interne)
|
||||
if (loginType == null &&
|
||||
state.extra != null &&
|
||||
state.extra is Map<String, dynamic>) {
|
||||
final extras = state.extra as Map<String, dynamic>;
|
||||
loginType = extras['type']?.toString();
|
||||
print('ROUTER DEBUG: Type from extras = $loginType');
|
||||
}
|
||||
|
||||
// 3. Normaliser et valider le type
|
||||
if (loginType != null) {
|
||||
loginType = loginType.trim().toLowerCase();
|
||||
// Vérifier explicitement que c'est 'user', sinon mettre 'admin'
|
||||
if (loginType != 'user') {
|
||||
loginType = 'admin';
|
||||
}
|
||||
} else {
|
||||
// Si aucun type n'est spécifié, retourner la page de splash
|
||||
print(
|
||||
'ROUTER: Aucun type spécifié, utilisation de la page splash');
|
||||
return const SplashPage();
|
||||
}
|
||||
|
||||
print('ROUTER: Type de connexion final: $loginType');
|
||||
|
||||
return LoginPage(
|
||||
key: Key('login_page_${loginType}'),
|
||||
loginType: loginType,
|
||||
);
|
||||
debugPrint('GoRoute: Affichage de LoginPage avec type: $type');
|
||||
return LoginPage(loginType: type);
|
||||
},
|
||||
),
|
||||
// Routes spécifiques pour chaque type de login
|
||||
GoRoute(
|
||||
path: '/login/user',
|
||||
name: 'login-user',
|
||||
builder: (context, state) {
|
||||
debugPrint('GoRoute: Affichage de LoginPage pour utilisateur');
|
||||
return const LoginPage(loginType: 'user');
|
||||
},
|
||||
),
|
||||
GoRoute(
|
||||
path: '/login/admin',
|
||||
name: 'login-admin',
|
||||
builder: (context, state) {
|
||||
debugPrint('GoRoute: Affichage de LoginPage pour admin');
|
||||
return const LoginPage(loginType: 'admin');
|
||||
},
|
||||
),
|
||||
GoRoute(
|
||||
path: '/register',
|
||||
builder: (context, state) => const RegisterPage(),
|
||||
name: 'register',
|
||||
builder: (context, state) {
|
||||
debugPrint('GoRoute: Affichage de RegisterPage');
|
||||
// Retournez votre page d'inscription ici
|
||||
return const Scaffold(
|
||||
body: Center(
|
||||
child: Text('Page d\'inscription - À implémenter'),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
// Pages administrateur
|
||||
GoRoute(
|
||||
path: '/admin',
|
||||
builder: (context, state) => const AdminDashboardPage(),
|
||||
routes: [
|
||||
// Ajouter d'autres routes admin ici
|
||||
],
|
||||
),
|
||||
|
||||
// Pages utilisateur
|
||||
GoRoute(
|
||||
path: '/user',
|
||||
builder: (context, state) => const UserDashboardPage(),
|
||||
routes: [
|
||||
// Ajouter d'autres routes utilisateur ici
|
||||
],
|
||||
name: 'user',
|
||||
builder: (context, state) {
|
||||
debugPrint('GoRoute: Affichage de UserDashboardPage');
|
||||
return const UserDashboardPage();
|
||||
},
|
||||
),
|
||||
GoRoute(
|
||||
path: '/admin',
|
||||
name: 'admin',
|
||||
builder: (context, state) {
|
||||
debugPrint('GoRoute: Affichage de AdminDashboardPage');
|
||||
return const AdminDashboardPage();
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
redirect: (context, state) {
|
||||
final currentPath = state.uri.path;
|
||||
debugPrint('GoRouter.redirect: currentPath = $currentPath');
|
||||
|
||||
return MaterialApp.router(
|
||||
debugShowCheckedModeBanner: false,
|
||||
title: 'GEOSECTOR',
|
||||
theme: AppTheme.lightTheme,
|
||||
darkTheme: AppTheme.darkTheme,
|
||||
themeMode: ThemeMode.system,
|
||||
routerConfig: router,
|
||||
// Pour la page racine, toujours autoriser l'affichage de la splash page
|
||||
if (currentPath == '/') {
|
||||
debugPrint('GoRouter.redirect: Autorisation splash page');
|
||||
return null;
|
||||
}
|
||||
|
||||
// Pages publiques qui ne nécessitent pas d'authentification
|
||||
final publicPaths = [
|
||||
'/login',
|
||||
'/login/user',
|
||||
'/login/admin',
|
||||
'/register'
|
||||
];
|
||||
if (publicPaths.any((path) => currentPath.startsWith(path))) {
|
||||
debugPrint(
|
||||
'GoRouter.redirect: Page publique autorisée: $currentPath');
|
||||
return null;
|
||||
}
|
||||
|
||||
// Vérifier l'authentification pour les pages protégées
|
||||
try {
|
||||
final isAuthenticated = userRepository.isLoggedIn;
|
||||
final currentUser = userRepository.currentUser;
|
||||
|
||||
debugPrint('GoRouter.redirect: isAuthenticated = $isAuthenticated');
|
||||
debugPrint('GoRouter.redirect: currentUser = ${currentUser?.email}');
|
||||
|
||||
// Si pas authentifié, rediriger vers la splash page
|
||||
if (!isAuthenticated) {
|
||||
debugPrint(
|
||||
'GoRouter.redirect: Non authentifié, redirection vers /');
|
||||
return '/';
|
||||
}
|
||||
|
||||
// Vérifier les permissions pour les pages admin
|
||||
if (currentPath.startsWith('/admin')) {
|
||||
final userRole = userRepository.getUserRole();
|
||||
final isAdmin = userRole > 1; // Admin = rôle 2 ou plus
|
||||
|
||||
debugPrint(
|
||||
'GoRouter.redirect: userRole = $userRole, isAdmin = $isAdmin');
|
||||
|
||||
if (!isAdmin) {
|
||||
debugPrint(
|
||||
'GoRouter.redirect: Pas admin, redirection vers /user');
|
||||
return '/user';
|
||||
}
|
||||
}
|
||||
|
||||
// Si on arrive ici, l'utilisateur a les permissions nécessaires
|
||||
debugPrint('GoRouter.redirect: Accès autorisé à $currentPath');
|
||||
return null;
|
||||
} catch (e) {
|
||||
debugPrint(
|
||||
'GoRouter.redirect: Erreur lors de la vérification auth: $e');
|
||||
// En cas d'erreur, rediriger vers la splash page pour sécurité
|
||||
return '/';
|
||||
}
|
||||
},
|
||||
// Listener pour déboguer les changements de route
|
||||
refreshListenable:
|
||||
userRepository, // Écouter les changements dans userRepository
|
||||
debugLogDiagnostics: true, // Activer les logs de débogage
|
||||
errorBuilder: (context, state) {
|
||||
debugPrint('GoRouter.errorBuilder: Erreur pour ${state.uri.path}');
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('Erreur de navigation'),
|
||||
backgroundColor: Colors.red,
|
||||
foregroundColor: Colors.white,
|
||||
),
|
||||
body: Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(24.0),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const Icon(Icons.error_outline, size: 64, color: Colors.red),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
'Page non trouvée',
|
||||
style: Theme.of(context).textTheme.headlineSmall,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
'Chemin: ${state.uri.path}',
|
||||
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
||||
color: Colors.grey[600],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
ElevatedButton.icon(
|
||||
onPressed: () {
|
||||
debugPrint('GoRouter.errorBuilder: Retour vers /');
|
||||
context.go('/');
|
||||
},
|
||||
icon: const Icon(Icons.home),
|
||||
label: const Text('Retour à l\'accueil'),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,7 +123,7 @@ class AppKeys {
|
||||
},
|
||||
1: {
|
||||
'titre': 'Espèce',
|
||||
'couleur': 0xFFB87333, // Couleur cuivrée
|
||||
'couleur': 0xFFDAA520, // Goldenrod
|
||||
'icon_data': Icons.payments_outlined,
|
||||
},
|
||||
2: {
|
||||
|
||||
@@ -169,21 +169,13 @@ class UserRepository extends ChangeNotifier {
|
||||
try {
|
||||
// Vérifier d'abord si la boîte est ouverte
|
||||
if (!Hive.isBoxOpen(AppKeys.usersBoxName)) {
|
||||
try {
|
||||
Hive.openBox<UserModel>(AppKeys.usersBoxName);
|
||||
} catch (e) {
|
||||
debugPrint(
|
||||
'Erreur lors de l\'ouverture de la boîte utilisateurs: $e');
|
||||
return null;
|
||||
}
|
||||
debugPrint('Boîte users non ouverte, tentative d\'ouverture...');
|
||||
return null; // Retourner null plutôt que d'essayer d'ouvrir ici
|
||||
}
|
||||
|
||||
// Chercher un utilisateur avec une session active - Il suffit qu'il ait un sessionId
|
||||
// Chercher un utilisateur avec une session active
|
||||
final activeUsers = _userBox.values
|
||||
.where((user) =>
|
||||
user.sessionId != null && // Vérifier que sessionId n'est pas null
|
||||
user.sessionId!
|
||||
.isNotEmpty) // Vérifier que sessionId n'est pas vide
|
||||
.where((user) => user.sessionId != null && user.sessionId!.isNotEmpty)
|
||||
.toList();
|
||||
|
||||
// S'il y a des utilisateurs actifs, retourner le premier
|
||||
@@ -267,6 +259,16 @@ class UserRepository extends ChangeNotifier {
|
||||
}
|
||||
}
|
||||
|
||||
/// Navigation après connexion réussie
|
||||
void navigateAfterLogin(BuildContext context) {
|
||||
final user = currentUser;
|
||||
|
||||
if (user != null && context.mounted) {
|
||||
final isAdmin = user.role == 1 || user.role == 2;
|
||||
context.go(isAdmin ? '/admin' : '/user');
|
||||
}
|
||||
}
|
||||
|
||||
// Méthode d'inscription (uniquement pour les administrateurs)
|
||||
Future<bool> register(String email, String password, String name,
|
||||
String amicaleName, String postalCode, String cityName) async {
|
||||
@@ -1064,28 +1066,8 @@ class UserRepository extends ChangeNotifier {
|
||||
}
|
||||
}
|
||||
|
||||
/// Méthode de déconnexion avec affichage d'un overlay de chargement
|
||||
/// et redirection vers la page de démarrage
|
||||
/// Cette méthode remplace AuthService.logout
|
||||
Future<bool> logoutWithUI(BuildContext context) async {
|
||||
final bool result = await LoadingOverlay.show(
|
||||
context: context,
|
||||
spinnerSize: 80.0, // Spinner plus grand
|
||||
strokeWidth: 6.0, // Trait plus épais
|
||||
future: logout(),
|
||||
);
|
||||
|
||||
// Si la déconnexion a réussi, rediriger vers la page de démarrage
|
||||
if (result && context.mounted) {
|
||||
// Utiliser GoRouter pour naviguer vers la page de démarrage
|
||||
GoRouter.of(context).go('/');
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Logout complet (sans UI)
|
||||
Future<bool> logout() async {
|
||||
// Méthode de déconnexion unique avec navigation vers / splash_page
|
||||
Future<bool> logout(BuildContext context) async {
|
||||
_isLoading = true;
|
||||
notifyListeners();
|
||||
|
||||
@@ -1097,9 +1079,15 @@ class UserRepository extends ChangeNotifier {
|
||||
final currentUser = getCurrentUser();
|
||||
if (currentUser == null) {
|
||||
debugPrint('Aucun utilisateur connecté, déconnexion terminée');
|
||||
// Nettoyage en profondeur même si aucun utilisateur n'est connecté
|
||||
await _deepCleanHiveBoxes();
|
||||
debugPrint('État isLoggedIn après nettoyage: $isLoggedIn');
|
||||
|
||||
// Toujours rediriger avec pushAndRemoveUntil pour forcer la navigation
|
||||
if (context.mounted) {
|
||||
debugPrint('Redirection forcée vers / après nettoyage');
|
||||
context.go('/');
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1112,13 +1100,9 @@ class UserRepository extends ChangeNotifier {
|
||||
await logoutAPI();
|
||||
} catch (e) {
|
||||
debugPrint('Erreur lors de la déconnexion API, mais on continue: $e');
|
||||
// Continuer le processus de déconnexion même si l'API échoue
|
||||
}
|
||||
}
|
||||
|
||||
// Effacer la session de l'utilisateur
|
||||
debugPrint('Mise à jour de l\'utilisateur pour effacer la session...');
|
||||
|
||||
// Supprimer la session API
|
||||
setSessionId(null);
|
||||
|
||||
@@ -1126,37 +1110,47 @@ class UserRepository extends ChangeNotifier {
|
||||
_cachedCurrentUser = null;
|
||||
debugPrint('Cache utilisateur réinitialisé (_cachedCurrentUser = null)');
|
||||
|
||||
// MODIFICATION IMPORTANTE: Nettoyage complet de toutes les boîtes Hive
|
||||
// Nettoyage complet de toutes les boîtes Hive
|
||||
debugPrint('Nettoyage profond des données Hive après déconnexion...');
|
||||
await _deepCleanHiveBoxes();
|
||||
|
||||
// Vérifier l'état après nettoyage
|
||||
debugPrint('État isLoggedIn après déconnexion: $isLoggedIn');
|
||||
debugPrint(
|
||||
'Valeur de currentUser après déconnexion: ${currentUser != null ? "non null" : "null"}');
|
||||
|
||||
// Vérifier si des utilisateurs restent dans la boîte
|
||||
if (Hive.isBoxOpen(AppKeys.usersBoxName)) {
|
||||
final remainingUsers = _userBox.values.toList();
|
||||
debugPrint(
|
||||
'Nombre d\'utilisateurs restants dans la boîte: ${remainingUsers.length}');
|
||||
}
|
||||
|
||||
// Réinitialiser l'état de HiveResetStateService
|
||||
hiveResetStateService.reset();
|
||||
debugPrint('État de HiveResetStateService réinitialisé');
|
||||
|
||||
debugPrint('Déconnexion terminée avec succès');
|
||||
|
||||
// Forcer la navigation avec pushAndRemoveUntil et attendre
|
||||
if (context.mounted) {
|
||||
debugPrint('Navigation forcée vers / après déconnexion');
|
||||
|
||||
// Attendre que toutes les opérations asynchrones soient terminées
|
||||
await Future.delayed(const Duration(milliseconds: 200));
|
||||
|
||||
// Navigation forcée qui supprime toute la pile de navigation
|
||||
context.go('/');
|
||||
|
||||
// Alternative si pushAndRemoveUntil ne fonctionne pas
|
||||
// context.pushReplacementNamed('/');
|
||||
}
|
||||
|
||||
notifyListeners();
|
||||
return true;
|
||||
} catch (e) {
|
||||
debugPrint('Erreur de déconnexion: $e');
|
||||
|
||||
// Même en cas d'erreur, essayer de naviguer vers la page d'accueil
|
||||
if (context.mounted) {
|
||||
debugPrint('Navigation d\'urgence vers / après erreur');
|
||||
context.go(
|
||||
'/',
|
||||
);
|
||||
}
|
||||
|
||||
return false;
|
||||
} finally {
|
||||
_isLoading = false;
|
||||
notifyListeners();
|
||||
// Vérification finale
|
||||
debugPrint('État final isLoggedIn: $isLoggedIn');
|
||||
}
|
||||
}
|
||||
|
||||
13
app/lib/core/services/app_info_service.dart
Normal file
13
app/lib/core/services/app_info_service.dart
Normal file
@@ -0,0 +1,13 @@
|
||||
import 'package:package_info_plus/package_info_plus.dart';
|
||||
|
||||
class AppInfoService {
|
||||
static PackageInfo? _packageInfo;
|
||||
|
||||
static Future<void> initialize() async {
|
||||
_packageInfo = await PackageInfo.fromPlatform();
|
||||
}
|
||||
|
||||
static String get version => _packageInfo?.version ?? '0.0.0';
|
||||
static String get buildNumber => _packageInfo?.buildNumber ?? '0';
|
||||
static String get fullVersion => 'v$version+$buildNumber';
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:geosector_app/core/repositories/user_repository.dart';
|
||||
import 'package:geosector_app/presentation/widgets/loading_overlay.dart';
|
||||
|
||||
/// Service qui gère les opérations d'authentification avec affichage d'un overlay de chargement
|
||||
class AuthService {
|
||||
final UserRepository _userRepository;
|
||||
|
||||
AuthService(this._userRepository);
|
||||
|
||||
/// Méthode de connexion avec affichage d'un overlay de chargement
|
||||
Future<bool> login(BuildContext context, String username, String password,
|
||||
{required String type}) async {
|
||||
return await LoadingOverlay.show(
|
||||
context: context,
|
||||
spinnerSize: 80.0, // Spinner plus grand
|
||||
strokeWidth: 6.0, // Trait plus épais
|
||||
future: _userRepository.login(username, password, type: type),
|
||||
);
|
||||
}
|
||||
|
||||
/// Méthode de déconnexion avec affichage d'un overlay de chargement
|
||||
/// et redirection vers la page de démarrage
|
||||
Future<bool> logout(BuildContext context) async {
|
||||
final bool result = await LoadingOverlay.show(
|
||||
context: context,
|
||||
spinnerSize: 80.0, // Spinner plus grand
|
||||
strokeWidth: 6.0, // Trait plus épais
|
||||
future: _userRepository.logout(),
|
||||
);
|
||||
|
||||
// Si la déconnexion a réussi, rediriger vers la page de démarrage
|
||||
if (result && context.mounted) {
|
||||
// Utiliser GoRouter pour naviguer vers la page de démarrage
|
||||
GoRouter.of(context).go('/');
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Vérifie si un utilisateur est connecté
|
||||
bool isLoggedIn() {
|
||||
return _userRepository.isLoggedIn;
|
||||
}
|
||||
|
||||
/// Récupère le rôle de l'utilisateur connecté
|
||||
int getUserRole() {
|
||||
return _userRepository.getUserRole();
|
||||
}
|
||||
}
|
||||
@@ -7,18 +7,70 @@ class AppTheme {
|
||||
static const Color accentColor = Color(0xFF00E09D); // Vert
|
||||
static const Color errorColor = Color(0xFFE41B13); // Rouge
|
||||
static const Color warningColor = Color(0xFFF7A278); // Orange
|
||||
static const Color backgroundLightColor =
|
||||
Color(0xFFF4F5F6); // Gris très clair
|
||||
static const Color backgroundLightColor = Color(0xFFF4F5F6); // Gris très clair
|
||||
static const Color backgroundDarkColor = Color(0xFF111827);
|
||||
static const Color textLightColor = Color(0xFF000000); // Noir
|
||||
static const Color textDarkColor = Color(0xFFF9FAFB);
|
||||
|
||||
// Couleurs de texte supplémentaires
|
||||
static const Color textSecondaryColor = Color(0xFF7F8C8D);
|
||||
static const Color textLightSecondaryColor = Color(0xFFBDC3C7);
|
||||
|
||||
// Couleurs des boutons
|
||||
static const Color buttonSuccessColor = Color(0xFF2ECC71);
|
||||
static const Color buttonDangerColor = Color(0xFFE74C3C);
|
||||
|
||||
// Couleurs des charts
|
||||
static const List<Color> chartColors = [
|
||||
primaryColor,
|
||||
accentColor,
|
||||
errorColor,
|
||||
warningColor,
|
||||
secondaryColor,
|
||||
Color(0xFF9B59B6),
|
||||
Color(0xFF1ABC9C),
|
||||
];
|
||||
|
||||
// Ombres
|
||||
static List<BoxShadow> cardShadow = [
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.05),
|
||||
spreadRadius: 1,
|
||||
blurRadius: 10,
|
||||
offset: const Offset(0, 3),
|
||||
),
|
||||
];
|
||||
|
||||
static List<BoxShadow> buttonShadow = [
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.1),
|
||||
spreadRadius: 1,
|
||||
blurRadius: 5,
|
||||
offset: const Offset(0, 2),
|
||||
),
|
||||
];
|
||||
|
||||
// Rayons des bordures
|
||||
static const double borderRadiusSmall = 4.0;
|
||||
static const double borderRadiusMedium = 8.0;
|
||||
static const double borderRadiusLarge = 12.0;
|
||||
static const double borderRadiusXL = 16.0;
|
||||
static const double borderRadiusRounded = 50.0;
|
||||
|
||||
// Espacement
|
||||
static const double spacingXS = 4.0;
|
||||
static const double spacingS = 8.0;
|
||||
static const double spacingM = 16.0;
|
||||
static const double spacingL = 24.0;
|
||||
static const double spacingXL = 32.0;
|
||||
static const double spacingXXL = 48.0;
|
||||
|
||||
// Thème clair
|
||||
static ThemeData get lightTheme {
|
||||
return ThemeData(
|
||||
useMaterial3: true,
|
||||
brightness: Brightness.light,
|
||||
fontFamily: 'Figtree', // Utilisation directe de la police locale
|
||||
fontFamily: 'Figtree',
|
||||
colorScheme: ColorScheme.light(
|
||||
primary: primaryColor,
|
||||
secondary: secondaryColor,
|
||||
@@ -29,24 +81,10 @@ class AppTheme {
|
||||
onSecondary: Colors.white,
|
||||
onBackground: textLightColor,
|
||||
onSurface: textLightColor,
|
||||
error: errorColor,
|
||||
),
|
||||
textTheme: const TextTheme().copyWith(
|
||||
displayLarge: const TextStyle(fontFamily: 'Figtree'),
|
||||
displayMedium: const TextStyle(fontFamily: 'Figtree'),
|
||||
displaySmall: const TextStyle(fontFamily: 'Figtree'),
|
||||
headlineLarge: const TextStyle(fontFamily: 'Figtree'),
|
||||
headlineMedium: const TextStyle(fontFamily: 'Figtree'),
|
||||
headlineSmall: const TextStyle(fontFamily: 'Figtree'),
|
||||
titleLarge: const TextStyle(fontFamily: 'Figtree'),
|
||||
titleMedium: const TextStyle(fontFamily: 'Figtree'),
|
||||
titleSmall: const TextStyle(fontFamily: 'Figtree'),
|
||||
bodyLarge: const TextStyle(fontFamily: 'Figtree'),
|
||||
bodyMedium: const TextStyle(fontFamily: 'Figtree'),
|
||||
bodySmall: const TextStyle(fontFamily: 'Figtree'),
|
||||
labelLarge: const TextStyle(fontFamily: 'Figtree'),
|
||||
labelMedium: const TextStyle(fontFamily: 'Figtree'),
|
||||
labelSmall: const TextStyle(fontFamily: 'Figtree'),
|
||||
),
|
||||
scaffoldBackgroundColor: backgroundLightColor,
|
||||
textTheme: _getTextTheme(textLightColor),
|
||||
appBarTheme: const AppBarTheme(
|
||||
backgroundColor: primaryColor,
|
||||
foregroundColor: Colors.white,
|
||||
@@ -56,9 +94,10 @@ class AppTheme {
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: primaryColor,
|
||||
foregroundColor: Colors.white,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),
|
||||
padding: const EdgeInsets.symmetric(horizontal: spacingL, vertical: spacingM),
|
||||
elevation: 2,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(50),
|
||||
borderRadius: BorderRadius.circular(borderRadiusRounded),
|
||||
),
|
||||
textStyle: const TextStyle(
|
||||
fontFamily: 'Figtree',
|
||||
@@ -67,35 +106,56 @@ class AppTheme {
|
||||
),
|
||||
),
|
||||
),
|
||||
outlinedButtonTheme: OutlinedButtonThemeData(
|
||||
style: OutlinedButton.styleFrom(
|
||||
foregroundColor: primaryColor,
|
||||
side: const BorderSide(color: primaryColor),
|
||||
padding: const EdgeInsets.symmetric(horizontal: spacingL, vertical: spacingM),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(borderRadiusMedium),
|
||||
),
|
||||
),
|
||||
),
|
||||
textButtonTheme: TextButtonThemeData(
|
||||
style: TextButton.styleFrom(
|
||||
foregroundColor: primaryColor,
|
||||
padding: const EdgeInsets.symmetric(horizontal: spacingM, vertical: spacingS),
|
||||
),
|
||||
),
|
||||
inputDecorationTheme: InputDecorationTheme(
|
||||
filled: true,
|
||||
fillColor: backgroundLightColor,
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderRadius: BorderRadius.circular(borderRadiusMedium),
|
||||
borderSide: BorderSide(
|
||||
color: textLightColor.withOpacity(0.1),
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderRadius: BorderRadius.circular(borderRadiusMedium),
|
||||
borderSide: BorderSide(
|
||||
color: textLightColor.withOpacity(0.1),
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderRadius: BorderRadius.circular(borderRadiusMedium),
|
||||
borderSide: const BorderSide(color: primaryColor, width: 2),
|
||||
),
|
||||
contentPadding:
|
||||
const EdgeInsets.symmetric(horizontal: 16, vertical: 16),
|
||||
contentPadding: const EdgeInsets.symmetric(horizontal: spacingM, vertical: spacingM),
|
||||
),
|
||||
cardTheme: CardTheme(
|
||||
cardTheme: CardThemeData(
|
||||
elevation: 2,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
borderRadius: BorderRadius.circular(borderRadiusXL),
|
||||
),
|
||||
color: Colors.white,
|
||||
),
|
||||
dividerTheme: const DividerThemeData(
|
||||
color: Color(0xFFECF0F1),
|
||||
thickness: 1,
|
||||
space: spacingM,
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -105,7 +165,7 @@ class AppTheme {
|
||||
return ThemeData(
|
||||
useMaterial3: true,
|
||||
brightness: Brightness.dark,
|
||||
fontFamily: 'Figtree', // Utilisation directe de la police locale
|
||||
fontFamily: 'Figtree',
|
||||
colorScheme: ColorScheme.dark(
|
||||
primary: primaryColor,
|
||||
secondary: secondaryColor,
|
||||
@@ -116,24 +176,10 @@ class AppTheme {
|
||||
onSecondary: Colors.white,
|
||||
onBackground: textDarkColor,
|
||||
onSurface: textDarkColor,
|
||||
error: errorColor,
|
||||
),
|
||||
textTheme: const TextTheme().copyWith(
|
||||
displayLarge: const TextStyle(fontFamily: 'Figtree'),
|
||||
displayMedium: const TextStyle(fontFamily: 'Figtree'),
|
||||
displaySmall: const TextStyle(fontFamily: 'Figtree'),
|
||||
headlineLarge: const TextStyle(fontFamily: 'Figtree'),
|
||||
headlineMedium: const TextStyle(fontFamily: 'Figtree'),
|
||||
headlineSmall: const TextStyle(fontFamily: 'Figtree'),
|
||||
titleLarge: const TextStyle(fontFamily: 'Figtree'),
|
||||
titleMedium: const TextStyle(fontFamily: 'Figtree'),
|
||||
titleSmall: const TextStyle(fontFamily: 'Figtree'),
|
||||
bodyLarge: const TextStyle(fontFamily: 'Figtree'),
|
||||
bodyMedium: const TextStyle(fontFamily: 'Figtree'),
|
||||
bodySmall: const TextStyle(fontFamily: 'Figtree'),
|
||||
labelLarge: const TextStyle(fontFamily: 'Figtree'),
|
||||
labelMedium: const TextStyle(fontFamily: 'Figtree'),
|
||||
labelSmall: const TextStyle(fontFamily: 'Figtree'),
|
||||
),
|
||||
scaffoldBackgroundColor: backgroundDarkColor,
|
||||
textTheme: _getTextTheme(textDarkColor),
|
||||
appBarTheme: const AppBarTheme(
|
||||
backgroundColor: Color(0xFF1F2937),
|
||||
foregroundColor: Colors.white,
|
||||
@@ -143,9 +189,10 @@ class AppTheme {
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: primaryColor,
|
||||
foregroundColor: Colors.white,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),
|
||||
padding: const EdgeInsets.symmetric(horizontal: spacingL, vertical: spacingM),
|
||||
elevation: 2,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(50),
|
||||
borderRadius: BorderRadius.circular(borderRadiusRounded),
|
||||
),
|
||||
textStyle: const TextStyle(
|
||||
fontFamily: 'Figtree',
|
||||
@@ -154,37 +201,78 @@ class AppTheme {
|
||||
),
|
||||
),
|
||||
),
|
||||
outlinedButtonTheme: OutlinedButtonThemeData(
|
||||
style: OutlinedButton.styleFrom(
|
||||
foregroundColor: primaryColor,
|
||||
side: const BorderSide(color: primaryColor),
|
||||
padding: const EdgeInsets.symmetric(horizontal: spacingL, vertical: spacingM),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(borderRadiusMedium),
|
||||
),
|
||||
),
|
||||
),
|
||||
textButtonTheme: TextButtonThemeData(
|
||||
style: TextButton.styleFrom(
|
||||
foregroundColor: primaryColor,
|
||||
padding: const EdgeInsets.symmetric(horizontal: spacingM, vertical: spacingS),
|
||||
),
|
||||
),
|
||||
inputDecorationTheme: InputDecorationTheme(
|
||||
filled: true,
|
||||
fillColor: const Color(0xFF374151),
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderRadius: BorderRadius.circular(borderRadiusMedium),
|
||||
borderSide: BorderSide(
|
||||
color: textDarkColor.withOpacity(0.1),
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderRadius: BorderRadius.circular(borderRadiusMedium),
|
||||
borderSide: BorderSide(
|
||||
color: textDarkColor.withOpacity(0.1),
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderRadius: BorderRadius.circular(borderRadiusMedium),
|
||||
borderSide: const BorderSide(color: primaryColor, width: 2),
|
||||
),
|
||||
contentPadding:
|
||||
const EdgeInsets.symmetric(horizontal: 16, vertical: 16),
|
||||
contentPadding: const EdgeInsets.symmetric(horizontal: spacingM, vertical: spacingM),
|
||||
),
|
||||
cardTheme: CardTheme(
|
||||
cardTheme: CardThemeData(
|
||||
elevation: 4,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
borderRadius: BorderRadius.circular(borderRadiusXL),
|
||||
),
|
||||
color: const Color(0xFF1F2937),
|
||||
),
|
||||
dividerTheme: DividerThemeData(
|
||||
color: textDarkColor.withOpacity(0.1),
|
||||
thickness: 1,
|
||||
space: spacingM,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Méthode helper pour générer le TextTheme
|
||||
static TextTheme _getTextTheme(Color textColor) {
|
||||
return TextTheme(
|
||||
displayLarge: TextStyle(fontFamily: 'Figtree', color: textColor),
|
||||
displayMedium: TextStyle(fontFamily: 'Figtree', color: textColor),
|
||||
displaySmall: TextStyle(fontFamily: 'Figtree', color: textColor),
|
||||
headlineLarge: TextStyle(fontFamily: 'Figtree', color: textColor),
|
||||
headlineMedium: TextStyle(fontFamily: 'Figtree', color: textColor),
|
||||
headlineSmall: TextStyle(fontFamily: 'Figtree', color: textColor),
|
||||
titleLarge: TextStyle(fontFamily: 'Figtree', color: textColor),
|
||||
titleMedium: TextStyle(fontFamily: 'Figtree', color: textColor),
|
||||
titleSmall: TextStyle(fontFamily: 'Figtree', color: textColor),
|
||||
bodyLarge: TextStyle(fontFamily: 'Figtree', color: textColor),
|
||||
bodyMedium: TextStyle(fontFamily: 'Figtree', color: textColor),
|
||||
bodySmall: TextStyle(fontFamily: 'Figtree', color: textColor.withOpacity(0.7)),
|
||||
labelLarge: TextStyle(fontFamily: 'Figtree', color: textColor),
|
||||
labelMedium: TextStyle(fontFamily: 'Figtree', color: textColor.withOpacity(0.7)),
|
||||
labelSmall: TextStyle(fontFamily: 'Figtree', color: textColor.withOpacity(0.7)),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_web_plugins/flutter_web_plugins.dart';
|
||||
import 'package:flutter/foundation.dart' show kIsWeb;
|
||||
import 'package:flutter_web_plugins/url_strategy.dart';
|
||||
import 'package:geosector_app/core/services/app_info_service.dart';
|
||||
import 'package:geosector_app/app.dart';
|
||||
import 'package:hive_flutter/hive_flutter.dart';
|
||||
import 'package:geosector_app/core/data/models/user_model.dart';
|
||||
@@ -13,88 +15,167 @@ import 'package:geosector_app/core/data/models/membre_model.dart';
|
||||
import 'package:geosector_app/core/data/models/user_sector_model.dart';
|
||||
import 'package:geosector_app/core/data/models/region_model.dart';
|
||||
import 'package:geosector_app/core/constants/app_keys.dart';
|
||||
import 'package:geosector_app/core/services/hive_reset_service.dart';
|
||||
import 'package:geosector_app/core/services/hive_reset_state_service.dart';
|
||||
// Import centralisé pour les modèles chat
|
||||
import 'package:geosector_app/chat/models/chat_adapters.dart';
|
||||
|
||||
void main() async {
|
||||
// IMPORTANT: Configurer l'URL strategy pour éviter les # dans les URLs
|
||||
usePathUrlStrategy();
|
||||
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
// Configurer le routage par chemin (URLs sans #)
|
||||
setUrlStrategy(PathUrlStrategy());
|
||||
// Initialiser les services essentiels
|
||||
await _initializeServices();
|
||||
|
||||
// Initialiser Hive avec gestion des erreurs
|
||||
bool hiveInitialized = false;
|
||||
final hiveInitialized = await _initializeHive();
|
||||
|
||||
// TEMPORAIREMENT: Ne pas marquer l'erreur pour éviter la redirection
|
||||
// if (!hiveInitialized) {
|
||||
// debugPrint('Incompatibilité détectée dans les données Hive. Marquage pour affichage du dialogue...');
|
||||
// hiveResetStateService.markAsReset();
|
||||
// }
|
||||
|
||||
// Configurer l'orientation de l'application (mobile uniquement)
|
||||
if (!kIsWeb) {
|
||||
await SystemChrome.setPreferredOrientations([
|
||||
DeviceOrientation.portraitUp,
|
||||
DeviceOrientation.portraitDown,
|
||||
]);
|
||||
}
|
||||
|
||||
// Lancer l'application
|
||||
runApp(const GeosectorApp());
|
||||
}
|
||||
|
||||
/// Initialise les services essentiels
|
||||
Future<void> _initializeServices() async {
|
||||
try {
|
||||
await AppInfoService.initialize();
|
||||
debugPrint('Services initialisés avec succès');
|
||||
} catch (e) {
|
||||
debugPrint('Erreur lors de l\'initialisation des services: $e');
|
||||
}
|
||||
}
|
||||
|
||||
/// Initialise Hive et les adaptateurs
|
||||
Future<bool> _initializeHive() async {
|
||||
try {
|
||||
// Initialiser Hive
|
||||
await Hive.initFlutter();
|
||||
|
||||
// Enregistrer les adaptateurs Hive pour les modèles principaux
|
||||
Hive.registerAdapter(UserModelAdapter());
|
||||
Hive.registerAdapter(AmicaleModelAdapter());
|
||||
Hive.registerAdapter(ClientModelAdapter());
|
||||
Hive.registerAdapter(OperationModelAdapter());
|
||||
Hive.registerAdapter(SectorModelAdapter());
|
||||
Hive.registerAdapter(PassageModelAdapter());
|
||||
Hive.registerAdapter(MembreModelAdapter());
|
||||
Hive.registerAdapter(UserSectorModelAdapter());
|
||||
// TODO: Décommenter après avoir généré le fichier region_model.g.dart
|
||||
// Hive.registerAdapter(RegionModelAdapter());
|
||||
|
||||
// Enregistrer les adaptateurs Hive pour le chat
|
||||
Hive.registerAdapter(ConversationModelAdapter());
|
||||
Hive.registerAdapter(MessageModelAdapter());
|
||||
Hive.registerAdapter(ParticipantModelAdapter());
|
||||
Hive.registerAdapter(AnonymousUserModelAdapter());
|
||||
Hive.registerAdapter(AudienceTargetModelAdapter());
|
||||
Hive.registerAdapter(NotificationSettingsAdapter());
|
||||
_registerHiveAdapters();
|
||||
|
||||
// Ouvrir uniquement les boîtes essentielles au démarrage
|
||||
try {
|
||||
// La boîte des utilisateurs est nécessaire pour vérifier si un utilisateur est déjà connecté
|
||||
await Hive.openBox<UserModel>(AppKeys.usersBoxName);
|
||||
// Boîte pour les amicales
|
||||
await Hive.openBox<AmicaleModel>(AppKeys.amicaleBoxName);
|
||||
// Boîte pour les clients
|
||||
await Hive.openBox<ClientModel>(AppKeys.clientsBoxName);
|
||||
// Boîte pour les préférences utilisateur générales
|
||||
await Hive.openBox(AppKeys.settingsBoxName);
|
||||
await _openEssentialHiveBoxes();
|
||||
|
||||
// Ouvrir les boîtes de chat également au démarrage pour le cache local
|
||||
await Hive.openBox<ConversationModel>(AppKeys.chatConversationsBoxName);
|
||||
await Hive.openBox<MessageModel>(AppKeys.chatMessagesBoxName);
|
||||
|
||||
hiveInitialized = true;
|
||||
} catch (e) {
|
||||
debugPrint('Erreur lors de l\'ouverture des boîtes Hive: $e');
|
||||
// Une erreur s'est produite lors de l'ouverture des boîtes, probablement due à une incompatibilité
|
||||
// Nous allons réinitialiser Hive
|
||||
hiveInitialized = false;
|
||||
}
|
||||
debugPrint('Hive initialisé avec succès');
|
||||
return true;
|
||||
} catch (e) {
|
||||
debugPrint('Erreur lors de l\'initialisation de Hive: $e');
|
||||
hiveInitialized = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// Enregistre tous les adaptateurs Hive
|
||||
void _registerHiveAdapters() {
|
||||
// Vérifier si les adaptateurs sont déjà enregistrés pour éviter les doublons
|
||||
if (!Hive.isAdapterRegistered(0)) {
|
||||
Hive.registerAdapter(UserModelAdapter());
|
||||
}
|
||||
if (!Hive.isAdapterRegistered(1)) {
|
||||
Hive.registerAdapter(AmicaleModelAdapter());
|
||||
}
|
||||
if (!Hive.isAdapterRegistered(2)) {
|
||||
Hive.registerAdapter(ClientModelAdapter());
|
||||
}
|
||||
if (!Hive.isAdapterRegistered(3)) {
|
||||
Hive.registerAdapter(OperationModelAdapter());
|
||||
}
|
||||
if (!Hive.isAdapterRegistered(4)) {
|
||||
Hive.registerAdapter(SectorModelAdapter());
|
||||
}
|
||||
if (!Hive.isAdapterRegistered(5)) {
|
||||
Hive.registerAdapter(PassageModelAdapter());
|
||||
}
|
||||
if (!Hive.isAdapterRegistered(6)) {
|
||||
Hive.registerAdapter(MembreModelAdapter());
|
||||
}
|
||||
if (!Hive.isAdapterRegistered(7)) {
|
||||
Hive.registerAdapter(UserSectorModelAdapter());
|
||||
}
|
||||
if (!Hive.isAdapterRegistered(8)) {
|
||||
Hive.registerAdapter(RegionModelAdapter());
|
||||
}
|
||||
|
||||
// Modèles de chat
|
||||
if (!Hive.isAdapterRegistered(9)) {
|
||||
Hive.registerAdapter(ConversationModelAdapter());
|
||||
}
|
||||
if (!Hive.isAdapterRegistered(10)) {
|
||||
Hive.registerAdapter(MessageModelAdapter());
|
||||
}
|
||||
if (!Hive.isAdapterRegistered(11)) {
|
||||
Hive.registerAdapter(ParticipantModelAdapter());
|
||||
}
|
||||
if (!Hive.isAdapterRegistered(12)) {
|
||||
Hive.registerAdapter(AnonymousUserModelAdapter());
|
||||
}
|
||||
if (!Hive.isAdapterRegistered(13)) {
|
||||
Hive.registerAdapter(AudienceTargetModelAdapter());
|
||||
}
|
||||
if (!Hive.isAdapterRegistered(14)) {
|
||||
Hive.registerAdapter(NotificationSettingsAdapter());
|
||||
}
|
||||
}
|
||||
|
||||
/// Ouvre les boîtes Hive essentielles
|
||||
Future<void> _openEssentialHiveBoxes() async {
|
||||
final boxesToOpen = [
|
||||
{'name': AppKeys.usersBoxName, 'type': 'UserModel'},
|
||||
{'name': AppKeys.amicaleBoxName, 'type': 'AmicaleModel'},
|
||||
{'name': AppKeys.clientsBoxName, 'type': 'ClientModel'},
|
||||
{'name': AppKeys.settingsBoxName, 'type': 'dynamic'},
|
||||
{'name': AppKeys.chatConversationsBoxName, 'type': 'ConversationModel'},
|
||||
{'name': AppKeys.chatMessagesBoxName, 'type': 'MessageModel'},
|
||||
];
|
||||
|
||||
for (final box in boxesToOpen) {
|
||||
try {
|
||||
final boxName = box['name'] as String;
|
||||
final boxType = box['type'] as String;
|
||||
|
||||
// Vérifier si la boîte est déjà ouverte
|
||||
if (Hive.isBoxOpen(boxName)) {
|
||||
debugPrint('Boîte $boxName déjà ouverte');
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (boxType) {
|
||||
case 'UserModel':
|
||||
await Hive.openBox<UserModel>(boxName);
|
||||
break;
|
||||
case 'AmicaleModel':
|
||||
await Hive.openBox<AmicaleModel>(boxName);
|
||||
break;
|
||||
case 'ClientModel':
|
||||
await Hive.openBox<ClientModel>(boxName);
|
||||
break;
|
||||
case 'ConversationModel':
|
||||
await Hive.openBox<ConversationModel>(boxName);
|
||||
break;
|
||||
case 'MessageModel':
|
||||
await Hive.openBox<MessageModel>(boxName);
|
||||
break;
|
||||
default:
|
||||
await Hive.openBox(boxName);
|
||||
}
|
||||
|
||||
debugPrint('Boîte $boxName ouverte avec succès');
|
||||
} catch (e) {
|
||||
debugPrint('Erreur lors de l\'ouverture de la boîte ${box['name']}: $e');
|
||||
// Ne pas lancer d'erreur, continuer avec les autres boîtes
|
||||
}
|
||||
}
|
||||
|
||||
// Si Hive n'a pas été initialisé correctement, marquer l'état pour afficher le dialogue
|
||||
if (!hiveInitialized) {
|
||||
debugPrint(
|
||||
'Incompatibilité détectée dans les données Hive. Marquage pour affichage du dialogue...');
|
||||
// Marquer Hive comme ayant été réinitialisé pour afficher le dialogue plus tard
|
||||
hiveResetStateService.markAsReset();
|
||||
}
|
||||
|
||||
// Les autres boîtes (operations, sectors, passages, user_sector) seront ouvertes après connexion
|
||||
// dans UserRepository.login() via la méthode _ensureBoxIsOpen()
|
||||
|
||||
// Définir l'orientation de l'application
|
||||
await SystemChrome.setPreferredOrientations([
|
||||
DeviceOrientation.portraitUp,
|
||||
DeviceOrientation.portraitDown,
|
||||
]);
|
||||
|
||||
// Lancer l'application directement sans AppProviders
|
||||
runApp(const GeoSectorApp());
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:geosector_app/shared/app_theme.dart';
|
||||
import 'package:geosector_app/core/theme/app_theme.dart';
|
||||
import 'package:geosector_app/presentation/widgets/chat/chat_sidebar.dart';
|
||||
import 'package:geosector_app/presentation/widgets/chat/chat_messages.dart';
|
||||
import 'package:geosector_app/presentation/widgets/chat/chat_input.dart';
|
||||
|
||||
@@ -3,18 +3,13 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter/foundation.dart' show kIsWeb;
|
||||
import 'dart:math' as math;
|
||||
import 'package:hive_flutter/hive_flutter.dart';
|
||||
import 'package:geosector_app/presentation/widgets/charts/activity_chart.dart';
|
||||
import 'package:geosector_app/presentation/widgets/charts/passage_pie_chart.dart';
|
||||
import 'package:geosector_app/presentation/widgets/charts/payment_pie_chart.dart';
|
||||
import 'package:geosector_app/presentation/widgets/charts/payment_data.dart';
|
||||
import 'package:geosector_app/presentation/widgets/sector_distribution_card.dart';
|
||||
import 'package:geosector_app/core/repositories/user_repository.dart';
|
||||
import 'package:geosector_app/core/repositories/passage_repository.dart';
|
||||
import 'package:geosector_app/presentation/widgets/charts/charts.dart';
|
||||
import 'package:geosector_app/core/data/models/passage_model.dart';
|
||||
import 'package:geosector_app/core/data/models/operation_model.dart';
|
||||
import 'package:geosector_app/core/data/models/sector_model.dart';
|
||||
import 'package:geosector_app/core/constants/app_keys.dart';
|
||||
import 'package:geosector_app/shared/app_theme.dart';
|
||||
import 'package:geosector_app/core/theme/app_theme.dart';
|
||||
|
||||
/// Class pour dessiner les petits points blancs sur le fond
|
||||
class DotsPainter extends CustomPainter {
|
||||
@@ -281,7 +276,7 @@ class _AdminDashboardHomePageState extends State<AdminDashboardHomePage> {
|
||||
0.0,
|
||||
(sum, passage) =>
|
||||
sum +
|
||||
(passage.montant != null && passage.montant.isNotEmpty
|
||||
(passage.montant.isNotEmpty
|
||||
? double.tryParse(passage.montant) ?? 0.0
|
||||
: 0.0));
|
||||
|
||||
@@ -310,10 +305,8 @@ class _AdminDashboardHomePageState extends State<AdminDashboardHomePage> {
|
||||
|
||||
// Compter les passages par membre
|
||||
for (final passage in passages) {
|
||||
if (passage.fkUser != null) {
|
||||
memberCounts[passage.fkUser!] =
|
||||
(memberCounts[passage.fkUser!] ?? 0) + 1;
|
||||
}
|
||||
memberCounts[passage.fkUser] =
|
||||
(memberCounts[passage.fkUser] ?? 0) + 1;
|
||||
}
|
||||
|
||||
// Récupérer les informations des membres
|
||||
@@ -504,7 +497,6 @@ class _AdminDashboardHomePageState extends State<AdminDashboardHomePage> {
|
||||
key: ValueKey(
|
||||
'sector_distribution_${isFirstLoad ? 'initial' : 'refreshed'}_$isLoading'),
|
||||
height: 200,
|
||||
forceRefresh: !isFirstLoad,
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -531,7 +523,6 @@ class _AdminDashboardHomePageState extends State<AdminDashboardHomePage> {
|
||||
key: ValueKey(
|
||||
'sector_distribution_${isFirstLoad ? 'initial' : 'refreshed'}_$isLoading'),
|
||||
height: 200,
|
||||
forceRefresh: !isFirstLoad,
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -550,12 +541,10 @@ class _AdminDashboardHomePageState extends State<AdminDashboardHomePage> {
|
||||
key: ValueKey(
|
||||
'activity_chart_${isFirstLoad ? 'initial' : 'refreshed'}_$isLoading'),
|
||||
height: 350,
|
||||
loadFromHive: true,
|
||||
showAllPassages:
|
||||
true, // Tous les passages, pas seulement ceux de l'utilisateur courant
|
||||
title: 'Passages réalisés par jour (15 derniers jours)',
|
||||
daysToShow: 15,
|
||||
forceRefresh: !isFirstLoad,
|
||||
),
|
||||
// Si vous avez besoin de passer l'ID de l'opération en cours, décommentez les lignes suivantes
|
||||
// child: ActivityChart(
|
||||
@@ -607,7 +596,7 @@ class _AdminDashboardHomePageState extends State<AdminDashboardHomePage> {
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
const Text(
|
||||
'Actions sur cette opération',
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
@@ -624,7 +613,7 @@ class _AdminDashboardHomePageState extends State<AdminDashboardHomePage> {
|
||||
context,
|
||||
'Exporter les données',
|
||||
Icons.file_download_outlined,
|
||||
AppTheme.buttonPrimaryColor,
|
||||
AppTheme.primaryColor,
|
||||
() {},
|
||||
),
|
||||
_buildActionButton(
|
||||
@@ -705,386 +694,54 @@ class _AdminDashboardHomePageState extends State<AdminDashboardHomePage> {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildChartCard(
|
||||
BuildContext context,
|
||||
String title,
|
||||
Widget chart,
|
||||
) {
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(AppTheme.borderRadiusMedium),
|
||||
boxShadow: AppTheme.cardShadow,
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(AppTheme.spacingM),
|
||||
child: Text(
|
||||
title,
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
),
|
||||
chart,
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Construit la carte de répartition par type de passage avec liste
|
||||
Widget _buildPassageTypeCard(BuildContext context) {
|
||||
return Container(
|
||||
height: 300, // Hauteur fixe de 300px
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(AppTheme.borderRadiusMedium),
|
||||
boxShadow: AppTheme.cardShadow,
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(AppTheme.spacingM),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
'Répartition par type de passage',
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
'$totalPassages passages',
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 16,
|
||||
color: AppTheme.primaryColor,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: AppTheme.spacingM),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
// Graphique à gauche
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: SizedBox(
|
||||
height: 180, // Taille réduite
|
||||
child: Builder(
|
||||
builder: (context) {
|
||||
// Vérifier si nous avons des données de passages
|
||||
if (passagesByType.isEmpty) {
|
||||
debugPrint(
|
||||
'AdminDashboardHomePage: Aucune donnée de passage disponible pour le graphique');
|
||||
return const Center(
|
||||
child: Text('Aucune donnée disponible'),
|
||||
);
|
||||
}
|
||||
|
||||
// Si nous avons des données, afficher le graphique
|
||||
// Mais d'abord, vérifier si tous les passages sont de type 2 (à finaliser)
|
||||
// qui est exclu par défaut dans PassagePieChart
|
||||
bool hasNonType2Passages = passagesByType.entries.any(
|
||||
(entry) => entry.key != 2 && entry.value > 0);
|
||||
|
||||
debugPrint(
|
||||
'AdminDashboardHomePage: Données pour le graphique: $passagesByType');
|
||||
|
||||
// Créer un widget personnalisé pour afficher le graphique ou un message
|
||||
// selon le contenu des données
|
||||
if (passagesByType.isEmpty) {
|
||||
debugPrint(
|
||||
'AdminDashboardHomePage: Aucune donnée de passage disponible');
|
||||
return const Center(
|
||||
child: Text('Aucune donnée disponible'),
|
||||
);
|
||||
}
|
||||
|
||||
// Vérifier si nous avons des données pour au moins un type
|
||||
int totalPassages = 0;
|
||||
passagesByType
|
||||
.forEach((_, count) => totalPassages += count);
|
||||
|
||||
if (totalPassages == 0) {
|
||||
debugPrint(
|
||||
'AdminDashboardHomePage: Aucun passage trouvé');
|
||||
return const Center(
|
||||
child: Text('Aucun passage trouvé'),
|
||||
);
|
||||
}
|
||||
|
||||
// Vérifier si tous les passages sont de type 2 (à finaliser)
|
||||
if (!hasNonType2Passages) {
|
||||
debugPrint(
|
||||
'AdminDashboardHomePage: Tous les passages sont de type 2 (à finaliser)');
|
||||
|
||||
// Créer un widget personnalisé pour afficher un message
|
||||
return Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.info_outline,
|
||||
color: Colors.orange,
|
||||
size: 40,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
const Text(
|
||||
'Uniquement des passages à finaliser',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
'${passagesByType[2] ?? 0} passages',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: Colors.orange,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
// Sinon, afficher le graphique avec les données
|
||||
debugPrint(
|
||||
'AdminDashboardHomePage: Affichage du graphique avec ${passagesByType.length} types');
|
||||
return PassagePieChart(
|
||||
size: 180,
|
||||
passagesByType: passagesByType,
|
||||
loadFromHive: false,
|
||||
isDonut: true,
|
||||
innerRadius: '50%',
|
||||
showIcons: false,
|
||||
showLegend: false,
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
// Liste des types à droite
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(left: AppTheme.spacingM),
|
||||
child: Column(
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.end, // Alignement à droite
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
...AppKeys.typesPassages.entries.map((entry) {
|
||||
final int typeId = entry.key;
|
||||
final Map<String, dynamic> typeInfo = entry.value;
|
||||
final int count = passagesByType[typeId] ?? 0;
|
||||
final Color color =
|
||||
Color(typeInfo['couleur2'] as int);
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(bottom: 8.0),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment
|
||||
.end, // Alignement à droite
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
'$count ${typeInfo['titres']}',
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: color,
|
||||
),
|
||||
textAlign: TextAlign
|
||||
.right, // Texte aligné à droite
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Container(
|
||||
width: 16,
|
||||
height: 16,
|
||||
decoration: BoxDecoration(
|
||||
color: color,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
return PassageSummaryCard(
|
||||
title: 'Répartition par type de passage',
|
||||
titleColor: AppTheme.primaryColor,
|
||||
titleIcon: Icons.route,
|
||||
height: 300,
|
||||
useValueListenable: false, // Utiliser les données statiques
|
||||
showAllPassages: true,
|
||||
excludePassageTypes: const [2], // Exclure "À finaliser"
|
||||
passagesByType: passagesByType,
|
||||
customTotalDisplay: (total) => '$totalPassages passages',
|
||||
isDesktop: MediaQuery.of(context).size.width > 800,
|
||||
backgroundIcon: Icons.route,
|
||||
backgroundIconColor: AppTheme.primaryColor,
|
||||
backgroundIconOpacity: 0.07,
|
||||
backgroundIconSize: 180,
|
||||
);
|
||||
}
|
||||
|
||||
// Construit la carte de répartition par mode de paiement
|
||||
Widget _buildPaymentTypeCard(BuildContext context) {
|
||||
return Container(
|
||||
height: 300, // Hauteur fixe de 300px
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(AppTheme.borderRadiusMedium),
|
||||
boxShadow: AppTheme.cardShadow,
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(AppTheme.spacingM),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
'Répartition par mode de paiement',
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
'${totalAmounts.toStringAsFixed(2)} €',
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 16,
|
||||
color: AppTheme.buttonSuccessColor,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: AppTheme.spacingM),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
// Graphique à gauche
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: SizedBox(
|
||||
height: 180, // Taille réduite
|
||||
child: PaymentPieChart(
|
||||
size: 180,
|
||||
payments: paymentData,
|
||||
isDonut: true,
|
||||
innerRadius: '50%',
|
||||
showIcons: false,
|
||||
showLegend: false,
|
||||
enable3DEffect:
|
||||
false, // Désactiver l'effet 3D pour conserver les couleurs originales
|
||||
effect3DIntensity: 0.0, // Pas d'intensité 3D
|
||||
enableEnhancedExplode: false, // Désactiver l'explosion
|
||||
useGradient:
|
||||
false, // Ne pas utiliser de dégradé pour conserver les couleurs originales
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
// Liste des types de règlement à droite
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(left: AppTheme.spacingM),
|
||||
child: Column(
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.end, // Alignement à droite
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
...[1, 2, 3].map((typeId) {
|
||||
// Uniquement les types 1, 2 et 3
|
||||
if (!AppKeys.typesReglements.containsKey(typeId)) {
|
||||
return const SizedBox
|
||||
.shrink(); // Ignorer si le type n'existe pas
|
||||
}
|
||||
|
||||
final Map<String, dynamic> typeInfo =
|
||||
AppKeys.typesReglements[typeId]!;
|
||||
|
||||
// Calculer le montant total pour ce type de règlement
|
||||
double amount = 0.0;
|
||||
for (final payment in paymentData) {
|
||||
if (payment.typeId == typeId) {
|
||||
amount = payment.amount;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Ne pas afficher si le montant est 0
|
||||
if (amount <= 0) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
final Color color =
|
||||
Color(typeInfo['couleur'] as int);
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(bottom: 8.0),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment
|
||||
.end, // Alignement à droite
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
'${amount.toStringAsFixed(2)} € ${typeInfo['titre']}',
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: color,
|
||||
),
|
||||
textAlign: TextAlign
|
||||
.right, // Texte aligné à droite
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Container(
|
||||
width: 16,
|
||||
height: 16,
|
||||
decoration: BoxDecoration(
|
||||
color: color,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
return PaymentSummaryCard(
|
||||
title: 'Répartition par mode de paiement',
|
||||
titleColor: AppTheme.buttonSuccessColor,
|
||||
titleIcon: Icons.euro,
|
||||
height: 300,
|
||||
useValueListenable: false, // Utiliser les données statiques
|
||||
showAllPayments: true,
|
||||
paymentsByType: _convertPaymentDataToMap(paymentData),
|
||||
customTotalDisplay: (total) => '${totalAmounts.toStringAsFixed(2)} €',
|
||||
isDesktop: MediaQuery.of(context).size.width > 800,
|
||||
backgroundIcon: Icons.euro,
|
||||
backgroundIconColor: AppTheme.primaryColor,
|
||||
backgroundIconOpacity: 0.07,
|
||||
backgroundIconSize: 180,
|
||||
);
|
||||
}
|
||||
|
||||
// Méthode helper pour convertir les PaymentData en Map
|
||||
Map<int, double> _convertPaymentDataToMap(List<PaymentData> paymentDataList) {
|
||||
final Map<int, double> result = {};
|
||||
for (final payment in paymentDataList) {
|
||||
result[payment.typeId] = payment.amount;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Widget _buildActionButton(
|
||||
BuildContext context,
|
||||
String label,
|
||||
|
||||
@@ -2,11 +2,7 @@ import 'package:geosector_app/app.dart'; // Pour accéder aux instances globales
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hive_flutter/hive_flutter.dart';
|
||||
import 'package:geosector_app/presentation/widgets/dashboard_layout.dart';
|
||||
import 'package:geosector_app/core/repositories/user_repository.dart';
|
||||
import 'package:geosector_app/core/constants/app_keys.dart';
|
||||
import 'package:geosector_app/shared/app_theme.dart';
|
||||
import 'package:geosector_app/presentation/widgets/loading_progress_overlay.dart';
|
||||
import 'package:geosector_app/core/models/loading_state.dart';
|
||||
import 'dart:math' as math;
|
||||
|
||||
// Import des pages admin
|
||||
@@ -54,14 +50,114 @@ class _AdminDashboardPageState extends State<AdminDashboardPage>
|
||||
// Liste des pages à afficher
|
||||
late final List<Widget> _pages;
|
||||
|
||||
// Index de la page Amicale et membres
|
||||
static const int entitePageIndex = 5;
|
||||
|
||||
// Référence à la boîte Hive pour les paramètres
|
||||
late Box _settingsBox;
|
||||
|
||||
// Overlay pour afficher la progression du chargement
|
||||
OverlayEntry? _progressOverlay;
|
||||
// Liste des éléments de navigation de base (toujours visibles)
|
||||
final List<_NavigationItem> _baseNavigationItems = [
|
||||
const _NavigationItem(
|
||||
label: 'Tableau de bord',
|
||||
icon: Icons.dashboard_outlined,
|
||||
selectedIcon: Icons.dashboard,
|
||||
page: AdminDashboardHomePage(),
|
||||
),
|
||||
const _NavigationItem(
|
||||
label: 'Statistiques',
|
||||
icon: Icons.bar_chart_outlined,
|
||||
selectedIcon: Icons.bar_chart,
|
||||
page: AdminStatisticsPage(),
|
||||
),
|
||||
const _NavigationItem(
|
||||
label: 'Historique',
|
||||
icon: Icons.history_outlined,
|
||||
selectedIcon: Icons.history,
|
||||
page: AdminHistoryPage(),
|
||||
),
|
||||
const _NavigationItem(
|
||||
label: 'Messages',
|
||||
icon: Icons.chat_outlined,
|
||||
selectedIcon: Icons.chat,
|
||||
page: AdminCommunicationPage(),
|
||||
),
|
||||
const _NavigationItem(
|
||||
label: 'Carte',
|
||||
icon: Icons.map_outlined,
|
||||
selectedIcon: Icons.map,
|
||||
page: AdminMapPage(),
|
||||
),
|
||||
];
|
||||
|
||||
// Éléments de navigation supplémentaires pour le rôle 2
|
||||
final List<_NavigationItem> _adminNavigationItems = [
|
||||
const _NavigationItem(
|
||||
label: 'Amicale & membres',
|
||||
icon: Icons.business_outlined,
|
||||
selectedIcon: Icons.business,
|
||||
page: AdminEntitePage(),
|
||||
requiredRole: 2,
|
||||
),
|
||||
const _NavigationItem(
|
||||
label: 'Opérations',
|
||||
icon: Icons.calendar_today_outlined,
|
||||
selectedIcon: Icons.calendar_today,
|
||||
page: Scaffold(body: Center(child: Text('Page Opérations'))),
|
||||
requiredRole: 2,
|
||||
),
|
||||
];
|
||||
|
||||
// Construire la liste des destinations de navigation en fonction du rôle
|
||||
List<NavigationDestination> _buildNavigationDestinations() {
|
||||
final destinations = <NavigationDestination>[];
|
||||
final currentUser = userRepository.getCurrentUser();
|
||||
|
||||
// Ajouter les éléments de base
|
||||
for (final item in _baseNavigationItems) {
|
||||
destinations.add(
|
||||
NavigationDestination(
|
||||
icon: Icon(item.icon),
|
||||
selectedIcon: Icon(item.selectedIcon),
|
||||
label: item.label,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Ajouter les éléments admin si l'utilisateur a le rôle requis
|
||||
if (currentUser?.role == 2) {
|
||||
for (final item in _adminNavigationItems) {
|
||||
if (item.requiredRole == null || item.requiredRole == 2) {
|
||||
destinations.add(
|
||||
NavigationDestination(
|
||||
icon: Icon(item.icon),
|
||||
selectedIcon: Icon(item.selectedIcon),
|
||||
label: item.label,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return destinations;
|
||||
}
|
||||
|
||||
// Construire la liste des pages en fonction du rôle
|
||||
List<Widget> _buildPages() {
|
||||
final pages = <Widget>[];
|
||||
final currentUser = userRepository.getCurrentUser();
|
||||
|
||||
// Ajouter les pages de base
|
||||
pages.addAll(_baseNavigationItems.map((item) => item.page));
|
||||
|
||||
// Ajouter les pages admin si l'utilisateur a le rôle requis
|
||||
if (currentUser?.role == 2) {
|
||||
for (final item in _adminNavigationItems) {
|
||||
if (item.requiredRole == null || item.requiredRole == 2) {
|
||||
pages.add(item.page);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return pages;
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@@ -72,35 +168,19 @@ class _AdminDashboardPageState extends State<AdminDashboardPage>
|
||||
debugPrint('Initialisation de AdminDashboardPage');
|
||||
|
||||
// Vérifier que userRepository est correctement initialisé
|
||||
if (userRepository == null) {
|
||||
debugPrint('ERREUR: userRepository est null dans AdminDashboardPage');
|
||||
debugPrint('userRepository est correctement initialisé');
|
||||
final currentUser = userRepository.getCurrentUser();
|
||||
if (currentUser == null) {
|
||||
debugPrint(
|
||||
'ERREUR: Aucun utilisateur connecté dans AdminDashboardPage');
|
||||
} else {
|
||||
debugPrint('userRepository est correctement initialisé');
|
||||
|
||||
// Vérifier l'utilisateur courant
|
||||
final currentUser = userRepository.getCurrentUser();
|
||||
if (currentUser == null) {
|
||||
debugPrint(
|
||||
'ERREUR: Aucun utilisateur connecté dans AdminDashboardPage',
|
||||
);
|
||||
} else {
|
||||
debugPrint(
|
||||
'Utilisateur connecté: ${currentUser.username} (${currentUser.id})',
|
||||
);
|
||||
}
|
||||
|
||||
// Écouter les changements d'état du UserRepository
|
||||
userRepository.addListener(_handleUserRepositoryChanges);
|
||||
debugPrint(
|
||||
'Utilisateur connecté: ${currentUser.username} (${currentUser.id})');
|
||||
}
|
||||
userRepository.addListener(_handleUserRepositoryChanges);
|
||||
|
||||
_pages = [
|
||||
const AdminDashboardHomePage(),
|
||||
const AdminStatisticsPage(),
|
||||
const AdminHistoryPage(),
|
||||
const AdminCommunicationPage(),
|
||||
const AdminMapPage(),
|
||||
const AdminEntitePage(),
|
||||
];
|
||||
// Initialiser les pages et les destinations
|
||||
_pages = _buildPages();
|
||||
|
||||
// Initialiser et charger les paramètres
|
||||
_initSettings();
|
||||
@@ -117,10 +197,7 @@ class _AdminDashboardPageState extends State<AdminDashboardPage>
|
||||
@override
|
||||
void dispose() {
|
||||
WidgetsBinding.instance.removeObserver(this);
|
||||
if (userRepository != null) {
|
||||
userRepository.removeListener(_handleUserRepositoryChanges);
|
||||
}
|
||||
_removeProgressOverlay();
|
||||
userRepository.removeListener(_handleUserRepositoryChanges);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@@ -134,19 +211,6 @@ class _AdminDashboardPageState extends State<AdminDashboardPage>
|
||||
// La barre de progression est désactivée, ne rien faire
|
||||
}
|
||||
|
||||
// Méthodes pour gérer l'overlay de progression (désactivées)
|
||||
void _showProgressOverlay(LoadingState state) {
|
||||
// La barre de progression est désactivée, ne rien faire
|
||||
}
|
||||
|
||||
void _updateProgressOverlay(LoadingState state) {
|
||||
// La barre de progression est désactivée, ne rien faire
|
||||
}
|
||||
|
||||
void _removeProgressOverlay() {
|
||||
// La barre de progression est désactivée, ne rien faire
|
||||
}
|
||||
|
||||
// Initialiser la boîte de paramètres et charger les préférences
|
||||
Future<void> _initSettings() async {
|
||||
try {
|
||||
@@ -233,47 +297,21 @@ class _AdminDashboardPageState extends State<AdminDashboardPage>
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
/// Construit la liste des destinations de navigation
|
||||
List<NavigationDestination> _buildNavigationDestinations() {
|
||||
// Destinations de base toujours présentes
|
||||
final List<NavigationDestination> destinations = [
|
||||
const NavigationDestination(
|
||||
icon: Icon(Icons.dashboard_outlined),
|
||||
selectedIcon: Icon(Icons.dashboard),
|
||||
label: 'Tableau de bord',
|
||||
),
|
||||
const NavigationDestination(
|
||||
icon: Icon(Icons.bar_chart_outlined),
|
||||
selectedIcon: Icon(Icons.bar_chart),
|
||||
label: 'Statistiques',
|
||||
),
|
||||
const NavigationDestination(
|
||||
icon: Icon(Icons.history_outlined),
|
||||
selectedIcon: Icon(Icons.history),
|
||||
label: 'Historique',
|
||||
),
|
||||
const NavigationDestination(
|
||||
icon: Icon(Icons.chat_outlined),
|
||||
selectedIcon: Icon(Icons.chat),
|
||||
label: 'Messages',
|
||||
),
|
||||
const NavigationDestination(
|
||||
icon: Icon(Icons.map_outlined),
|
||||
selectedIcon: Icon(Icons.map),
|
||||
label: 'Carte',
|
||||
),
|
||||
];
|
||||
|
||||
// Ajouter la destination "Amicale et membres"
|
||||
destinations.add(
|
||||
const NavigationDestination(
|
||||
icon: Icon(Icons.business_outlined),
|
||||
selectedIcon: Icon(Icons.business),
|
||||
label: 'Amicale',
|
||||
),
|
||||
);
|
||||
|
||||
return destinations;
|
||||
}
|
||||
}
|
||||
|
||||
// Classe pour représenter une destination de navigation avec sa page associée
|
||||
class _NavigationItem {
|
||||
final String label;
|
||||
final IconData icon;
|
||||
final IconData selectedIcon;
|
||||
final Widget page;
|
||||
final int? requiredRole; // null si accessible à tous les rôles
|
||||
|
||||
const _NavigationItem({
|
||||
required this.label,
|
||||
required this.icon,
|
||||
required this.selectedIcon,
|
||||
required this.page,
|
||||
this.requiredRole,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import 'package:geosector_app/core/constants/app_keys.dart';
|
||||
import 'package:geosector_app/core/services/location_service.dart';
|
||||
import 'package:geosector_app/core/data/models/sector_model.dart';
|
||||
import 'package:geosector_app/core/data/models/passage_model.dart';
|
||||
import '../../shared/app_theme.dart';
|
||||
import 'package:geosector_app/core/theme/app_theme.dart';
|
||||
|
||||
class AdminMapPage extends StatefulWidget {
|
||||
const AdminMapPage({Key? key}) : super(key: key);
|
||||
|
||||
@@ -1,14 +1,6 @@
|
||||
import 'package:geosector_app/app.dart'; // Pour accéder aux instances globales
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:geosector_app/app.dart'; // Pour accéder aux instances globales
|
||||
import 'package:geosector_app/presentation/widgets/charts/activity_chart.dart';
|
||||
import 'package:geosector_app/presentation/widgets/charts/passage_pie_chart.dart';
|
||||
import 'package:geosector_app/presentation/widgets/charts/payment_pie_chart.dart';
|
||||
import 'package:geosector_app/presentation/widgets/charts/payment_data.dart';
|
||||
import 'package:geosector_app/presentation/widgets/charts/combined_chart.dart';
|
||||
import 'package:geosector_app/core/repositories/passage_repository.dart';
|
||||
import 'package:geosector_app/core/repositories/user_repository.dart';
|
||||
import '../../shared/app_theme.dart';
|
||||
import 'package:geosector_app/core/theme/app_theme.dart';
|
||||
import 'package:geosector_app/presentation/widgets/charts/charts.dart';
|
||||
import 'dart:math' as math;
|
||||
|
||||
/// Class pour dessiner les petits points blancs sur le fond
|
||||
@@ -186,7 +178,6 @@ class _AdminStatisticsPageState extends State<AdminStatisticsPage> {
|
||||
const SizedBox(height: AppTheme.spacingM),
|
||||
ActivityChart(
|
||||
height: 350,
|
||||
loadFromHive: true,
|
||||
showAllPassages: true,
|
||||
title: '',
|
||||
daysToShow: _daysToShow,
|
||||
@@ -210,13 +201,21 @@ class _AdminStatisticsPageState extends State<AdminStatisticsPage> {
|
||||
Expanded(
|
||||
child: _buildChartCard(
|
||||
'Répartition par type de passage',
|
||||
PassagePieChart(
|
||||
size: 300,
|
||||
loadFromHive: true,
|
||||
PassageSummaryCard(
|
||||
title: '',
|
||||
titleColor: AppTheme.primaryColor,
|
||||
titleIcon: Icons.pie_chart,
|
||||
height: 300,
|
||||
useValueListenable: true,
|
||||
showAllPassages: true,
|
||||
excludePassageTypes: const [
|
||||
2
|
||||
], // Exclure "À finaliser"
|
||||
userId: _selectedUser != 'Tous'
|
||||
? _getUserIdFromName(_selectedUser)
|
||||
: null,
|
||||
isDesktop:
|
||||
MediaQuery.of(context).size.width > 800,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -224,7 +223,7 @@ class _AdminStatisticsPageState extends State<AdminStatisticsPage> {
|
||||
Expanded(
|
||||
child: _buildChartCard(
|
||||
'Répartition par mode de paiement',
|
||||
PaymentPieChart(
|
||||
const PaymentPieChart(
|
||||
payments: [
|
||||
PaymentData(
|
||||
typeId: 1,
|
||||
@@ -258,19 +257,26 @@ class _AdminStatisticsPageState extends State<AdminStatisticsPage> {
|
||||
children: [
|
||||
_buildChartCard(
|
||||
'Répartition par type de passage',
|
||||
PassagePieChart(
|
||||
size: 300,
|
||||
loadFromHive: true,
|
||||
PassageSummaryCard(
|
||||
title: '',
|
||||
titleColor: AppTheme.primaryColor,
|
||||
titleIcon: Icons.pie_chart,
|
||||
height: 300,
|
||||
useValueListenable: true,
|
||||
showAllPassages: true,
|
||||
excludePassageTypes: const [
|
||||
2
|
||||
], // Exclure "À finaliser"
|
||||
userId: _selectedUser != 'Tous'
|
||||
? _getUserIdFromName(_selectedUser)
|
||||
: null,
|
||||
isDesktop: MediaQuery.of(context).size.width > 800,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: AppTheme.spacingM),
|
||||
_buildChartCard(
|
||||
'Répartition par mode de paiement',
|
||||
PaymentPieChart(
|
||||
const PaymentPieChart(
|
||||
payments: [
|
||||
PaymentData(
|
||||
typeId: 1,
|
||||
@@ -357,7 +363,7 @@ class _AdminStatisticsPageState extends State<AdminStatisticsPage> {
|
||||
icon: const Icon(Icons.print),
|
||||
label: const Text('Imprimer'),
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: AppTheme.buttonSecondaryColor,
|
||||
backgroundColor: AppTheme.secondaryColor,
|
||||
foregroundColor: Colors.white,
|
||||
),
|
||||
),
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'dart:math' as math;
|
||||
import 'dart:convert';
|
||||
import 'package:flutter/foundation.dart' show kIsWeb, kDebugMode;
|
||||
import 'dart:js' as js;
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:go_router/src/state.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:geosector_app/core/repositories/user_repository.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:geosector_app/core/services/app_info_service.dart';
|
||||
import 'package:geosector_app/presentation/widgets/custom_button.dart';
|
||||
import 'package:geosector_app/presentation/widgets/custom_text_field.dart';
|
||||
import 'package:geosector_app/core/services/location_service.dart';
|
||||
import 'package:geosector_app/core/services/connectivity_service.dart';
|
||||
import 'package:geosector_app/presentation/widgets/connectivity_indicator.dart';
|
||||
import 'package:package_info_plus/package_info_plus.dart';
|
||||
import 'package:geosector_app/app.dart'; // Pour accéder aux instances globales
|
||||
|
||||
class LoginPage extends StatefulWidget {
|
||||
@@ -51,6 +52,7 @@ class _LoginPageState extends State<LoginPage> {
|
||||
final _passwordController = TextEditingController();
|
||||
final _usernameFocusNode = FocusNode();
|
||||
bool _obscurePassword = true;
|
||||
String _appVersion = '';
|
||||
|
||||
// Type de connexion (utilisateur ou administrateur)
|
||||
late String _loginType;
|
||||
@@ -63,6 +65,37 @@ class _LoginPageState extends State<LoginPage> {
|
||||
// État de la connexion Internet
|
||||
bool _isConnected = false;
|
||||
|
||||
Future<void> _getAppVersion() async {
|
||||
try {
|
||||
final packageInfo = await PackageInfo.fromPlatform();
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_appVersion = packageInfo.version;
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
debugPrint('Erreur lors de la récupération de la version: $e');
|
||||
// Fallback sur la version du AppInfoService si elle existe
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_appVersion = AppInfoService.fullVersion
|
||||
.split(' ')
|
||||
.last; // Extraire juste le numéro
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _checkConnectivity() async {
|
||||
await connectivityService.checkConnectivity();
|
||||
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_isConnected = connectivityService.isConnected;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
@@ -163,6 +196,12 @@ class _LoginPageState extends State<LoginPage> {
|
||||
}
|
||||
});
|
||||
|
||||
// Récupérer la version de l'application
|
||||
_getAppVersion();
|
||||
|
||||
// Vérification de connectivité au démarrage
|
||||
_checkConnectivity();
|
||||
|
||||
// Pré-remplir le champ username avec l'identifiant du dernier utilisateur connecté
|
||||
// seulement si le rôle correspond au type de login
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
@@ -538,6 +577,14 @@ class _LoginPageState extends State<LoginPage> {
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
AppInfoService.fullVersion,
|
||||
style: theme.textTheme.bodySmall?.copyWith(
|
||||
color: theme.colorScheme.primary.withOpacity(0.7),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
// Ajouter un texte de débogage uniquement en mode développement
|
||||
if (kDebugMode)
|
||||
Text(
|
||||
@@ -558,7 +605,38 @@ class _LoginPageState extends State<LoginPage> {
|
||||
const SizedBox(height: 16),
|
||||
|
||||
// Indicateur de connectivité
|
||||
ConnectivityIndicator(),
|
||||
const ConnectivityIndicator(),
|
||||
const SizedBox(height: 16),
|
||||
|
||||
if (!kIsWeb && !_isConnected)
|
||||
Container(
|
||||
margin: const EdgeInsets.only(top: 16),
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
color: theme.colorScheme.error.withOpacity(0.1),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
border: Border.all(
|
||||
color:
|
||||
theme.colorScheme.error.withOpacity(0.3),
|
||||
),
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
Icon(Icons.signal_wifi_off,
|
||||
color: theme.colorScheme.error, size: 32),
|
||||
const SizedBox(height: 8),
|
||||
Text('Connexion Internet requise',
|
||||
style: theme.textTheme.titleMedium
|
||||
?.copyWith(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: theme.colorScheme.error)),
|
||||
const SizedBox(height: 8),
|
||||
const Text(
|
||||
'Veuillez vous connecter à Internet (WiFi ou données mobiles) pour pouvoir vous connecter.'),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
const SizedBox(height: 16),
|
||||
|
||||
// Formulaire de connexion
|
||||
@@ -689,7 +767,7 @@ class _LoginPageState extends State<LoginPage> {
|
||||
alignment: Alignment.centerRight,
|
||||
child: TextButton(
|
||||
onPressed: () {
|
||||
// Naviguer vers la page de récupération de mot de passe
|
||||
_showForgotPasswordDialog(context);
|
||||
},
|
||||
child: Text(
|
||||
'Mot de passe oublié ?',
|
||||
@@ -863,10 +941,10 @@ class _LoginPageState extends State<LoginPage> {
|
||||
onPressed: () {
|
||||
context.go('/register');
|
||||
},
|
||||
child: Text(
|
||||
child: const Text(
|
||||
'Inscription Administrateur',
|
||||
style: TextStyle(
|
||||
color: theme.colorScheme.tertiary,
|
||||
color: Colors.blue,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
@@ -897,8 +975,255 @@ class _LoginPageState extends State<LoginPage> {
|
||||
),
|
||||
),
|
||||
),
|
||||
// Badge de version en bas à droite
|
||||
if (_appVersion.isNotEmpty)
|
||||
Positioned(
|
||||
bottom: 16,
|
||||
right: 16,
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 8,
|
||||
vertical: 4,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: theme.colorScheme.primary.withOpacity(0.1),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
border: Border.all(
|
||||
color: theme.colorScheme.primary.withOpacity(0.3),
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
child: Text(
|
||||
'v$_appVersion',
|
||||
style: theme.textTheme.bodySmall?.copyWith(
|
||||
color: theme.colorScheme.primary.withOpacity(0.8),
|
||||
fontSize: 10,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Affiche la boîte de dialogue pour la récupération de mot de passe
|
||||
void _showForgotPasswordDialog(BuildContext context) {
|
||||
final emailController = TextEditingController();
|
||||
final formKey = GlobalKey<FormState>();
|
||||
bool isLoading = false;
|
||||
|
||||
showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (BuildContext context) {
|
||||
return StatefulBuilder(builder: (context, setState) {
|
||||
return AlertDialog(
|
||||
title: const Row(
|
||||
children: [
|
||||
Icon(Icons.lock_reset, color: Colors.blue),
|
||||
SizedBox(width: 10),
|
||||
Text('Récupération de mot de passe'),
|
||||
],
|
||||
),
|
||||
content: Form(
|
||||
key: formKey,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Text(
|
||||
'Veuillez entrer votre adresse email pour recevoir un nouveau mot de passe.',
|
||||
style: TextStyle(fontSize: 14),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
CustomTextField(
|
||||
controller: emailController,
|
||||
label: 'Email',
|
||||
hintText: 'Entrez votre email',
|
||||
prefixIcon: Icons.email_outlined,
|
||||
keyboardType: TextInputType.emailAddress,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Veuillez entrer votre email';
|
||||
}
|
||||
if (!RegExp(r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$')
|
||||
.hasMatch(value)) {
|
||||
return 'Veuillez entrer un email valide';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: const Text('Annuler'),
|
||||
),
|
||||
ElevatedButton(
|
||||
onPressed: isLoading
|
||||
? null
|
||||
: () async {
|
||||
if (formKey.currentState!.validate()) {
|
||||
setState(() {
|
||||
isLoading = true;
|
||||
});
|
||||
|
||||
try {
|
||||
// Vérifier la connexion Internet
|
||||
await connectivityService.checkConnectivity();
|
||||
if (!connectivityService.isConnected) {
|
||||
throw Exception('Aucune connexion Internet');
|
||||
}
|
||||
|
||||
// Construire l'URL de l'API
|
||||
final baseUrl = Uri.base.origin;
|
||||
final apiUrl = '$baseUrl/api/lostpassword';
|
||||
|
||||
print('Envoi de la requête à: $apiUrl');
|
||||
print('Email: ${emailController.text.trim()}');
|
||||
|
||||
http.Response? response;
|
||||
|
||||
try {
|
||||
// Envoyer la requête à l'API
|
||||
response = await http.post(
|
||||
Uri.parse(apiUrl),
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: json.encode({
|
||||
'email': emailController.text.trim(),
|
||||
}),
|
||||
);
|
||||
|
||||
print('Réponse reçue: ${response.statusCode}');
|
||||
print('Corps de la réponse: ${response.body}');
|
||||
|
||||
// Si la réponse est 404, c'est peut-être un problème de route
|
||||
if (response.statusCode == 404) {
|
||||
// Essayer avec une URL alternative
|
||||
final alternativeUrl =
|
||||
'$baseUrl/api/index.php/lostpassword';
|
||||
print(
|
||||
'Tentative avec URL alternative: $alternativeUrl');
|
||||
|
||||
final alternativeResponse = await http.post(
|
||||
Uri.parse(alternativeUrl),
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: json.encode({
|
||||
'email': emailController.text.trim(),
|
||||
}),
|
||||
);
|
||||
|
||||
print(
|
||||
'Réponse alternative reçue: ${alternativeResponse.statusCode}');
|
||||
print(
|
||||
'Corps de la réponse alternative: ${alternativeResponse.body}');
|
||||
|
||||
// Si la réponse alternative est un succès, utiliser cette réponse
|
||||
if (alternativeResponse.statusCode == 200) {
|
||||
response = alternativeResponse;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
print(
|
||||
'Erreur lors de l\'envoi de la requête: $e');
|
||||
throw Exception('Erreur de connexion: $e');
|
||||
}
|
||||
|
||||
// Traiter la réponse
|
||||
if (response != null &&
|
||||
response.statusCode == 200) {
|
||||
// Modifier le contenu de la boîte de dialogue pour afficher le message de succès
|
||||
setState(() {
|
||||
isLoading = false;
|
||||
});
|
||||
|
||||
// Remplacer le contenu de la boîte de dialogue par un message de succès
|
||||
showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (BuildContext context) {
|
||||
// Fermer automatiquement la boîte de dialogue après 2 secondes
|
||||
Future.delayed(Duration(seconds: 2), () {
|
||||
if (Navigator.of(context).canPop()) {
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
});
|
||||
|
||||
return const AlertDialog(
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.check_circle,
|
||||
color: Colors.green,
|
||||
size: 48,
|
||||
),
|
||||
SizedBox(height: 16),
|
||||
Text(
|
||||
'Vous recevrez un nouveau mot de passe par email',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(fontSize: 16),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
} else {
|
||||
// Fermer la boîte de dialogue actuelle
|
||||
Navigator.of(context).pop();
|
||||
|
||||
// Afficher un message d'erreur
|
||||
final responseData = json.decode(response.body);
|
||||
throw Exception(responseData['message'] ??
|
||||
'Erreur lors de la récupération du mot de passe');
|
||||
}
|
||||
} catch (e) {
|
||||
// Afficher un message d'erreur
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(e
|
||||
.toString()
|
||||
.contains('Exception:')
|
||||
? e.toString().split('Exception: ')[1]
|
||||
: 'Erreur lors de la récupération du mot de passe'),
|
||||
backgroundColor: Colors.red,
|
||||
),
|
||||
);
|
||||
} finally {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
isLoading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
child: isLoading
|
||||
? SizedBox(
|
||||
width: 20,
|
||||
height: 20,
|
||||
child: CircularProgressIndicator(
|
||||
strokeWidth: 2,
|
||||
valueColor:
|
||||
AlwaysStoppedAnimation<Color>(Colors.white),
|
||||
),
|
||||
)
|
||||
: Text('Recevoir un nouveau mot de passe'),
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Colors.blue,
|
||||
foregroundColor: Colors.white,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,9 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:hive_flutter/hive_flutter.dart';
|
||||
import 'package:geosector_app/core/repositories/user_repository.dart';
|
||||
import 'package:geosector_app/core/theme/app_theme.dart';
|
||||
import 'package:geosector_app/app.dart'; // Pour accéder aux instances globales
|
||||
import 'package:geosector_app/core/services/app_info_service.dart';
|
||||
import 'package:geosector_app/core/constants/app_keys.dart';
|
||||
import 'package:geosector_app/core/data/models/user_model.dart';
|
||||
import 'package:geosector_app/core/data/models/amicale_model.dart';
|
||||
@@ -15,10 +13,11 @@ import 'package:geosector_app/core/data/models/membre_model.dart';
|
||||
import 'package:geosector_app/core/data/models/user_sector_model.dart';
|
||||
import 'package:geosector_app/chat/models/conversation_model.dart';
|
||||
import 'package:geosector_app/chat/models/message_model.dart';
|
||||
import 'package:geosector_app/core/services/hive_reset_state_service.dart';
|
||||
import 'package:geosector_app/presentation/widgets/clear_cache_dialog.dart';
|
||||
import 'dart:async';
|
||||
import 'dart:math' as math;
|
||||
import 'package:flutter/foundation.dart' show kIsWeb;
|
||||
import 'package:package_info_plus/package_info_plus.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
class SplashPage extends StatefulWidget {
|
||||
const SplashPage({super.key});
|
||||
@@ -58,12 +57,28 @@ class _SplashPageState extends State<SplashPage>
|
||||
String _statusMessage = "Initialisation...";
|
||||
double _progress = 0.0;
|
||||
bool _showButtons = false;
|
||||
String _appVersion = '';
|
||||
|
||||
final List<String> _initializationSteps = [
|
||||
"Initialisation des services...",
|
||||
"Vérification de l'authentification...",
|
||||
"Chargement des données..."
|
||||
];
|
||||
Future<void> _getAppVersion() async {
|
||||
try {
|
||||
final packageInfo = await PackageInfo.fromPlatform();
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_appVersion = packageInfo.version;
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
debugPrint('Erreur lors de la récupération de la version: $e');
|
||||
// Fallback sur la version du AppInfoService si elle existe
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_appVersion = AppInfoService.fullVersion
|
||||
.split(' ')
|
||||
.last; // Extraire juste le numéro
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@@ -89,33 +104,12 @@ class _SplashPageState extends State<SplashPage>
|
||||
// Démarrer l'animation immédiatement
|
||||
_animationController.forward();
|
||||
|
||||
// Vérifier si Hive a été réinitialisé
|
||||
_checkHiveReset();
|
||||
_getAppVersion();
|
||||
|
||||
// Simuler le processus d'initialisation
|
||||
_startInitialization();
|
||||
}
|
||||
|
||||
// Méthode pour vérifier si Hive a été réinitialisé et afficher le dialogue si nécessaire
|
||||
void _checkHiveReset() {
|
||||
// Vérifier si Hive a été réinitialisé et si le dialogue n'a pas encore été affiché
|
||||
if (hiveResetStateService.wasReset && !hiveResetStateService.dialogShown) {
|
||||
// Attendre que le widget soit complètement construit
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
if (mounted) {
|
||||
// Afficher le dialogue de nettoyage du cache
|
||||
ClearCacheDialog.show(
|
||||
context,
|
||||
onClose: () {
|
||||
// Marquer le dialogue comme ayant été affiché
|
||||
hiveResetStateService.markDialogAsShown();
|
||||
},
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_animationController.dispose();
|
||||
@@ -123,11 +117,11 @@ class _SplashPageState extends State<SplashPage>
|
||||
}
|
||||
|
||||
void _startInitialization() async {
|
||||
// Étape 1: Initialisation des services
|
||||
// Étape 1: Initialisation des boîtes Hive (0% à 75%)
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_statusMessage = _initializationSteps[0];
|
||||
_progress = 0.2;
|
||||
_statusMessage = "Initialisation des données...";
|
||||
_progress = 0.0;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -135,20 +129,11 @@ class _SplashPageState extends State<SplashPage>
|
||||
await _initializeAllHiveBoxes();
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
|
||||
// Étape 2: Vérification de l'authentification
|
||||
// Étape 2: Initialisation des services (75% à 100%)
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_statusMessage = _initializationSteps[1];
|
||||
_progress = 0.4;
|
||||
});
|
||||
}
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
|
||||
// Étape 3: Chargement des données
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_statusMessage = _initializationSteps[2];
|
||||
_progress = 1.0; // Directement à 100% après la 3ème étape
|
||||
_statusMessage = "Préparation de l'application...";
|
||||
_progress = 0.75;
|
||||
});
|
||||
}
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
@@ -157,15 +142,8 @@ class _SplashPageState extends State<SplashPage>
|
||||
setState(() {
|
||||
_isInitializing = false;
|
||||
_showButtons = true;
|
||||
_progress = 1.0; // S'assurer que la barre est à 100%
|
||||
});
|
||||
|
||||
// Attendre quelques secondes avant de rediriger automatiquement
|
||||
// si l'utilisateur est déjà connecté
|
||||
if (userRepository.isLoggedIn) {
|
||||
Timer(const Duration(seconds: 2), () {
|
||||
_redirectToAppropriateScreen();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -202,8 +180,8 @@ class _SplashPageState extends State<SplashPage>
|
||||
},
|
||||
];
|
||||
|
||||
// Calculer l'incrément de progression pour chaque boîte
|
||||
final progressIncrement = 0.2 / boxesToOpen.length;
|
||||
// Calculer l'incrément de progression pour chaque boîte (0.75 / nombre de boîtes)
|
||||
final progressIncrement = 0.75 / boxesToOpen.length;
|
||||
double currentProgress = 0.0;
|
||||
|
||||
// Ouvrir chaque boîte si elle n'est pas déjà ouverte
|
||||
@@ -212,12 +190,11 @@ class _SplashPageState extends State<SplashPage>
|
||||
final displayName = boxesToOpen[i]['display'] as String;
|
||||
|
||||
// Mettre à jour la barre de progression et le message
|
||||
currentProgress += progressIncrement;
|
||||
currentProgress = progressIncrement * (i + 1);
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_statusMessage = displayName;
|
||||
_progress =
|
||||
0.2 * (currentProgress / 0.2); // Normaliser entre 0 et 0.2
|
||||
_progress = currentProgress;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -266,10 +243,27 @@ class _SplashPageState extends State<SplashPage>
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_statusMessage = 'Toutes les boîtes sont prêtes';
|
||||
_progress = 0.2;
|
||||
_progress = 0.8;
|
||||
});
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
}
|
||||
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_statusMessage = "Préparation de l'application...";
|
||||
_progress = 0.9;
|
||||
});
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
}
|
||||
|
||||
// Finalisation
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_isInitializing = false;
|
||||
_showButtons = true;
|
||||
_progress = 1.0;
|
||||
});
|
||||
}
|
||||
debugPrint('Toutes les boîtes Hive sont maintenant ouvertes');
|
||||
} catch (e) {
|
||||
debugPrint('Erreur lors de l\'initialisation des boîtes Hive: $e');
|
||||
@@ -283,33 +277,9 @@ class _SplashPageState extends State<SplashPage>
|
||||
}
|
||||
}
|
||||
|
||||
void _redirectToAppropriateScreen() {
|
||||
if (!mounted) return;
|
||||
|
||||
// Utiliser l'instance globale de userRepository définie dans app.dart
|
||||
if (userRepository.isLoggedIn) {
|
||||
debugPrint('SplashPage: Redirection d\'utilisateur connecté');
|
||||
|
||||
// Récupérer directement le rôle utilisateur
|
||||
final roleValue = userRepository.getUserRole();
|
||||
debugPrint('SplashPage: Rôle utilisateur = $roleValue');
|
||||
|
||||
// Redirection simple basée sur le rôle
|
||||
if (roleValue > 1) {
|
||||
debugPrint('SplashPage: Redirection vers /admin (rôle $roleValue > 1)');
|
||||
context.go('/admin');
|
||||
} else {
|
||||
debugPrint('SplashPage: Redirection vers /user (rôle $roleValue = 1)');
|
||||
context.go('/user');
|
||||
}
|
||||
}
|
||||
// Ne redirige plus vers la landing page
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
final size = MediaQuery.of(context).size;
|
||||
|
||||
return Scaffold(
|
||||
body: Stack(
|
||||
@@ -424,7 +394,8 @@ class _SplashPageState extends State<SplashPage>
|
||||
duration: const Duration(milliseconds: 500),
|
||||
child: ElevatedButton(
|
||||
onPressed: () {
|
||||
context.go('/login', extra: {'type': 'user'});
|
||||
context.go(
|
||||
'/login/user'); // Utiliser la route spécifique
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Colors.green,
|
||||
@@ -449,13 +420,14 @@ class _SplashPageState extends State<SplashPage>
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
|
||||
// Bouton Connexion Administrateur
|
||||
// Bouton Connexion Administrateur
|
||||
AnimatedOpacity(
|
||||
opacity: _showButtons ? 1.0 : 0.0,
|
||||
duration: const Duration(milliseconds: 500),
|
||||
child: ElevatedButton(
|
||||
onPressed: () {
|
||||
context.go('/login', extra: {'type': 'admin'});
|
||||
context.go(
|
||||
'/login/admin'); // Utiliser la route spécifique
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Colors.red,
|
||||
@@ -479,18 +451,74 @@ class _SplashPageState extends State<SplashPage>
|
||||
),
|
||||
),
|
||||
|
||||
const SizedBox(height: 16),
|
||||
const SizedBox(
|
||||
height: 32), // 2 espaces sous le bouton précédent
|
||||
|
||||
// Lien d'inscription
|
||||
// Bouton d'inscription
|
||||
AnimatedOpacity(
|
||||
opacity: _showButtons ? 1.0 : 0.0,
|
||||
duration: const Duration(milliseconds: 500),
|
||||
child: TextButton(
|
||||
child: ElevatedButton(
|
||||
onPressed: () {
|
||||
context.go('/register');
|
||||
},
|
||||
child: Text(
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Colors.blue,
|
||||
foregroundColor: Colors.white,
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 40,
|
||||
vertical: 16,
|
||||
),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(30),
|
||||
),
|
||||
elevation: 2,
|
||||
),
|
||||
child: const Text(
|
||||
'Pas encore inscrit ?',
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
const SizedBox(height: 16),
|
||||
|
||||
// Lien vers le site web
|
||||
AnimatedOpacity(
|
||||
opacity: _showButtons ? 1.0 : 0.0,
|
||||
duration: const Duration(milliseconds: 500),
|
||||
child: TextButton.icon(
|
||||
onPressed: () {
|
||||
// Déterminer l'URL du site web en fonction de l'environnement
|
||||
String webUrl = 'https://geosector.fr';
|
||||
|
||||
if (kIsWeb) {
|
||||
final host = Uri.base.host;
|
||||
if (host.startsWith('dapp.')) {
|
||||
webUrl = 'https://dev.geosector.fr';
|
||||
} else if (host.startsWith('rapp.')) {
|
||||
webUrl = 'https://rec.geosector.fr';
|
||||
} else if (host.startsWith('app.')) {
|
||||
webUrl = 'https://geosector.fr';
|
||||
}
|
||||
}
|
||||
|
||||
// Ouvrir l'URL dans une nouvelle fenêtre/onglet
|
||||
launchUrl(
|
||||
Uri.parse(webUrl),
|
||||
mode: LaunchMode.externalApplication,
|
||||
);
|
||||
},
|
||||
icon: Icon(
|
||||
Icons.language,
|
||||
size: 18,
|
||||
color: theme.colorScheme.primary,
|
||||
),
|
||||
label: Text(
|
||||
'Site web Geosector',
|
||||
style: TextStyle(
|
||||
color: theme.colorScheme.primary,
|
||||
fontWeight: FontWeight.w500,
|
||||
@@ -506,6 +534,38 @@ class _SplashPageState extends State<SplashPage>
|
||||
),
|
||||
),
|
||||
),
|
||||
// Badge de version en bas à droite
|
||||
if (_appVersion.isNotEmpty)
|
||||
Positioned(
|
||||
bottom: 16,
|
||||
right: 16,
|
||||
child: AnimatedOpacity(
|
||||
opacity: _showButtons ? 0.7 : 0.5,
|
||||
duration: const Duration(milliseconds: 500),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 8,
|
||||
vertical: 4,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: theme.colorScheme.primary.withOpacity(0.1),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
border: Border.all(
|
||||
color: theme.colorScheme.primary,
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
child: Text(
|
||||
'v$_appVersion',
|
||||
style: theme.textTheme.bodySmall?.copyWith(
|
||||
color: theme.colorScheme.primary,
|
||||
fontSize: 10,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,12 +1,12 @@
|
||||
import 'package:geosector_app/app.dart'; // Pour accéder aux instances globales
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:geosector_app/app.dart'; // Pour accéder aux instances globales
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:hive_flutter/hive_flutter.dart';
|
||||
import 'package:geosector_app/core/repositories/user_repository.dart';
|
||||
import 'package:geosector_app/core/theme/app_theme.dart';
|
||||
import 'package:geosector_app/core/constants/app_keys.dart';
|
||||
import 'package:geosector_app/presentation/widgets/dashboard_layout.dart';
|
||||
import 'package:geosector_app/presentation/widgets/passages/passage_form.dart';
|
||||
|
||||
// Import des pages utilisateur
|
||||
import 'user_dashboard_home_page.dart';
|
||||
@@ -94,73 +94,85 @@ class _UserDashboardPageState extends State<UserDashboardPage> {
|
||||
final bool shouldShowNoOperationMessage = isStandardUser && !hasOperation;
|
||||
final bool shouldShowNoSectorMessage = isStandardUser && !hasSectors;
|
||||
|
||||
// Définir les actions supplémentaires pour l'AppBar
|
||||
List<Widget>? additionalActions;
|
||||
if (shouldShowNoOperationMessage || shouldShowNoSectorMessage) {
|
||||
additionalActions = [
|
||||
// Bouton de déconnexion uniquement si l'utilisateur n'a pas d'opération
|
||||
TextButton.icon(
|
||||
icon: const Icon(Icons.logout, color: Colors.white),
|
||||
label: const Text('Se déconnecter',
|
||||
style: TextStyle(color: Colors.white)),
|
||||
onPressed: () async {
|
||||
// Utiliser directement userRepository pour la déconnexion
|
||||
await userRepository.logoutWithUI(context);
|
||||
// La redirection est gérée dans logoutWithUI
|
||||
},
|
||||
style: TextButton.styleFrom(
|
||||
backgroundColor: AppTheme.accentColor,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||
// Si l'utilisateur n'a pas d'opération ou de secteur, utiliser DashboardLayout avec un body spécial
|
||||
if (shouldShowNoOperationMessage) {
|
||||
return DashboardLayout(
|
||||
title: 'GEOSECTOR',
|
||||
selectedIndex: 0, // Index par défaut
|
||||
onDestinationSelected: (index) {
|
||||
// Ne rien faire car l'utilisateur ne peut pas naviguer
|
||||
},
|
||||
destinations: const [
|
||||
NavigationDestination(
|
||||
icon: Icon(Icons.warning_outlined),
|
||||
selectedIcon: Icon(Icons.warning),
|
||||
label: 'Accès restreint',
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 16), // Espacement à droite
|
||||
];
|
||||
],
|
||||
showNewPassageButton: false,
|
||||
body: _buildNoOperationMessage(context),
|
||||
);
|
||||
}
|
||||
|
||||
return shouldShowNoOperationMessage
|
||||
? _buildNoOperationMessage(context)
|
||||
: (shouldShowNoSectorMessage
|
||||
? _buildNoSectorMessage(context)
|
||||
: DashboardLayout(
|
||||
title: 'GEOSECTOR',
|
||||
selectedIndex: _selectedIndex,
|
||||
onDestinationSelected: (index) {
|
||||
setState(() {
|
||||
_selectedIndex = index;
|
||||
_saveSettings(); // Sauvegarder l'index de page sélectionné
|
||||
});
|
||||
},
|
||||
destinations: const [
|
||||
NavigationDestination(
|
||||
icon: Icon(Icons.dashboard_outlined),
|
||||
selectedIcon: Icon(Icons.dashboard),
|
||||
label: 'Tableau de bord',
|
||||
),
|
||||
NavigationDestination(
|
||||
icon: Icon(Icons.bar_chart_outlined),
|
||||
selectedIcon: Icon(Icons.bar_chart),
|
||||
label: 'Stats',
|
||||
),
|
||||
NavigationDestination(
|
||||
icon: Icon(Icons.history_outlined),
|
||||
selectedIcon: Icon(Icons.history),
|
||||
label: 'Historique',
|
||||
),
|
||||
NavigationDestination(
|
||||
icon: Icon(Icons.chat_outlined),
|
||||
selectedIcon: Icon(Icons.chat),
|
||||
label: 'Messages',
|
||||
),
|
||||
NavigationDestination(
|
||||
icon: Icon(Icons.map_outlined),
|
||||
selectedIcon: Icon(Icons.map),
|
||||
label: 'Carte',
|
||||
),
|
||||
],
|
||||
additionalActions: additionalActions,
|
||||
onNewPassagePressed: () => _showPassageForm(context),
|
||||
body: _pages[_selectedIndex],
|
||||
));
|
||||
if (shouldShowNoSectorMessage) {
|
||||
return DashboardLayout(
|
||||
title: 'GEOSECTOR',
|
||||
selectedIndex: 0, // Index par défaut
|
||||
onDestinationSelected: (index) {
|
||||
// Ne rien faire car l'utilisateur ne peut pas naviguer
|
||||
},
|
||||
destinations: const [
|
||||
NavigationDestination(
|
||||
icon: Icon(Icons.warning_outlined),
|
||||
selectedIcon: Icon(Icons.warning),
|
||||
label: 'Accès restreint',
|
||||
),
|
||||
],
|
||||
showNewPassageButton: false,
|
||||
body: _buildNoSectorMessage(context),
|
||||
);
|
||||
}
|
||||
|
||||
// Utilisateur normal avec accès complet
|
||||
return DashboardLayout(
|
||||
title: 'GEOSECTOR',
|
||||
selectedIndex: _selectedIndex,
|
||||
onDestinationSelected: (index) {
|
||||
setState(() {
|
||||
_selectedIndex = index;
|
||||
_saveSettings(); // Sauvegarder l'index de page sélectionné
|
||||
});
|
||||
},
|
||||
destinations: const [
|
||||
NavigationDestination(
|
||||
icon: Icon(Icons.dashboard_outlined),
|
||||
selectedIcon: Icon(Icons.dashboard),
|
||||
label: 'Tableau de bord',
|
||||
),
|
||||
NavigationDestination(
|
||||
icon: Icon(Icons.bar_chart_outlined),
|
||||
selectedIcon: Icon(Icons.bar_chart),
|
||||
label: 'Stats',
|
||||
),
|
||||
NavigationDestination(
|
||||
icon: Icon(Icons.history_outlined),
|
||||
selectedIcon: Icon(Icons.history),
|
||||
label: 'Historique',
|
||||
),
|
||||
NavigationDestination(
|
||||
icon: Icon(Icons.chat_outlined),
|
||||
selectedIcon: Icon(Icons.chat),
|
||||
label: 'Messages',
|
||||
),
|
||||
NavigationDestination(
|
||||
icon: Icon(Icons.map_outlined),
|
||||
selectedIcon: Icon(Icons.map),
|
||||
label: 'Carte',
|
||||
),
|
||||
],
|
||||
onNewPassagePressed: () => _showPassageForm(context),
|
||||
body: _pages[_selectedIndex],
|
||||
);
|
||||
}
|
||||
|
||||
// Message pour les utilisateurs sans opération assignée
|
||||
@@ -269,110 +281,90 @@ class _UserDashboardPageState extends State<UserDashboardPage> {
|
||||
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
title: Text(
|
||||
'Nouveau passage',
|
||||
style: TextStyle(
|
||||
color: theme.colorScheme.primary,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
builder: (context) => Dialog(
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
),
|
||||
content: SingleChildScrollView(
|
||||
child: Container(
|
||||
constraints: const BoxConstraints(
|
||||
maxWidth: 600,
|
||||
maxHeight: 700,
|
||||
),
|
||||
padding: const EdgeInsets.all(24),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
TextField(
|
||||
decoration: InputDecoration(
|
||||
labelText: 'Adresse',
|
||||
prefixIcon: const Icon(Icons.location_on),
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
// En-tête de la modale
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
'Nouveau passage',
|
||||
style: theme.textTheme.headlineSmall?.copyWith(
|
||||
color: theme.colorScheme.primary,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
DropdownButtonFormField<int>(
|
||||
decoration: InputDecoration(
|
||||
labelText: 'Type de passage',
|
||||
prefixIcon: const Icon(Icons.category),
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
),
|
||||
items: const [
|
||||
DropdownMenuItem(
|
||||
value: 1,
|
||||
child: Text('Effectué'),
|
||||
),
|
||||
DropdownMenuItem(
|
||||
value: 2,
|
||||
child: Text('À finaliser'),
|
||||
),
|
||||
DropdownMenuItem(
|
||||
value: 3,
|
||||
child: Text('Refusé'),
|
||||
),
|
||||
DropdownMenuItem(
|
||||
value: 4,
|
||||
child: Text('Don'),
|
||||
),
|
||||
DropdownMenuItem(
|
||||
value: 5,
|
||||
child: Text('Lot'),
|
||||
),
|
||||
DropdownMenuItem(
|
||||
value: 6,
|
||||
child: Text('Maison vide'),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.close),
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
),
|
||||
],
|
||||
onChanged: (value) {},
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
TextField(
|
||||
decoration: InputDecoration(
|
||||
labelText: 'Commentaire',
|
||||
prefixIcon: const Icon(Icons.comment),
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
const Divider(),
|
||||
const SizedBox(height: 16),
|
||||
|
||||
// Formulaire de passage
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
child: PassageForm(
|
||||
onSubmit: (formData) {
|
||||
// Traiter les données du formulaire
|
||||
_handlePassageSubmission(context, formData);
|
||||
},
|
||||
),
|
||||
),
|
||||
maxLines: 3,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: Text(
|
||||
'Annuler',
|
||||
style: TextStyle(
|
||||
color: theme.colorScheme.error,
|
||||
),
|
||||
),
|
||||
),
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
// Enregistrer le passage
|
||||
Navigator.of(context).pop();
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: const Text('Passage enregistré avec succès'),
|
||||
backgroundColor: theme.colorScheme.primary,
|
||||
),
|
||||
);
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: theme.colorScheme.primary,
|
||||
foregroundColor: theme.colorScheme.onPrimary,
|
||||
),
|
||||
child: const Text('Enregistrer'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Traiter la soumission du formulaire de passage
|
||||
void _handlePassageSubmission(
|
||||
BuildContext context, Map<String, dynamic> formData) {
|
||||
// Fermer la modale
|
||||
Navigator.of(context).pop();
|
||||
|
||||
// Ici vous pouvez traiter les données du formulaire
|
||||
// Par exemple, les envoyer au repository ou à un service
|
||||
|
||||
// Pour l'instant, afficher un message de succès
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content:
|
||||
Text('Passage enregistré avec succès pour ${formData['adresse']}'),
|
||||
backgroundColor: Theme.of(context).colorScheme.primary,
|
||||
behavior: SnackBarBehavior.floating,
|
||||
),
|
||||
);
|
||||
|
||||
// TODO: Intégrer avec votre logique métier
|
||||
// Exemple :
|
||||
// try {
|
||||
// await passageRepository.createPassage(formData);
|
||||
// // Rafraîchir les données si nécessaire
|
||||
// } catch (e) {
|
||||
// ScaffoldMessenger.of(context).showSnackBar(
|
||||
// SnackBar(
|
||||
// content: Text('Erreur lors de l\'enregistrement: $e'),
|
||||
// backgroundColor: Theme.of(context).colorScheme.error,
|
||||
// ),
|
||||
// );
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
import 'package:geosector_app/app.dart'; // Pour accéder aux instances globales
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:geosector_app/app.dart'; // Pour accéder aux instances globales
|
||||
import 'package:fl_chart/fl_chart.dart';
|
||||
import 'package:geosector_app/core/theme/app_theme.dart';
|
||||
import 'package:geosector_app/presentation/widgets/charts/charts.dart';
|
||||
import 'package:geosector_app/core/repositories/user_repository.dart';
|
||||
|
||||
class UserStatisticsPage extends StatefulWidget {
|
||||
const UserStatisticsPage({super.key});
|
||||
@@ -58,8 +55,9 @@ class _UserStatisticsPageState extends State<UserStatisticsPage> {
|
||||
|
||||
const SizedBox(height: 24),
|
||||
|
||||
// Résumé par type de règlement
|
||||
_buildPaymentTypeSummary(theme, isDesktop),
|
||||
// Résumé par type de règlement
|
||||
_buildPaymentTypeSummary(theme, isDesktop),
|
||||
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -363,219 +361,34 @@ class _UserStatisticsPageState extends State<UserStatisticsPage> {
|
||||
|
||||
// Construction du résumé par type de passage
|
||||
Widget _buildPassageTypeSummary(ThemeData theme, bool isDesktop) {
|
||||
// Dans une implémentation réelle, ces données seraient filtrées par secteur
|
||||
// en fonction de _selectedSectorId
|
||||
return Card(
|
||||
elevation: 4,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'Répartition par type de passage',
|
||||
style: theme.textTheme.titleMedium?.copyWith(
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
Row(
|
||||
children: [
|
||||
// Graphique circulaire
|
||||
Expanded(
|
||||
flex: isDesktop ? 1 : 2,
|
||||
child: SizedBox(
|
||||
height: 200,
|
||||
child: PassagePieChart(
|
||||
passagesByType: {
|
||||
1: 60, // Effectués
|
||||
2: 15, // À finaliser
|
||||
3: 10, // Refusés
|
||||
4: 8, // Dons
|
||||
5: 5, // Lots
|
||||
6: 2, // Maisons vides
|
||||
},
|
||||
size: 140,
|
||||
labelSize: 12,
|
||||
showPercentage: true,
|
||||
showIcons: false, // Désactiver les icônes
|
||||
isDonut: true, // Activer le format donut
|
||||
innerRadius: '50%' // Rayon interne du donut
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
// Légende
|
||||
if (isDesktop)
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
_buildLegendItem(
|
||||
'Effectués', '60%', const Color(0xFF4CAF50)),
|
||||
_buildLegendItem(
|
||||
'À finaliser', '15%', const Color(0xFFFF9800)),
|
||||
_buildLegendItem(
|
||||
'Refusés', '10%', const Color(0xFFF44336)),
|
||||
_buildLegendItem('Dons', '8%', const Color(0xFF03A9F4)),
|
||||
_buildLegendItem('Lots', '5%', const Color(0xFF0D47A1)),
|
||||
_buildLegendItem(
|
||||
'Maisons vides', '2%', const Color(0xFF9E9E9E)),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
if (!isDesktop)
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(height: 16),
|
||||
_buildLegendItem('Effectués', '60%', const Color(0xFF4CAF50)),
|
||||
_buildLegendItem(
|
||||
'À finaliser', '15%', const Color(0xFFFF9800)),
|
||||
_buildLegendItem('Refusés', '10%', const Color(0xFFF44336)),
|
||||
_buildLegendItem('Dons', '8%', const Color(0xFF03A9F4)),
|
||||
_buildLegendItem('Lots', '5%', const Color(0xFF0D47A1)),
|
||||
_buildLegendItem(
|
||||
'Maisons vides', '2%', const Color(0xFF9E9E9E)),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
return PassageSummaryCard(
|
||||
title: 'Répartition par type de passage',
|
||||
titleColor: theme.colorScheme.primary,
|
||||
titleIcon: Icons.pie_chart,
|
||||
height: 300,
|
||||
useValueListenable: true,
|
||||
userId: userRepository.getCurrentUser()?.id,
|
||||
showAllPassages: false,
|
||||
excludePassageTypes: const [2], // Exclure "À finaliser"
|
||||
isDesktop: isDesktop,
|
||||
);
|
||||
}
|
||||
|
||||
// Construction du résumé par type de règlement
|
||||
Widget _buildPaymentTypeSummary(ThemeData theme, bool isDesktop) {
|
||||
// Dans une implémentation réelle, ces données seraient filtrées par secteur
|
||||
// en fonction de _selectedSectorId
|
||||
return Card(
|
||||
elevation: 4,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'Répartition par type de règlement',
|
||||
style: theme.textTheme.titleMedium?.copyWith(
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
Row(
|
||||
children: [
|
||||
// Graphique circulaire
|
||||
Expanded(
|
||||
flex: isDesktop ? 1 : 2,
|
||||
child: SizedBox(
|
||||
height: 200,
|
||||
child: PieChart(
|
||||
PieChartData(
|
||||
sectionsSpace: 2,
|
||||
centerSpaceRadius: 40,
|
||||
sections: [
|
||||
_buildPieChartSection(
|
||||
'Espèces', 30, const Color(0xFF4CAF50), 0),
|
||||
_buildPieChartSection(
|
||||
'Chèques', 45, const Color(0xFF2196F3), 1),
|
||||
_buildPieChartSection(
|
||||
'CB', 25, const Color(0xFFF44336), 2),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
// Légende
|
||||
if (isDesktop)
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
_buildLegendItem(
|
||||
'Espèces', '30%', const Color(0xFF4CAF50)),
|
||||
_buildLegendItem(
|
||||
'Chèques', '45%', const Color(0xFF2196F3)),
|
||||
_buildLegendItem('CB', '25%', const Color(0xFFF44336)),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
if (!isDesktop)
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(height: 16),
|
||||
_buildLegendItem('Espèces', '30%', const Color(0xFF4CAF50)),
|
||||
_buildLegendItem('Chèques', '45%', const Color(0xFF2196F3)),
|
||||
_buildLegendItem('CB', '25%', const Color(0xFFF44336)),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Construction d'une section de graphique circulaire
|
||||
PieChartSectionData _buildPieChartSection(
|
||||
String title, double value, Color color, int index) {
|
||||
return PieChartSectionData(
|
||||
color: color,
|
||||
value: value,
|
||||
title: '$value%',
|
||||
radius: 60,
|
||||
titleStyle: const TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.white,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Construction d'un élément de légende
|
||||
Widget _buildLegendItem(String title, String value, Color color) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(bottom: 8.0),
|
||||
child: Row(
|
||||
children: [
|
||||
Container(
|
||||
width: 16,
|
||||
height: 16,
|
||||
decoration: BoxDecoration(
|
||||
color: color,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Text(
|
||||
title,
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
Text(
|
||||
value,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: color,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
Widget _buildPaymentTypeSummary(ThemeData theme, bool isDesktop) {
|
||||
return PaymentSummaryCard(
|
||||
title: 'Répartition par type de règlement',
|
||||
titleColor: AppTheme.accentColor,
|
||||
titleIcon: Icons.pie_chart,
|
||||
height: 300,
|
||||
useValueListenable: true,
|
||||
userId: userRepository.getCurrentUser()?.id,
|
||||
showAllPayments: false,
|
||||
isDesktop: isDesktop,
|
||||
backgroundIcon: Icons.euro_symbol,
|
||||
backgroundIconColor: Colors.blue,
|
||||
backgroundIconOpacity: 0.05,
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,22 +1,20 @@
|
||||
import 'dart:convert';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_map/flutter_map.dart';
|
||||
import 'package:geosector_app/core/data/models/amicale_model.dart';
|
||||
import 'package:geosector_app/core/repositories/user_repository.dart';
|
||||
import 'package:geosector_app/core/repositories/region_repository.dart';
|
||||
import 'package:geosector_app/core/services/api_service.dart';
|
||||
import 'package:geosector_app/presentation/widgets/mapbox_map.dart';
|
||||
import 'package:latlong2/latlong.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'custom_text_field.dart';
|
||||
|
||||
class EntiteForm extends StatefulWidget {
|
||||
class AmicaleForm extends StatefulWidget {
|
||||
final AmicaleModel? amicale;
|
||||
final Function(AmicaleModel)? onSubmit;
|
||||
final bool readOnly;
|
||||
|
||||
const EntiteForm({
|
||||
const AmicaleForm({
|
||||
Key? key,
|
||||
this.amicale,
|
||||
this.onSubmit,
|
||||
@@ -24,10 +22,10 @@ class EntiteForm extends StatefulWidget {
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<EntiteForm> createState() => _EntiteFormState();
|
||||
State<AmicaleForm> createState() => _AmicaleFormState();
|
||||
}
|
||||
|
||||
class _EntiteFormState extends State<EntiteForm> {
|
||||
class _AmicaleFormState extends State<AmicaleForm> {
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
|
||||
// Controllers
|
||||
@@ -52,9 +50,6 @@ class _EntiteFormState extends State<EntiteForm> {
|
||||
bool _chkActive = true;
|
||||
bool _chkStripe = false;
|
||||
|
||||
// Liste des régions (sera chargée depuis le store)
|
||||
List<Map<String, dynamic>> _regions = [];
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
@@ -81,36 +76,6 @@ class _EntiteFormState extends State<EntiteForm> {
|
||||
_chkAcceptSms = amicale?.chkAcceptSms ?? false;
|
||||
_chkActive = amicale?.chkActive ?? true;
|
||||
_chkStripe = amicale?.chkStripe ?? false;
|
||||
|
||||
// Charger les régions depuis le repository
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
_loadRegions();
|
||||
});
|
||||
}
|
||||
|
||||
void _loadRegions() {
|
||||
try {
|
||||
final regionRepository =
|
||||
Provider.of<RegionRepository>(context, listen: false);
|
||||
if (!regionRepository.isLoaded) {
|
||||
// Initialiser le repository si ce n'est pas déjà fait
|
||||
regionRepository.init().then((_) {
|
||||
setState(() {
|
||||
_regions = regionRepository.getRegionsForDropdown();
|
||||
});
|
||||
});
|
||||
} else {
|
||||
setState(() {
|
||||
_regions = regionRepository.getRegionsForDropdown();
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
debugPrint('Erreur lors du chargement des régions: $e');
|
||||
// Utiliser une liste vide en cas d'erreur
|
||||
setState(() {
|
||||
_regions = [];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -130,7 +95,7 @@ class _EntiteFormState extends State<EntiteForm> {
|
||||
}
|
||||
|
||||
// Appeler l'API pour mettre à jour l'entité
|
||||
Future<void> _updateEntite(AmicaleModel amicale) async {
|
||||
Future<void> _updateAmicale(AmicaleModel amicale) async {
|
||||
try {
|
||||
// Afficher un indicateur de chargement
|
||||
showDialog(
|
||||
@@ -175,7 +140,7 @@ class _EntiteFormState extends State<EntiteForm> {
|
||||
try {
|
||||
// Obtenir l'instance du service API
|
||||
final apiService = Provider.of<ApiService>(context, listen: false);
|
||||
|
||||
|
||||
// Appeler la méthode post du service API
|
||||
await apiService.post('/entite/update', data: data);
|
||||
|
||||
@@ -185,7 +150,7 @@ class _EntiteFormState extends State<EntiteForm> {
|
||||
// Afficher un message de succès
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
content: Text('Entité mise à jour avec succès'),
|
||||
content: Text('Amicale mise à jour avec succès'),
|
||||
backgroundColor: Colors.green,
|
||||
),
|
||||
);
|
||||
@@ -204,7 +169,8 @@ class _EntiteFormState extends State<EntiteForm> {
|
||||
// Afficher un message d'erreur
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text('Erreur lors de la mise à jour de l\'entité: $error'),
|
||||
content:
|
||||
Text('Erreur lors de la mise à jour de l\'amicale: $error'),
|
||||
backgroundColor: Colors.red,
|
||||
),
|
||||
);
|
||||
@@ -277,8 +243,8 @@ class _EntiteFormState extends State<EntiteForm> {
|
||||
chkActive: _chkActive,
|
||||
);
|
||||
|
||||
// Appeler l'API pour mettre à jour l'entité
|
||||
_updateEntite(amicale);
|
||||
// Appeler l'API pour mettre à jour l'amicale
|
||||
_updateAmicale(amicale);
|
||||
|
||||
// Appeler la fonction onSubmit si elle existe (pour la compatibilité avec le code existant)
|
||||
if (widget.onSubmit != null) {
|
||||
@@ -391,8 +357,8 @@ class _EntiteFormState extends State<EntiteForm> {
|
||||
width: 20,
|
||||
height: 20,
|
||||
child: const Icon(
|
||||
Icons.location_on,
|
||||
color: Color(0xFF20335E),
|
||||
Icons.fireplace_rounded,
|
||||
color: Color.fromARGB(255, 212, 34, 31),
|
||||
size: 20,
|
||||
),
|
||||
),
|
||||
@@ -424,6 +390,72 @@ class _EntiteFormState extends State<EntiteForm> {
|
||||
);
|
||||
}
|
||||
|
||||
// Construire le dropdown pour la région
|
||||
Widget _buildRegionDropdown(bool restrictedFieldsReadOnly) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// Afficher le libellé de la région en lecture seule
|
||||
if (_libRegion != null && _libRegion!.isNotEmpty)
|
||||
Container(
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 16),
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).inputDecorationTheme.fillColor,
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
),
|
||||
child: Text(
|
||||
_libRegion!,
|
||||
style: Theme.of(context).textTheme.bodyLarge?.copyWith(
|
||||
color: Theme.of(context).colorScheme.onSurface,
|
||||
),
|
||||
),
|
||||
)
|
||||
else
|
||||
Container(
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 16),
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).inputDecorationTheme.fillColor,
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
),
|
||||
child: Text(
|
||||
'Aucune région définie',
|
||||
style: Theme.of(context).textTheme.bodyLarge?.copyWith(
|
||||
color: Theme.of(context).hintColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
// Construire une option checkbox
|
||||
Widget _buildCheckboxOption({
|
||||
required String label,
|
||||
required bool value,
|
||||
required void Function(bool?)? onChanged,
|
||||
}) {
|
||||
return Row(
|
||||
children: [
|
||||
Checkbox(
|
||||
value: value,
|
||||
onChanged: onChanged,
|
||||
activeColor: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
Expanded(
|
||||
child: Text(
|
||||
label,
|
||||
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
||||
color: Theme.of(context).colorScheme.onBackground,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
// Construire le formulaire principal
|
||||
Widget _buildMainForm(ThemeData theme, bool restrictedFieldsReadOnly) {
|
||||
return Column(
|
||||
@@ -887,4 +919,46 @@ class _EntiteFormState extends State<EntiteForm> {
|
||||
widget.readOnly || !canEditRestrictedFields;
|
||||
|
||||
// Calculer la largeur maximale du formulaire pour les écrans larges
|
||||
final screenWidth = MediaQuery.of(context
|
||||
final screenWidth = MediaQuery.of(context).size.width;
|
||||
final maxFormWidth = screenWidth > 800 ? 800.0 : screenWidth;
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(
|
||||
widget.readOnly ? 'Détails de l\'amicale' : 'Modifier l\'amicale'),
|
||||
backgroundColor: theme.appBarTheme.backgroundColor,
|
||||
foregroundColor: theme.appBarTheme.foregroundColor,
|
||||
),
|
||||
body: Center(
|
||||
child: Container(
|
||||
width: maxFormWidth,
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Form(
|
||||
key: _formKey,
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// Header avec logo et minimap
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
// Section Logo
|
||||
_buildLogoSection(),
|
||||
// Section MiniMap
|
||||
_buildMiniMap(),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
|
||||
// Formulaire principal
|
||||
_buildMainForm(theme, restrictedFieldsReadOnly),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user