ts-tat/lib/Screens/plans/list_plans.dart
2025-04-02 15:47:15 +05:30

426 lines
17 KiB
Dart

import 'dart:convert';
import 'dart:core';
import 'package:frontend/data/models/plan.dart';
import 'package:go_router/go_router.dart';
import 'package:http/http.dart' as http;
import 'package:flutter/material.dart';
import 'package:frontend/config/apiUrl.dart';
import 'package:responsive_builder/responsive_builder.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../../routes/custom_appBar.dart';
import '../../routes/custom_drawer.dart';
class ListPlans extends StatefulWidget{
const ListPlans({super.key});
@override
_ListPlansState createState() => _ListPlansState();
}
class _ListPlansState extends State<ListPlans>{
late Future<List<Plan>> futurePlans;
String? userId;
String? token;
@override
void initState(){
super.initState();
getToken();
initializeData();
// futurePlans = fetchPlans();
}
Future<void> initializeData ()async{
token = await getToken();
userId = await getUserId();
if(token == null || userId == null){
print("Token or USerId missing");
return;
}
else{
setState(() {
futurePlans = fetchPlans();
});
}
}
Future<String?> getUserId() async {
final prefs = await SharedPreferences.getInstance();
final String? userDataString = prefs.getString('user_data');
if(userDataString != null){
try{
final Map<String,dynamic> userData = jsonDecode(userDataString);
return userData["user_id"]?.toString();
}catch(e){
return null;
}
}
return null;
}
Future<String?> getToken() async {
final prefs = await SharedPreferences.getInstance();
return prefs.getString('auth_token');
}
// Fetch API Data
Future<List<Plan>> fetchPlans() async {
// final String apiUrldata = '$apiUrl/api/plans';
final String apiUrldata = '$apiUrl/api/plans?user_id=$userId';
// final token = await getToken();
if (token == null) {
throw Exception('Token not found. Please log in.');
}
final response = await http.get(
Uri.parse(apiUrldata),
headers: {
'Authorization': 'Bearer $token', // Add token here
'Content-Type': 'application/json',
},
);
if (response.statusCode == 200) {
final data = json.decode(response.body);
List<dynamic> plansJson = data['data'];
return plansJson.map((json) => Plan.fromJson(json)).toList();
} else {
throw Exception('Failed to load plans');
}
}
Future <Map<String,dynamic>> getViewPlan(String planId) async{
final String apiUrldata = '$apiUrl/api/plans/find/$planId';
print("API URL: $apiUrldata");
// final token = await getToken();
if (token == null) {
throw Exception('Token not found. Please log in.');
}
final response = await http.put(
Uri.parse(apiUrldata),
headers: {
'Authorization': 'Bearer $token', // Add token here
'Content-Type': 'application/json',
},
);
if (response.statusCode == 200) {
final Map<String,dynamic>? resData = json.decode(response.body);
return resData?["data"];
} else {
throw Exception('Failed to load plans');
}
}
void viewPlan(String planId, {bool isViewMode = false}) async{
try {
Map<String, dynamic> planData = await getViewPlan(planId);
print("ViewAAA - $planData");
context.go('/createPlan',extra: {'planData': planData, 'isViewMode': isViewMode} );
} catch (e) {
print("Error fetching plan: $e");
}
}
Widget build(BuildContext context) {
return ResponsiveBuilder(builder: (context, sizingInfo) {
bool isDesktop = sizingInfo.deviceScreenType == DeviceScreenType.desktop;
return Scaffold(
backgroundColor: Colors.white,
appBar: isDesktop ? null : const CustomAppBar(title: 'Home'),
drawer: isDesktop ? null : CustomDrawer(isDesktop: false),
body: Row(
children: [
if (isDesktop) CustomDrawer(isDesktop: true),
Expanded(child: buildTableLayout(isDesktop))
],
),
);
});
}
Widget buildTableLayout(isDesktop) {
return Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
const Text('Plans List',
style:
TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
IconButton(
icon: const Icon(Icons.keyboard_arrow_down),
onPressed: () {},
),
],
),
ElevatedButton(
style: ElevatedButton.styleFrom(
foregroundColor: Colors.white,
backgroundColor: Colors.blueAccent),
onPressed: () {
context.go('/createPlan');
if (!isDesktop) Navigator.pop(context);
},
child: Row(
children: [
Icon(Icons.add_circle,color: Colors.white,),
SizedBox(width: 5,),
Text('NewPlan'),
],
),
),
],
),
const SizedBox(height: 10),
FutureBuilder<List<Plan>>(
future: futurePlans, // Use the futurePlans variable
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(child: CircularProgressIndicator());
} else if (snapshot.hasError) {
return Center(child: Text("Error: ${snapshot.error}"));
} else if (!snapshot.hasData || snapshot.data!.isEmpty) {
return const Center(child: Text("No plans available"));
}
List<Plan> plans = snapshot.data!; // Extract the list of plans
// Ensure planId is sorted in descending order
plans.sort((a, b) => int.parse(b.planId.toString()).compareTo(int.parse(a.planId.toString())));
// return ResponsiveBuilder(
// builder: (context, sizingInfo) {
// bool isTabletOrDesktop = sizingInfo.isTablet || sizingInfo.isDesktop;
//
// return SingleChildScrollView(
// scrollDirection: Axis.horizontal,
// child: Container(
// color: Colors.grey,
// child: SizedBox(
// width: MediaQuery.of(context).size.width ,
// child: SingleChildScrollView(
// scrollDirection: Axis.vertical,
// // scrollDirection: isTabletOrDesktop ? Axis.vertical : Axis.horizontal,
//
// // constraints: isTabletOrDesktop
// // ? const BoxConstraints(maxWidth: double.infinity)
// // : BoxConstraints.tightFor(width: 600),
//
//
// child: DataTable(
// // columnSpacing: 50.0,
// dividerThickness: 0.5, // Reduce the thickness of row dividers
// border: TableBorder(
// horizontalInside: BorderSide(width: 0.5, color: Colors.grey.shade200), // Reduce horizontal line thickness
// ),
// columns: const [
// DataColumn(label: Text('Plan ID', style: TextStyle(color: Colors.grey, fontWeight: FontWeight.bold,))),
// DataColumn(label: Text('Trip Title', style: TextStyle(color: Colors.grey, fontWeight: FontWeight.bold,))),
// DataColumn(label: Text('Trip Type', style: TextStyle(color: Colors.grey, fontWeight: FontWeight.bold,))),
// DataColumn(label: Text('Cost Center', style: TextStyle(color: Colors.grey, fontWeight: FontWeight.bold,))),
// // DataColumn(label: Text('Functional Department', style: TextStyle(color: Colors.grey, fontWeight: FontWeight.bold,))),
// // DataColumn(label: Text('Purpose Of Travel', style: TextStyle(color: Colors.grey, fontWeight: FontWeight.bold,))),
// // DataColumn(label: Text('Description', style: TextStyle(color: Colors.grey, fontWeight: FontWeight.bold,))),
// //
// DataColumn(label: Text('Is Billable', style: TextStyle(color: Colors.grey, fontWeight: FontWeight.bold,))),
// DataColumn(label: Text('Status', style: TextStyle(color: Colors.grey, fontWeight: FontWeight.bold,))),
// DataColumn(label: Text('Actions', style: TextStyle(color: Colors.grey, fontWeight: FontWeight.bold,))),
// ],
// rows: plans.map((plan) {
// return DataRow(cells: [
// DataCell(Text(plan.planId)),
// // DataCell(Text(plan.tripTitle)),
// DataCell(Row(
// children: [
// Flexible(
// child: Text(
// plan.tripTitle,
// softWrap: true,
// overflow: TextOverflow.ellipsis, // Adds "..." if text is too long
// ),
// ),
// ],
// )),
//
//
// DataCell(Text(plan.tripType)),
// DataCell(Text(plan.costCenter)),
// // DataCell(Text(plan.functionalDepartment)),
// // DataCell(Text(plan.purposeOfTravel)),
// // DataCell(Text(plan.description)),
// //
// DataCell(Text(plan.isBillable)),
// DataCell(Text(plan.status)),
// DataCell(
// TextButton(
// onPressed: () {
// viewPlan(plan.planId);
// print("View button clicked for ${plan.planId}");
// },
// child: const Text('View',
// style: TextStyle(color: Colors.blueAccent)),
// ),
// ),
// ]);
// }).toList(),
// ),
//
//
// ),
// ),
// ),
// );
//
// },
// );
return Expanded(
child: SingleChildScrollView(
// scrollDirection: Axis.horizontal, // Outer wrapper for horizontal scrolling
scrollDirection: Axis.vertical,
child: SizedBox(
width: MediaQuery.of(context).size.width * 1.5,
// width: MediaQuery.of(context).size.width , // Ensure table is wider than screen
// width: double.infinity , // Ensure table is wider than screen
child: SingleChildScrollView(
// scrollDirection: Axis.vertical, // Inner wrapper for vertical scrolling
scrollDirection: Axis.horizontal, // Inner wrapper for vertical scrolling
child: ConstrainedBox(
constraints: BoxConstraints(minWidth: 1300),
// width: MediaQuery.of(context).size.width ,
child: Container(
// color: Colors.amber,
child: DataTable(
columnSpacing: 50.0, // Adjust spacing between columns
dividerThickness: 0.5,
border: TableBorder(
horizontalInside: BorderSide(width: 0.5, color: Colors.grey.shade200),
),
columns: const [
DataColumn(label: Text('Plan ID', style: TextStyle(fontWeight: FontWeight.bold))),
DataColumn(label: Text('Trip Title', style: TextStyle(fontWeight: FontWeight.bold))),
DataColumn(label: Text('Trip Type', style: TextStyle(fontWeight: FontWeight.bold))),
DataColumn(label: Text('Cost Center', style: TextStyle(fontWeight: FontWeight.bold))),
DataColumn(label: Text('Is Billable', style: TextStyle(fontWeight: FontWeight.bold))),
DataColumn(label: Text('Status', style: TextStyle(fontWeight: FontWeight.bold))),
DataColumn(label: Text('Actions', style: TextStyle(fontWeight: FontWeight.bold))),
],
rows: plans.map((plan) {
return DataRow(cells: [
DataCell(Text(plan.planId)),
DataCell(Text(plan.tripTitle, softWrap: true, overflow: TextOverflow.ellipsis)),
DataCell(Text(plan.tripType)),
DataCell(Text(plan.costCenter)),
DataCell(Text(plan.isBillable)),
DataCell(
Container(
padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 10), // Padding for better look
decoration: BoxDecoration(
color: plan.status == "Active" ? Colors.green.shade50 : Colors.grey.shade50, // Background color
borderRadius: BorderRadius.circular(10), // Rounded corners
),
child: Text(
plan.status,
style: TextStyle(
color: plan.status == "Active" ? Colors.green : Colors.grey, // Text color
fontWeight: FontWeight.bold, // Optional: Make text bold
),
),
),
),
DataCell(
Row(
children:[
IconButton(
icon: Icon(Icons.remove_red_eye, color: Colors.blue),
onPressed: () {
viewPlan(plan.planId, isViewMode: true);
},
),
IconButton(
icon: Icon(Icons.edit, color: Colors.green),
onPressed: () {
viewPlan(plan.planId, isViewMode: false);
},
),
// IconButton(
// icon: Icon(Icons.delete, color: Colors.red),
// onPressed: () {
// deletePlan(plan.planId);
// },
// ),
]
)
),
]);
}).toList(),
),
),
),
),
),
),
);
},
),
],
),
);
}
}