2026-04-15
This commit is contained in:
1 parent
d01e5ba860
commit
96de59e9be
46 files changed
+1299
-1191
No files matched your search
@@ -1,12 +1,14 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:taxglide/consts/app_asstes.dart';
|
||||
import 'package:taxglide/consts/app_style.dart';
|
||||
import 'package:taxglide/consts/comman_webscoket.dart';
|
||||
import 'package:taxglide/consts/local_store.dart';
|
||||
import 'package:taxglide/consts/notification_webscoket.dart';
|
||||
import 'package:taxglide/controller/api_contoller.dart';
|
||||
import 'package:taxglide/view/Mahi_chat/live_chat_screen.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:taxglide/consts/responsive_helper.dart';
|
||||
|
||||
class CommanChatBox extends ConsumerStatefulWidget {
|
||||
final String? chatId;
|
||||
@@ -86,11 +88,12 @@ class _CommanChatBoxState extends ConsumerState<CommanChatBox> {
|
||||
}
|
||||
|
||||
final id = snapshot.data ?? "0";
|
||||
final r = ResponsiveUtils(context);
|
||||
final countAsync = ref.watch(countProvider(id));
|
||||
|
||||
return Positioned(
|
||||
right: 20,
|
||||
bottom: 120,
|
||||
bottom: r.spacing(mobile: 35, tablet: 45, desktop: 55),
|
||||
child: Stack(
|
||||
clipBehavior: Clip.none,
|
||||
children: [
|
||||
@@ -154,10 +157,9 @@ class _CommanChatBoxState extends ConsumerState<CommanChatBox> {
|
||||
),
|
||||
child: Text(
|
||||
data.count.toString(),
|
||||
style: const TextStyle(
|
||||
style: AppTextStyles.bold.copyWith(
|
||||
color: Colors.white,
|
||||
fontSize: 11,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 10,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -13,6 +13,9 @@ import 'package:taxglide/view/screens/home_screen.dart';
|
||||
import 'package:taxglide/view/screens/list_service_screen.dart';
|
||||
import 'package:taxglide/view/screens/profile/employee_profile/employee_profile_screen.dart';
|
||||
import 'package:taxglide/view/screens/profile/profile_screen.dart';
|
||||
import 'package:curved_labeled_navigation_bar/curved_navigation_bar.dart';
|
||||
import 'package:curved_labeled_navigation_bar/curved_navigation_bar_item.dart';
|
||||
import 'package:taxglide/consts/app_style.dart';
|
||||
|
||||
class MainController extends ConsumerStatefulWidget {
|
||||
final Widget? child; // Optional child (like ServiceRequestScreen)
|
||||
@@ -39,7 +42,7 @@ class _MainControllerState extends ConsumerState<MainController> {
|
||||
final List<String> _labels = [
|
||||
'Home',
|
||||
'Services',
|
||||
'Service Details',
|
||||
'Task Status',
|
||||
'Profile',
|
||||
];
|
||||
|
||||
@@ -177,65 +180,6 @@ class _MainControllerState extends ConsumerState<MainController> {
|
||||
body: Stack(
|
||||
children: [
|
||||
mainContent,
|
||||
|
||||
/// ✅ Bottom Navigation Bar
|
||||
Positioned(
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
child: SafeArea(
|
||||
top: false,
|
||||
child: Container(
|
||||
width: size.width,
|
||||
height: 80,
|
||||
child: Stack(
|
||||
clipBehavior: Clip.none,
|
||||
children: [
|
||||
CustomPaint(
|
||||
size: Size(size.width, 80),
|
||||
painter: BNBCustomPainter(),
|
||||
),
|
||||
Center(
|
||||
heightFactor: 0.6,
|
||||
child: GestureDetector(
|
||||
onTap: () {},
|
||||
child: CustomPaint(
|
||||
painter: PentagonPainter(
|
||||
color: const Color(0xFF61277A),
|
||||
),
|
||||
child: Container(
|
||||
width: 70,
|
||||
height: 70,
|
||||
alignment: Alignment.center,
|
||||
child: Image.asset(
|
||||
AppAssets.maincontroller,
|
||||
color: Colors.white,
|
||||
fit: BoxFit.contain,
|
||||
height: 40,
|
||||
width: 40,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: size.width,
|
||||
height: 80,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
_buildNavItem(Icons.home, 0, _labels[0]),
|
||||
_buildNavItem(Icons.list_alt_sharp, 1, _labels[1]),
|
||||
SizedBox(width: size.width * 0.20),
|
||||
_buildNavItem(Icons.history_edu, 2, _labels[2]),
|
||||
_buildNavItem(Icons.person_2, 3, _labels[3]),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
dashboardAsync.when(
|
||||
data: (dashboard) {
|
||||
final int? chatIdInt = dashboard.generalChatId;
|
||||
@@ -253,199 +197,89 @@ class _MainControllerState extends ConsumerState<MainController> {
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// ✅ Navigation Logic with Refresh
|
||||
Widget _buildNavItem(IconData icon, int index, String label) {
|
||||
bool isSelected = currentIndex == index;
|
||||
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
// 🔹 If inside ServiceRequestScreen
|
||||
if (widget.child != null) {
|
||||
if (widget.initialIndex == index) return;
|
||||
|
||||
if (widget.sourceTabIndex == 0 && index == 1) {
|
||||
Get.offAll(() => const MainController(initialIndex: 1));
|
||||
return;
|
||||
}
|
||||
|
||||
if (widget.sourceTabIndex == 1 && index == 1) return;
|
||||
|
||||
Get.offAll(() => MainController(initialIndex: index));
|
||||
return;
|
||||
}
|
||||
|
||||
// 🔹 If same tab tapped again → refresh
|
||||
if (currentIndex == index) {
|
||||
_refreshTab(index);
|
||||
return;
|
||||
}
|
||||
|
||||
// 🔹 Switch to a different tab
|
||||
setBottomBarIndex(index);
|
||||
},
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
AnimatedContainer(
|
||||
duration: const Duration(milliseconds: 200),
|
||||
padding: const EdgeInsets.all(6),
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
border: isSelected
|
||||
? Border.all(color: const Color(0xFF61277A), width: 2)
|
||||
: null,
|
||||
),
|
||||
child: Icon(
|
||||
icon,
|
||||
color: isSelected
|
||||
? const Color(0xFF61277A)
|
||||
: const Color(0xFF6C7278),
|
||||
size: isSelected ? 19.5 : 20.8,
|
||||
),
|
||||
),
|
||||
if (isSelected)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 4),
|
||||
child: Text(
|
||||
label,
|
||||
style: const TextStyle(
|
||||
color: Color(0xFF61277A),
|
||||
bottomNavigationBar: SafeArea(
|
||||
top: false,
|
||||
child: CurvedNavigationBar(
|
||||
backgroundColor: Color(0xFF61277A),
|
||||
buttonBackgroundColor: Colors.white,
|
||||
color: Colors.white,
|
||||
animationDuration: const Duration(milliseconds: 300),
|
||||
index: currentIndex,
|
||||
items: [
|
||||
CurvedNavigationBarItem(
|
||||
child: Icon(
|
||||
Icons.home,
|
||||
color: currentIndex == 0 ? Colors.black : const Color(0xFF6C7278),
|
||||
),
|
||||
label: _labels[0],
|
||||
labelStyle: (currentIndex == 0 ? AppTextStyles.bold : AppTextStyles.bold).copyWith(
|
||||
color: currentIndex == 0 ? const Color(0xFF61277A) : const Color(0xFF6C7278),
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
CurvedNavigationBarItem(
|
||||
child: Icon(
|
||||
Icons.list_alt_sharp,
|
||||
color: currentIndex == 1 ? Colors.black : const Color(0xFF6C7278),
|
||||
),
|
||||
label: _labels[1],
|
||||
labelStyle: (currentIndex == 0 ? AppTextStyles.bold : AppTextStyles.bold).copyWith(
|
||||
color: currentIndex == 1 ? const Color(0xFF61277A) : const Color(0xFF6C7278),
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
CurvedNavigationBarItem(
|
||||
child: Icon(
|
||||
Icons.history_edu,
|
||||
color: currentIndex == 2 ? Colors.black : const Color(0xFF6C7278),
|
||||
),
|
||||
label: _labels[2],
|
||||
labelStyle: (currentIndex == 0 ? AppTextStyles.bold : AppTextStyles.bold).copyWith(
|
||||
color: currentIndex == 2 ? const Color(0xFF61277A) : const Color(0xFF6C7278),
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
CurvedNavigationBarItem(
|
||||
child: Icon(
|
||||
Icons.person_2,
|
||||
color: currentIndex == 3 ? Colors.black : const Color(0xFF6C7278),
|
||||
),
|
||||
label: _labels[3],
|
||||
labelStyle: (currentIndex == 0 ? AppTextStyles.bold : AppTextStyles.bold).copyWith(
|
||||
color: currentIndex == 3 ? const Color(0xFF61277A) : const Color(0xFF6C7278),
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
],
|
||||
onTap: (index) {
|
||||
// 🔹 If inside ServiceRequestScreen
|
||||
if (widget.child != null) {
|
||||
if (widget.initialIndex == index) return;
|
||||
|
||||
if (widget.sourceTabIndex == 0 && index == 1) {
|
||||
Get.offAll(() => const MainController(initialIndex: 1));
|
||||
return;
|
||||
}
|
||||
|
||||
if (widget.sourceTabIndex == 1 && index == 1) return;
|
||||
|
||||
Get.offAll(() => MainController(initialIndex: index));
|
||||
return;
|
||||
}
|
||||
|
||||
// 🔹 If same tab tapped again → refresh
|
||||
if (currentIndex == index) {
|
||||
_refreshTab(index);
|
||||
return;
|
||||
}
|
||||
|
||||
// 🔹 Switch to a different tab
|
||||
setBottomBarIndex(index);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// ✅ Custom Curved Bottom Navigation Painter
|
||||
class BNBCustomPainter extends CustomPainter {
|
||||
@override
|
||||
void paint(Canvas canvas, Size size) {
|
||||
Paint paint = Paint()
|
||||
..color = Colors.white
|
||||
..style = PaintingStyle.fill;
|
||||
|
||||
Path path = Path();
|
||||
path.moveTo(0, 20);
|
||||
path.quadraticBezierTo(size.width * 0.20, 0, size.width * 0.35, 0);
|
||||
path.quadraticBezierTo(size.width * 0.40, 0, size.width * 0.40, 20);
|
||||
path.arcToPoint(
|
||||
Offset(size.width * 0.60, 20),
|
||||
radius: const Radius.circular(20.0),
|
||||
clockwise: false,
|
||||
);
|
||||
path.quadraticBezierTo(size.width * 0.60, 0, size.width * 0.65, 0);
|
||||
path.quadraticBezierTo(size.width * 0.80, 0, size.width, 20);
|
||||
path.lineTo(size.width, size.height);
|
||||
path.lineTo(0, size.height);
|
||||
path.close();
|
||||
|
||||
canvas.drawShadow(path, Colors.black.withOpacity(0.2), 5, true);
|
||||
canvas.drawPath(path, paint);
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldRepaint(CustomPainter oldDelegate) => false;
|
||||
}
|
||||
|
||||
/// ✅ Pentagon Button Painter
|
||||
/// ✅ Pentagon Button Painter
|
||||
class PentagonPainter extends CustomPainter {
|
||||
final Color color;
|
||||
final double cornerRadius;
|
||||
|
||||
PentagonPainter({
|
||||
required this.color,
|
||||
this.cornerRadius = 8.0, // Adjust this value for more/less rounding
|
||||
});
|
||||
|
||||
@override
|
||||
void paint(Canvas canvas, Size size) {
|
||||
final paint = Paint()
|
||||
..color = color
|
||||
..style = PaintingStyle.fill;
|
||||
|
||||
final double w = size.width;
|
||||
final double cx = w / 2;
|
||||
final double cy = size.height / 2;
|
||||
final double r = w / 2;
|
||||
|
||||
// Calculate pentagon vertices
|
||||
List<Offset> vertices = [];
|
||||
for (int i = 0; i < 5; i++) {
|
||||
double angle = (72 * i - 90) * math.pi / 180;
|
||||
double x = cx + r * 0.95 * math.cos(angle);
|
||||
double y = cy + r * 0.95 * math.sin(angle);
|
||||
vertices.add(Offset(x, y));
|
||||
}
|
||||
|
||||
// Create path with rounded corners
|
||||
final path = Path();
|
||||
|
||||
for (int i = 0; i < vertices.length; i++) {
|
||||
final current = vertices[i];
|
||||
final next = vertices[(i + 1) % vertices.length];
|
||||
final prev = vertices[(i - 1 + vertices.length) % vertices.length];
|
||||
|
||||
// Calculate direction vectors
|
||||
final toCurrent = Offset(current.dx - prev.dx, current.dy - prev.dy);
|
||||
final toNext = Offset(next.dx - current.dx, next.dy - current.dy);
|
||||
|
||||
// Normalize and scale by corner radius
|
||||
final lengthToCurrent = math.sqrt(
|
||||
toCurrent.dx * toCurrent.dx + toCurrent.dy * toCurrent.dy,
|
||||
);
|
||||
final lengthToNext = math.sqrt(
|
||||
toNext.dx * toNext.dx + toNext.dy * toNext.dy,
|
||||
);
|
||||
|
||||
final normalizedToCurrent = Offset(
|
||||
toCurrent.dx / lengthToCurrent,
|
||||
toCurrent.dy / lengthToCurrent,
|
||||
);
|
||||
final normalizedToNext = Offset(
|
||||
toNext.dx / lengthToNext,
|
||||
toNext.dy / lengthToNext,
|
||||
);
|
||||
|
||||
// Points before and after the corner
|
||||
final beforeCorner = Offset(
|
||||
current.dx - normalizedToCurrent.dx * cornerRadius,
|
||||
current.dy - normalizedToCurrent.dy * cornerRadius,
|
||||
);
|
||||
final afterCorner = Offset(
|
||||
current.dx + normalizedToNext.dx * cornerRadius,
|
||||
current.dy + normalizedToNext.dy * cornerRadius,
|
||||
);
|
||||
|
||||
if (i == 0) {
|
||||
path.moveTo(beforeCorner.dx, beforeCorner.dy);
|
||||
} else {
|
||||
path.lineTo(beforeCorner.dx, beforeCorner.dy);
|
||||
}
|
||||
|
||||
// Draw rounded corner using quadratic bezier
|
||||
path.quadraticBezierTo(
|
||||
current.dx,
|
||||
current.dy,
|
||||
afterCorner.dx,
|
||||
afterCorner.dy,
|
||||
);
|
||||
}
|
||||
path.close();
|
||||
|
||||
canvas.drawShadow(path, Colors.black.withOpacity(0.3), 4, true);
|
||||
canvas.drawPath(path, paint);
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldRepaint(CustomPainter oldDelegate) => false;
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user