Untitled
unknown
plain_text
a year ago
30 kB
11
Indexable
import 'dart:io';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:iskylarpm/controllers/auth_services.dart';
import 'package:iskylarpm/models/clientModel.dart';
import 'package:iskylarpm/theme/apptheme.dart';
import 'package:datetime_picker_formfield/datetime_picker_formfield.dart';
import 'package:iskylarpm/theme/common_snackbar.dart';
import 'package:iskylarpm/utils/show_snackbar.dart';
import 'package:iskylarpm/views/client_pages/allClient.dart';
import 'package:provider/provider.dart';
import '../../models/userProviders.dart';
class AddProjectScreen extends StatefulWidget {
const AddProjectScreen({super.key});
@override
State<AddProjectScreen> createState() => _AddProjectScreenState();
}
class _AddProjectScreenState extends State<AddProjectScreen> {
List<TextEditingController> amountControllers = [];
List<TextEditingController> detailsControllers = [];
List<bool> showButton = [];
File? uploadDoc1;
File? uploadDoc2;
File? uploadDoc3;
File? uploadDoc4;
Future<void> pickedFile(int i) async {
var result = await FilePicker.platform.pickFiles(
allowMultiple: false,
);
if (result != null) {
setState(() {
if (i == 1) {
uploadDoc1 = File(result.files[0].path!);
} else if (i == 2) {
uploadDoc2 = File(result.files[0].path!);
} else if (i == 3) {
uploadDoc3 = File(result.files[0].path!);
} else if (i == 4) {
uploadDoc4 = File(result.files[0].path!);
}
});
} else {
showSnackBar(context, 'No File Selected');
}
}
final format = DateFormat("yyyy-MM-dd");
final _formKey = GlobalKey<FormState>();
final GlobalKey<ScaffoldState> sKey = GlobalKey<ScaffoldState>();
String selectedValue = '';
String selectedProject = 'Active';
String selectedBilling = 'Fixed Cost';
final List<String> items = [
"Active",
"Completed",
"Cancelled",
"On hold",
"Upcoming",
"Pending",
"Overdue",
"Not started",
"Priority",
];
final List<String> billing = ['Fixed Cost', 'Hourly', 'Monthly'];
final TextEditingController _startDateController = TextEditingController();
final TextEditingController _nameController = TextEditingController();
final TextEditingController _descController = TextEditingController();
final TextEditingController _totalAmountController = TextEditingController();
AuthService authService = AuthService();
Future<void> projectAdd({
required String projectDate,
required String projectName,
required String description,
required String client,
required String projectStatus,
required String totalAmount,
required String billingMethod,
required List<Map<String, String>> milestoneDetails,
required String userId,
File? document1,
File? document2,
File? document3,
File? document4,
}) async {
await authService.addproject(
context: context,
projectDate: projectDate,
projectName: projectName,
description: description,
client: client,
projectStatus: projectStatus,
totalAmount: totalAmount,
billingMethod: billingMethod,
milestoneDetails: milestoneDetails,
userId: userId,
documents1: document1,
documents2: document2,
documents3: document3,
documents4: document4,
);
}
bool isLoading = true;
Map<String, List<ClientModel>>? allClients;
Future<void> getAllClient() async {
if (!isLoading) {
setState(() {
isLoading = true;
});
}
allClients = await authService.getClient(context: context);
if (allClients == null) {
showSnackBar(context, 'Something went wrong. Try again!');
} else {
setState(() {
isLoading = false;
});
}
}
List<String> clients = [];
final List<Widget> rows = [];
@override
void initState() {
super.initState();
getAllClient();
addRow();
}
@override
Widget build(BuildContext context) {
var user = Provider.of<UserProvider>(context).user;
var mediaQuery = MediaQuery.of(context);
double height = mediaQuery.size.height;
double width = mediaQuery.size.width;
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
scrolledUnderElevation: 0,
backgroundColor: Colors.white,
leading: BackButton(),
title: Text(
'Add Project',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.w500),
),
),
body: SafeArea(
child: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 5),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: height * 0.02),
Text(
'Basic Information',
style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500),
),
Padding(
padding: const EdgeInsets.only(top: 15),
child: RichText(
text: TextSpan(
children: [
TextSpan(
text: "Project start date",
style: TextStyle(
color: Colors.grey.shade500,
fontSize: 15.0,
),
),
WidgetSpan(
alignment: PlaceholderAlignment.top,
child: Icon(
Icons.star,
color: Colors.red,
size: 8,
),
),
],
),
),
),
SizedBox(height: 5),
Container(
height: height * 0.05,
width: width,
decoration: BoxDecoration(
border: Border.all(color: Colors.grey.shade400),
borderRadius: BorderRadius.circular(5),
),
child: DateTimeField(
controller: _startDateController,
decoration: const InputDecoration(
contentPadding:
EdgeInsets.symmetric(horizontal: 10, vertical: 10),
suffixIcon: Icon(
Icons.calendar_today,
color: Colors.grey,
),
hintStyle: TextStyle(
color: Color(0xFFB7798B),
fontWeight: FontWeight.w500,
fontSize: 15,
),
border: InputBorder.none,
),
format: format,
onShowPicker: (context, currentValue) {
return showDatePicker(
context: context,
firstDate: DateTime(1900),
initialDate: currentValue ?? DateTime.now(),
lastDate: DateTime(2100),
);
},
),
),
SizedBox(height: 20),
RichText(
text: TextSpan(
children: [
TextSpan(
text: "Project name",
style: TextStyle(
color: Colors.grey.shade500,
fontSize: 15.0,
),
),
WidgetSpan(
alignment: PlaceholderAlignment.top,
child: Icon(
Icons.star,
color: Colors.red,
size: 8,
),
),
],
),
),
SizedBox(height: 5),
SizedBox(
height: height * 0.05,
child: Form(
key: _formKey,
child: TextFormField(
controller: _nameController,
validator: (value) {
if (value!.isEmpty) {
return 'Please enter project name';
}
return null;
},
cursorColor: Colors.grey,
decoration: InputDecoration(
contentPadding: EdgeInsets.only(left: 10),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(5),
borderSide: BorderSide(color: Colors.grey),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(5),
borderSide: BorderSide(color: Colors.grey),
),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(5),
borderSide: BorderSide(color: Colors.grey),
),
),
),
),
),
SizedBox(height: 20),
Text(
'Description',
style: TextStyle(
color: Colors.grey.shade500,
fontSize: 15.0,
),
),
SizedBox(height: 5),
TextField(
controller: _descController,
maxLines: 4,
decoration: InputDecoration(
contentPadding:
EdgeInsets.symmetric(horizontal: 10, vertical: 10),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(5),
borderSide: BorderSide(color: Colors.grey),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(5),
borderSide: BorderSide(color: Colors.grey),
),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(5),
borderSide: BorderSide(color: Colors.grey),
),
),
),
SizedBox(height: 20),
Text(
'Client',
style: TextStyle(
color: Colors.grey.shade500,
fontSize: 15.0,
),
),
SizedBox(height: 5),
Container(
height: height * 0.05,
width: width,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5),
border: Border.all(color: Colors.grey.shade400),
),
child: DropdownButtonHideUnderline(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 10),
child: DropdownButton<String>(
dropdownColor: Colors.white,
value: selectedValue,
onChanged: (String? newValue) {
setState(() {
selectedValue = newValue!;
});
},
items: clients
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
),
),
),
),
SizedBox(height: 20),
Text(
'Project Status',
style: TextStyle(
color: Colors.grey.shade500,
fontSize: 15.0,
),
),
SizedBox(height: 5),
Container(
height: height * 0.05,
width: width,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5),
border: Border.all(color: Colors.grey.shade400),
),
child: DropdownButtonHideUnderline(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 10),
child: DropdownButton<String>(
dropdownColor: Colors.white,
value: selectedProject,
onChanged: (String? newValue) {
setState(() {
selectedProject = newValue!;
});
},
items: items.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
),
),
),
),
SizedBox(height: 30),
Text(
'Billing',
style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500),
),
SizedBox(height: 10),
Text(
'Total amount',
style: TextStyle(
color: Colors.grey.shade500,
fontSize: 15.0,
),
),
SizedBox(height: 5),
Container(
height: height * 0.06,
width: width,
decoration: BoxDecoration(
border: Border.all(
color: Colors.grey.shade400,
),
borderRadius: BorderRadius.circular(8.0),
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.only(left: 15),
child: Text(
'INR',
style: TextStyle(fontSize: 16.0),
),
),
SizedBox(width: 8.0),
Text(
"|",
style: TextStyle(fontSize: 25, color: Colors.grey),
),
Expanded(
child: TextField(
controller: _totalAmountController,
cursorColor: Colors.grey,
keyboardType: TextInputType.number,
decoration: InputDecoration(
alignLabelWithHint: true,
contentPadding: EdgeInsets.only(left: 10),
hintText: 'Enter amount',
hintStyle: TextStyle(color: Colors.grey),
border: InputBorder.none,
),
),
),
],
),
),
SizedBox(height: 20),
Text(
'BILLING METHOD',
style: TextStyle(
color: Colors.grey.shade500,
fontSize: 15.0,
),
),
SizedBox(height: 5),
Container(
height: height * 0.05,
width: width,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5),
border: Border.all(color: Colors.grey.shade400),
),
child: DropdownButtonHideUnderline(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 10),
child: DropdownButton<String>(
dropdownColor: Colors.white,
value: selectedBilling,
onChanged: (String? newValue) {
setState(() {
selectedBilling = newValue!;
});
},
items:
billing.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
),
),
),
),
SizedBox(height: 20),
Text(
'MILESTONE DETAIL',
style: TextStyle(
color: Colors.grey.shade500,
fontSize: 15.0,
),
),
SizedBox(height: 10),
Column(
children: [
...rows,
SizedBox(height: height * 0.02),
Row(
children: [
SizedBox(
width: width * 0.37,
height: height * 0.05,
child: TextField(
controller: amountControllers.isNotEmpty
? amountControllers.last
: TextEditingController(),
cursorColor: Colors.grey,
keyboardType: TextInputType.number,
decoration: InputDecoration(
contentPadding: EdgeInsets.only(left: 10),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(5),
borderSide: BorderSide(color: Colors.grey),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(5),
borderSide: BorderSide(color: Colors.grey),
),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(5),
borderSide: BorderSide(color: Colors.grey),
),
alignLabelWithHint: true,
hintText: 'Enter amount',
hintStyle: TextStyle(color: Colors.grey),
),
),
),
SizedBox(width: 20),
SizedBox(
width: width * 0.4,
height: height * 0.05,
child: TextField(
controller: detailsControllers.isNotEmpty
? detailsControllers.last
: TextEditingController(),
cursorColor: Colors.grey,
decoration: InputDecoration(
contentPadding: EdgeInsets.only(left: 10),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(5),
borderSide: BorderSide(color: Colors.grey),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(5),
borderSide: BorderSide(color: Colors.grey),
),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(5),
borderSide: BorderSide(color: Colors.grey),
),
alignLabelWithHint: true,
hintStyle: TextStyle(color: Colors.grey),
),
),
),
IconButton(
onPressed: addRow,
icon: Icon(Icons.add_circle_outline),
color: AppTheme.primaryColor,
),
],
),
],
),
SizedBox(height: height * 0.03),
Text(
'DOCUMENT',
style: TextStyle(
color: Colors.grey.shade500,
fontSize: 15.0,
),
),
SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
buildDocumentUploadButton(1, uploadDoc1, width, height),
buildDocumentUploadButton(2, uploadDoc2, width, height),
],
),
SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
buildDocumentUploadButton(3, uploadDoc3, width, height),
buildDocumentUploadButton(4, uploadDoc4, width, height),
],
),
SizedBox(height: height * 0.03),
SizedBox(height: height * 0.02),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
buildActionButton('Cancel', AppTheme.primaryColor, () {
Navigator.pop(context);
}, width, height),
buildActionButton('Save', Colors.white, () async {
showProgressIndicator(context);
List<Map<String, String>> milestoneDetails = [];
for (int i = 0; i < amountControllers.length; i++) {
milestoneDetails.add({
'amount': amountControllers[i].text,
'details': detailsControllers[i].text,
});
}
await projectAdd(
projectDate: _startDateController.text,
projectName: _nameController.text,
description: _descController.text,
client: selectedValue.toString(),
projectStatus: selectedProject.toString(),
totalAmount: _totalAmountController.text,
billingMethod: selectedBilling.toString(),
milestoneDetails: milestoneDetails,
userId: user.id!,
document1: uploadDoc1,
document2: uploadDoc2,
document3: uploadDoc3,
document4: uploadDoc4,
);
}, width, height, AppTheme.primaryColor),
],
),
SizedBox(height: 15),
],
),
),
),
),
);
}
void addRow() {
setState(() {
TextEditingController amountController = TextEditingController();
TextEditingController detailsController = TextEditingController();
amountControllers.add(amountController);
detailsControllers.add(detailsController);
rows.add(
Column(
children: [
SizedBox(height: 10),
Row(
children: [
buildMilestoneTextField(amountController, 'Enter amount'),
SizedBox(width: 20),
buildMilestoneTextField(detailsController, 'Enter details'),
IconButton(
onPressed: () {
removeRow(amountControllers.length - 1);
},
icon: Icon(Icons.remove_circle_outline),
color: Colors.red,
),
if (amountControllers.length == rows.length)
IconButton(
onPressed: addRow,
icon: Icon(Icons.add_circle_outline),
color: AppTheme.primaryColor,
),
],
),
],
),
);
});
}
void removeRow(int index) {
setState(() {
if (index < amountControllers.length) {
amountControllers[index].dispose();
detailsControllers[index].dispose();
amountControllers.removeAt(index);
detailsControllers.removeAt(index);
rows.removeAt(index);
if (amountControllers.isEmpty) {
addRow();
}
}
});
}
Widget buildDocumentUploadButton(
int docNumber, File? uploadDoc, double width, double height) {
return InkWell(
onTap: () {
showModalBottomSheet(
context: context,
builder: (BuildContext context) {
return Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20),
topRight: Radius.circular(20),
),
),
width: width,
height: height * .12,
padding: EdgeInsets.all(16.0),
child: CircleAvatar(
radius: 25,
backgroundColor: Colors.grey.shade300,
child: IconButton(
onPressed: () async {
Navigator.of(context).pop();
await pickedFile(docNumber);
},
icon: Icon(
Icons.filter,
color: AppTheme.primaryColor,
),
),
),
);
},
);
},
child: Container(
height: height * 0.05,
width: width * 0.4,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5),
color: AppTheme.primaryColor,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.upload,
color: Colors.white,
size: 15,
),
SizedBox(width: 10),
Text(
uploadDoc != null
? uploadDoc.path.split('/').last
: 'Upload Document',
style: TextStyle(color: Colors.white, fontSize: 10),
),
],
),
),
);
}
Widget buildActionButton(String label, Color textColor, VoidCallback onTap,
double width, double height, Color? backgroundColor) {
return InkWell(
onTap: onTap,
child: Container(
height: height * 0.05,
width: width * 0.37,
decoration: BoxDecoration(
color: backgroundColor ?? Colors.transparent,
borderRadius: BorderRadius.circular(5),
border: backgroundColor == null
? Border.all(color: textColor)
: Border.all(color: Colors.transparent),
),
child: Center(
child: Text(
label,
style: TextStyle(
color: textColor,
),
),
),
),
);
}
Widget buildMilestoneTextField(
TextEditingController controller, String hintText) {
return Expanded(
child: TextField(
controller: controller,
cursorColor: Colors.grey,
decoration: InputDecoration(
contentPadding: EdgeInsets.only(left: 10),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(5),
borderSide: BorderSide(color: Colors.grey),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(5),
borderSide: BorderSide(color: Colors.grey),
),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(5),
borderSide: BorderSide(color: Colors.grey),
),
alignLabelWithHint: true,
hintText: hintText,
hintStyle: TextStyle(color: Colors.grey),
),
),
);
}
}
Editor is loading...
Leave a Comment