second commit

This commit is contained in:
Anbarasu
2026-05-27 10:35:09 +05:30
parent c53794c04c
commit 1435ac47b0
501 changed files with 52818 additions and 0 deletions

View File

@@ -0,0 +1,563 @@
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart';
import 'package:intl/intl.dart';
import 'package:shimmer/shimmer.dart';
import '../../Controller/Dashboard/Dashboardcontroller.dart';
import '../../Controller/Dashboard/Tabs/Ordercontroller.dart';
import '../../Controller/products/product_controller.dart';
import '../../Globalwidgets/textwidget.dart';
import '../../Helper/Constants/AssetConstants.dart';
import '../../Helper/Constants/Colorconstants.dart';
import '../../Helper/Logger.dart';
import '../../widgets/product_bottom_sheet.dart';
import '../More/Notification/Notificationview.dart';
import '../Orders/orderDetails.dart';
class DashboardView extends StatelessWidget {
DashboardView({super.key});
final DashboardController dashboardController = Get.put(DashboardController());
final CurrentOrderController currentOrderController = Get.put(CurrentOrderController());
final ProductController productController = Get.put(ProductController());
@override
Widget build(BuildContext context) {
SystemChrome.setSystemUIOverlayStyle(
const SystemUiOverlayStyle(
statusBarColor: Colors.transparent, // or your color
statusBarIconBrightness: Brightness.dark, // Android icons
statusBarBrightness: Brightness.light, // iOS icons
),
);
return DefaultTabController(
length: 4,
child: Builder(
builder: (context) {
final TabController tabController = DefaultTabController.of(context);
// Listen to tab changes (tap or swipe)
tabController.addListener(() {
if (!tabController.indexIsChanging) {
String status;
switch (tabController.index) {
case 0:
status = 'created';
break;
case 1:
status = 'ongoing';
break;
case 2:
status = 'delivered';
break;
case 3:
status = 'cancelled';
break;
default:
status = 'created';
}
// Only fetch if not already loaded
currentOrderController.getOrder(status);
if (!currentOrderController.hasLoaded(status)) {
currentOrderController.getOrder(status);
}
}
});
return GetBuilder<DashboardController>(
initState: (_) {
logger.i('Init state triggered in View : ');
WidgetsBinding.instance.addPostFrameCallback((_) {
dashboardController.getDetails();
dashboardController.getTenantInfo();
currentOrderController.getOrder('created'); // Initial fetch for Placed tab
});
},
builder: (dashboardCtrl) {
return Scaffold(
appBar: AppBar(
automaticallyImplyLeading: false,
toolbarHeight: 70,
elevation: 0,
backgroundColor: ColorConstants.secondaryColor,
actions: [
Padding(
padding: EdgeInsets.only(right: 15),
child: InkWell(
onTap: () {
Get.to(() => NotificationView());
},
child: Icon(
Icons.notifications,
color: ColorConstants.darkGreyColor,
),
),
),
],
title: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TextWidget(
text: dashboardCtrl.tenantInfo?.tenantname ?? '',
fontWeight: FontWeight.w700,
fontSize: 20,
),
SizedBox(height: 5),
Row(
children: [
Icon(Icons.location_on_outlined, color: ColorConstants.darkGreyColor, size: 15),
TextWidget(
text: dashboardCtrl.tenantInfo?.locationname ?? '',
fontWeight: FontWeight.w500,
fontSize: 14,
),
],
)
],
),
bottom: TabBar(
physics: NeverScrollableScrollPhysics(),
tabs: [
Tab(text: 'Placed'),
Tab(text: 'Ongoing'),
Tab(text: 'Completed'),
Tab(text: 'Cancelled'),
],
labelColor: ColorConstants.primaryColor,
unselectedLabelColor: ColorConstants.darkGreyColor?.withOpacity(0.5),
indicatorColor: ColorConstants.primaryColor,
labelStyle: TextStyle(fontWeight: FontWeight.w600, fontSize: 14),
unselectedLabelStyle: TextStyle(fontWeight: FontWeight.w400, fontSize: 12),
),
),
body: TabBarView(
physics: const NeverScrollableScrollPhysics(),
children: [
OrderTabView(orderStatus: 'created'),
OrderTabView(orderStatus: 'ongoing'),
OrderTabView(orderStatus: 'delivered'),
OrderTabView(orderStatus: 'cancelled'),
],
),
);
},
);
},
),
);
}
}
class OrderTabView extends StatelessWidget {
final String orderStatus;
final CurrentOrderController currentOrderController = Get.find<CurrentOrderController>();
OrderTabView({
super.key,
required this.orderStatus,
});
@override
Widget build(BuildContext context) {
return Obx(() {
final orders = currentOrderController.getOrdersByStatus(orderStatus);
final isLoading = currentOrderController.getLoadingByStatus(orderStatus).value;
// Show shimmer only on first load
if (isLoading && !currentOrderController.hasLoaded(orderStatus)) {
return Center(child: ShimmerListView(height: 200));
}
if (orders.isEmpty) {
return emptyOrdersWidget();
}
return ListView.builder(
padding: const EdgeInsets.only(top: 10),
itemCount: orders.length,
itemBuilder: (context, index) {
final order = orders[index];
return InkWell(
onTap: () async {
final orderId = order.orderheaderid ?? 0;
final productController = Get.find<ProductController>();
await productController.getProductDetails(orderId);
if (context.mounted) {
Navigator.push(
context,
MaterialPageRoute(
builder: (_) => OrderDetailsPage(
orderDetails: order,
productDetails: productController.productDetail,
controller: currentOrderController,
),
),
);
}
},
child: OrderCard(
orderStatus: order.orderstatus ?? '',
orderId: order.orderid ?? '',
orderDateTime: order.orderdate ?? '',
customerName: order.deliverycustomer ?? '',
phoneNumber: order.deliverycontactno ?? '',
deliveryLocation: order.deliveryaddress ?? '',
onInfoTap: () async {
final orderId = order.orderheaderid ?? 1;
final productController = Get.find<ProductController>();
await productController.getProductDetails(orderId);
for (var product in productController.productDetail ?? []) {
if (product.productimage != null) {
precacheImage(
CachedNetworkImageProvider(product.productimage ?? ''),
context,
);
}
}
if (context.mounted) {
ProductBottomSheet.show(context, productController.productDetail ?? []);
}
},
),
);
},
);
});
}
}
/// Shimmer Card widget
class ShimmerListView extends StatelessWidget {
final double height;
const ShimmerListView({super.key, required this.height});
@override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: 10,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
child: Shimmer.fromColors(
baseColor: Colors.grey.shade300,
highlightColor: Colors.grey.shade100,
child: Container(
height: height,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
),
child: Row(
children: [
Container(
width: 60,
height: 60,
margin: const EdgeInsets.all(10),
decoration: BoxDecoration(
color: Colors.grey.shade400,
borderRadius: BorderRadius.circular(8),
),
),
const SizedBox(width: 10),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
height: 14,
width: double.infinity,
color: Colors.grey.shade400,
),
const SizedBox(height: 10),
Container(
height: 12,
width: 150,
color: Colors.grey.shade400,
),
],
),
)
],
),
),
),
);
},
);
}
}
showConfirmationBottomSheet(
BuildContext context, {
required VoidCallback onAccept,
VoidCallback? onCancel,
String title = "Confirmation",
String message = "Are you sure you want to continue?",
}) {
showModalBottomSheet(
context: context,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
),
backgroundColor: Colors.white,
builder: (context) {
return Padding(
padding: const EdgeInsets.fromLTRB(20, 20, 20, 30),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(
title,
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.w600,
),
),
const SizedBox(height: 12),
Text(
message,
style: TextStyle(fontSize: 15, color: Colors.grey[700]),
textAlign: TextAlign.center,
),
const SizedBox(height: 24),
Row(
children: [
Expanded(
child: OutlinedButton(
onPressed: () {
Navigator.pop(context);
Future.microtask(() => onCancel?.call());
},
style: OutlinedButton.styleFrom(
side: const BorderSide(color: Colors.grey),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
),
child: const Text('Cancel'),
),
),
const SizedBox(width: 12),
Expanded(
child: ElevatedButton(
onPressed: () {
Navigator.pop(context);
Future.microtask(() => onAccept());
},
style: ElevatedButton.styleFrom(
backgroundColor: ColorConstants.primaryColor,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
),
child: const Text('Accept'),
),
),
],
),
],
),
);
},
);
}
class OrderCard extends StatelessWidget {
final String orderId;
final String orderDateTime;
final String customerName;
final String phoneNumber;
final String orderStatus;
final String deliveryLocation;
final VoidCallback? onInfoTap;
const OrderCard({
super.key,
required this.orderId,
required this.orderDateTime,
required this.customerName,
required this.phoneNumber,
required this.orderStatus,
required this.deliveryLocation,
this.onInfoTap,
});
@override
Widget build(BuildContext context) {
DateTime dateTime = DateTime.parse(orderDateTime);
logger.i('orderDateTime : ${dateTime}');
final dataStr = dateTime.toLocal().toString().split(' ')[0];
final timeStr = DateFormat('h:mm a').format(dateTime);
return Card(
elevation: 0,
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 5),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
child: Padding(
padding: const EdgeInsets.all(10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
const Icon(Icons.confirmation_number_outlined, color: Colors.deepPurple),
const SizedBox(width: 6),
TextWidget(
text: 'Order ID: $orderId',
fontWeight: FontWeight.w700,
fontSize: 16,
),
],
),
IconButton(
icon: const Icon(Icons.info_outline_rounded, color: Colors.grey),
onPressed: onInfoTap ?? () {},
),
],
),
const SizedBox(height: 5),
Row(
children: [
const Icon(Icons.calendar_today_outlined, size: 20, color: Colors.teal),
const SizedBox(width: 6),
TextWidget(text: '$dataStr$timeStr'),
Spacer(),
Container(
margin: const EdgeInsets.only(top: 4),
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
decoration: BoxDecoration(
color: _getStatusColor(orderStatus).withOpacity(0.1),
borderRadius: BorderRadius.circular(12),
),
child: TextWidget(
text: orderStatus,
fontWeight: FontWeight.w600,
fontSize: 13,
color: _getStatusColor(orderStatus),
),
),
],
),
const Divider(height: 24, thickness: 0.7),
Row(
children: [
const Icon(Icons.person_outline, color: Colors.indigo, size: 20,),
const SizedBox(width: 6),
Expanded(
child: TextWidget(
text: customerName,
fontWeight: FontWeight.w500,
)
),
],
),
const SizedBox(height: 8),
Row(
children: [
const Icon(Icons.phone_outlined, color: Colors.green, size: 20),
const SizedBox(width: 6),
TextWidget(text: phoneNumber),
],
),
const SizedBox(height: 8),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Icon(Icons.location_on_outlined, color: Colors.redAccent, size: 20),
const SizedBox(width: 6),
Expanded(
child: TextWidget(
text: deliveryLocation,
textHeight: 1.4,
),
),
],
),
],
),
),
);
}
}
Color _getStatusColor(String status) {
switch (status.toLowerCase()) {
case 'created':
return Colors.blueGrey;
case 'assigned':
return Colors.indigo;
case 'accepted':
return Colors.teal;
case 'arrived':
return Colors.blue;
case 'picked':
return Colors.deepPurple;
case 'delivered':
return Colors.green;
case 'cancelled':
return Colors.red;
default:
return Colors.grey;
}
}
Widget emptyOrdersWidget() {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
SizedBox(height:10),
Image.asset(
AssetConstants.noOrdersFound,
height: 200,
width: 200,
fit: BoxFit.fill,
),
TextWidget(
text: 'No Orders Yet!',
color: ColorConstants.blackColor,
fontSize: 18,
fontWeight: FontWeight.w700,
maxLines: 2,
textAlign: TextAlign.center,
),
SizedBox(height: 10),
TextWidget(
text: 'Stay tuned, your next order will appear here soon!',
color: ColorConstants.blackColor,
fontSize: 14,
fontWeight: FontWeight.normal,
maxLines: 2,
textAlign: TextAlign.center,
),
],
),
);
}