From 91912fcc95de60ad2aaa515f157edc2e132c2935 Mon Sep 17 00:00:00 2001 From: Vaibhav Date: Thu, 29 Aug 2024 12:31:36 +0530 Subject: [PATCH] Profile UI & Product manual api integrate --- lib/models/product_manual_model.dart | 48 ++++++ lib/models/profile_response.dart | 4 + lib/provider/product_manual_provider.dart | 42 +++++ lib/screens/products_manual_screen.dart | 150 +++++++++++------- lib/screens/profile_screen.dart | 58 ++++--- lib/screens/view_pdf_screen.dart | 30 ++++ lib/services/api_urls.dart | 1 + macos/Flutter/GeneratedPluginRegistrant.swift | 2 + pubspec.lock | 62 +++++++- pubspec.yaml | 1 + 10 files changed, 308 insertions(+), 90 deletions(-) create mode 100644 lib/models/product_manual_model.dart create mode 100644 lib/provider/product_manual_provider.dart create mode 100644 lib/screens/view_pdf_screen.dart diff --git a/lib/models/product_manual_model.dart b/lib/models/product_manual_model.dart new file mode 100644 index 0000000..26b4451 --- /dev/null +++ b/lib/models/product_manual_model.dart @@ -0,0 +1,48 @@ +class ProductManualModel { + final ProductManualDetail productManualDetail; + final String id; + final String title; + final String createdAt; + final String updatedAt; + final int version; + + ProductManualModel({ + required this.productManualDetail, + required this.id, + required this.title, + required this.createdAt, + required this.updatedAt, + required this.version, + }); + + factory ProductManualModel.fromJson(Map json) { + return ProductManualModel( + productManualDetail: ProductManualDetail.fromJson(json['product_manual']), + id: json['_id'], + title: json['title'], + createdAt: json['createdAt'], + updatedAt: json['updatedAt'], + version: json['__v'], + ); + } +} + +class ProductManualDetail { + final String publicId; + final String url; + final String filename; + + ProductManualDetail({ + required this.publicId, + required this.url, + required this.filename, + }); + + factory ProductManualDetail.fromJson(Map json) { + return ProductManualDetail( + publicId: json['public_id'], + url: json['url'], + filename: json['filename'], + ); + } +} diff --git a/lib/models/profile_response.dart b/lib/models/profile_response.dart index a98a743..a365a1b 100644 --- a/lib/models/profile_response.dart +++ b/lib/models/profile_response.dart @@ -32,6 +32,7 @@ class MyData { String? uniqueId; String? createdAt; String? updatedAt; + String? designation; int? iV; MyData( @@ -43,6 +44,7 @@ class MyData { this.uniqueId, this.createdAt, this.updatedAt, + this.designation, this.iV}); MyData.fromJson(Map json) { @@ -54,6 +56,7 @@ class MyData { uniqueId = json['uniqueId']; createdAt = json['createdAt']; updatedAt = json['updatedAt']; + designation = json['designation']; iV = json['__v']; } @@ -67,6 +70,7 @@ class MyData { data['uniqueId'] = uniqueId; data['createdAt'] = createdAt; data['updatedAt'] = updatedAt; + data['designation'] = designation; data['__v'] = iV; return data; } diff --git a/lib/provider/product_manual_provider.dart b/lib/provider/product_manual_provider.dart new file mode 100644 index 0000000..a7e6f73 --- /dev/null +++ b/lib/provider/product_manual_provider.dart @@ -0,0 +1,42 @@ +import 'package:cheminova/models/product_manual_model.dart'; +import 'package:cheminova/services/api_urls.dart'; +import 'package:cheminova/services/api_client.dart'; + +import 'package:dio/dio.dart'; +import 'package:flutter/material.dart'; + +class ProductManualProvider extends ChangeNotifier { + ProductManualProvider() { + getProductManualList(); + } + bool _isLoading = false; + List _productManualList = []; + final _apiClient = ApiClient(); + + List get productManualList => _productManualList; + bool get isLoading => _isLoading; + + void setLoading(bool loading) { + _isLoading = loading; + notifyListeners(); + } + + Future getProductManualList() async { + setLoading(true); + try { + Response response = await _apiClient.get(ApiUrls.getProductsManual); + + if (response.statusCode == 200) { + List data = + (response.data['productManuals'] as List) + .map((json) => ProductManualModel.fromJson(json)) + .toList(); + _productManualList = data; + } + } catch (e) { + print("Error occurred: $e"); + } finally { + setLoading(false); + } + } +} diff --git a/lib/screens/products_manual_screen.dart b/lib/screens/products_manual_screen.dart index 84a7f63..ecb3530 100644 --- a/lib/screens/products_manual_screen.dart +++ b/lib/screens/products_manual_screen.dart @@ -1,67 +1,103 @@ +import 'package:cheminova/screens/view_pdf_screen.dart'; import 'package:flutter/material.dart'; import 'package:cheminova/widgets/common_background.dart'; import 'package:cheminova/widgets/common_drawer.dart'; import 'package:cheminova/widgets/common_app_bar.dart'; import 'package:cheminova/widgets/common_elevated_button.dart'; +import 'package:provider/provider.dart'; -class ProductsManualScreen extends StatelessWidget { +import '../models/product_manual_model.dart'; +import '../provider/product_manual_provider.dart'; + +class ProductsManualScreen extends StatefulWidget { const ProductsManualScreen({super.key}); + @override + State createState() => _ProductsManualScreenState(); +} + +class _ProductsManualScreenState extends State { + late ProductManualProvider _productManualProvider; + + @override + void initState() { + _productManualProvider = ProductManualProvider(); + super.initState(); + } + @override Widget build(BuildContext context) { - return CommonBackground( - child: Scaffold( - backgroundColor: Colors.transparent, - appBar: CommonAppBar( - actions: [ - IconButton( - onPressed: () { - Navigator.pop(context); - }, - icon: Image.asset('assets/Back_attendance.png'), - padding: const EdgeInsets.only(right: 20), - ), - ], - title: const Text('Products Manual', + return ChangeNotifierProvider( + create: (_) => _productManualProvider, + builder: (context, child) => CommonBackground( + child: Scaffold( + backgroundColor: Colors.transparent, + appBar: CommonAppBar( + actions: [ + IconButton( + onPressed: () { + Navigator.pop(context); + }, + icon: Image.asset('assets/Back_attendance.png'), + padding: const EdgeInsets.only(right: 20), + ), + ], + title: const Text( + 'Products Manual', style: TextStyle( fontSize: 20, color: Colors.black, fontWeight: FontWeight.w400, - fontFamily: 'Anek')), - backgroundColor: Colors.transparent, - elevation: 0, - ), - drawer: const CommonDrawer(), - body: Padding( - padding: const EdgeInsets.all(16.0), - child: SingleChildScrollView( - physics: const BouncingScrollPhysics(), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const SizedBox(height: 16), - Container( - padding: const EdgeInsets.all(20.0).copyWith(top: 30, bottom: 30), - decoration: BoxDecoration( - border: Border.all(color: Colors.white), - color: const Color(0xffB4D1E5).withOpacity(0.9), - borderRadius: BorderRadius.circular(26.0), + fontFamily: 'Anek'), + ), + backgroundColor: Colors.transparent, + elevation: 0, + ), + drawer: const CommonDrawer(), + body: Padding( + padding: const EdgeInsets.all(16.0), + child: SingleChildScrollView( + physics: const BouncingScrollPhysics(), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const SizedBox(height: 16), + Consumer( + builder: (context, provider, child) { + if (provider.isLoading) { + return const Center( + child: CircularProgressIndicator(), + ); + } + + if (provider.productManualList.isEmpty) { + return const Center( + child: Text('No products available.')); + } + + return Container( + padding: const EdgeInsets.all(20.0) + .copyWith(top: 30, bottom: 30), + decoration: BoxDecoration( + border: Border.all(color: Colors.white), + color: const Color(0xffB4D1E5).withOpacity(0.9), + borderRadius: BorderRadius.circular(26.0), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: provider.productManualList + .map( + (product) => + _buildProductButton(context, product), + ) + .toList(), + ), + ); + }, ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - _buildProductButton('Product 1'), - _buildProductButton('Product 2'), - _buildProductButton('Product 3'), - _buildProductButton('Product 4'), - _buildProductButton('Product 5'), - _buildProductButton('Product 6'), - _buildProductButton('Product 7'), - ], - ), - ), - ], + ], + ), ), ), ), @@ -69,20 +105,22 @@ class ProductsManualScreen extends StatelessWidget { ); } - Widget _buildProductButton(String productName) { + Widget _buildProductButton(BuildContext context, ProductManualModel product) { return Padding( padding: const EdgeInsets.only(bottom: 15), child: CommonElevatedButton( borderRadius: 30, width: double.infinity, height: kToolbarHeight - 10, - text: productName, + text: product.title, backgroundColor: const Color(0xff004791), - onPressed: () { - // Handle product button press - debugPrint('$productName pressed'); - }, + onPressed: () => Navigator.push( + context, + MaterialPageRoute( + builder: (context) => ViewPdfScreen(productManualModel: product), + ), + ), ), ); } -} \ No newline at end of file +} diff --git a/lib/screens/profile_screen.dart b/lib/screens/profile_screen.dart index e68e2e1..3526459 100644 --- a/lib/screens/profile_screen.dart +++ b/lib/screens/profile_screen.dart @@ -1,9 +1,9 @@ +import 'package:cheminova/provider/home_provider.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:cheminova/widgets/common_app_bar.dart'; import 'package:cheminova/widgets/common_background.dart'; import 'package:cheminova/widgets/common_drawer.dart'; - class ProfileScreen extends StatelessWidget { const ProfileScreen({Key? key}) : super(key: key); @@ -30,40 +30,36 @@ class ProfileScreen extends StatelessWidget { ), ], ), - body: SingleChildScrollView( - child: Column( - children: [ - Container( - padding: const EdgeInsets.all(20.0).copyWith(top: 15, bottom: 30), - margin: const EdgeInsets.symmetric(horizontal: 30.0, vertical: 20.0), - decoration: BoxDecoration( - border: Border.all(color: Colors.white), - color: const Color(0xffB4D1E5).withOpacity(0.9), - borderRadius: BorderRadius.circular(26.0), - ), + body: Consumer( + builder: (context, profileProvider, child) { + final profileData = profileProvider.profileResponse?.myData!; + return SingleChildScrollView( child: Column( - crossAxisAlignment: CrossAxisAlignment.start, children: [ - // const Text( - // 'User Profile', - // style: TextStyle( - // fontSize: 30, - // color: Colors.black, - // fontWeight: FontWeight.w500, - // fontFamily: 'Roboto', - // ), - // ), - const SizedBox(height: 20), - _buildProfileItem('Name', 'Vaibhav Gurjar'), - _buildProfileItem('ID', 'EMP001'), - _buildProfileItem('Designation', 'Sales Cordinator'), - _buildProfileItem('Email ID', 'vaibhav.gurjar20001@gmail.com'), - _buildProfileItem('Mobile Number', '8839033630'), + Container( + padding: const EdgeInsets.all(20.0).copyWith(top: 15, bottom: 30), + margin: const EdgeInsets.symmetric(horizontal: 30.0, vertical: 20.0), + decoration: BoxDecoration( + border: Border.all(color: Colors.white), + color: const Color(0xffB4D1E5).withOpacity(0.9), + borderRadius: BorderRadius.circular(26.0), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox(height: 20), + _buildProfileItem('Name', profileData?.name ?? ''), + _buildProfileItem('ID', profileData?.sId ?? ''), + _buildProfileItem('Email ID', profileData?.email ?? ''), + _buildProfileItem('Mobile Number', profileData?.mobileNumber ?? ''), + _buildProfileItem('Designation', profileData?.designation ?? ''), + ], + ), + ), ], ), - ), - ], - ), + ); + }, ), ), ), diff --git a/lib/screens/view_pdf_screen.dart b/lib/screens/view_pdf_screen.dart new file mode 100644 index 0000000..008bac5 --- /dev/null +++ b/lib/screens/view_pdf_screen.dart @@ -0,0 +1,30 @@ +import 'package:cheminova/models/product_manual_model.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_cached_pdfview/flutter_cached_pdfview.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: const PDF( + fitEachPage: true, + fitPolicy: FitPolicy.BOTH, + autoSpacing: false) + .cachedFromUrl( + widget.productManualModel.productManualDetail.url, + placeholder: (progress) => + Center(child: Text('$progress %')), + errorWidget: (error) => + Center(child: Text(error.toString()))))); + } +} diff --git a/lib/services/api_urls.dart b/lib/services/api_urls.dart index 192d4d6..4d11778 100644 --- a/lib/services/api_urls.dart +++ b/lib/services/api_urls.dart @@ -20,4 +20,5 @@ class ApiUrls { static const String dailyTaskUrl = '${baseUrl}task/tasks/'; static const String kycSelectTaskUrl = '${baseUrl}task/task/type/Collect KYC'; static const String updateTaskInventoryUrl = '${baseUrl}task/update-task-status/'; + static const String getProductsManual = '${baseUrl}productmanual/getall'; } diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 09f2a94..d64d061 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -13,6 +13,7 @@ import flutter_local_notifications import flutter_secure_storage_macos import geolocator_apple import path_provider_foundation +import sqflite func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin")) @@ -23,4 +24,5 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin")) GeolocatorPlugin.register(with: registry.registrar(forPlugin: "GeolocatorPlugin")) PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) + SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) } diff --git a/pubspec.lock b/pubspec.lock index 81f2d3d..b92dcef 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -374,6 +374,22 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_cache_manager: + dependency: transitive + description: + name: flutter_cache_manager + sha256: "400b6592f16a4409a7f2bb929a9a7e38c72cceb8ffb99ee57bbf2cb2cecf8386" + url: "https://pub.dev" + source: hosted + version: "3.4.1" + flutter_cached_pdfview: + dependency: "direct main" + description: + name: flutter_cached_pdfview + sha256: e0019798549828fec482585137cd91c35f19d64b4b4fd5b475b4a1eea9507463 + url: "https://pub.dev" + source: hosted + version: "0.4.2" flutter_gen: dependency: "direct main" description: @@ -430,6 +446,14 @@ packages: url: "https://pub.dev" source: hosted version: "7.2.0" + flutter_pdfview: + dependency: transitive + description: + name: flutter_pdfview + sha256: a9055bf920c7095bf08c2781db431ba23577aa5da5a056a7152dc89a18fbec6f + url: "https://pub.dev" + source: hosted + version: "1.3.2" flutter_plugin_android_lifecycle: dependency: transitive description: @@ -852,10 +876,10 @@ packages: dependency: transitive description: name: path_provider - sha256: c9e7d3a4cd1410877472158bee69963a4579f78b68c65a2b7d40d1a7a88bb161 + sha256: fec0d61223fba3154d87759e3cc27fe2c8dc498f6386c6d6fc80d1afdd1bf378 url: "https://pub.dev" source: hosted - version: "2.1.3" + version: "2.1.4" path_provider_android: dependency: transitive description: @@ -1016,6 +1040,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.0" + rxdart: + dependency: transitive + description: + name: rxdart + sha256: "5c3004a4a8dbb94bd4bf5412a4def4acdaa12e12f269737a5751369e12d1a962" + url: "https://pub.dev" + source: hosted + version: "0.28.0" shelf: dependency: transitive description: @@ -1061,6 +1093,22 @@ packages: url: "https://pub.dev" source: hosted version: "7.0.0" + sqflite: + dependency: transitive + description: + name: sqflite + sha256: a43e5a27235518c03ca238e7b4732cf35eabe863a369ceba6cbefa537a66f16d + url: "https://pub.dev" + source: hosted + version: "2.3.3+1" + sqflite_common: + dependency: transitive + description: + name: sqflite_common + sha256: "7b41b6c3507854a159e24ae90a8e3e9cc01eb26a477c118d6dca065b5f55453e" + url: "https://pub.dev" + source: hosted + version: "2.5.4+2" stack_trace: dependency: transitive description: @@ -1093,6 +1141,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.0" + synchronized: + dependency: transitive + description: + name: synchronized + sha256: a824e842b8a054f91a728b783c177c1e4731f6b124f9192468457a8913371255 + url: "https://pub.dev" + source: hosted + version: "3.2.0" table_calendar: dependency: "direct main" description: @@ -1270,5 +1326,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.4.3 <4.0.0" + dart: ">=3.5.0 <4.0.0" flutter: ">=3.22.0" diff --git a/pubspec.yaml b/pubspec.yaml index 467255b..592efa5 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -49,6 +49,7 @@ dependencies: firebase_messaging: ^15.0.4 flutter_local_notifications: ^17.2.1+2 firebase_crashlytics: ^4.0.4 + flutter_cached_pdfview: ^0.4.2 dev_dependencies: flutter_test: