Untitled
unknown
plain_text
a year ago
30 kB
8
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