528 lines
19 KiB
Dart
528 lines
19 KiB
Dart
import 'package:flutter/cupertino.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
import 'package:jwt_decode/jwt_decode.dart';
|
|
|
|
import '../../../../core/services/api_service.dart';
|
|
import '../../../../data/services/auth_service.dart';
|
|
import '../../../layouts/main_layout.dart';
|
|
import '../../../layouts/responsive_layout.dart';
|
|
import '../../../providers/manager_provider.dart';
|
|
import '../../../providers/userRoleProvider.dart';
|
|
|
|
class ProfilePopUp extends ConsumerStatefulWidget {
|
|
const ProfilePopUp({super.key});
|
|
|
|
@override
|
|
ConsumerState<ProfilePopUp> createState() => ProfilePopUpState();
|
|
}
|
|
|
|
class ProfilePopUpState extends ConsumerState<ProfilePopUp> {
|
|
late ApiService apiService;
|
|
|
|
List<Map<String, dynamic>> filteredIncentiveData = [];
|
|
List<Map<String, dynamic>> getAgentIncentiveFileData = [];
|
|
Map<String, dynamic>? profileData;
|
|
|
|
dynamic roleIdRaw;
|
|
dynamic roleId;
|
|
dynamic role;
|
|
|
|
bool isProfile = true;
|
|
bool isLoading = false;
|
|
String? _token;
|
|
dynamic latestId;
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
apiService = ApiService();
|
|
// getAgentList();
|
|
_initializeToken();
|
|
// Future.microtask(() {
|
|
// final id = ref.read(managerIdProvider);
|
|
// if (id != null) {
|
|
// getAgentList(id);
|
|
//
|
|
// // staff/managerIncentiveFileList?manager_id=1
|
|
// }
|
|
// });
|
|
}
|
|
|
|
Future<void> _initializeToken() async {
|
|
_token = await AuthService.getToken();
|
|
print("profileDataAPISERTOKEN - $_token");
|
|
final Map<String, dynamic> decodedToken = Jwt.parseJwt(_token!);
|
|
setState(() {
|
|
profileData = decodedToken['data'];
|
|
});
|
|
print('profileDatadecodedTokenProfile : $decodedToken');
|
|
print('profileDatadecodedTokenProfile : $profileData');
|
|
|
|
// await getList();
|
|
|
|
Future.microtask(() {
|
|
role = ref.read(userRoleProvider);
|
|
if (role != null) {
|
|
getList();
|
|
}
|
|
});
|
|
}
|
|
|
|
Future<void> getList() async {
|
|
setState(() {
|
|
isLoading = true;
|
|
});
|
|
|
|
roleIdRaw = profileData?['role_id'];
|
|
roleId = roleIdRaw is String ? int.tryParse(roleIdRaw) : roleIdRaw as int?;
|
|
|
|
if (roleId == 1) {
|
|
final managerIdRaw = profileData?['manager_id'];
|
|
final managerId = managerIdRaw is String
|
|
? int.tryParse(managerIdRaw)
|
|
: managerIdRaw as int?;
|
|
if (managerId != null) {
|
|
getIncenctiveFileList(managerId);
|
|
}
|
|
} else if (roleId != 1 && roleId != 2 && roleId != 3) {
|
|
final agentIdRaw = profileData?['id'];
|
|
final agentId = agentIdRaw is String
|
|
? int.tryParse(agentIdRaw)
|
|
: agentIdRaw as int?;
|
|
if (agentId != null) {
|
|
getIncenctiveFileList(agentId);
|
|
}
|
|
}
|
|
|
|
setState(() {
|
|
isLoading = false;
|
|
});
|
|
}
|
|
|
|
Future<void> getIncenctiveFileList(id) async {
|
|
// print('getClaimList agentId - $agentId');
|
|
|
|
setState(() {
|
|
isLoading = true;
|
|
});
|
|
|
|
try {
|
|
final response;
|
|
|
|
final roleIdRaw = profileData?['role_id'];
|
|
final roleId = roleIdRaw is String
|
|
? int.tryParse(roleIdRaw)
|
|
: roleIdRaw as int?;
|
|
if (roleId == 1) {
|
|
response = await apiService.fetchManagerIncentiveList(id);
|
|
} else {
|
|
response = await apiService.fetchAgentIncentiveList(id, type: 'incentive');
|
|
}
|
|
|
|
if (response['status'] == 'success') {
|
|
print('AgentIncentive - ${response['data']}');
|
|
setState(() {
|
|
getAgentIncentiveFileData = List<Map<String, dynamic>>.from(
|
|
response['data'],
|
|
);
|
|
print('API AgentIncentive - $getAgentIncentiveFileData');
|
|
|
|
filteredIncentiveData = List.from(getAgentIncentiveFileData);
|
|
print('originalData - $filteredIncentiveData');
|
|
|
|
// Sort descending by created_on
|
|
filteredIncentiveData.sort((a, b) {
|
|
final dateA =
|
|
DateTime.tryParse(a['created_on'].toString()) ?? DateTime(1970);
|
|
final dateB =
|
|
DateTime.tryParse(b['created_on'].toString()) ?? DateTime(1970);
|
|
return dateB.compareTo(dateA); // newest first
|
|
});
|
|
|
|
// Get the latest ID (from the first element after sorting)
|
|
if (filteredIncentiveData.isNotEmpty) {
|
|
latestId = filteredIncentiveData.first['id'];
|
|
print("Latest incentive id: $latestId");
|
|
}
|
|
|
|
print('sortedData - $filteredIncentiveData');
|
|
});
|
|
} else {
|
|
getAgentIncentiveFileData = [];
|
|
}
|
|
} catch (e) {
|
|
print('Exception occurred: $e');
|
|
} finally {
|
|
setState(() {
|
|
isLoading = false;
|
|
});
|
|
}
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return SelectionArea(
|
|
child:Container(
|
|
padding: const EdgeInsets.all(6),
|
|
width: 450,
|
|
color: Colors.white,
|
|
// color: Colors.white,
|
|
child: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
crossAxisAlignment: CrossAxisAlignment.center,
|
|
children: [
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
Text(
|
|
isProfile ? 'My Profile' : 'Incentive Files',
|
|
style: _topheaderStyle,
|
|
),
|
|
Spacer(),
|
|
Container(
|
|
width: 25,
|
|
height: 25,
|
|
decoration: BoxDecoration(
|
|
color: Colors.white,
|
|
// color: const Color(0xFFF1F1F1),
|
|
borderRadius: BorderRadius.circular(10.0),
|
|
),
|
|
child: InkWell(
|
|
borderRadius: BorderRadius.circular(10.0),
|
|
onTap: () {
|
|
Navigator.of(context).pop(); // closes the popup
|
|
},
|
|
child: Tooltip(
|
|
message: 'Close',
|
|
child: const Icon(Icons.close, size: 18),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
|
|
isProfile
|
|
? Container(
|
|
color: Colors.white,
|
|
padding: ResponsiveLayout.isMobile(context)
|
|
? EdgeInsets.all(16.0)
|
|
: null,
|
|
child: isLoading
|
|
? const Center(child: CircularProgressIndicator())
|
|
: Column(
|
|
children: [
|
|
const SizedBox(height: 25),
|
|
Container(
|
|
width: 70,
|
|
height: 70,
|
|
decoration: BoxDecoration(
|
|
// color: Color(0xFFD9D9D9),
|
|
color: Colors.white,
|
|
borderRadius: BorderRadius.circular(30.0),
|
|
),
|
|
child: Icon(
|
|
Icons.person_outline,
|
|
size: 50,
|
|
color: Colors.black,
|
|
),
|
|
),
|
|
const SizedBox(height: 10),
|
|
Text(
|
|
profileData?['name'] ?? '-',
|
|
style: _headerStyle,
|
|
),
|
|
Text(
|
|
(role == 'agent') ? 'partner' : role ?? '-',
|
|
style: TextStyle(
|
|
fontSize: 14,
|
|
fontWeight: FontWeight.w400,
|
|
color: Color(0xFF000000),
|
|
),
|
|
),
|
|
const SizedBox(height: 26),
|
|
if (hasValidValue(profileData?['mobile'])) ...[
|
|
Row(
|
|
children: [
|
|
const Icon(
|
|
Icons.phone_outlined,
|
|
size: 20,
|
|
color: Colors.black,
|
|
),
|
|
const SizedBox(width: 8),
|
|
Text(
|
|
profileData?['mobile'] ?? '-',
|
|
style: _dataBold,
|
|
),
|
|
],
|
|
),
|
|
const SizedBox(height: 8),
|
|
],
|
|
if (hasValidValue(profileData?['email'])) ...[
|
|
Row(
|
|
children: [
|
|
const Icon(
|
|
Icons.email_outlined,
|
|
size: 18,
|
|
color: Colors.black,
|
|
),
|
|
const SizedBox(width: 8),
|
|
Text(
|
|
profileData?['email'] ?? '-',
|
|
style: _dataBold,
|
|
),
|
|
],
|
|
),
|
|
const SizedBox(height: 16),
|
|
],
|
|
|
|
if (hasValidValue(profileData?['address'])) ...[
|
|
if ((roleId != 1) &&
|
|
(roleId != 2) &&
|
|
(roleId != 3)) ...[
|
|
Row(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
const Icon(
|
|
Icons.location_on_outlined,
|
|
size: 18,
|
|
color: Colors.black,
|
|
),
|
|
const SizedBox(width: 8),
|
|
|
|
Expanded(
|
|
child: Text(
|
|
profileData?['address'] ?? '-',
|
|
style: _dataBold,
|
|
softWrap: true,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
const SizedBox(height: 20),
|
|
],
|
|
],
|
|
|
|
if ((roleId == 5)) ...[
|
|
// Staff, Handler doesn't have this part Only Manager and agent have
|
|
Container(
|
|
padding: const EdgeInsets.all(6),
|
|
color: Color(0xffEDF6F5),
|
|
child: GestureDetector(
|
|
onTap: () {
|
|
print("Download - $latestId");
|
|
dynamic path;
|
|
|
|
if (roleId == 1) {
|
|
path =
|
|
'staff/downloadManagerIncentiveFile?id=$latestId';
|
|
} else if (roleId != 1 && roleId != 2) {
|
|
path =
|
|
'agent/downloadAgentIncentiveFile?id=$latestId';
|
|
}
|
|
apiService.getPdfDownload(path, latestId);
|
|
},
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
Icon(Icons.download),
|
|
SizedBox(width: 8),
|
|
Text(
|
|
"Download Incentive file",
|
|
style: _dataSub,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
const SizedBox(height: 10),
|
|
TextButton(
|
|
onPressed: () {
|
|
setState(() {
|
|
isProfile = false;
|
|
});
|
|
},
|
|
child: Text(
|
|
"View Previous Files",
|
|
style: TextStyle(
|
|
color: Color(0xff425B5B),
|
|
decoration: TextDecoration
|
|
.underline, // 👈 underline
|
|
decorationThickness: 1.5,
|
|
),
|
|
),
|
|
),
|
|
],
|
|
const SizedBox(height: 16),
|
|
],
|
|
),
|
|
)
|
|
: Container(
|
|
color: Colors.white,
|
|
padding: ResponsiveLayout.isMobile(context)
|
|
? EdgeInsets.all(16.0)
|
|
: null,
|
|
child: Column(
|
|
children: [
|
|
const SizedBox(height: 10),
|
|
isLoading
|
|
? const Center(child: CircularProgressIndicator())
|
|
: filteredIncentiveData.isEmpty
|
|
? const Center(
|
|
child: Text("No incentive files found"),
|
|
)
|
|
: SizedBox(
|
|
height: ResponsiveLayout.isMobile(context)
|
|
? MediaQuery.of(context).size.height * 0.4
|
|
: 450,
|
|
child: ListView.builder(
|
|
// padding: const EdgeInsets.all(8),
|
|
itemCount: filteredIncentiveData.length,
|
|
itemBuilder: (context, index) {
|
|
final file = filteredIncentiveData[index];
|
|
|
|
return Padding(
|
|
padding: const EdgeInsets.symmetric(
|
|
vertical: 2.0,
|
|
),
|
|
child: IncentiveFileRow(
|
|
fileName:
|
|
file['incentive_file_name'] ??
|
|
"Unknown",
|
|
date: file['incentive_month'] ?? "-",
|
|
onUpload: () {
|
|
print("Upload ${file['id']}");
|
|
final selectedId = file['id'];
|
|
|
|
dynamic path;
|
|
|
|
if (roleId == 1) {
|
|
path =
|
|
'staff/downloadManagerIncentiveFile?id=$selectedId';
|
|
} else if (roleId != 1 && roleId != 2) {
|
|
path =
|
|
'agent/downloadAgentIncentiveFile?id=$selectedId';
|
|
}
|
|
apiService.getPdfDownload(
|
|
path,
|
|
selectedId,
|
|
);
|
|
},
|
|
),
|
|
);
|
|
},
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
));
|
|
}
|
|
|
|
bool hasValidValue(dynamic value) {
|
|
if (value == null) return false;
|
|
if (value is String) return value.trim().isNotEmpty;
|
|
return true; // for numbers, bool, etc.
|
|
}
|
|
|
|
static final _dataBold = TextStyle(
|
|
fontSize: 11.8,
|
|
fontWeight: FontWeight.w400,
|
|
color: Color(0xFF000000),
|
|
);
|
|
|
|
static final _dataSub = TextStyle(
|
|
fontSize: 12,
|
|
fontWeight: FontWeight.w500,
|
|
color: Color(0xFF000000),
|
|
);
|
|
|
|
static const _headerStyle = TextStyle(
|
|
color: Colors.black,
|
|
fontWeight: FontWeight.w700,
|
|
fontSize: 20,
|
|
);
|
|
|
|
static const _topheaderStyle = TextStyle(
|
|
color: Colors.black,
|
|
fontWeight: FontWeight.w600,
|
|
fontSize: 18,
|
|
);
|
|
}
|
|
|
|
class IncentiveFileRow extends StatelessWidget {
|
|
final String fileName;
|
|
final String date;
|
|
final VoidCallback? onUpload;
|
|
// final VoidCallback? onDelete;
|
|
|
|
const IncentiveFileRow({
|
|
super.key,
|
|
required this.fileName,
|
|
required this.date,
|
|
this.onUpload,
|
|
// this.onDelete,
|
|
});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Container(
|
|
padding: const EdgeInsets.symmetric(vertical: 7.0),
|
|
// margin: const EdgeInsets.only(bottom: 5), // spacing between rows
|
|
decoration: BoxDecoration(
|
|
// color: Colors.amber.shade50,
|
|
border: Border(
|
|
bottom: BorderSide(width: 0.6, color: const Color(0xFFE3E3E3)),
|
|
),
|
|
),
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
// crossAxisAlignment: CrossAxisAlignment.center,
|
|
mainAxisSize: MainAxisSize.min,
|
|
|
|
children: [
|
|
Container(
|
|
padding: const EdgeInsets.all(6.0),
|
|
decoration: BoxDecoration(
|
|
color: const Color(0xFFF4F6F8),
|
|
borderRadius: BorderRadius.circular(8.0),
|
|
border: Border.all(color: const Color(0xFFE3E3E3)),
|
|
),
|
|
child: const Icon(Icons.file_present, color: Color(0xFF838587)),
|
|
),
|
|
const SizedBox(width: 10),
|
|
Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
SizedBox(
|
|
width: 100,
|
|
child: Text(
|
|
fileName,
|
|
|
|
style: const TextStyle(
|
|
fontWeight: FontWeight.w600,
|
|
color: Color(0xFF1D1B20),
|
|
),
|
|
overflow: TextOverflow.ellipsis,
|
|
softWrap: true,
|
|
maxLines: 1,
|
|
),
|
|
),
|
|
Text(date, style: const TextStyle(color: Color(0xFF6E6E6E))),
|
|
],
|
|
),
|
|
const Spacer(),
|
|
GestureDetector(
|
|
onTap: onUpload,
|
|
child: const Icon(
|
|
Icons.file_download_outlined,
|
|
color: Color(0xFF6E6E6E),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|