From d4966a91139be8a17eca557dd3c5f7855135627e Mon Sep 17 00:00:00 2001 From: Sneha Date: Wed, 17 Sep 2025 12:32:00 +0530 Subject: [PATCH] plans screen added --- images/backbutton_appbar.png | Bin 0 -> 836 bytes images/help_appbar.png | Bin 0 -> 2856 bytes images/search.png | Bin 0 -> 1776 bytes lib/common/dashboard.dart | 50 ++-- lib/common/settings.dart | 2 +- lib/orders/all_orders.dart | 98 ++++--- lib/orders/search_order_appbar.dart | 67 +++-- lib/plans/all_plans.dart | 404 ++++++++++++++++++++++++++++ lib/plans/plan_requests.dart | 294 ++++++++++++++++++++ lib/plans/plans_model.dart | 19 ++ lib/plans/search_plan_appbar.dart | 92 +++++++ 11 files changed, 957 insertions(+), 69 deletions(-) create mode 100644 images/backbutton_appbar.png create mode 100644 images/help_appbar.png create mode 100644 images/search.png create mode 100644 lib/plans/all_plans.dart create mode 100644 lib/plans/plan_requests.dart create mode 100644 lib/plans/plans_model.dart create mode 100644 lib/plans/search_plan_appbar.dart diff --git a/images/backbutton_appbar.png b/images/backbutton_appbar.png new file mode 100644 index 0000000000000000000000000000000000000000..0d1c569006427d6e8820b2a01749831553965394 GIT binary patch literal 836 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 S;I66w0000eK8^c literal 0 HcmV?d00001 diff --git a/lib/common/dashboard.dart b/lib/common/dashboard.dart index f9b5a49..427063a 100644 --- a/lib/common/dashboard.dart +++ b/lib/common/dashboard.dart @@ -1,11 +1,15 @@ import 'dart:convert'; import 'dart:io'; +import 'package:flutter/cupertino.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:image_picker/image_picker.dart'; import 'package:supplier_new/common/settings.dart'; import 'package:supplier_new/orders/all_orders.dart'; +import 'package:supplier_new/orders/order_requests.dart'; +import 'package:supplier_new/plans/all_plans.dart'; +import 'package:supplier_new/plans/plan_requests.dart'; import 'package:supplier_new/resources/fleet.dart'; import 'package:supplier_new/set_rates/set_rates.dart'; @@ -32,8 +36,8 @@ class _DashboardScreenState extends State { // Define a list of widgets for each screen final List _screens = [ HomeScreen(), - HomeScreen(), - HomeScreen(), + AllOrders(), + AllPlans(), FleetStep1Page(), HomeScreen(), ]; @@ -251,7 +255,7 @@ class _DashboardScreenState extends State { _scaffoldKey.currentState?.openEndDrawer(); return false; // Prevent the default back action (exit the app) } - else if (_currentIndex == 2) { + else if (_currentIndex == 0) { final shouldPop = await showDialog( context: context, builder: (context) { @@ -339,7 +343,7 @@ class _DashboardScreenState extends State { } else { setState(() { - _currentIndex = 2; + _currentIndex = 0; }); return false; } @@ -347,7 +351,7 @@ class _DashboardScreenState extends State { child: Scaffold( key: _scaffoldKey, backgroundColor: Colors.white, - appBar: AppBar( + appBar: _currentIndex==0?AppBar( backgroundColor: Colors.white, elevation: 0, scrolledUnderElevation: 0, @@ -392,7 +396,7 @@ class _DashboardScreenState extends State { _scaffoldKey.currentState?.openDrawer(); }, ), - ), + ):null, drawer: Drawer( width: MediaQuery.of(context).size.width, backgroundColor: Colors.white, @@ -566,7 +570,7 @@ class _DashboardScreenState extends State { style: fontTextStyle(20,Color(0XFF2A2A2A),FontWeight.w500), ), Visibility( - visible:AppSettings.loginType.toString().toLowerCase()=='user', + visible:true, child: Text( AppSettings.email, style: fontTextStyle(14,Color(0XFF2A2A2A),FontWeight.w400), @@ -809,19 +813,35 @@ class _HomeScreenState extends State { /// Requests Section Row( - children: const [ + children: [ Expanded( - child: RequestCard( - title: "Order Requests", - subtitle: "1 new request", + child: GestureDetector( + onTap: (){ + Navigator.push( + context, + new MaterialPageRoute( + builder: (__) => new OrderRequestsPage())); + }, + child: RequestCard( + title: "Order Requests", + subtitle: "1 new request", + ), ), ), SizedBox(width: 12), Expanded( - child: RequestCard( - title: "Plan Requests", - subtitle: "2 new request", - ), + child: GestureDetector( + onTap: (){ + Navigator.push( + context, + new MaterialPageRoute( + builder: (__) => new PlanRequestPage())); + }, + child: RequestCard( + title: "Plan Requests", + subtitle: "2 new request", + ), + ) ), ], ) diff --git a/lib/common/settings.dart b/lib/common/settings.dart index ffd3fc6..625156b 100644 --- a/lib/common/settings.dart +++ b/lib/common/settings.dart @@ -373,7 +373,7 @@ class AppSettings{ static Future saveAvailableReportAndLocationsInMemory( dynamic input) async { // save login name information - await saveData('username', input['simplydata']['username'], 'STRING'); + await saveData('username', input['simplydata']['suppliername'], 'STRING'); await saveData('logintype', input['simplydata']['loginType'], 'STRING'); await saveData('all_motor_access', input['simplydata']['all_motor_access'], 'STRING'); await saveData('buildingname', input['simplydata']['buildingName'], 'STRING'); diff --git a/lib/orders/all_orders.dart b/lib/orders/all_orders.dart index 649e854..465a4f6 100644 --- a/lib/orders/all_orders.dart +++ b/lib/orders/all_orders.dart @@ -52,6 +52,26 @@ class _AllOrdersState extends State { time: "09:30 PM, Yesterday", extraInfo: "Cancelled by user", ), + OrdersModel( + date: DateTime(2025, 8, 25), + imageAsset: "images/building.png",// sample image + status: "assigned", + title: "Lakeview Towers", + location: "Madhapur", + quantity: "8,000L - Tanker Water", + time: "09:30 PM, Yesterday", + extraInfo: "Assigned to Madhav", + ), + OrdersModel( + date: DateTime(2025, 8, 26), + imageAsset: "images/building.png",// sample image + status: "pending", + title: "Lakeview Towers", + location: "Madhapur", + quantity: "8,000L - Tanker Water", + time: "09:30 PM, Yesterday", + extraInfo: "", + ), ]; // ✅ Group orders by date @@ -266,11 +286,32 @@ class OrderCard extends StatelessWidget { Color _getStatusColor() { switch (order.status.toLowerCase()) { case "completed": - return Colors.green; + return Color(0XFFC4E8C3); case "in-progress": - return Colors.blue; + return Color(0XFFE8F2FF); case "cancelled": - return Colors.red; + return Color(0XFFFCEDEC); + case "assigned": + return Color(0XFFF9DBC6); + case "pending": + return Color(0XFFFDF3D3); + default: + return Colors.grey; + } + } + + Color _getTextStatusColor() { + switch (order.status.toLowerCase()) { + case "completed": + return Color(0XFF0A9E04); + case "in-progress": + return Color(0XFF1D7AFC); + case "cancelled": + return Color(0XFFE2483D); + case "assigned": + return Color(0XFFE56910); + case "pending": + return Color(0XFFD0AE3C); default: return Colors.grey; } @@ -279,6 +320,7 @@ class OrderCard extends StatelessWidget { @override Widget build(BuildContext context) { final statusColor = _getStatusColor(); + final textStatusColor = _getTextStatusColor(); return Padding(padding: EdgeInsets.fromLTRB(0, 8, 0, 0), child: Container( @@ -301,13 +343,13 @@ class OrderCard extends StatelessWidget { ClipRRect( borderRadius: const BorderRadius.only( topLeft: Radius.circular(12), - bottomLeft: Radius.circular(12), + bottomLeft: Radius.circular(0), ), child: order.imageAsset != null ? Image.asset( order.imageAsset!, - height: 100, - width: 100, + height: 145, + width: 145, fit: BoxFit.cover, ) : Image.network( @@ -332,63 +374,43 @@ class OrderCard extends StatelessWidget { vertical: 2, ), decoration: BoxDecoration( - color: statusColor.withOpacity(0.1), - borderRadius: BorderRadius.circular(8), + color: statusColor, + borderRadius: BorderRadius.circular(4), ), child: Text( order.status, - style: TextStyle( - fontSize: 11, - fontWeight: FontWeight.w600, - color: statusColor, - ), + style: fontTextStyle(10,textStatusColor,FontWeight.w400) ), ), const SizedBox(height: 6), Text( order.title, - style: const TextStyle( - fontSize: 15, - fontWeight: FontWeight.w600, - ), + style:fontTextStyle(16,Color(0XFF2D2E30),FontWeight.w600) ), Text( order.location, - style: TextStyle( - fontSize: 12, - color: Colors.grey.shade600, - ), + style: fontTextStyle(12,Color(0XFF646566),FontWeight.w400) ), const SizedBox(height: 4), Text( order.quantity, - style: const TextStyle( - fontSize: 13, - fontWeight: FontWeight.w500, - ), + style: fontTextStyle(14,Color(0XFF444444),FontWeight.w500) ), Text( order.time, - style: TextStyle( - fontSize: 12, - color: Colors.grey.shade600, - ), + style:fontTextStyle(12,Color(0XFF939495),FontWeight.w400) ), const SizedBox(height: 4), Text( order.extraInfo, - style: TextStyle( - fontSize: 12, - color: order.status == "in-progress" - ? Colors.blue - : Colors.grey.shade600, - fontWeight: order.status == "in-progress" - ? FontWeight.w600 - : FontWeight.w400, - ), + style:fontTextStyle(12, order.status == "in-progress" + ? Color(0XFF1D7AFC) + : Color(0XFF646566),FontWeight.w400) + + ), ], ), diff --git a/lib/orders/search_order_appbar.dart b/lib/orders/search_order_appbar.dart index d484bdd..c2eb385 100644 --- a/lib/orders/search_order_appbar.dart +++ b/lib/orders/search_order_appbar.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:supplier_new/common/settings.dart'; class SearchOrderAppBar extends StatelessWidget implements PreferredSizeWidget { final TextEditingController controller; @@ -16,36 +17,72 @@ class SearchOrderAppBar extends StatelessWidget implements PreferredSizeWidget { Widget build(BuildContext context) { return AppBar( backgroundColor: Colors.white, + scrolledUnderElevation: 0, elevation: 0, - leading: IconButton( - icon: const Icon(Icons.arrow_back, color: Colors.black), - onPressed: onBack, + leading: GestureDetector( + onTap: () { + Navigator.pop(context); + }, + child: Padding( + padding: const EdgeInsets.fromLTRB( + 8, 8, 8, 8), // Add padding if needed + child: Image.asset( + 'images/backbutton_appbar.png', + height: 24, + width: 24,// Replace with your image path + fit: BoxFit.contain, // Adjust the fit + ), + ), ), titleSpacing: 0, title: Container( height: 40, decoration: BoxDecoration( color: Colors.white, - borderRadius: BorderRadius.circular(24), - border: Border.all(color: Colors.grey.shade400), + borderRadius: BorderRadius.circular(22), + border: Border.all(color: Color(0XFF939495)), ), child: TextField( controller: controller, - decoration: const InputDecoration( + decoration: InputDecoration( hintText: "Search order", - hintStyle: TextStyle(fontSize: 14, color: Colors.grey), - prefixIcon: Icon(Icons.search, color: Colors.grey), + hintStyle: fontTextStyle(16, Color(0XFF646566), FontWeight.w400), + prefixIcon: SizedBox( + height: 20, + width: 20, + child: Padding( + padding: const EdgeInsets.all(8.0), // adjust spacing + child: Image.asset( + 'images/search.png', + fit: BoxFit.contain, + ), + ), + ), border: InputBorder.none, - contentPadding: EdgeInsets.symmetric(vertical: 10), + contentPadding: const EdgeInsets.symmetric(vertical: 0), + ), + style: fontTextStyle(16,Color(0XFF2A2A2A),FontWeight.w400), ), ), - actions: [ - IconButton( - icon: const Icon(Icons.help_outline, color: Colors.black), - onPressed: onHelp, - ), - const SizedBox(width: 8), + + actions: [ + Padding(padding: EdgeInsets.all(8), + child: + GestureDetector( + onTap: () { + }, + child: Padding( + padding: const EdgeInsets.fromLTRB( + 8, 8, 8, 8), // Add padding if needed + child: Image.asset( + 'images/help_appbar.png', + height: 24, + width: 24,// Replace with your image path + fit: BoxFit.contain, // Adjust the fit + ), + ), + ),) ], ); } diff --git a/lib/plans/all_plans.dart b/lib/plans/all_plans.dart new file mode 100644 index 0000000..95cca86 --- /dev/null +++ b/lib/plans/all_plans.dart @@ -0,0 +1,404 @@ +import 'package:flutter/material.dart'; +import 'package:supplier_new/common/settings.dart'; +import 'package:supplier_new/plans/plan_requests.dart'; +import 'package:supplier_new/plans/plans_model.dart'; +import 'package:supplier_new/plans/search_plan_appbar.dart'; + +class AllPlans extends StatefulWidget { + const AllPlans({super.key}); + + @override + State createState() => _AllPlansState(); +} + +class _AllPlansState extends State { + final TextEditingController searchController = TextEditingController(); + + @override + Widget build(BuildContext context) { + final List plans = [ + PlansModel( + status: "Active", + apartment: "Green Valley Apartments", + liters: "10,000 L - Drinking water", + price: "₹3,400", + advance: "10% Advance", + deliveries: "10/22 Deliveries", + frequency: "4/week", + ), + PlansModel( + status: "Active", + apartment: "Lakeview Towers", + liters: "8,000 L - Drinking water", + price: "₹2,900", + advance: "5% Advance", + deliveries: "8/20 Deliveries", + frequency: "3/week", + ), + PlansModel( + status: "Active", + apartment: "Hilltop Residency", + liters: "12,000 L - Drinking water", + price: "₹4,500", + advance: "15% Advance", + deliveries: "12/25 Deliveries", + frequency: "5/week", + ), + PlansModel( + status: "Inactive", + apartment: "Silver Oak Villas", + liters: "6,000 L - Drinking water", + price: "₹2,100", + advance: "0% Advance", + deliveries: "0/15 Deliveries", + frequency: "0/week", + ), + ]; + + return Scaffold( + backgroundColor: const Color(0XFFFFFFFF), + appBar: SearchPlanAppBar( + controller: searchController, + onBack: () => Navigator.pop(context), + onHelp: () { + print("Help tapped"); + }, + ), + body: SingleChildScrollView( + child: Column( + children: [ + /// 🔹 Grey top section + Container( + decoration: const BoxDecoration( + color: Color(0XFFF2F2F2), + borderRadius: BorderRadius.only( + bottomLeft: Radius.circular(24), + bottomRight: Radius.circular(24), + ), + ), + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 24), + child: Column( + children: [ + Text( + "05", + style: fontTextStyle(64, const Color(0XFF2D2E30), FontWeight.w700), + ), + Text( + "Active Plans", + style: fontTextStyle(24, const Color(0XFF2D2E30), FontWeight.w600), + ), + const SizedBox(height: 24), + + /// Bore Water + Drinking Water + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + PlanCategoryCard( + image: Image.asset( + 'images/bore-water.png', + fit: BoxFit.contain, + height: 40, + width: 40, + ), + value: "02", + label: "Bore Water", + ), + PlanCategoryCard( + image: Image.asset( + 'images/drinking-water.png', + height: 40, + width: 40, + fit: BoxFit.contain, + ), + value: "03", + label: "Drinking Water", + ), + ], + ), + const SizedBox(height: 24), + + /// Button + SizedBox( + width: double.infinity, + child: ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: const Color(0XFF8270DB), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(32), + ), + padding: const EdgeInsets.symmetric( + horizontal: 16, vertical: 16), + ), + onPressed: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => const PlanRequestPage()), + ); + }, + child: Text( + "View Plan Requests", + style: fontTextStyle( + 16, const Color(0XFFFFFFFF), FontWeight.w500), + ), + ), + ), + ], + ), + ), + + + + /// 🔹 White bottom section (filters + list) + Container( + color: Color(0XFFFFFFFF), + child: Column( + children: [ + const SizedBox(height: 12), + + /// Filters Row + SingleChildScrollView( + scrollDirection: Axis.horizontal, + padding: const EdgeInsets.symmetric(horizontal: 12), + child: Row( + children: [ + FilterChipWidget(label: "Building"), + const SizedBox(width: 8), + FilterChipWidget(label: "Status"), + const SizedBox(width: 8), + FilterChipWidget(label: "Date"), + const SizedBox(width: 8), + FilterChipWidget(label: "Amount"), + ], + ), + ), + + const SizedBox(height: 20), + + /// Order List + ListView.builder( + padding: const EdgeInsets.all(12), + itemCount: plans.length, + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemBuilder: (context, index) { + final delivery = plans[index]; + return PlansCard(delivery: delivery); + }, + ), + ], + ), + ), + ], + ), + ), + ); + } +} + +/// Curve clipper for smooth transition +class SmallCurveClipper extends CustomClipper { + @override + Path getClip(Size size) { + final path = Path(); + path.lineTo(0, 0); + path.lineTo(0, size.height); + + // Smooth downward curve + path.quadraticBezierTo( + size.width / 2, -20, // control point (curve depth) + size.width, size.height, + ); + + path.lineTo(size.width, 0); + path.close(); + return path; + } + + @override + bool shouldReclip(covariant CustomClipper oldClipper) => false; +} + +/// Category Card +class PlanCategoryCard extends StatelessWidget { + final Image image; + final String value; + final String label; + + const PlanCategoryCard({ + super.key, + required this.image, + required this.value, + required this.label, + }); + + @override + Widget build(BuildContext context) { + return Column( + children: [ + SizedBox(width: 40, height: 40, child: image), + const SizedBox(height: 8), + Text( + value, + style: fontTextStyle(20, const Color(0XFF515253), FontWeight.w700), + ), + const SizedBox(height: 4), + Text( + label, + style: fontTextStyle(16, const Color(0XFF515253), FontWeight.w400), + ), + ], + ); + } +} + +/// Filter Chip +class FilterChipWidget extends StatelessWidget { + final String label; + const FilterChipWidget({super.key, required this.label}); + + @override + Widget build(BuildContext context) { + return ChoiceChip( + label: Text(label), + selected: false, + onSelected: (_) {}, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(20), + ), + backgroundColor: Colors.white, + side: BorderSide(color: Colors.grey.shade300), + ); + } +} + +/// Plan Card +class PlansCard extends StatelessWidget { + final PlansModel delivery; + + const PlansCard({super.key, required this.delivery}); + + @override + Widget build(BuildContext context) { + bool isActive = delivery.status == "Active"; + + return Container( + margin: const EdgeInsets.only(bottom: 12), + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(12), + border: Border.all(color: const Color(0xFFE5E5E5)), + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.03), + blurRadius: 5, + offset: const Offset(0, 2), + ) + ], + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Status Chip + Container( + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2), + decoration: BoxDecoration( + color: isActive ? const Color(0xFFE9F9EE) : const Color(0xFFF2F2F2), + borderRadius: BorderRadius.circular(6), + border: Border.all( + color: isActive ? const Color(0xFF3BB273) : Colors.grey.shade400, + ), + ), + child: Text( + delivery.status, + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w500, + color: isActive ? const Color(0xFF3BB273) : Colors.grey.shade600, + ), + ), + ), + const SizedBox(height: 8), + + // Apartment + Price Row + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + delivery.apartment, + style: const TextStyle( + fontSize: 15, + fontWeight: FontWeight.w600, + color: Color(0xFF2A2A2A), + ), + ), + Text( + delivery.price, + style: const TextStyle( + fontSize: 15, + fontWeight: FontWeight.w600, + color: Color(0xFF2A2A2A), + ), + ), + ], + ), + const SizedBox(height: 4), + + // Liters & Advance + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + delivery.liters, + style: const TextStyle( + fontSize: 14, + fontWeight: FontWeight.w500, + color: Color(0xFF7B5AF4), + ), + ), + Text( + delivery.advance, + style: const TextStyle( + fontSize: 12, + color: Color(0xFF646566), + ), + ), + ], + ), + const SizedBox(height: 12), + + // Deliveries row with background + Container( + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 8), + decoration: BoxDecoration( + color: const Color(0xFFF8F6FF), + borderRadius: BorderRadius.circular(8), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + delivery.deliveries, + style: const TextStyle( + fontSize: 13, + fontWeight: FontWeight.w500, + color: Color(0xFF2A2A2A), + ), + ), + Text( + delivery.frequency, + style: const TextStyle( + fontSize: 13, + fontWeight: FontWeight.w500, + color: Color(0xFF7B5AF4), + ), + ), + ], + ), + ), + ], + ), + ); + } +} diff --git a/lib/plans/plan_requests.dart b/lib/plans/plan_requests.dart new file mode 100644 index 0000000..91745a1 --- /dev/null +++ b/lib/plans/plan_requests.dart @@ -0,0 +1,294 @@ +import 'package:flutter/material.dart'; + +class PlanRequestPage extends StatefulWidget { + const PlanRequestPage({super.key}); + + @override + State createState() => _PlanRequestPageState(); +} + +class _PlanRequestPageState extends State { + final TextEditingController searchController = TextEditingController(); + + // ✅ Sample orders list + final List allPlans = [ + PlanModel( + status: "New", + title: "Green Valley Apartments", + location: "Gachibowli", + description: "10,000 L - Drinking water", + price: "₹3,400", + ), + PlanModel( + status: "Expires in 15m", + title: "Lakeview Towers", + location: "Madhapur", + description: "8,000 L - Borewell water", + price: "₹2,700", + ), + PlanModel( + status: "Expired", + title: "Sunrise Residency", + location: "Kukatpally", + description: "12,000 L - Tanker water", + price: "₹4,000", + ), + PlanModel( + status: "Rejected", + title: "Skyline Apartments", + location: "Kompally", + description: "5,000 L - Drinking water", + price: "₹1,600", + ), + PlanModel( + status: "Pending", + title: "Skyline Apartments", + location: "Kompally", + description: "5,000 L - Drinking water", + price: "₹1,600", + ), + PlanModel( + status: "Rejected", + title: "Elite Towers", + location: "Hitech City", + description: "20,000 L - Borewell water", + price: "₹6,000", + ), + ]; + + @override + Widget build(BuildContext context) { + // ✅ Split orders into rejected and others + final rejectedPlans = + allPlans.where((o) => o.status.toLowerCase() == "rejected").toList(); + final otherPlans = + allPlans.where((o) => o.status.toLowerCase() != "rejected").toList(); + + return Scaffold( + backgroundColor: Colors.white, + appBar: AppBar( + backgroundColor: Colors.white, + elevation: 0, + leading: IconButton( + icon: const Icon(Icons.arrow_back, color: Colors.black), + onPressed: () => Navigator.pop(context), + ), + title: const Text( + "Plan Requests", + style: TextStyle( + color: Colors.black, + fontSize: 16, + fontWeight: FontWeight.w600, + ), + ), + centerTitle: false, + actions: [ + IconButton( + icon: const Icon(Icons.help_outline, color: Colors.black), + onPressed: () {}, + ), + const SizedBox(width: 8), + ], + ), + body: Padding( + padding: const EdgeInsets.all(12.0), + child: Column( + children: [ + /// Search bar + Row( + children: [ + Expanded( + child: Container( + height: 42, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(24), + border: Border.all(color: Colors.grey.shade300), + color: Colors.white, + ), + child: TextField( + controller: searchController, + decoration: const InputDecoration( + hintText: "Search", + prefixIcon: Icon(Icons.search, color: Colors.grey), + border: InputBorder.none, + contentPadding: EdgeInsets.symmetric(vertical: 10), + ), + ), + ), + ), + const SizedBox(width: 10), + Container( + height: 42, + width: 42, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(12), + border: Border.all(color: Colors.grey.shade300), + color: Colors.white, + ), + child: IconButton( + icon: const Icon(Icons.sort, size: 20, color: Colors.black), + onPressed: () {}, + ), + ), + ], + ), + + const SizedBox(height: 16), + + /// Orders List + Expanded( + child: ListView( + children: [ + // Active / Other Orders + ...otherPlans.map((o) => OrderCard(order: o)), + + // Rejected Orders Section + if (rejectedPlans.isNotEmpty) ...[ + const SizedBox(height: 12), + const Text( + "Rejected Requests", + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w600, + color: Colors.black, + ), + ), + const SizedBox(height: 8), + ...rejectedPlans.map((o) => OrderCard(order: o)), + ], + ], + ), + ), + ], + ), + ), + ); + } +} + +/// Order Model +class PlanModel { + final String status; + final String title; + final String location; + final String description; + final String price; + + PlanModel({ + required this.status, + required this.title, + required this.location, + required this.description, + required this.price, + }); +} + +/// Order Card widget +class OrderCard extends StatelessWidget { + final PlanModel order; + + const OrderCard({super.key, required this.order}); + + Color _getStatusColor() { + switch (order.status.toLowerCase()) { + case "new": + return Colors.blue; + case "expires in 15m": + case "expires in 5m": + return Colors.orange; + case "expired": + return Colors.grey; + case "rejected": + return Colors.red; + default: + return Colors.black; + } + } + + @override + Widget build(BuildContext context) { + final statusColor = _getStatusColor(); + + return Container( + margin: const EdgeInsets.only(bottom: 12), + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(12), + border: Border.all(color: Colors.grey.shade300), + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + /// Left content + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Status chip + Container( + padding: const EdgeInsets.symmetric( + horizontal: 8, + vertical: 4, + ), + decoration: BoxDecoration( + color: statusColor.withOpacity(0.1), + borderRadius: BorderRadius.circular(8), + ), + child: Text( + order.status, + style: TextStyle( + fontSize: 11, + fontWeight: FontWeight.w600, + color: statusColor, + ), + ), + ), + const SizedBox(height: 6), + + // Title + Text( + order.title, + style: const TextStyle( + fontSize: 15, + fontWeight: FontWeight.w600, + ), + ), + + // Location + Text( + order.location, + style: TextStyle( + fontSize: 12, + color: Colors.grey.shade600, + ), + ), + + const SizedBox(height: 4), + + // Description + Text( + order.description, + style: const TextStyle( + fontSize: 12, + color: Colors.blue, + fontWeight: FontWeight.w500, + ), + ), + ], + ), + ), + + /// Price + Text( + order.price, + style: const TextStyle( + fontSize: 15, + fontWeight: FontWeight.w600, + ), + ), + ], + ), + ); + } +} diff --git a/lib/plans/plans_model.dart b/lib/plans/plans_model.dart new file mode 100644 index 0000000..59c36a0 --- /dev/null +++ b/lib/plans/plans_model.dart @@ -0,0 +1,19 @@ +class PlansModel { + final String status; + final String apartment; + final String liters; + final String price; + final String advance; + final String deliveries; + final String frequency; + + PlansModel({ + required this.status, + required this.apartment, + required this.liters, + required this.price, + required this.advance, + required this.deliveries, + required this.frequency, + }); +} \ No newline at end of file diff --git a/lib/plans/search_plan_appbar.dart b/lib/plans/search_plan_appbar.dart new file mode 100644 index 0000000..6e7f823 --- /dev/null +++ b/lib/plans/search_plan_appbar.dart @@ -0,0 +1,92 @@ +import 'package:flutter/material.dart'; +import 'package:supplier_new/common/settings.dart'; + +class SearchPlanAppBar extends StatelessWidget implements PreferredSizeWidget { + final TextEditingController controller; + final VoidCallback onBack; + final VoidCallback onHelp; + + const SearchPlanAppBar({ + super.key, + required this.controller, + required this.onBack, + required this.onHelp, + }); + + @override + Widget build(BuildContext context) { + return AppBar( + backgroundColor: Colors.white, + scrolledUnderElevation: 0, + elevation: 0, + leading: GestureDetector( + onTap: () { + Navigator.pop(context); + }, + child: Padding( + padding: const EdgeInsets.fromLTRB( + 8, 8, 8, 8), // Add padding if needed + child: Image.asset( + 'images/backbutton_appbar.png', + height: 24, + width: 24,// Replace with your image path + fit: BoxFit.contain, // Adjust the fit + ), + ), + ), + titleSpacing: 0, + title: Container( + height: 40, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(22), + border: Border.all(color: Color(0XFF939495)), + ), + child: TextField( + controller: controller, + decoration: InputDecoration( + hintText: "Search Plan", + hintStyle: fontTextStyle(16, Color(0XFF646566), FontWeight.w400), + prefixIcon: SizedBox( + height: 20, + width: 20, + child: Padding( + padding: const EdgeInsets.all(8.0), // adjust spacing + child: Image.asset( + 'images/search.png', + fit: BoxFit.contain, + ), + ), + ), + border: InputBorder.none, + contentPadding: const EdgeInsets.symmetric(vertical: 0), + + ), + style: fontTextStyle(16,Color(0XFF2A2A2A),FontWeight.w400), + ), + ), + + actions: [ + Padding(padding: EdgeInsets.all(8), + child: + GestureDetector( + onTap: () { + }, + child: Padding( + padding: const EdgeInsets.fromLTRB( + 8, 8, 8, 8), // Add padding if needed + child: Image.asset( + 'images/help_appbar.png', + height: 24, + width: 24,// Replace with your image path + fit: BoxFit.contain, // Adjust the fit + ), + ), + ),) + ], + ); + } + + @override + Size get preferredSize => const Size.fromHeight(kToolbarHeight); +}