EnQList added policy detls
This commit is contained in:
parent
53a86a8e21
commit
485894ba98
File diff suppressed because one or more lines are too long
@ -27,6 +27,7 @@ import '../../presentation/screens/home/home_screen.dart';
|
|||||||
import '../../presentation/screens/login/login_screen.dart';
|
import '../../presentation/screens/login/login_screen.dart';
|
||||||
import '../../presentation/screens/payout/payout_screen.dart';
|
import '../../presentation/screens/payout/payout_screen.dart';
|
||||||
import '../../presentation/screens/splash/splash_screen.dart';
|
import '../../presentation/screens/splash/splash_screen.dart';
|
||||||
|
import '../../presentation/screens/staff/Enquiry/enquiry_inline_Edit_17Nov.dart';
|
||||||
import '../../presentation/screens/staff/Enquiry/enquiry_inline_list.dart';
|
import '../../presentation/screens/staff/Enquiry/enquiry_inline_list.dart';
|
||||||
import '../../presentation/screens/staff/Enquiry/enquiry_list.dart';
|
import '../../presentation/screens/staff/Enquiry/enquiry_list.dart';
|
||||||
import '../../presentation/screens/staff/policy/policy.dart';
|
import '../../presentation/screens/staff/policy/policy.dart';
|
||||||
@ -178,6 +179,8 @@ final GoRouter appRouter = GoRouter(
|
|||||||
GoRoute(
|
GoRoute(
|
||||||
path: AppRoutes.enquiryForStaff,
|
path: AppRoutes.enquiryForStaff,
|
||||||
builder: (context, state) => const EnquiryListStaffInline(),
|
builder: (context, state) => const EnquiryListStaffInline(),
|
||||||
|
// builder: (context, state) => const EnquiryListStaffInlineTST(),
|
||||||
|
|
||||||
// builder: (context, state) => const EnquiryStaff(),
|
// builder: (context, state) => const EnquiryStaff(),
|
||||||
),
|
),
|
||||||
GoRoute(
|
GoRoute(
|
||||||
|
|||||||
@ -91,6 +91,44 @@ class ApiService {
|
|||||||
}
|
}
|
||||||
// --------------------------- COMMON FILES __________________________________________
|
// --------------------------- COMMON FILES __________________________________________
|
||||||
|
|
||||||
|
Future<Map<String, dynamic>> createUserData(data, path) async {
|
||||||
|
print('path - $path');
|
||||||
|
final url = Uri.parse('${Env.apiUrl}$path');
|
||||||
|
|
||||||
|
if (_token == null) {
|
||||||
|
await _initializeToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
print("data------- $data}");
|
||||||
|
|
||||||
|
final headers = {
|
||||||
|
'Authorization': 'Bearer $_token' ?? '',
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'app-signature': Env.App_Signature,
|
||||||
|
};
|
||||||
|
|
||||||
|
final response = await _makePostRequestJson(url, data, headers);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Map<String, dynamic>> fetchUploadEnquiryFiles(dynamic enqId) async {
|
||||||
|
// print(_token);
|
||||||
|
if (_token == null) {
|
||||||
|
await _initializeToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
final url = Uri.parse(
|
||||||
|
'${Env.apiUrl}enquiry/enquiryFiles?enquiry_id=$enqId',
|
||||||
|
);
|
||||||
|
|
||||||
|
final headers = {
|
||||||
|
'Authorization': 'Bearer $_token' ?? '',
|
||||||
|
'app-signature': Env.App_Signature,
|
||||||
|
};
|
||||||
|
final response = await _makeGetRequest(url, headers);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
Future<Map<String, dynamic>> logoutUsingAPI(agentId) async {
|
Future<Map<String, dynamic>> logoutUsingAPI(agentId) async {
|
||||||
// print(_token);
|
// print(_token);
|
||||||
if (_token == null) {
|
if (_token == null) {
|
||||||
@ -762,6 +800,23 @@ class ApiService {
|
|||||||
|
|
||||||
//------------------------------------ Quotation ------------------------------------------------
|
//------------------------------------ Quotation ------------------------------------------------
|
||||||
|
|
||||||
|
Future<Map<String, dynamic>> fetchQuickQuotationList(int managerId) async {
|
||||||
|
// print(_token);
|
||||||
|
if (_token == null) {
|
||||||
|
await _initializeToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
final url = Uri.parse(
|
||||||
|
'${Env.apiUrl}enquiry/getQuickQuoteEnquiryList?manager_id=${managerId}',
|
||||||
|
);
|
||||||
|
final headers = {
|
||||||
|
'Authorization': 'Bearer $_token' ?? '',
|
||||||
|
'app-signature': Env.App_Signature,
|
||||||
|
};
|
||||||
|
final response = await _makeGetRequest(url, headers);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
Future<Map<String, dynamic>> fetchQuotationList(int managerId) async {
|
Future<Map<String, dynamic>> fetchQuotationList(int managerId) async {
|
||||||
// print(_token);
|
// print(_token);
|
||||||
if (_token == null) {
|
if (_token == null) {
|
||||||
@ -1212,7 +1267,6 @@ class ApiService {
|
|||||||
|
|
||||||
// --------------------------------- PayOut Module----------------------------------------------
|
// --------------------------------- PayOut Module----------------------------------------------
|
||||||
Future<Map<String, dynamic>> getCommissionRateList(data) async {
|
Future<Map<String, dynamic>> getCommissionRateList(data) async {
|
||||||
|
|
||||||
final url = Uri.parse('${Env.apiUrl}/invoice/commission-rate-list');
|
final url = Uri.parse('${Env.apiUrl}/invoice/commission-rate-list');
|
||||||
|
|
||||||
// final token = await getToken(); // Fetch token
|
// final token = await getToken(); // Fetch token
|
||||||
@ -1235,7 +1289,6 @@ class ApiService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<Map<String, dynamic>> getCreateOrUpdate(data) async {
|
Future<Map<String, dynamic>> getCreateOrUpdate(data) async {
|
||||||
|
|
||||||
final url = Uri.parse('${Env.apiUrl}/invoice/create-or-update');
|
final url = Uri.parse('${Env.apiUrl}/invoice/create-or-update');
|
||||||
|
|
||||||
// final token = await getToken(); // Fetch token
|
// final token = await getToken(); // Fetch token
|
||||||
@ -1289,6 +1342,22 @@ class ApiService {
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<Map<String, dynamic>> delete(ID, path) async {
|
||||||
|
// print(_token);
|
||||||
|
if (_token == null) {
|
||||||
|
await _initializeToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
final url = Uri.parse('${Env.apiUrl}$path');
|
||||||
|
|
||||||
|
final headers = {
|
||||||
|
'Authorization': 'Bearer $_token' ?? '',
|
||||||
|
'app-signature': Env.App_Signature,
|
||||||
|
};
|
||||||
|
final response = await _makeGetRequest(url, headers);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
Future<Map<String, dynamic>> getInvoiceDetails(ID) async {
|
Future<Map<String, dynamic>> getInvoiceDetails(ID) async {
|
||||||
// print(_token);
|
// print(_token);
|
||||||
if (_token == null) {
|
if (_token == null) {
|
||||||
|
|||||||
@ -11,6 +11,8 @@ import '../../data/services/auth_service.dart';
|
|||||||
import '../providers/manager_provider.dart';
|
import '../providers/manager_provider.dart';
|
||||||
import '../providers/userRoleProvider.dart';
|
import '../providers/userRoleProvider.dart';
|
||||||
import '../screens/UserManagement/Profile/profile_web.dart';
|
import '../screens/UserManagement/Profile/profile_web.dart';
|
||||||
|
import '../screens/staff/Enquiry/Proposal_QuickCreation/Proposal_QuickCreation.dart';
|
||||||
|
import '../themes/indicators/side_Drawer_Panel.dart';
|
||||||
|
|
||||||
class AppHeader extends ConsumerStatefulWidget implements PreferredSizeWidget {
|
class AppHeader extends ConsumerStatefulWidget implements PreferredSizeWidget {
|
||||||
const AppHeader({super.key});
|
const AppHeader({super.key});
|
||||||
@ -380,7 +382,11 @@ class _AppHeaderState extends ConsumerState<AppHeader> {
|
|||||||
size: 20,
|
size: 20,
|
||||||
),
|
),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
debugPrint("Notifications tapped");
|
SideDrawerPanel.show(
|
||||||
|
context: context,
|
||||||
|
title: 'Proposal Creation',
|
||||||
|
child: CreateProposal_Quick(),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
tooltip: 'Create Proposal',
|
tooltip: 'Create Proposal',
|
||||||
),
|
),
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
1469
lib/presentation/screens/staff/Enquiry/Proposal_QuickCreation/re
Normal file
1469
lib/presentation/screens/staff/Enquiry/Proposal_QuickCreation/re
Normal file
File diff suppressed because it is too large
Load Diff
@ -39,13 +39,13 @@ import '../../../themes/indicators/text_field_theme_inline_editor.dart'
|
|||||||
import '../../../widgets/custom_Stdate_EnDate_Filter.dart';
|
import '../../../widgets/custom_Stdate_EnDate_Filter.dart';
|
||||||
import '../assignStaff.dart';
|
import '../assignStaff.dart';
|
||||||
|
|
||||||
class EnquiryListStaffInline extends ConsumerStatefulWidget {
|
class EnquiryListStaffInlineTST extends ConsumerStatefulWidget {
|
||||||
const EnquiryListStaffInline({super.key});
|
const EnquiryListStaffInlineTST({super.key});
|
||||||
@override
|
@override
|
||||||
ConsumerState<EnquiryListStaffInline> createState() => EnquiryStaffState();
|
ConsumerState<EnquiryListStaffInlineTST> createState() => EnquiryStaffState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class EnquiryStaffState extends ConsumerState<EnquiryListStaffInline> {
|
class EnquiryStaffState extends ConsumerState<EnquiryListStaffInlineTST> {
|
||||||
int currentPage = 1;
|
int currentPage = 1;
|
||||||
int itemsPerPage = 10;
|
int itemsPerPage = 10;
|
||||||
late ApiService apiService;
|
late ApiService apiService;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
293
lib/presentation/screens/staff/Enquiry/multi_file_list.dart
Normal file
293
lib/presentation/screens/staff/Enquiry/multi_file_list.dart
Normal file
@ -0,0 +1,293 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import 'package:file_picker/file_picker.dart';
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/src/widgets/framework.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
|
import 'package:http/http.dart' as http;
|
||||||
|
import 'package:nhance_partner/presentation/themes/indicators/mutli_FileUpload.dart';
|
||||||
|
|
||||||
|
import '../../../../core/config/env.dart';
|
||||||
|
import '../../../../core/services/api_service.dart';
|
||||||
|
import '../../../../data/services/auth_service.dart';
|
||||||
|
import '../../../../data/utils/toastNotification.dart';
|
||||||
|
import '../../../themes/indicators/multi_fileUploadService.dart';
|
||||||
|
|
||||||
|
class MultipleFileWidget extends ConsumerStatefulWidget {
|
||||||
|
dynamic enqId;
|
||||||
|
MultipleFileWidget({super.key, required this.enqId});
|
||||||
|
|
||||||
|
@override
|
||||||
|
ConsumerState<MultipleFileWidget> createState() => MultipleFileWidgetState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class MultipleFileWidgetState extends ConsumerState<MultipleFileWidget> {
|
||||||
|
List<PlatformFile> uploadedFiles = [];
|
||||||
|
final fileService = MultiFileUploadService();
|
||||||
|
late ApiService apiService;
|
||||||
|
bool isLoading = false;
|
||||||
|
dynamic _token;
|
||||||
|
|
||||||
|
List<Map<String, dynamic>> getUploadedData = [];
|
||||||
|
List<Map<String, dynamic>> originalData = [];
|
||||||
|
List<Map<String, dynamic>> filteredData = [];
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
fileService.clearAll();
|
||||||
|
apiService = ApiService();
|
||||||
|
_initializeToken();
|
||||||
|
getList();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _initializeToken() async {
|
||||||
|
_token = await AuthService.getToken();
|
||||||
|
print("APISERTOKEN - $_token");
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> getList() async {
|
||||||
|
setState(() {
|
||||||
|
isLoading = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
final response = await apiService.fetchUploadEnquiryFiles(widget.enqId);
|
||||||
|
|
||||||
|
if (response['status'] == 'success') {
|
||||||
|
print('E113 => getfetchUploadEnquiryFiles=');
|
||||||
|
print('E113 => getfetchUploadEnquiryFiles=> ${response['data']}');
|
||||||
|
setState(() {
|
||||||
|
getUploadedData = List<Map<String, dynamic>>.from(response['data']);
|
||||||
|
originalData = getUploadedData;
|
||||||
|
filteredData = List.from(originalData);
|
||||||
|
print('originalData - $originalData');
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
getUploadedData = [];
|
||||||
|
originalData = [];
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
print('Exception occurred: $e');
|
||||||
|
} finally {
|
||||||
|
setState(() {
|
||||||
|
isLoading = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> handleSave() async {
|
||||||
|
final request = http.MultipartRequest(
|
||||||
|
'POST',
|
||||||
|
Uri.parse('${Env.apiUrl}enquiry/uploadEnquiryFiles'),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (_token == null) {
|
||||||
|
throw Exception('Token not found. Please log in.');
|
||||||
|
}
|
||||||
|
request.headers['Authorization'] = 'Bearer $_token';
|
||||||
|
request.headers['app-signature'] = Env.App_Signature;
|
||||||
|
if (MultiFileUploadService().files.isEmpty) {
|
||||||
|
setState(() {
|
||||||
|
MultiFileUploadWidget.hasFiles = false;
|
||||||
|
});
|
||||||
|
ToastHelper.showErrorToast(
|
||||||
|
context,
|
||||||
|
'Please upload at least one document',
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// final id = int.tryParse(enqId.toString()) ?? 0;
|
||||||
|
|
||||||
|
// get uploaded files
|
||||||
|
final uploadedFiles = MultiFileUploadService().files;
|
||||||
|
print("📁 Total uploaded files: ${uploadedFiles.length}");
|
||||||
|
print(
|
||||||
|
"📂 File list (original names): ${uploadedFiles.map((f) => f.file.name).toList()}",
|
||||||
|
);
|
||||||
|
|
||||||
|
// Validate all labels present (optional but recommended)
|
||||||
|
for (final uf in uploadedFiles) {
|
||||||
|
print(
|
||||||
|
"📝 Checking label for file: ${uf.file.name}, current label: '${uf.label}'",
|
||||||
|
);
|
||||||
|
if ((uf.label ?? '').trim().isEmpty) {
|
||||||
|
ToastHelper.showErrorToast(
|
||||||
|
context,
|
||||||
|
'Please enter name for all uploaded documents',
|
||||||
|
);
|
||||||
|
setState(() => isLoading = false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add files
|
||||||
|
for (var uf in uploadedFiles) {
|
||||||
|
final pf = uf.file;
|
||||||
|
if (pf.bytes != null) {
|
||||||
|
request.files.add(
|
||||||
|
http.MultipartFile.fromBytes('files[]', pf.bytes!, filename: pf.name),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ✅ Combine all names into a JSON array string
|
||||||
|
final claimDocNames = uploadedFiles.map((uf) => uf.label.trim()).toList();
|
||||||
|
final encodedNames = jsonEncode(claimDocNames);
|
||||||
|
request.fields['files_doc_names'] = encodedNames;
|
||||||
|
request.fields['enquiry_id'] = widget.enqId!;
|
||||||
|
// ✅ Debug print
|
||||||
|
print("Payload being sent:");
|
||||||
|
print("Files: ${uploadedFiles.map((f) => f.file.name).toList()}");
|
||||||
|
print("Names (JSON): $encodedNames");
|
||||||
|
|
||||||
|
final response = await request.send();
|
||||||
|
final responseBody = await response.stream.bytesToString();
|
||||||
|
final decoded = jsonDecode(responseBody);
|
||||||
|
if (decoded['status'] == 'success') {
|
||||||
|
ToastHelper.showSuccessToast(context, 'File Uploaded');
|
||||||
|
setState(() {
|
||||||
|
isLoading = false;
|
||||||
|
});
|
||||||
|
print('Form data submitted successfully');
|
||||||
|
fileService.clearAll();
|
||||||
|
getList();
|
||||||
|
} else {
|
||||||
|
ToastHelper.showErrorToast(context, "Failed: ${decoded['message']}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> handleDelete(id) async {
|
||||||
|
setState(() {
|
||||||
|
isLoading = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
final path = 'enquiry/deleteEnquiryFile?file_id=$id';
|
||||||
|
print('path - $path');
|
||||||
|
try {
|
||||||
|
final response = await apiService.delete(id, path);
|
||||||
|
|
||||||
|
print("response");
|
||||||
|
print("response - $response");
|
||||||
|
print("response - ${response['status']}");
|
||||||
|
|
||||||
|
if (response['status'] == 'success') {
|
||||||
|
ToastHelper.showSuccessToast(context, response['message']);
|
||||||
|
getList();
|
||||||
|
} else {
|
||||||
|
ToastHelper.showSuccessToast(context, response['message']);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
print('Exception occurred: $e');
|
||||||
|
} finally {
|
||||||
|
setState(() {
|
||||||
|
isLoading = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
color: Color(0xFFFFFFFF),
|
||||||
|
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text('File Upload', style: GoogleFonts.poppins(fontSize: 11)),
|
||||||
|
SizedBox(height: 3),
|
||||||
|
MultiFileUploadWidget(),
|
||||||
|
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
|
children: [
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
handleSave();
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 6.0, vertical: 2),
|
||||||
|
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(8.0),
|
||||||
|
color: Color(0xFF2E7D6E),
|
||||||
|
// color: Color(0xFF425B5B),
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
'Save',
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
color: Colors.white,
|
||||||
|
fontSize: 11,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
|
||||||
|
SizedBox(height: 5),
|
||||||
|
Column(
|
||||||
|
children: List.generate(originalData.length, (index) {
|
||||||
|
final item = originalData[index];
|
||||||
|
final fileName = item['file_name'] ?? '';
|
||||||
|
final fileId = item['id'] ?? '';
|
||||||
|
|
||||||
|
return Container(
|
||||||
|
// margin: const EdgeInsets.only(bottom: 6),
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 6),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.circular(2),
|
||||||
|
border: Border(
|
||||||
|
bottom: BorderSide(
|
||||||
|
width: 0.2,
|
||||||
|
color: Colors.blueGrey.shade100,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Icon(
|
||||||
|
Icons.file_present_outlined,
|
||||||
|
size: 16,
|
||||||
|
color: Colors.grey[700],
|
||||||
|
),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
fileName,
|
||||||
|
style: GoogleFonts.poppins(fontSize: 11),
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
final path =
|
||||||
|
'api/enquiry/downloadEnquiryFiles?file_id=$fileId';
|
||||||
|
print("Uploadpath $path");
|
||||||
|
apiService.getPdfDownload(path, fileId);
|
||||||
|
},
|
||||||
|
child: Icon(Icons.download, size: 16, color: Colors.blue),
|
||||||
|
),
|
||||||
|
|
||||||
|
// DELETE BUTTON (optional)
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
handleDelete(fileId);
|
||||||
|
},
|
||||||
|
child: Icon(Icons.delete, size: 16, color: Colors.red),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -483,6 +483,11 @@ class RaiseEnqFormState extends ConsumerState<RaiseEnqForm> {
|
|||||||
label: "Partner Name",
|
label: "Partner Name",
|
||||||
).copyWith(
|
).copyWith(
|
||||||
filled: true,
|
filled: true,
|
||||||
|
// errorStyle: const TextStyle(
|
||||||
|
// fontSize: 9,
|
||||||
|
//
|
||||||
|
// // height: 0.0
|
||||||
|
// ),
|
||||||
fillColor:
|
fillColor:
|
||||||
Colors.white, // 👈 makes the dropdown input white
|
Colors.white, // 👈 makes the dropdown input white
|
||||||
isDense: true,
|
isDense: true,
|
||||||
|
|||||||
@ -503,38 +503,6 @@ class CreateProposalFormState extends ConsumerState<CreateProposalForm> {
|
|||||||
height: MediaQuery.of(context).size.height * 0.525,
|
height: MediaQuery.of(context).size.height * 0.525,
|
||||||
child: buildFormFields(context),
|
child: buildFormFields(context),
|
||||||
),
|
),
|
||||||
|
|
||||||
// Row(
|
|
||||||
// crossAxisAlignment: CrossAxisAlignment.end,
|
|
||||||
// mainAxisAlignment: MainAxisAlignment.end,
|
|
||||||
// children: [
|
|
||||||
// GestureDetector(
|
|
||||||
// onTap: () {
|
|
||||||
// handleDone();
|
|
||||||
// // widget.onSubmit(controller.text.trim());
|
|
||||||
// // Navigator.of(context).pop();
|
|
||||||
// },
|
|
||||||
// child: Container(
|
|
||||||
// padding: const EdgeInsets.symmetric(
|
|
||||||
// horizontal: 25.0,
|
|
||||||
// vertical: 10,
|
|
||||||
// ),
|
|
||||||
// decoration: BoxDecoration(
|
|
||||||
// borderRadius: BorderRadius.circular(8.0),
|
|
||||||
// color: const Color(0xFF425B5B),
|
|
||||||
// ),
|
|
||||||
// child: Text(
|
|
||||||
// 'Save',
|
|
||||||
// style: GoogleFonts.poppins(
|
|
||||||
// color: Colors.white,
|
|
||||||
// fontSize: 12,
|
|
||||||
// fontWeight: FontWeight.w600,
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ),
|
|
||||||
// ],
|
|
||||||
// ),
|
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,6 +8,8 @@ class ThemedUploadField extends StatefulWidget {
|
|||||||
final String? hintText;
|
final String? hintText;
|
||||||
final double? txtwidth;
|
final double? txtwidth;
|
||||||
final double? txtheight;
|
final double? txtheight;
|
||||||
|
final double? fontSZ;
|
||||||
|
final double? borderCirculr;
|
||||||
final Color? backgroundColor;
|
final Color? backgroundColor;
|
||||||
final Color? borderColor;
|
final Color? borderColor;
|
||||||
final Color? errorBorderColor;
|
final Color? errorBorderColor;
|
||||||
@ -23,6 +25,8 @@ class ThemedUploadField extends StatefulWidget {
|
|||||||
super.key,
|
super.key,
|
||||||
this.hintText,
|
this.hintText,
|
||||||
this.txtwidth,
|
this.txtwidth,
|
||||||
|
this.borderCirculr,
|
||||||
|
this.fontSZ,
|
||||||
this.txtheight,
|
this.txtheight,
|
||||||
this.backgroundColor,
|
this.backgroundColor,
|
||||||
this.borderColor,
|
this.borderColor,
|
||||||
@ -89,7 +93,9 @@ class _ThemedUploadFieldState extends State<ThemedUploadField> {
|
|||||||
),
|
),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: widget.backgroundColor ?? Colors.white,
|
color: widget.backgroundColor ?? Colors.white,
|
||||||
borderRadius: BorderRadius.circular(10),
|
borderRadius: BorderRadius.circular(
|
||||||
|
widget.borderCirculr ?? 10,
|
||||||
|
),
|
||||||
border: Border.all(
|
border: Border.all(
|
||||||
color: errorMessage != null
|
color: errorMessage != null
|
||||||
? (widget.errorBorderColor ?? Colors.red)
|
? (widget.errorBorderColor ?? Colors.red)
|
||||||
@ -108,7 +114,7 @@ class _ThemedUploadFieldState extends State<ThemedUploadField> {
|
|||||||
widget.hintText ??
|
widget.hintText ??
|
||||||
"Upload Document",
|
"Upload Document",
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 12,
|
fontSize: widget.fontSZ ?? 12,
|
||||||
color: errorMessage != null
|
color: errorMessage != null
|
||||||
? Colors.red
|
? Colors.red
|
||||||
: Colors.black,
|
: Colors.black,
|
||||||
@ -119,6 +125,7 @@ class _ThemedUploadFieldState extends State<ThemedUploadField> {
|
|||||||
const Icon(
|
const Icon(
|
||||||
Icons.file_upload_outlined,
|
Icons.file_upload_outlined,
|
||||||
color: Colors.black,
|
color: Colors.black,
|
||||||
|
size: 12,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
||||||
|
|||||||
@ -51,7 +51,7 @@ class _ThemedMultiFileUploadFieldState
|
|||||||
Future<void> _pickFile() async {
|
Future<void> _pickFile() async {
|
||||||
final error = await fileService.pickFiles(
|
final error = await fileService.pickFiles(
|
||||||
maxFileSizeInMB: 3,
|
maxFileSizeInMB: 3,
|
||||||
allowedExtensions: widget.allowedExtensions,
|
// allowedExtensions: widget.allowedExtensions,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (error != null) {
|
if (error != null) {
|
||||||
@ -60,6 +60,9 @@ class _ThemedMultiFileUploadFieldState
|
|||||||
context,
|
context,
|
||||||
).showSnackBar(SnackBar(content: Text(error)));
|
).showSnackBar(SnackBar(content: Text(error)));
|
||||||
} else if (fileService.pickFiles != null) {
|
} else if (fileService.pickFiles != null) {
|
||||||
|
print('Files Picked ');
|
||||||
|
print('Files Picked fileService - ${fileService.pickFiles}');
|
||||||
|
|
||||||
// setState(() {
|
// setState(() {
|
||||||
// selectedFileName = fileService.pickFiles!.name;
|
// selectedFileName = fileService.pickFiles!.name;
|
||||||
// errorMessage = null;
|
// errorMessage = null;
|
||||||
|
|||||||
@ -1,51 +1,71 @@
|
|||||||
import 'package:file_picker/file_picker.dart';
|
import 'package:file_picker/file_picker.dart';
|
||||||
|
import 'package:flutter/widgets.dart';
|
||||||
|
|
||||||
|
class UploadedFile {
|
||||||
|
final PlatformFile file;
|
||||||
|
final TextEditingController controller;
|
||||||
|
UploadedFile({required this.file})
|
||||||
|
: controller = TextEditingController(
|
||||||
|
text: file.extension != null
|
||||||
|
? file.name.replaceAll('.${file.extension}', '')
|
||||||
|
: file.name,
|
||||||
|
);
|
||||||
|
|
||||||
|
String get label => controller.text;
|
||||||
|
void dispose() => controller.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
class MultiFileUploadService {
|
class MultiFileUploadService {
|
||||||
MultiFileUploadService._();
|
MultiFileUploadService._();
|
||||||
static final MultiFileUploadService _instance = MultiFileUploadService._();
|
static final MultiFileUploadService _instance = MultiFileUploadService._();
|
||||||
factory MultiFileUploadService() => _instance;
|
factory MultiFileUploadService() => _instance;
|
||||||
|
|
||||||
final List<PlatformFile> _files = [];
|
final List<UploadedFile> _files = [];
|
||||||
|
|
||||||
List<PlatformFile> get files => List.unmodifiable(_files);
|
// Expose as unmodifiable but containing UploadedFile objects
|
||||||
|
List<UploadedFile> get files => List.unmodifiable(_files);
|
||||||
|
|
||||||
// Allowed extensions
|
// Allowed extensions
|
||||||
// static const allowedExtensions = ['pdf', 'png', 'jpg', 'jpeg', 'heic'];
|
static const allowedExtensions = ['pdf', 'png', 'jpg', 'jpeg', 'heic'];
|
||||||
static const defaultAllowedExtensions = ['pdf', 'png', 'jpg', 'jpeg'];
|
|
||||||
|
|
||||||
Future<String?> pickFiles({
|
Future<String?> pickFiles({int maxFileSizeInMB = 3}) async {
|
||||||
int maxFileSizeInMB = 3,
|
|
||||||
List<String>? allowedExtensions,
|
|
||||||
}) async {
|
|
||||||
final extensions = allowedExtensions ?? defaultAllowedExtensions;
|
|
||||||
final result = await FilePicker.platform.pickFiles(
|
final result = await FilePicker.platform.pickFiles(
|
||||||
allowMultiple: true,
|
allowMultiple: true,
|
||||||
withData: true,
|
withData: true,
|
||||||
type: FileType.custom,
|
type: FileType.custom,
|
||||||
allowedExtensions: extensions,
|
allowedExtensions: allowedExtensions,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
for (final file in result.files) {
|
for (final pf in result.files) {
|
||||||
final ext = file.extension?.toLowerCase() ?? '';
|
final ext = pf.extension?.toLowerCase() ?? '';
|
||||||
final sizeInMB = (file.size / (1024 * 1024));
|
final sizeInMB = (pf.size / (1024 * 1024));
|
||||||
|
|
||||||
if (!allowedExtensions!.contains(ext)) {
|
if (!allowedExtensions.contains(ext)) {
|
||||||
return "Unsupported file format: ${file.name}";
|
return "Unsupported file format: ${pf.name}";
|
||||||
}
|
}
|
||||||
if (sizeInMB > maxFileSizeInMB) {
|
if (sizeInMB > maxFileSizeInMB) {
|
||||||
return "File too large (${file.name}). Max $maxFileSizeInMB MB allowed.";
|
return "File too large (${pf.name}). Max $maxFileSizeInMB MB allowed.";
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
_files.addAll(result.files);
|
// Wrap PlatformFile in our UploadedFile model
|
||||||
|
_files.add(UploadedFile(file: pf));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return null; // success
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeFileAt(int index) {
|
void removeFileAt(int index) {
|
||||||
if (index >= 0 && index < _files.length) _files.removeAt(index);
|
if (index >= 0 && index < _files.length) {
|
||||||
|
_files[index].dispose();
|
||||||
|
_files.removeAt(index);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void clearAll() => _files.clear();
|
void clearAll() {
|
||||||
|
for (final f in _files) {
|
||||||
|
f.dispose();
|
||||||
|
}
|
||||||
|
_files.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
|
|
||||||
|
import '../../layouts/responsive_layout.dart';
|
||||||
import 'multi_fileUploadService.dart';
|
import 'multi_fileUploadService.dart';
|
||||||
|
|
||||||
class MultiFileUploadWidget extends StatefulWidget {
|
class MultiFileUploadWidget extends StatefulWidget {
|
||||||
@ -6,6 +9,8 @@ class MultiFileUploadWidget extends StatefulWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
State<MultiFileUploadWidget> createState() => _MultiFileUploadWidgetState();
|
State<MultiFileUploadWidget> createState() => _MultiFileUploadWidgetState();
|
||||||
|
|
||||||
|
static bool hasFiles = false; // ✅ Static variable to check from parent
|
||||||
}
|
}
|
||||||
|
|
||||||
class _MultiFileUploadWidgetState extends State<MultiFileUploadWidget> {
|
class _MultiFileUploadWidgetState extends State<MultiFileUploadWidget> {
|
||||||
@ -40,13 +45,16 @@ class _MultiFileUploadWidgetState extends State<MultiFileUploadWidget> {
|
|||||||
} else {
|
} else {
|
||||||
setState(() {
|
setState(() {
|
||||||
errorMessage = null;
|
errorMessage = null;
|
||||||
|
MultiFileUploadWidget.hasFiles = fileService.files.isNotEmpty;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _removeFile(int index) {
|
void _removeFile(int index) {
|
||||||
fileService.removeFileAt(index);
|
fileService.removeFileAt(index);
|
||||||
setState(() {});
|
setState(() {
|
||||||
|
MultiFileUploadWidget.hasFiles = fileService.files.isNotEmpty;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -56,44 +64,117 @@ class _MultiFileUploadWidgetState extends State<MultiFileUploadWidget> {
|
|||||||
return Column(
|
return Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
|
// if (ResponsiveLayout.isMobile(context)) ...[
|
||||||
OutlinedButton.icon(
|
OutlinedButton.icon(
|
||||||
onPressed: _pickFiles,
|
onPressed: _pickFiles,
|
||||||
icon: const Icon(
|
icon: const Icon(
|
||||||
Icons.file_upload_outlined,
|
Icons.file_upload_outlined,
|
||||||
color: Color(0xFFE26728),
|
color: Color(0xFF2E7D6E),
|
||||||
size: 24,
|
size: 18,
|
||||||
),
|
),
|
||||||
label: const Text(
|
label: const Text(
|
||||||
"Upload Documents",
|
"Upload Documents",
|
||||||
style: TextStyle(fontSize: 14, color: Colors.black),
|
style: TextStyle(fontSize: 11, color: Colors.black),
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
),
|
),
|
||||||
style: OutlinedButton.styleFrom(
|
style: OutlinedButton.styleFrom(
|
||||||
side: const BorderSide(color: Color(0xFFE26728)),
|
side: const BorderSide(color: Color(0xFF2E7D6E)),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
const SizedBox(height: 3),
|
||||||
|
Text(
|
||||||
|
"Supports only PDF, PNG, JPG, JPEG,HEIC formats (max 10 MB each)",
|
||||||
|
style: GoogleFonts.poppins(fontSize: 8, color: Colors.grey),
|
||||||
|
),
|
||||||
|
// ]
|
||||||
|
// else ...[
|
||||||
|
// Row(
|
||||||
|
// children: [
|
||||||
|
// OutlinedButton.icon(
|
||||||
|
// onPressed: _pickFiles,
|
||||||
|
// icon: const Icon(
|
||||||
|
// Icons.file_upload_outlined,
|
||||||
|
// color: Color(0xFFE26728),
|
||||||
|
// size: 24,
|
||||||
|
// ),
|
||||||
|
// label: const Text(
|
||||||
|
// "Upload Documents",
|
||||||
|
// style: TextStyle(fontSize: 14, color: Colors.black),
|
||||||
|
// overflow: TextOverflow.ellipsis,
|
||||||
|
// ),
|
||||||
|
// style: OutlinedButton.styleFrom(
|
||||||
|
// side: const BorderSide(color: Color(0xFFE26728)),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// const SizedBox(width: 12),
|
||||||
|
// // const Expanded(
|
||||||
|
// // child: Text(
|
||||||
|
// // "Supports only PDF, PNG, JPG, JPEG,HEIC formats (max 10 MB each)",
|
||||||
|
// // style: TextStyle(fontSize: 12, color: Colors.grey),
|
||||||
|
// // overflow: TextOverflow.ellipsis,
|
||||||
|
// // ),
|
||||||
|
// // ),
|
||||||
|
// ],
|
||||||
|
// ),
|
||||||
|
// ],
|
||||||
|
|
||||||
|
// if (fileService.files.isEmpty && errorMessage == null) ...[
|
||||||
|
// const SizedBox(height: 4),
|
||||||
|
// const Text(
|
||||||
|
// "Required",
|
||||||
|
// style: TextStyle(color: Colors.red, fontSize: 12),
|
||||||
|
// ),
|
||||||
|
// ],
|
||||||
if (errorMessage != null) ...[
|
if (errorMessage != null) ...[
|
||||||
const SizedBox(height: 4),
|
const SizedBox(height: 4),
|
||||||
Text(
|
Text(
|
||||||
errorMessage!,
|
errorMessage!,
|
||||||
style: const TextStyle(color: Colors.red, fontSize: 12),
|
style: GoogleFonts.poppins(color: Colors.red, fontSize: 12),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
...files.asMap().entries.map((entry) {
|
|
||||||
final index = entry.key;
|
|
||||||
final file = entry.value;
|
|
||||||
|
|
||||||
return ListTile(
|
...fileService.files.asMap().entries.map((entry) {
|
||||||
dense: true,
|
final index = entry.key;
|
||||||
contentPadding: EdgeInsets.zero,
|
final uploaded = entry.value; // UploadedFile
|
||||||
title: Text(file.name, style: const TextStyle(fontSize: 14)),
|
|
||||||
trailing: IconButton(
|
return Column(
|
||||||
icon: const Icon(Icons.close, color: Colors.red),
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
onPressed: () => _removeFile(index),
|
children: [
|
||||||
),
|
ListTile(
|
||||||
|
dense: true,
|
||||||
|
contentPadding: EdgeInsets.zero,
|
||||||
|
title: Text(
|
||||||
|
uploaded.file.name,
|
||||||
|
style: GoogleFonts.poppins(fontSize: 11),
|
||||||
|
),
|
||||||
|
trailing: IconButton(
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
splashRadius: 2,
|
||||||
|
icon: const Icon(Icons.close, color: Colors.red, size: 14),
|
||||||
|
onPressed: () => _removeFile(index),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
// Padding(
|
||||||
|
// padding: const EdgeInsets.only(
|
||||||
|
// left: 8.0,
|
||||||
|
// bottom: 8.0,
|
||||||
|
// right: 8.0,
|
||||||
|
// ),
|
||||||
|
// child: TextField(
|
||||||
|
// controller: uploaded.controller,
|
||||||
|
// style: GoogleFonts.poppins(fontSize: 11),
|
||||||
|
// decoration: InputDecoration(
|
||||||
|
// labelText: 'Enter document name',
|
||||||
|
// labelStyle: GoogleFonts.poppins(fontSize: 11),
|
||||||
|
//
|
||||||
|
// border: const OutlineInputBorder(),
|
||||||
|
// isDense: true,
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
],
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
|
|||||||
121
lib/presentation/themes/indicators/side_Drawer_Panel.dart
Normal file
121
lib/presentation/themes/indicators/side_Drawer_Panel.dart
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
|
|
||||||
|
/// A reusable side drawer that slides in from the right
|
||||||
|
/// Takes up 1/3 of the screen width
|
||||||
|
class SideDrawerPanel extends StatelessWidget {
|
||||||
|
final Widget child;
|
||||||
|
final String? title;
|
||||||
|
final VoidCallback? onClose;
|
||||||
|
final double? width;
|
||||||
|
|
||||||
|
const SideDrawerPanel({
|
||||||
|
Key? key,
|
||||||
|
required this.child,
|
||||||
|
this.title,
|
||||||
|
this.onClose,
|
||||||
|
this.width,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final screenWidth = MediaQuery.of(context).size.width;
|
||||||
|
final drawerWidth = width ?? screenWidth / 2;
|
||||||
|
|
||||||
|
return Container(
|
||||||
|
width: drawerWidth,
|
||||||
|
height: MediaQuery.of(context).size.height,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: Colors.black.withOpacity(0.1),
|
||||||
|
blurRadius: 10,
|
||||||
|
spreadRadius: 2,
|
||||||
|
offset: const Offset(-2, 0),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
// Header
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.all(8),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: const Color(0xFFFFFFFF),
|
||||||
|
// color: const Color(0xFFF8F9FF),
|
||||||
|
border: Border(bottom: BorderSide(color: Colors.grey.shade200)),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
if (title != null)
|
||||||
|
Text(
|
||||||
|
'Proposal Creation',
|
||||||
|
style: GoogleFonts.poppins(
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: const Color(0xFF1E293B),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Spacer(),
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(Icons.close),
|
||||||
|
onPressed: onClose ?? () => Navigator.of(context).pop(),
|
||||||
|
color: Colors.grey.shade600,
|
||||||
|
tooltip: 'Close',
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
// Content
|
||||||
|
Expanded(
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
padding: const EdgeInsets.all(8),
|
||||||
|
// child: child,
|
||||||
|
child: Material(
|
||||||
|
color: Colors.white,
|
||||||
|
elevation: 0,
|
||||||
|
child: child, // Your CreateProposal_Quick()
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Show the drawer as a modal overlay
|
||||||
|
static Future<T?> show<T>({
|
||||||
|
required BuildContext context,
|
||||||
|
required Widget child,
|
||||||
|
String? title,
|
||||||
|
double? width,
|
||||||
|
bool barrierDismissible = true,
|
||||||
|
}) {
|
||||||
|
return showGeneralDialog<T>(
|
||||||
|
context: context,
|
||||||
|
barrierDismissible: barrierDismissible,
|
||||||
|
barrierLabel: 'Drawer',
|
||||||
|
barrierColor: Colors.black.withOpacity(0.5),
|
||||||
|
transitionDuration: const Duration(milliseconds: 300),
|
||||||
|
pageBuilder: (context, animation, secondaryAnimation) {
|
||||||
|
return Align(
|
||||||
|
alignment: Alignment.centerRight,
|
||||||
|
child: SideDrawerPanel(title: title, width: width, child: child),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
transitionBuilder: (context, animation, secondaryAnimation, child) {
|
||||||
|
return SlideTransition(
|
||||||
|
position: Tween<Offset>(begin: const Offset(1, 0), end: Offset.zero)
|
||||||
|
.animate(
|
||||||
|
CurvedAnimation(parent: animation, curve: Curves.easeInOut),
|
||||||
|
),
|
||||||
|
child: child,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -20,6 +20,7 @@ class ThemedFormField extends HookWidget {
|
|||||||
this.backgroundColor,
|
this.backgroundColor,
|
||||||
this.highlightColor,
|
this.highlightColor,
|
||||||
this.borderColor,
|
this.borderColor,
|
||||||
|
this.bordedRad,
|
||||||
this.errorBorderColor,
|
this.errorBorderColor,
|
||||||
this.errorTextColor,
|
this.errorTextColor,
|
||||||
this.readOnly = false, // ✅ new
|
this.readOnly = false, // ✅ new
|
||||||
@ -37,6 +38,7 @@ class ThemedFormField extends HookWidget {
|
|||||||
|
|
||||||
final double? verticalPad;
|
final double? verticalPad;
|
||||||
final double? horizonalPad;
|
final double? horizonalPad;
|
||||||
|
final double? bordedRad;
|
||||||
final double? enableBorderWidth;
|
final double? enableBorderWidth;
|
||||||
final String? hintText;
|
final String? hintText;
|
||||||
final Color? textColr;
|
final Color? textColr;
|
||||||
@ -116,7 +118,7 @@ class ThemedFormField extends HookWidget {
|
|||||||
horizontal: 10,
|
horizontal: 10,
|
||||||
),
|
),
|
||||||
border: OutlineInputBorder(
|
border: OutlineInputBorder(
|
||||||
borderRadius: BorderRadius.circular(10),
|
borderRadius: BorderRadius.circular(bordedRad ?? 10),
|
||||||
// borderSide: BorderSide(color: Color(0xFF50A398)),
|
// borderSide: BorderSide(color: Color(0xFF50A398)),
|
||||||
borderSide: BorderSide(
|
borderSide: BorderSide(
|
||||||
color: borderColor ?? Color(0xFFFFFFFF),
|
color: borderColor ?? Color(0xFFFFFFFF),
|
||||||
@ -124,7 +126,7 @@ class ThemedFormField extends HookWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
enabledBorder: OutlineInputBorder(
|
enabledBorder: OutlineInputBorder(
|
||||||
borderRadius: BorderRadius.circular(10),
|
borderRadius: BorderRadius.circular(bordedRad ?? 10),
|
||||||
// borderSide: BorderSide(color: Color(0xFF50A398)),
|
// borderSide: BorderSide(color: Color(0xFF50A398)),
|
||||||
borderSide: BorderSide(
|
borderSide: BorderSide(
|
||||||
color: borderColor ?? backgroundColor ?? Color(0xFFFFFFFF),
|
color: borderColor ?? backgroundColor ?? Color(0xFFFFFFFF),
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user