Untitled
unknown
plain_text
9 months ago
38 kB
6
Indexable
import 'dart:io'; import 'package:datetime_picker_formfield/datetime_picker_formfield.dart'; import 'package:file_picker/file_picker.dart'; import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; import 'package:provider/provider.dart'; import '../../controllers/auth_services.dart'; import '../../models/clientModel.dart'; import '../../models/userProviders.dart'; import '../../theme/apptheme.dart'; import '../../theme/common_snackbar.dart'; import '../../utils/show_snackbar.dart'; import '../client_pages/allClient.dart'; class AddProjectScreen extends StatefulWidget { const AddProjectScreen({super.key}); @override State<AddProjectScreen> createState() => _AddProjectScreenState(); } class _AddProjectScreenState extends State<AddProjectScreen> { List<TextEditingController> amount = []; List<TextEditingController> details = []; 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 String amount, required String details, 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, amount: amount, details: details, 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(); // Initialize with one empty row addInitialRow(); } void addInitialRow() { _amountControllers.add(TextEditingController()); _detailsControllers.add(TextEditingController()); rows.add(buildRow(0)); } @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, ), Row( children: [ Text( 'AMOUNT', style: TextStyle( color: Colors.grey.shade500, fontSize: 15.0, ), ), SizedBox( width: width * 0.27, ), Text( 'DETAIL', style: TextStyle( color: Colors.grey.shade500, fontSize: 15.0, ), ) ], ), SizedBox( height: 10, ), Column( children: [ ...rows, ], ), SizedBox( height: height * 0.03, ), Text( 'DOCUMENT', style: TextStyle( color: Colors.grey.shade500, fontSize: 15.0, ), ), SizedBox( height: 20, ), Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ 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(1); }, 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( uploadDoc1 != null ? uploadDoc1!.path.split('/').last : 'Upload Document', style: TextStyle( color: Colors.white, fontSize: 10), ) ]), ), ), SizedBox( height: 20, ), 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(2); }, 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( uploadDoc2 != null ? uploadDoc2!.path.split('/').last : 'Upload Document', style: TextStyle( color: Colors.white, fontSize: 10), ) ]), ), ), ], ), SizedBox( height: 20, ), Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ 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(3); }, 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( uploadDoc3 != null ? uploadDoc3!.path.split('/').last : 'Upload Document', style: TextStyle( color: Colors.white, fontSize: 10), ) ]), ), ), SizedBox( height: 20, ), 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(4); }, 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( uploadDoc4 != null ? uploadDoc4!.path.split('/').last : 'Upload Document', style: TextStyle( color: Colors.white, fontSize: 10), ) ]), ), ), ], ), SizedBox( height: height * 0.03, ), SizedBox(height: height * 0.02), Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ InkWell( onTap: () { Navigator.pop(context); }, child: Container( height: height * 0.05, width: width * 0.37, decoration: BoxDecoration( border: Border.all( color: AppTheme.primaryColor, ), borderRadius: BorderRadius.circular(5)), child: Center( child: Text( 'Cancel', style: TextStyle( color: AppTheme.primaryColor, ), ), ), ), ), InkWell( onTap: () async { if (_formKey.currentState!.validate()) { showProgressIndicator(context); await projectAdd( projectDate: _startDateController.text, projectName: _nameController.text, description: _descController.text, client: selectedValue.toString(), projectStatus: selectedProject.toString(), totalAmount: _totalAmountController.text, billingMethod: selectedBilling.toString(), amount: amount.map((e) => e.text).join(','), details: details.map((e) => e.text).join(','), userId: user.id!, document1: uploadDoc1, document2: uploadDoc2, document3: uploadDoc3, document4: uploadDoc4, ); } }, child: Container( height: height * 0.05, width: width * 0.37, decoration: BoxDecoration( color: AppTheme.primaryColor, borderRadius: BorderRadius.circular(5)), child: Center( child: Text( "Save", style: TextStyle(color: Colors.white), ), ), ), ), ], ), SizedBox( height: 15, ), ], ), ), ), ), ); } Widget buildRow(int index) { var mediaQuery = MediaQuery.of(context); double height = mediaQuery.size.height; double width = mediaQuery.size.width; return Column( children: [ SizedBox( height: height * 0.015, ), Row( children: [ SizedBox( width: width * 0.37, height: height * 0.05, child: TextField( controller: _amountControllers[index], 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[index], 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: () { if (index == _amountControllers.length - 1) { addRow(); } else { removeRow(index); } }, icon: Icon(index == _amountControllers.length - 1 ? Icons.add_circle_outline : Icons.remove_circle_outline), color: AppTheme.primaryColor, ), ], ), ], ); } List<TextEditingController> _amountControllers = []; List<TextEditingController> _detailsControllers = []; List<bool> showAddButton = [true]; void addRow() { setState(() { _amountControllers.add(TextEditingController()); _detailsControllers.add(TextEditingController()); rows.add(buildRow(_amountControllers.length - 1)); }); } 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) { addInitialRow(); } } }); } }
Editor is loading...
Leave a Comment