diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 32cd1dd..7c7f3d0 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,4 +1,7 @@ + + + [].obs; + + // Service to fetch data + final ProductMannualService productMannualService = ProductMannualService(); + + // Loading state + var isLoading = false.obs; + + // Method to fetch product manuals from the service + void fetchProductManuals() async { + try { + // Set loading to true + isLoading.value = true; + SharedPreferences prefs = await SharedPreferences.getInstance(); + String? token = prefs.getString('token'); + var manuals = await productMannualService.getProductManuals(token!); + + // If data is returned, update the list + if (manuals != null) { + productManualList.value = manuals; + } else { + productManualList.value = []; // If no data, set an empty list + } + } catch (e) { + // Handle error here, for example logging or showing an error message + print("Error fetching product manuals: $e"); + } finally { + // Set loading to false + isLoading.value = false; + } + } + + @override + void onInit() { + // Fetch product manuals when the controller is initialized + fetchProductManuals(); + super.onInit(); + } +} diff --git a/lib/controller/product_mannual_service.dart b/lib/controller/product_mannual_service.dart new file mode 100644 index 0000000..937835c --- /dev/null +++ b/lib/controller/product_mannual_service.dart @@ -0,0 +1,36 @@ + + +import '../models/product_mannual_model.dart'; +import '../utils/common_api_service.dart'; // Replace with your actual common API service import + +class ProductMannualService { + Future?> getProductManuals(String token) async { + try { + String url = "/api/productmanual/getall"; // Base URL to fetch product manuals + + final response = await commonApiService>( + method: "GET", + url: url, + additionalHeaders: { // Pass the token here + 'Authorization': 'Bearer $token', + }, + fromJson: (json) { + if (json['productManuals'] != null) { + // Map the list of product manuals from the response + final List productManuals = (json['productManuals'] as List) + .map((manualJson) => ProductManualModel.fromJson(manualJson as Map)) + .toList(); + return productManuals; + } else { + return []; + } + }, + ); + return response; + } catch (e) { + + print(e.toString()); + return null; + } + } +} diff --git a/lib/models/product_mannual_model.dart b/lib/models/product_mannual_model.dart new file mode 100644 index 0000000..795f62d --- /dev/null +++ b/lib/models/product_mannual_model.dart @@ -0,0 +1,120 @@ +class ProductManualModel { + final String id; + final String title; + final ProductManualDetails productManual; + final String createdAt; + final String updatedAt; + + ProductManualModel({ + required this.id, + required this.title, + required this.productManual, + required this.createdAt, + required this.updatedAt, + }); + + // Factory method to create a ProductManualModel from JSON + factory ProductManualModel.fromJson(Map json) { + return ProductManualModel( + id: json['_id'] ?? '', + title: json['title'] ?? '', + productManual: ProductManualDetails.fromJson(json['product_manual']), + createdAt: json['createdAt'], + updatedAt: json['updatedAt'], + ); + } + + // Method to convert a ProductManualModel to JSON + Map toJson() { + return { + '_id': id, + 'title': title, + 'product_manual': productManual.toJson(), + 'createdAt': createdAt, + 'updatedAt': updatedAt, + }; + } + + // Override toString for better debugging + @override + String toString() { + return 'ProductManualModel(id: $id, title: $title, productManual: $productManual, createdAt: $createdAt, updatedAt: $updatedAt)'; + } +} + +class ProductManualDetails { + final String publicId; + final String url; + final String filename; + + ProductManualDetails({ + required this.publicId, + required this.url, + required this.filename, + }); + + // Factory method to create ProductManualDetails from JSON + factory ProductManualDetails.fromJson(Map json) { + return ProductManualDetails( + publicId: json['public_id'] ?? '', + url: json['url'] ?? '', + filename: json['filename'] ?? '', + ); + } + + // Method to convert ProductManualDetails to JSON + Map toJson() { + return { + 'public_id': publicId, + 'url': url, + 'filename': filename, + }; + } + + // Override toString for better debugging + @override + String toString() { + return 'ProductManualDetails(publicId: $publicId, url: $url, filename: $filename)'; + } +} + +// Model for handling the entire response +class ProductManualResponse { + final bool success; + final List productManuals; + final int total; + + ProductManualResponse({ + required this.success, + required this.productManuals, + required this.total, + }); + + // Factory method to create ProductManualResponse from JSON + factory ProductManualResponse.fromJson(Map json) { + var productList = (json['productManuals'] as List) + .map((manual) => ProductManualModel.fromJson(manual)) + .toList(); + + return ProductManualResponse( + success: json['success'] ?? false, + productManuals: productList, + total: json['total'] ?? 0, + ); + } + + // Method to convert ProductManualResponse to JSON + Map toJson() { + return { + 'success': success, + 'productManuals': productManuals.map((manual) => manual.toJson()).toList(), + 'total': total, + }; + } + + // Override toString for better debugging + @override + String toString() { + return 'ProductManualResponse(success: $success, total: $total, productManuals: $productManuals)'; + } +} diff --git a/lib/models/product_model1.dart b/lib/models/product_model1.dart index bfaa077..b90aab3 100644 --- a/lib/models/product_model1.dart +++ b/lib/models/product_model1.dart @@ -9,6 +9,7 @@ class Product { final Brand brand; final int price; int quantity; + bool selected; final int gst; final int hsnCode; final String description; @@ -24,6 +25,7 @@ class Product { required this.brand, required this.price, this.quantity =1, + this.selected=false, required this.gst, required this.hsnCode, required this.description, diff --git a/lib/screens/authentication/change_password_screen.dart b/lib/screens/authentication/change_password_screen.dart index 91aa32f..7a534e4 100644 --- a/lib/screens/authentication/change_password_screen.dart +++ b/lib/screens/authentication/change_password_screen.dart @@ -138,7 +138,7 @@ class _ChangePasswordScreenState extends State { hintText: "Current Password", labelText: "Current Password", controller: authController.currentpassController, - obscureText: true, + obscureText: false, keyboardType: TextInputType.text, ), @@ -146,7 +146,7 @@ class _ChangePasswordScreenState extends State { InputField( hintText: "New Password", labelText: "New Password", - obscureText: true, + obscureText: false, controller: authController.newpassController, keyboardType: TextInputType.text, ), @@ -154,7 +154,7 @@ class _ChangePasswordScreenState extends State { InputField( hintText: "Confirm Password", labelText: "Confirm Password", - obscureText: true, + obscureText: false, controller: authController.confirmpassController, keyboardType: TextInputType.text, ), diff --git a/lib/screens/authentication/controller/auth_controller.dart b/lib/screens/authentication/controller/auth_controller.dart index 252db3d..ab08871 100644 --- a/lib/screens/authentication/controller/auth_controller.dart +++ b/lib/screens/authentication/controller/auth_controller.dart @@ -1,5 +1,6 @@ import 'package:cheminova/screens/authentication/controller/auth_service.dart'; import 'package:cheminova/screens/home_screen.dart'; +import 'package:cheminova/utils/show_snackbar.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:shared_preferences/shared_preferences.dart'; @@ -25,8 +26,12 @@ class AuthController extends GetxController { isLoading.value = false; update(); if (response != null) { + showSnackbar("Your Successfully logged In!"); Get.offAll(() => const HomeScreen()); } + else if(response == null){ + showSnackbar("Please Enter Valid Email or Password"); + } } Future forgotpass() async{ @@ -39,7 +44,7 @@ class AuthController extends GetxController { isLoading.value = false; update(); if(response != null){ - + showSnackbar("Email sent successfully"); } } diff --git a/lib/screens/authentication/login_screen.dart b/lib/screens/authentication/login_screen.dart index 8613807..546d577 100644 --- a/lib/screens/authentication/login_screen.dart +++ b/lib/screens/authentication/login_screen.dart @@ -1,13 +1,12 @@ -import 'dart:ui'; -import 'package:cheminova/screens/authentication/controller/auth_controller.dart'; -import 'package:cheminova/screens/authentication/forget_password_screen.dart'; -import 'package:cheminova/screens/authentication/verify_phone_screen.dart'; -import 'package:cheminova/widgets/custom_button.dart'; -import 'package:cheminova/widgets/input_field.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; import 'package:get/get.dart'; import 'package:google_fonts/google_fonts.dart'; +import '../../widgets/comman_text_from_filed.dart'; +import '../../widgets/custom_button.dart'; +import 'controller/auth_controller.dart'; +import 'forget_password_screen.dart'; +// Make sure you import HomeScreen class LoginScreen extends StatefulWidget { const LoginScreen({super.key}); @@ -19,6 +18,8 @@ class LoginScreen extends StatefulWidget { class _LoginScreenState extends State { final formKey = GlobalKey(); final authController = Get.put(AuthController()); + final String emailPattern = r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$'; + final String passwordPattern = r'^.{6,}$'; // At least 6 characters @override Widget build(BuildContext context) { @@ -30,9 +31,7 @@ class _LoginScreenState extends State { decoration: const BoxDecoration( image: DecorationImage( fit: BoxFit.cover, - image: AssetImage( - 'assets/images/image_1.png', - ), + image: AssetImage('assets/images/image_1.png'), ), borderRadius: BorderRadius.only( bottomLeft: Radius.circular(50.0), @@ -45,131 +44,159 @@ class _LoginScreenState extends State { ), ), SingleChildScrollView( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - SizedBox(height: Get.height * 0.1), - Container( - margin: const EdgeInsets.symmetric(vertical: 20), - child: Text( - 'Welcome', - style: GoogleFonts.getFont( - 'Roboto', - fontWeight: FontWeight.w400, - fontSize: 24, - height: 1.5, - color: const Color(0xFFFFFFFF), + child: Form( + key: formKey, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + SizedBox(height: Get.height * 0.1), + Container( + margin: const EdgeInsets.symmetric(vertical: 20), + child: Text( + 'Welcome', + style: GoogleFonts.getFont( + 'Roboto', + fontWeight: FontWeight.w400, + fontSize: 24, + height: 1.5, + color: const Color(0xFFFFFFFF), + ), ), ), - ), - Container( - decoration: BoxDecoration( - color: const Color(0xFFFFFFFF), - borderRadius: BorderRadius.circular(14), - ), - child: Container( - width: Get.width * 0.7, - height: Get.height * 0.07, - padding: const EdgeInsets.all(10), + Container( + decoration: BoxDecoration( + color: const Color(0xFFFFFFFF), + borderRadius: BorderRadius.circular(14), + ), child: Container( - decoration: const BoxDecoration( - image: DecorationImage( - fit: BoxFit.fill, - image: AssetImage( - 'assets/images/px_cheminova_svg.png', + width: Get.width * 0.7, + height: Get.height * 0.07, + padding: const EdgeInsets.all(10), + child: Container( + decoration: const BoxDecoration( + image: DecorationImage( + fit: BoxFit.fill, + image: AssetImage( + 'assets/images/px_cheminova_svg.png', + ), ), ), ), ), ), - ), - SizedBox(height: Get.height * 0.05), - Card( - margin: const EdgeInsets.symmetric(horizontal: 24), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(19), - side: const BorderSide(color: Color(0xFFFDFDFD)), - ), - color: const Color(0xFFB4D1E5).withOpacity(0.9), - child: Padding( - padding: const EdgeInsets.all(16.0), - child: Column( - children: [ - Container( - alignment: Alignment.centerLeft, - padding: const EdgeInsets.only(bottom: 10), - child: SvgPicture.asset( - 'assets/svg/login.svg', - height: Get.height * 0.05, - ), - ), - Container( - padding: const EdgeInsets.only(bottom: 10), - alignment: Alignment.centerLeft, - child: Text( - 'Login', - style: GoogleFonts.getFont( - 'Roboto', - fontWeight: FontWeight.w500, - fontSize: 30, - height: 1.2, + SizedBox(height: Get.height * 0.05), + Card( + margin: const EdgeInsets.symmetric(horizontal: 24), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(19), + side: const BorderSide(color: Color(0xFFFDFDFD)), + ), + color: const Color(0xFFB4D1E5).withOpacity(0.9), + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + children: [ + Container( + alignment: Alignment.centerLeft, + padding: const EdgeInsets.only(bottom: 10), + child: SvgPicture.asset( + 'assets/svg/login.svg', + height: Get.height * 0.05, ), ), - ), - Container( - padding: const EdgeInsets.only(bottom: 10), - alignment: Alignment.centerLeft, - child: Text( - 'Sign in to Continue', - style: GoogleFonts.getFont( - 'Roboto', - fontWeight: FontWeight.w300, - fontSize: 14, - height: 1.8, + Container( + padding: const EdgeInsets.only(bottom: 10), + alignment: Alignment.centerLeft, + child: Text( + 'Login', + style: GoogleFonts.getFont( + 'Roboto', + fontWeight: FontWeight.w500, + fontSize: 30, + height: 1.2, + ), ), ), - ), - InputField( - hintText: "Email", - labelText: "Email", - controller: authController.emailController, - keyboardType: TextInputType.emailAddress, - ), - InputField( - hintText: "Password", - labelText: "Password", - controller: authController.passwordController, - obscureText: true, - ), - const SizedBox(height: 30), - GestureDetector( - onTap: () => - Get.to(() => const ForgetPasswordScreen()), - child: Text( - 'Forgot password?', - style: GoogleFonts.getFont( - 'Roboto', - fontWeight: FontWeight.w400, - fontSize: 20, - height: 1, - letterSpacing: -0.2, + Container( + padding: const EdgeInsets.only(bottom: 10), + alignment: Alignment.centerLeft, + child: Text( + 'Sign in to Continue', + style: GoogleFonts.getFont( + 'Roboto', + fontWeight: FontWeight.w300, + fontSize: 14, + height: 1.8, + ), ), ), - ), - const SizedBox(height: 30), - Obx( - () => CustomButton( - text: "Login", - onPressed: () => authController.login(), - isLoading: authController.isLoading.value, + CommonTextFormField( + controller: authController.emailController, + keyboardType: TextInputType.emailAddress, + validator: (value) { + if (value == null || value.isEmpty) { + return 'Please enter your email id'; + } + if (!RegExp(emailPattern).hasMatch(value)) { + return 'Please Enter valid email'; + } + return null; + }, + title: 'Email', + label: "Email", ), - ), - ], + const SizedBox(height: 15), + CommonTextFormField( + controller: authController.passwordController, + validator: (value) { + if (value == null || value.isEmpty) { + return 'Please enter your password'; + } + if (!RegExp(passwordPattern).hasMatch(value)) { + return 'Please Enter valid password'; + } + return null; + }, + obscureText: true, + title: 'Password', + maxLines: 1, + label: "Password", + ), + const SizedBox(height: 30), + GestureDetector( + onTap: () => + Get.to(() => const ForgetPasswordScreen()), + child: Text( + 'Forgot password?', + style: GoogleFonts.getFont( + 'Roboto', + fontWeight: FontWeight.w400, + fontSize: 20, + height: 1, + letterSpacing: -0.2, + ), + ), + ), + const SizedBox(height: 30), + Obx( + () => CustomButton( + text: "Login", + onPressed: () { + if (formKey.currentState!.validate()) { + // Perform login action + authController.login(); + } + }, + isLoading: authController.isLoading.value, + ), + ), + ], + ), ), ), - ), - ], + ], + ), ), ), ], diff --git a/lib/screens/order/order_confermation_screen.dart b/lib/screens/order/order_confermation_screen.dart index 589799c..2e84da5 100644 --- a/lib/screens/order/order_confermation_screen.dart +++ b/lib/screens/order/order_confermation_screen.dart @@ -16,7 +16,8 @@ import '../../models/product_model1.dart'; class OrderConfermationScreen extends StatefulWidget { Product? productModel; PlacedOrderModel? placedOrder; - OrderConfermationScreen({super.key,this.productModel,this.placedOrder}); + List? selectedProducts; + OrderConfermationScreen({super.key,this.productModel,this.placedOrder,this.selectedProducts}); @override State createState() => @@ -143,10 +144,10 @@ class _OrderConfermationScreenState extends State { padding: EdgeInsets.all(Get.width * 0.02), child: ListView.builder( padding: EdgeInsets.zero, - itemCount: _cartController.cartList.length, + itemCount: _cartController.selectedProducts.length, itemBuilder: (context, index) => ProductCard( - productModel:_cartController.cartList[index], + productModel:_cartController.selectedProducts[index], isCheckout: true, ), ), diff --git a/lib/screens/order_management/order_management_detail_screen.dart b/lib/screens/order_management/order_management_detail_screen.dart index 95b5b61..c1729d7 100644 --- a/lib/screens/order_management/order_management_detail_screen.dart +++ b/lib/screens/order_management/order_management_detail_screen.dart @@ -1,10 +1,9 @@ +import 'package:auto_size_text/auto_size_text.dart'; import 'package:cheminova/controller/get_order_placed_controller.dart'; import 'package:cheminova/models/oder_place_model.dart'; import 'package:cheminova/models/order_item_model.dart'; import 'package:cheminova/models/place_order_list_model.dart'; -import 'package:cheminova/models/product_model.dart'; -import 'package:cheminova/screens/order_management/order_fullfilment_screen.dart'; -import 'package:cheminova/widgets/product_card.dart'; + import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; @@ -49,7 +48,7 @@ Future adduni()async { final List uniqueOrders = []; for (var order in _getPlacedOrderController.placedOrders) { - if (uniqueOrderIds.add(order.id)) { + if (uniqueOrderIds.add(order.uniqueId)) { uniqueOrders.add(order); } } @@ -158,7 +157,7 @@ Future adduni()async { fontWeight: FontWeight.bold, ), ), - Text(widget.placedOrderList!.id), + Text(widget.placedOrderList!.uniqueId), ], ), ), @@ -283,6 +282,7 @@ Future adduni()async { ), SizedBox( width: Get.width, + height: Get.height*0.06, child: Padding( padding: const EdgeInsets.fromLTRB(8, 8, 8, 0), @@ -295,7 +295,8 @@ Future adduni()async { fontWeight: FontWeight.bold, ), ), - Text("${widget.placedOrderList!.shipTo}") + AutoSizeText("${widget.placedOrderList!.shipTo}",maxLines: 4, + overflow:TextOverflow.ellipsis,) ], ), ), diff --git a/lib/screens/order_management/order_management_screen.dart b/lib/screens/order_management/order_management_screen.dart index d8c0ae5..d0fc0e7 100644 --- a/lib/screens/order_management/order_management_screen.dart +++ b/lib/screens/order_management/order_management_screen.dart @@ -177,7 +177,7 @@ class _OrderManagementScreenState extends State { mainAxisAlignment: MainAxisAlignment.start, children: [ Text("Order ID: ", style: GoogleFonts.roboto(fontSize: 14, fontWeight: FontWeight.bold)), - Text("${order.id}") + Text("${order.uniqueId}") ], ), ), diff --git a/lib/screens/product/cart_screen.dart b/lib/screens/product/cart_screen.dart index 97f40f4..0e1581f 100644 --- a/lib/screens/product/cart_screen.dart +++ b/lib/screens/product/cart_screen.dart @@ -1,5 +1,4 @@ -import 'package:cheminova/models/oder_place_model.dart'; -import 'package:cheminova/models/product_model.dart'; + import 'package:cheminova/screens/order/checkout_screen.dart'; import 'package:cheminova/widgets/my_drawer.dart'; import 'package:cheminova/widgets/product_card.dart'; @@ -9,12 +8,14 @@ import 'package:get/get.dart'; import 'package:google_fonts/google_fonts.dart'; import '../../controller/cart_controller.dart'; +import '../../models/oder_place_model.dart'; import '../../models/product_model1.dart'; class CartScreen extends StatefulWidget { - Product? productModel; + Product? productModel; PlacedOrderModel? placedOrder; - CartScreen({super.key, this.productModel,this.placedOrder}); + + CartScreen({super.key, this.productModel, this.placedOrder}); @override State createState() => _CartScreenState(); @@ -23,12 +24,33 @@ class CartScreen extends StatefulWidget { class _CartScreenState extends State { final CartController _cartController = Get.find(); - // @override + bool _selectAll = true; // Default to true to select all products + + @override void initState() { super.initState(); if (widget.productModel != null) { _cartController.addToCart(widget.productModel!); } + // Ensure all products are pre-selected by default + _cartController.initializeSelections(); + _checkIfAllSelected(); // Check if all products are selected by default + } + + void _toggleSelectAll(bool? value) { + setState(() { + _selectAll = value ?? false; + _cartController.selectAllProducts(_selectAll); + }); + } + + void _checkIfAllSelected() { + // This function checks if all items are selected or not and updates _selectAll + setState(() { + _selectAll = _cartController.cartList.every( + (product) => _cartController.selectedProducts.contains(product), + ); + }); } @override @@ -62,8 +84,8 @@ class _CartScreenState extends State { ), ), ], - title: Center( - child: const Text( + title: const Center( + child: Text( "Cart", ), ), @@ -77,136 +99,441 @@ class _CartScreenState extends State { fit: BoxFit.cover, ), SafeArea( - child: Column( - children: [ - SizedBox( - height: Get.height * 0.02, - ), - Card( - margin: const EdgeInsets.symmetric(horizontal: 18), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(19), - side: const BorderSide(color: Color(0xFFFDFDFD)), + child: Obx(() { + if (_cartController.cartList.isEmpty) { + return Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Image.asset( + 'assets/images/cart.png', + width: Get.width * 0.5, + height: Get.width * 0.5, + ), + const SizedBox(height: 20), + Text( + 'Your Cart is empty', + style: GoogleFonts.roboto( + fontSize: 24, + fontWeight: FontWeight.w500, + color: Colors.white, + ), + ), + ], ), - color: const Color(0xFFB4D1E5).withOpacity(0.9), - child: Padding( - padding: const EdgeInsets.all(12.0), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - SizedBox( - height: Get.height * 0.6, - child: Obx(() { - return ListView.builder( + ); + } + return Column( + children: [ + SizedBox( + height: Get.height * 0.02, + ), + Card( + margin: const EdgeInsets.symmetric(horizontal: 18), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(19), + side: const BorderSide(color: Color(0xFFFDFDFD)), + ), + color: const Color(0xFFB4D1E5).withOpacity(0.9), + child: Padding( + padding: const EdgeInsets.all(12.0), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + // "Select All" Checkbox + Row( + children: [ + Checkbox( + value: _selectAll, + onChanged: _toggleSelectAll, + ), + Text( + "Select All", + style: GoogleFonts.roboto( + fontSize: 16, + fontWeight: FontWeight.w500, + ), + ), + ], + ), + SizedBox( + height: Get.height * 0.6, + child: ListView.builder( padding: EdgeInsets.zero, itemCount: _cartController.cartList.length, - itemBuilder: (context, index) => ProductCard( - productModel: _cartController.cartList[index], - isInCart: true, - placedOrder:widget.placedOrder, - ), - ); - }), - ), - const SizedBox( - height: 10, - ), - Obx(() { - return Row( + itemBuilder: (context, index) { + return Row( + children: [ + Checkbox( + value: _cartController.selectedProducts.contains( + _cartController.cartList[index]), + onChanged: (value) { + _cartController.toggleProductSelection( + _cartController.cartList[index], + value!, + ); + _checkIfAllSelected(); // Check if all are selected after each toggle + }, + ), + Expanded( + child: ProductCard( + productModel: + _cartController.cartList[index], + isInCart: true, + placedOrder: widget.placedOrder, + ), + ), + ], + ); + }, + ), + ), + const SizedBox(height: 10), + Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "Subtotal ", style: GoogleFonts.roboto( fontSize: 15, - color: Colors.black, - fontWeight: FontWeight.bold + fontWeight: FontWeight.bold, ), ), - Text("₹ ${_cartController.subtotal.value}"), + Obx(() => + Text("₹ ${_cartController.subtotal.value}")), ], - ); - - }), - - - // const SizedBox( - // height: 16, - // ), - Obx(() { - return Row( + ), + Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "GST ", style: GoogleFonts.roboto( fontSize: 15, - color: Colors.black, - fontWeight: FontWeight.bold - + fontWeight: FontWeight.bold, ), ), - Text("₹ ${_cartController.gstTotal.value}"), + Obx(() => + Text("₹ ${_cartController.gstTotal.value}")), ], - ); - - }), - Obx(() { - return Row( + ), + Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "Total Amount ", style: GoogleFonts.roboto( fontSize: 15, - color: Colors.black, - fontWeight: FontWeight.bold + fontWeight: FontWeight.bold, ), ), - Text(" ₹ ${_cartController.grandTotal.value}"), + Obx(() => Text( + "₹ ${_cartController.grandTotal.value}")), ], - ); - - }), - ], - ), - ), - ), - SizedBox( - height: Get.height * 0.025, - ), - SizedBox( - width: Get.width * 0.9, - height: Get.height * 0.06, - child: ElevatedButton( - onPressed: () => Get.to(() => CheckoutScreen( - - productModel:widget.productModel - )), - style: ElevatedButton.styleFrom( - foregroundColor: Colors.white, - backgroundColor: const Color(0xFF00784C), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(10), - ), - ), - child: Text( - "Proceed to Checkout", - style: GoogleFonts.roboto( - fontSize: 16, - fontWeight: FontWeight.w600, + ), + ], ), ), ), - ), - ], - ), + SizedBox(height: Get.height * 0.020), + SizedBox( + width: Get.width * 0.9, + height: Get.height * 0.06, + child: ElevatedButton( + onPressed: () => Get.to(() => CheckoutScreen( + selectedProducts: _cartController.selectedProducts, + )), + style: ElevatedButton.styleFrom( + foregroundColor: Colors.white, + backgroundColor: const Color(0xFF00784C), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + ), + child: Text( + "Proceed to Checkout", + style: GoogleFonts.roboto( + fontSize: 16, + fontWeight: FontWeight.w600, + ), + ), + ), + ), + ], + ); + }), ), ], ), ); } } + + + + + +// import 'package:cheminova/models/oder_place_model.dart'; +// import 'package:cheminova/models/product_model.dart'; +// import 'package:cheminova/screens/order/checkout_screen.dart'; +// import 'package:cheminova/widgets/my_drawer.dart'; +// import 'package:cheminova/widgets/product_card.dart'; +// import 'package:flutter/material.dart'; +// import 'package:flutter_svg/svg.dart'; +// import 'package:get/get.dart'; +// import 'package:google_fonts/google_fonts.dart'; +// +// import '../../controller/cart_controller.dart'; +// import '../../models/product_model1.dart'; +// +// class CartScreen extends StatefulWidget { +// Product? productModel; +// PlacedOrderModel? placedOrder; +// +// CartScreen({super.key, this.productModel, this.placedOrder}); +// +// @override +// State createState() => _CartScreenState(); +// } +// +// class _CartScreenState extends State { +// final CartController _cartController = Get.find(); +// +// bool _selectAll = false; // State to track "Select All" checkbox +// +// @override +// void initState() { +// super.initState(); +// if (widget.productModel != null) { +// _cartController.addToCart(widget.productModel!); +// } +// } +// +// void _toggleSelectAll(bool? value) { +// setState(() { +// _selectAll = value ?? false; +// _cartController.cartList.forEach((product) { +// _cartController.toggleProductSelection(product, _selectAll); +// }); +// }); +// } +// +// @override +// Widget build(BuildContext context) { +// return Scaffold( +// extendBodyBehindAppBar: true, +// appBar: AppBar( +// backgroundColor: Colors.transparent, +// elevation: 0, +// leading: Builder( +// builder: (context) { +// return GestureDetector( +// onTap: () => Scaffold.of(context).openDrawer(), +// child: Padding( +// padding: const EdgeInsets.all(16.0), +// child: SvgPicture.asset( +// 'assets/svg/menu.svg', +// ), +// ), +// ); +// }, +// ), +// actions: [ +// GestureDetector( +// onTap: () => Get.back(), +// child: Padding( +// padding: const EdgeInsets.all(8.0), +// child: SvgPicture.asset( +// 'assets/svg/back_arrow.svg', +// ), +// ), +// ), +// ], +// title: Center( +// child: const Text( +// "Cart", +// ), +// ), +// ), +// drawer: const MyDrawer(), +// body: Stack( +// fit: StackFit.expand, +// children: [ +// Image.asset( +// 'assets/images/image_1.png', +// fit: BoxFit.cover, +// ), +// SafeArea( +// child: Obx(() { +// if (_cartController.cartList.isEmpty) { +// return Center( +// child: Column( +// mainAxisAlignment: MainAxisAlignment.center, +// children: [ +// Image.asset( +// 'assets/images/cart.png', +// width: Get.width * 0.5, +// height: Get.width * 0.5, +// ), +// const SizedBox(height: 20), +// Text( +// 'Your Cart is empty', +// style: GoogleFonts.roboto( +// fontSize: 24, +// fontWeight: FontWeight.w500, +// color: Colors.white, +// ), +// ), +// ], +// ), +// ); +// } +// return Column( +// children: [ +// SizedBox( +// height: Get.height * 0.02, +// ), +// Card( +// margin: const EdgeInsets.symmetric(horizontal: 18), +// shape: RoundedRectangleBorder( +// borderRadius: BorderRadius.circular(19), +// side: const BorderSide(color: Color(0xFFFDFDFD)), +// ), +// color: const Color(0xFFB4D1E5).withOpacity(0.9), +// child: Padding( +// padding: const EdgeInsets.all(12.0), +// child: Column( +// mainAxisSize: MainAxisSize.min, +// children: [ +// // "Select All" Checkbox +// Row( +// children: [ +// Checkbox( +// value: _selectAll, +// onChanged: _toggleSelectAll, +// ), +// Text( +// "Select All", +// style: GoogleFonts.roboto( +// fontSize: 16, +// fontWeight: FontWeight.w500, +// ), +// ), +// ], +// ), +// SizedBox( +// height: Get.height * 0.6, +// child: ListView.builder( +// padding: EdgeInsets.zero, +// itemCount: _cartController.cartList.length, +// itemBuilder: (context, index) { +// return Row( +// children: [ +// Checkbox( +// value: _cartController +// .cartList[index].selected, +// onChanged: (value) { +// setState(() { +// +// }); +// _cartController.toggleProductSelection( +// _cartController.cartList[index], +// value!); +// }, +// ), +// Expanded( +// child: ProductCard( +// productModel: +// _cartController.cartList[index], +// isInCart: true, +// placedOrder: widget.placedOrder, +// ), +// ), +// ], +// ); +// }, +// ), +// ), +// const SizedBox(height: 10), +// Row( +// mainAxisAlignment: MainAxisAlignment.spaceBetween, +// children: [ +// Text( +// "Subtotal ", +// style: GoogleFonts.roboto( +// fontSize: 15, +// color: Colors.black, +// fontWeight: FontWeight.bold, +// ), +// ), +// Obx(() => Text("₹ ${_cartController.subtotal.value}")), +// ], +// ), +// Row( +// mainAxisAlignment: MainAxisAlignment.spaceBetween, +// children: [ +// Text( +// "GST ", +// style: GoogleFonts.roboto( +// fontSize: 15, +// color: Colors.black, +// fontWeight: FontWeight.bold, +// ), +// ), +// Obx(() => Text("₹ ${_cartController.gstTotal.value}")), +// ], +// ), +// Row( +// mainAxisAlignment: MainAxisAlignment.spaceBetween, +// children: [ +// Text( +// "Total Amount ", +// style: GoogleFonts.roboto( +// fontSize: 15, +// color: Colors.black, +// fontWeight: FontWeight.bold, +// ), +// ), +// Obx(() => Text("₹ ${_cartController.grandTotal.value}")), +// ], +// ), +// ], +// ), +// ), +// ), +// SizedBox(height: Get.height * 0.020), +// SizedBox( +// width: Get.width * 0.9, +// height: Get.height * 0.06, +// child: ElevatedButton( +// onPressed: () => Get.to(() => CheckoutScreen( +// productModel: widget.productModel, +// )), +// style: ElevatedButton.styleFrom( +// foregroundColor: Colors.white, +// backgroundColor: const Color(0xFF00784C), +// shape: RoundedRectangleBorder( +// borderRadius: BorderRadius.circular(10), +// ), +// ), +// child: Text( +// "Proceed to Checkout", +// style: GoogleFonts.roboto( +// fontSize: 16, +// fontWeight: FontWeight.w600, +// ), +// ), +// ), +// ), +// ], +// ); +// }), +// ), +// ], +// ), +// ); +// } +// } diff --git a/lib/screens/product/pdf_screen.dart b/lib/screens/product/pdf_screen.dart new file mode 100644 index 0000000..09f988b --- /dev/null +++ b/lib/screens/product/pdf_screen.dart @@ -0,0 +1,26 @@ + +import 'package:cheminova/models/product_mannual_model.dart'; +import 'package:flutter/material.dart'; +import 'package:syncfusion_flutter_pdfviewer/pdfviewer.dart'; + + +class ViewPdfScreen extends StatefulWidget { + final ProductManualModel productManualModel; + const ViewPdfScreen({super.key, required this.productManualModel}); + + @override + State createState() => _ViewPdfScreenState(); +} + +class _ViewPdfScreenState extends State { + @override + Widget build(BuildContext context) { + return Scaffold( + body: SafeArea( + child: SfPdfViewer.network( + widget.productManualModel.productManual.url, + ), + ), + ); + } +} diff --git a/lib/screens/product/product_mannual.dart b/lib/screens/product/product_mannual.dart new file mode 100644 index 0000000..efbe0fb --- /dev/null +++ b/lib/screens/product/product_mannual.dart @@ -0,0 +1,134 @@ +import 'package:cheminova/controller/product_mannual_controller.dart'; +import 'package:cheminova/models/product_mannual_model.dart'; +import 'package:cheminova/screens/product/pdf_screen.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:get/get.dart'; +import '../../widgets/custom_button.dart'; + +class ProductsManualScreen extends StatefulWidget { + const ProductsManualScreen({super.key}); + + @override + _ProductsManualScreenState createState() => _ProductsManualScreenState(); +} + +class _ProductsManualScreenState extends State { + final ProductManualController _productManualController = Get.put(ProductManualController()); + + @override + void initState() { + super.initState(); + _productManualController.fetchProductManuals(); // Fetch product manual list from API + } + + @override + Widget build(BuildContext context) { + return Scaffold( + extendBodyBehindAppBar: true, + appBar: _buildAppBar(), + body: Stack( + alignment: Alignment.topCenter, + children: [ + _buildBackgroundImage(), + Center( + child: SingleChildScrollView( + child: _buildCardContent(), + ), + ), + ], + ), + ); + } + + // Extract AppBar to its own method + AppBar _buildAppBar() { + return AppBar( + backgroundColor: Colors.transparent, + elevation: 0, + leading: GestureDetector( + onTap: () => Get.back(), + child: Padding( + padding: const EdgeInsets.all(16.0), + child: SvgPicture.asset('assets/svg/menu.svg'), + ), + ), + actions: [ + GestureDetector( + onTap: () => Get.back(), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: SvgPicture.asset('assets/svg/back_arrow.svg'), + ), + ), + ], + ); + } + + // Extract background image widget + Widget _buildBackgroundImage() { + return Container( + height: 900, + decoration: const BoxDecoration( + image: DecorationImage( + fit: BoxFit.cover, + image: AssetImage('assets/images/image_1.png'), + ), + ), + child: SizedBox( + width: Get.width, + height: Get.height * 0.7, + ), + ); + } + + // Build the card content + Widget _buildCardContent() { + return Obx(() { + if (_productManualController.isLoading.value) { + return const CircularProgressIndicator(); // Loading state + } + + if (_productManualController.productManualList.isEmpty) { + return const Text("No product manuals available"); // Empty state + } + + return Card( + margin: const EdgeInsets.symmetric(horizontal: 24), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(19), + side: const BorderSide(color: Color(0xFFFDFDFD)), + ), + color: const Color(0xFFB4D1E5).withOpacity(0.9), + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + children: _buildProductButtons(), + ), + ), + ); + }); + } + + // Method to create a list of CustomButtons for products dynamically from API data + List _buildProductButtons() { + return _productManualController.productManualList.map((productManual) { + return CustomButton( + text: productManual.title ?? "No Title", // Dynamically fetch product name + onPressed: () => _navigateToPdfScreen(productManual), + ); + }).toList(); + } + + // Method to handle navigation to PDF screen + void _navigateToPdfScreen(ProductManualModel productManual) { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => ViewPdfScreen( + productManualModel: productManual, + ), + ), + ); + } +} diff --git a/lib/widgets/input_field.dart b/lib/widgets/input_field.dart index ddb26f1..ae7c3d5 100644 --- a/lib/widgets/input_field.dart +++ b/lib/widgets/input_field.dart @@ -1,22 +1,31 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; -class InputField extends StatelessWidget { +class InputField extends StatefulWidget { final String hintText; final String labelText; final TextEditingController controller; final bool obscureText; final TextInputType? keyboardType; + final String? Function(String?)? validator;// Add this line for validation - const InputField({ + InputField({ super.key, required this.hintText, required this.labelText, required this.controller, this.obscureText = false, this.keyboardType = TextInputType.text, + this.validator, // Add this }); + @override + State createState() => _InputFieldState(); +} + +class _InputFieldState extends State { + bool _isObscured = true; + @override Widget build(BuildContext context) { return Container( @@ -24,15 +33,16 @@ class InputField extends StatelessWidget { width: Get.width * 0.9, padding: const EdgeInsets.fromLTRB(6, 10, 10, 0), child: TextFormField( - controller: controller, - obscureText: obscureText, - keyboardType: keyboardType, + controller: widget.controller, + obscureText: widget.obscureText && _isObscured, + keyboardType: widget.keyboardType, decoration: InputDecoration( - labelText: labelText, - hintText: hintText, + labelText: widget.labelText, + hintText: widget.hintText, labelStyle: const TextStyle( color: Color(0xFF000000), ), + enabledBorder: const OutlineInputBorder( borderSide: BorderSide(color: Colors.grey), borderRadius: BorderRadius.all(Radius.circular(8)), @@ -42,10 +52,24 @@ class InputField extends StatelessWidget { borderRadius: BorderRadius.all(Radius.circular(8)), ), contentPadding: - const EdgeInsets.symmetric(vertical: 10, horizontal: 16), + const EdgeInsets.symmetric(vertical: 10, horizontal: 16), fillColor: Colors.white, filled: true, + // suffixIcon: widget.obscureText + // ? IconButton( + // icon: Icon( + // _isObscured ? Icons.visibility : Icons.visibility_off, + // color: Colors.grey, + // ), + // onPressed: () { + // setState(() { + // _isObscured = !_isObscured; + // }); + // }, + // ) + // : null, ), + validator: widget.validator, // Add this for validation ), ); } diff --git a/lib/widgets/product_card.dart b/lib/widgets/product_card.dart index 8718634..6a58ac5 100644 --- a/lib/widgets/product_card.dart +++ b/lib/widgets/product_card.dart @@ -9,7 +9,6 @@ import 'package:get/get.dart'; import 'package:google_fonts/google_fonts.dart'; import '../models/product_model1.dart'; - import '../utils/show_snackbar.dart'; class ProductCard extends StatefulWidget { @@ -69,7 +68,7 @@ class _ProductCardState extends State { borderRadius: BorderRadius.circular(15.0), child: Container( height: Get.height * 0.15, - width: Get.width * 0.30, + width: Get.width * 0.31, decoration: BoxDecoration( image: DecorationImage( image: AssetImage("assets/images/product.png"), @@ -79,172 +78,169 @@ class _ProductCardState extends State { ), ), ), - const SizedBox( - width: 10, - ), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - capitalizeFirstLetter(widget.productModel!.name), - style: GoogleFonts.roboto( - fontSize: 16, - fontWeight: FontWeight.w500, - ), - ), - Text( - capitalizeFirstLetter(widget.productModel!.category!.categoryName), - style: GoogleFonts.roboto( - fontSize: 14, - fontWeight: FontWeight.w400, - ), - ), - Text( - "₹ ${widget.productModel!.price.toString()}", - style: GoogleFonts.roboto( - fontSize: 22, - fontWeight: FontWeight.w700, - ), - ), - showQuantity - ? Text( - "Quantity: ${currentQuantity}", - style: GoogleFonts.roboto( - fontSize: 15, - fontWeight: FontWeight.w700, - ), - ) - : const SizedBox(), - widget.isCheckout - ? const SizedBox() - : widget.isInCart - ? Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + Expanded( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 3.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ - Container( - height: 40, - width: 100, - decoration: BoxDecoration( - color: const Color(0xFF004791), - borderRadius: BorderRadius.circular(10), + Text( + capitalizeFirstLetter(widget.productModel!.name), + style: GoogleFonts.roboto( + fontSize: 16, + fontWeight: FontWeight.w500, ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, + ), + Text( + capitalizeFirstLetter(widget.productModel!.category!.categoryName), + style: GoogleFonts.roboto( + fontSize: 14, + fontWeight: FontWeight.w400, + ), + ), + Text( + "₹ ${widget.productModel!.price.toString()}", + style: GoogleFonts.roboto( + fontSize: 22, + fontWeight: FontWeight.w700, + ), + ), + if (showQuantity) + Text( + "Quantity: ${currentQuantity}", + style: GoogleFonts.roboto( + fontSize: 15, + fontWeight: FontWeight.w700, + ), + ), + if (!widget.isCheckout) + widget.isInCart + ? Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - SizedBox( - height: 24, - width: 24, - child: ElevatedButton( - onPressed: () { - _cartController.decreaseQuantity(widget.productModel!); - setState(() { - currentQuantity = _cartController - .cartList - .firstWhere((p) => p.id == widget.productModel!.id) - .quantity; - }); - }, - style: ElevatedButton.styleFrom( - padding: EdgeInsets.zero, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), - ), - child: Text( - '-', - style: GoogleFonts.roboto( - fontSize: 16, - fontWeight: FontWeight.w800, - ), - ), + Container( + height: Get.height * 0.04, + width: Get.width * 0.21, + decoration: BoxDecoration( + color: const Color(0xFF004791), + borderRadius: BorderRadius.circular(10), ), - ), - Text( - "${currentQuantity}", - style: const TextStyle( - color: Colors.white, - fontSize: 16, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + SizedBox( + height: 24, + width: 24, + child: ElevatedButton( + onPressed: () { + _cartController.decreaseQuantity(widget.productModel!); + setState(() { + currentQuantity = _cartController + .cartList + .firstWhere((p) => p.id == widget.productModel!.id) + .quantity; + }); + }, + style: ElevatedButton.styleFrom( + padding: EdgeInsets.zero, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + ), + child: Text( + '-', + style: GoogleFonts.roboto( + fontSize: 16, + fontWeight: FontWeight.w800, + ), + ), + ), + ), + Text( + "${currentQuantity}", + style: const TextStyle( + color: Colors.white, + fontSize: 16, + ), + ), + SizedBox( + height: 22, + width: 22, + child: ElevatedButton( + onPressed: () { + _cartController.increaseQuantity(widget.productModel!); + setState(() { + currentQuantity = _cartController + .cartList + .firstWhere((p) => p.id == widget.productModel!.id) + .quantity; + }); + }, + style: ElevatedButton.styleFrom( + padding: EdgeInsets.zero, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + ), + child: Text( + '+', + style: GoogleFonts.roboto( + fontSize: 16, + fontWeight: FontWeight.w800, + ), + ), + ), + ), + ], ), ), SizedBox( - height: 24, - width: 24, - child: ElevatedButton( - onPressed: () { - _cartController.increaseQuantity(widget.productModel!); - setState(() { - currentQuantity = _cartController - .cartList - .firstWhere((p) => p.id == widget.productModel!.id) - .quantity; - }); - }, - style: ElevatedButton.styleFrom( - padding: EdgeInsets.zero, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8.0), - ), - ), - child: Text( - '+', - style: GoogleFonts.roboto( - fontSize: 16, - fontWeight: FontWeight.w800, - ), - ), + width: 2.0, + ), + IconButton( + onPressed: () { + _cartController.removeFromCart(widget.productModel!); + showSnackbar("Product has been removed successfully!"); + setState(() { + currentQuantity = 1; + }); + }, + icon: const Icon( + Icons.delete_outline_rounded, + color: Colors.red, ), ), ], + ) + : ElevatedButton( + onPressed: () { + if (isProductInCart) { + showSnackbar("Product already added to cart"); + } else { + _cartController.addToCart(widget.productModel!); + showSnackbar("Product successfully added to your cart"); + } + }, + style: ElevatedButton.styleFrom( + foregroundColor: Colors.white, + backgroundColor: const Color(0xFF00784C), + padding: const EdgeInsets.symmetric(horizontal: 18, vertical: 8), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(30), + ), + ), + child: Text( + "Add To Cart", + style: GoogleFonts.roboto( + fontSize: 14, + fontWeight: FontWeight.w600, + ), + ), ), - ), - SizedBox( - width: 20.0, - ), - IconButton( - onPressed: () { - _cartController.removeFromCart(widget.productModel!); - showSnackbar("Product has been removed successfully!"); - setState(() { - currentQuantity = 1; - }); - }, - icon: const Icon( - Icons.delete_outline_rounded, - color: Colors.red, - ), - ) ], - ) - : ElevatedButton( - onPressed: () { - if (isProductInCart) { - showSnackbar("Product already added to cart"); - } else { - _cartController.addToCart(widget.productModel!); - showSnackbar("Product successfully added to your cart"); - // setState(() { - // currentQuantity = widget.productModel!.quantity; - // }); - } - }, - style: ElevatedButton.styleFrom( - foregroundColor: Colors.white, - backgroundColor: const Color(0xFF00784C), - padding: const EdgeInsets.symmetric(horizontal: 18, vertical: 8), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(30), - ), - ), - child: Text( - "Add To Cart", - style: GoogleFonts.roboto( - fontSize: 14, - fontWeight: FontWeight.w600, - ), - ), ), - ], - ) + ), + ), ], ), ), diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc index e71a16d..7299b5c 100644 --- a/linux/flutter/generated_plugin_registrant.cc +++ b/linux/flutter/generated_plugin_registrant.cc @@ -6,6 +6,14 @@ #include "generated_plugin_registrant.h" +#include +#include void fl_register_plugins(FlPluginRegistry* registry) { + g_autoptr(FlPluginRegistrar) file_selector_linux_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin"); + file_selector_plugin_register_with_registrar(file_selector_linux_registrar); + g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); + url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); } diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index 2e1de87..786ff5c 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -3,6 +3,8 @@ # list(APPEND FLUTTER_PLUGIN_LIST + file_selector_linux + url_launcher_linux ) list(APPEND FLUTTER_FFI_PLUGIN_LIST diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index b8e2b22..2d07bbf 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -5,10 +5,18 @@ import FlutterMacOS import Foundation +import device_info_plus +import file_selector_macos import path_provider_foundation import shared_preferences_foundation +import syncfusion_pdfviewer_macos +import url_launcher_macos func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin")) + FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin")) PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) + SyncfusionFlutterPdfViewerPlugin.register(with: registry.registrar(forPlugin: "SyncfusionFlutterPdfViewerPlugin")) + UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) } diff --git a/pubspec.lock b/pubspec.lock index b1fbc8c..cd75b92 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -17,6 +17,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.11.0" + auto_size_text: + dependency: "direct main" + description: + name: auto_size_text + sha256: "3f5261cd3fb5f2a9ab4e2fc3fba84fd9fcaac8821f20a1d4e71f557521b22599" + url: "https://pub.dev" + source: hosted + version: "3.0.0" boolean_selector: dependency: transitive description: @@ -49,6 +57,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.18.0" + convert: + dependency: transitive + description: + name: convert + sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" + url: "https://pub.dev" + source: hosted + version: "3.1.1" + cross_file: + dependency: transitive + description: + name: cross_file + sha256: "7caf6a750a0c04effbb52a676dce9a4a592e10ad35c34d6d2d0e4811160d5670" + url: "https://pub.dev" + source: hosted + version: "0.3.4+2" crypto: dependency: transitive description: @@ -57,6 +81,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.3" + csc_picker: + dependency: "direct main" + description: + name: csc_picker + sha256: "7e5d6023a81f53b89a7fb0369953fd4dc676f7ea20e9a0c0707973a5f0aedf14" + url: "https://pub.dev" + source: hosted + version: "0.2.7" cupertino_icons: dependency: "direct main" description: @@ -65,6 +97,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.8" + device_info_plus: + dependency: transitive + description: + name: device_info_plus + sha256: a7fd703482b391a87d60b6061d04dfdeab07826b96f9abd8f5ed98068acc0074 + url: "https://pub.dev" + source: hosted + version: "10.1.2" + device_info_plus_platform_interface: + dependency: transitive + description: + name: device_info_plus_platform_interface + sha256: "282d3cf731045a2feb66abfe61bbc40870ae50a3ed10a4d3d217556c35c8c2ba" + url: "https://pub.dev" + source: hosted + version: "7.0.1" dio: dependency: "direct main" description: @@ -105,6 +153,46 @@ packages: url: "https://pub.dev" source: hosted version: "7.0.0" + file_selector_linux: + dependency: transitive + description: + name: file_selector_linux + sha256: "045d372bf19b02aeb69cacf8b4009555fb5f6f0b7ad8016e5f46dd1387ddd492" + url: "https://pub.dev" + source: hosted + version: "0.9.2+1" + file_selector_macos: + dependency: transitive + description: + name: file_selector_macos + sha256: f42eacb83b318e183b1ae24eead1373ab1334084404c8c16e0354f9a3e55d385 + url: "https://pub.dev" + source: hosted + version: "0.9.4" + file_selector_platform_interface: + dependency: transitive + description: + name: file_selector_platform_interface + sha256: a3994c26f10378a039faa11de174d7b78eb8f79e4dd0af2a451410c1a5c3f66b + url: "https://pub.dev" + source: hosted + version: "2.6.2" + file_selector_windows: + dependency: transitive + description: + name: file_selector_windows + sha256: "2ad726953f6e8affbc4df8dc78b77c3b4a060967a291e528ef72ae846c60fb69" + url: "https://pub.dev" + source: hosted + version: "0.9.3+2" + fixnum: + dependency: transitive + description: + name: fixnum + sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1" + url: "https://pub.dev" + source: hosted + version: "1.1.0" flutter: dependency: "direct main" description: flutter @@ -118,6 +206,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.2" + flutter_plugin_android_lifecycle: + dependency: transitive + description: + name: flutter_plugin_android_lifecycle + sha256: "9ee02950848f61c4129af3d6ec84a1cfc0e47931abc746b03e7a3bc3e8ff6eda" + url: "https://pub.dev" + source: hosted + version: "2.0.22" flutter_svg: dependency: "direct main" description: @@ -160,6 +256,22 @@ packages: url: "https://pub.dev" source: hosted version: "6.2.1" + hive: + dependency: transitive + description: + name: hive + sha256: "8dcf6db979d7933da8217edcec84e9df1bdb4e4edc7fc77dbd5aa74356d6d941" + url: "https://pub.dev" + source: hosted + version: "2.2.3" + hive_flutter: + dependency: "direct main" + description: + name: hive_flutter + sha256: dca1da446b1d808a51689fb5d0c6c9510c0a2ba01e22805d492c73b68e33eecc + url: "https://pub.dev" + source: hosted + version: "1.1.0" http: dependency: "direct main" description: @@ -176,6 +288,70 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.2" + image_picker: + dependency: "direct main" + description: + name: image_picker + sha256: "021834d9c0c3de46bf0fe40341fa07168407f694d9b2bb18d532dc1261867f7a" + url: "https://pub.dev" + source: hosted + version: "1.1.2" + image_picker_android: + dependency: transitive + description: + name: image_picker_android + sha256: "8c5abf0dcc24fe6e8e0b4a5c0b51a5cf30cefdf6407a3213dae61edc75a70f56" + url: "https://pub.dev" + source: hosted + version: "0.8.12+12" + image_picker_for_web: + dependency: transitive + description: + name: image_picker_for_web + sha256: "65d94623e15372c5c51bebbcb820848d7bcb323836e12dfdba60b5d3a8b39e50" + url: "https://pub.dev" + source: hosted + version: "3.0.5" + image_picker_ios: + dependency: transitive + description: + name: image_picker_ios + sha256: "6703696ad49f5c3c8356d576d7ace84d1faf459afb07accbb0fae780753ff447" + url: "https://pub.dev" + source: hosted + version: "0.8.12" + image_picker_linux: + dependency: transitive + description: + name: image_picker_linux + sha256: "4ed1d9bb36f7cd60aa6e6cd479779cc56a4cb4e4de8f49d487b1aaad831300fa" + url: "https://pub.dev" + source: hosted + version: "0.2.1+1" + image_picker_macos: + dependency: transitive + description: + name: image_picker_macos + sha256: "3f5ad1e8112a9a6111c46d0b57a7be2286a9a07fc6e1976fdf5be2bd31d4ff62" + url: "https://pub.dev" + source: hosted + version: "0.2.1+1" + image_picker_platform_interface: + dependency: transitive + description: + name: image_picker_platform_interface + sha256: "9ec26d410ff46f483c5519c29c02ef0e02e13a543f882b152d4bfd2f06802f80" + url: "https://pub.dev" + source: hosted + version: "2.10.0" + image_picker_windows: + dependency: transitive + description: + name: image_picker_windows + sha256: "6ad07afc4eb1bc25f3a01084d28520496c4a3bb0cb13685435838167c9dcedeb" + url: "https://pub.dev" + source: hosted + version: "0.2.1+1" intl: dependency: "direct main" description: @@ -184,6 +360,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.19.0" + js: + dependency: transitive + description: + name: js + sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf + url: "https://pub.dev" + source: hosted + version: "0.7.1" leak_tracker: dependency: transitive description: @@ -248,6 +432,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.12.0" + mime: + dependency: transitive + description: + name: mime + sha256: "801fd0b26f14a4a58ccb09d5892c3fbdeff209594300a542492cf13fba9d247a" + url: "https://pub.dev" + source: hosted + version: "1.0.6" path: dependency: transitive description: @@ -413,6 +605,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.10.0" + sprintf: + dependency: transitive + description: + name: sprintf + sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23" + url: "https://pub.dev" + source: hosted + version: "7.0.0" stack_trace: dependency: transitive description: @@ -437,6 +637,70 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.0" + syncfusion_flutter_core: + dependency: transitive + description: + name: syncfusion_flutter_core + sha256: "6e67726b85812afc7105725a23620b876ab7f6b04b8410e211330ffb8c2cdbe8" + url: "https://pub.dev" + source: hosted + version: "26.2.14" + syncfusion_flutter_pdf: + dependency: transitive + description: + name: syncfusion_flutter_pdf + sha256: "59a1173dc34a1fac0a41aff7a2bb6f3c1578f1bfd749ea8b24379018434ba5a5" + url: "https://pub.dev" + source: hosted + version: "26.2.14" + syncfusion_flutter_pdfviewer: + dependency: "direct main" + description: + name: syncfusion_flutter_pdfviewer + sha256: b54ffe621a0e2155cfc913ee55efcd160e2dc8d21c2b9185f4a9996e0ccc9424 + url: "https://pub.dev" + source: hosted + version: "26.2.14" + syncfusion_flutter_signaturepad: + dependency: transitive + description: + name: syncfusion_flutter_signaturepad + sha256: "5f8955d4ee64f342b389928111ebfad041e75003415eedee802f3af1d4ce7036" + url: "https://pub.dev" + source: hosted + version: "26.2.14" + syncfusion_pdfviewer_macos: + dependency: transitive + description: + name: syncfusion_pdfviewer_macos + sha256: "1eec60fe44cc357072a0b872e4b0a82edef741463fda2b3a95a6973d7a615ec1" + url: "https://pub.dev" + source: hosted + version: "26.2.14" + syncfusion_pdfviewer_platform_interface: + dependency: transitive + description: + name: syncfusion_pdfviewer_platform_interface + sha256: e128a2875226dc1d922ac0366d0804aa0ee7a52be23799cc6d84d78fd32ce092 + url: "https://pub.dev" + source: hosted + version: "26.2.14" + syncfusion_pdfviewer_web: + dependency: transitive + description: + name: syncfusion_pdfviewer_web + sha256: "5625c2e658e5d680ea240ea5f5daedf6a0acd563cec026a38b8cb5643783ce4f" + url: "https://pub.dev" + source: hosted + version: "26.2.14" + syncfusion_pdfviewer_windows: + dependency: transitive + description: + name: syncfusion_pdfviewer_windows + sha256: f6c56fea4b77ada9d7ddab6ed67a4a25317a2efd1007309e8938c01f1d952b20 + url: "https://pub.dev" + source: hosted + version: "26.2.14" term_glyph: dependency: transitive description: @@ -461,6 +725,78 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.2" + url_launcher: + dependency: transitive + description: + name: url_launcher + sha256: "21b704ce5fa560ea9f3b525b43601c678728ba46725bab9b01187b4831377ed3" + url: "https://pub.dev" + source: hosted + version: "6.3.0" + url_launcher_android: + dependency: transitive + description: + name: url_launcher_android + sha256: f0c73347dfcfa5b3db8bc06e1502668265d39c08f310c29bff4e28eea9699f79 + url: "https://pub.dev" + source: hosted + version: "6.3.9" + url_launcher_ios: + dependency: transitive + description: + name: url_launcher_ios + sha256: e43b677296fadce447e987a2f519dcf5f6d1e527dc35d01ffab4fff5b8a7063e + url: "https://pub.dev" + source: hosted + version: "6.3.1" + url_launcher_linux: + dependency: transitive + description: + name: url_launcher_linux + sha256: e2b9622b4007f97f504cd64c0128309dfb978ae66adbe944125ed9e1750f06af + url: "https://pub.dev" + source: hosted + version: "3.2.0" + url_launcher_macos: + dependency: transitive + description: + name: url_launcher_macos + sha256: "9a1a42d5d2d95400c795b2914c36fdcb525870c752569438e4ebb09a2b5d90de" + url: "https://pub.dev" + source: hosted + version: "3.2.0" + url_launcher_platform_interface: + dependency: transitive + description: + name: url_launcher_platform_interface + sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029" + url: "https://pub.dev" + source: hosted + version: "2.3.2" + url_launcher_web: + dependency: transitive + description: + name: url_launcher_web + sha256: "772638d3b34c779ede05ba3d38af34657a05ac55b06279ea6edd409e323dca8e" + url: "https://pub.dev" + source: hosted + version: "2.3.3" + url_launcher_windows: + dependency: transitive + description: + name: url_launcher_windows + sha256: "49c10f879746271804767cb45551ec5592cdab00ee105c06dddde1a98f73b185" + url: "https://pub.dev" + source: hosted + version: "3.1.2" + uuid: + dependency: transitive + description: + name: uuid + sha256: f33d6bb662f0e4f79dcd7ada2e6170f3b3a2530c28fc41f49a411ddedd576a77 + url: "https://pub.dev" + source: hosted + version: "4.5.0" vector_graphics: dependency: transitive description: @@ -509,6 +845,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.0" + win32: + dependency: transitive + description: + name: win32 + sha256: "68d1e89a91ed61ad9c370f9f8b6effed9ae5e0ede22a270bdfa6daf79fc2290a" + url: "https://pub.dev" + source: hosted + version: "5.5.4" + win32_registry: + dependency: transitive + description: + name: win32_registry + sha256: "723b7f851e5724c55409bb3d5a32b203b3afe8587eaf5dafb93a5fed8ecda0d6" + url: "https://pub.dev" + source: hosted + version: "1.1.4" xdg_directories: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 7cc76b3..43e7be2 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -44,6 +44,11 @@ dependencies: logger: ^2.4.0 get_storage: ^2.1.1 intl: ^0.19.0 + hive_flutter: ^1.1.0 + syncfusion_flutter_pdfviewer: ^26.2.14 + image_picker: ^1.1.2 + csc_picker: ^0.2.7 + auto_size_text: ^3.0.0 dev_dependencies: flutter_test: diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index 8b6d468..779f0ee 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -6,6 +6,15 @@ #include "generated_plugin_registrant.h" +#include +#include +#include void RegisterPlugins(flutter::PluginRegistry* registry) { + FileSelectorWindowsRegisterWithRegistrar( + registry->GetRegistrarForPlugin("FileSelectorWindows")); + SyncfusionPdfviewerWindowsPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("SyncfusionPdfviewerWindowsPlugin")); + UrlLauncherWindowsRegisterWithRegistrar( + registry->GetRegistrarForPlugin("UrlLauncherWindows")); } diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index b93c4c3..3757972 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -3,6 +3,9 @@ # list(APPEND FLUTTER_PLUGIN_LIST + file_selector_windows + syncfusion_pdfviewer_windows + url_launcher_windows ) list(APPEND FLUTTER_FFI_PLUGIN_LIST