chat count implemented

design_3.0_cx_module
WaseemAbbasi22 1 month ago
parent a7c206e6f4
commit 2425c78cf9

@ -1,9 +1,12 @@
import 'dart:developer';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/modules/cm_module/service_request_detail_provider.dart'; import 'package:test_sa/modules/cm_module/service_request_detail_provider.dart';
import 'package:test_sa/new_views/common_widgets/custom_badge.dart';
import 'chat_page.dart'; import 'chat_page.dart';
import 'chat_provider.dart'; import 'chat_provider.dart';
@ -74,24 +77,31 @@ class _ChatWidgetState extends State<ChatWidget> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return widget.isShow return widget.isShow
? Consumer<ChatProvider>(builder: (pContext, requestProvider, _) { ? Consumer<ChatProvider>(builder: (pContext, chatProvider, _) {
return IconButton( final int unreadCount = (!chatProvider.chatLoginTokenLoading && (chatProvider.chatParticipantModel?.unreadCount ?? 0) > 0) ? chatProvider.chatParticipantModel!.unreadCount! : 0;
icon: const Icon(Icons.chat_bubble), return CustomBadge2(
onPressed: () { value: unreadCount,
Navigator.push( top: 2,
context, right: 2,
CupertinoPageRoute( minSize: 18,
builder: (context) => ChatPage( child: IconButton(
moduleId: widget.moduleId, icon: const Icon(Icons.chat_bubble),
requestId: widget.requestId, onPressed: () {
title: widget.title, Navigator.push(
readOnly: widget.isReadOnly, context,
assigneeEmployeeNumber: widget.assigneeEmployeeNumber, CupertinoPageRoute(
contactEmployeeINumber: widget.contactEmployeeINumber, builder: (context) => ChatPage(
myLoginUserID: widget.myLoginUserID, moduleId: widget.moduleId,
))); requestId: widget.requestId,
}, title: widget.title,
).toShimmer(context: context, isShow: requestProvider.chatLoginTokenLoading, radius: 30, height: 30, width: 30); readOnly: widget.isReadOnly,
assigneeEmployeeNumber: widget.assigneeEmployeeNumber,
contactEmployeeINumber: widget.contactEmployeeINumber,
myLoginUserID: widget.myLoginUserID,
)));
},
).toShimmer(context: context, isShow: chatProvider.chatLoginTokenLoading, radius: 30, height: 30, width: 30),
);
}) })
: const SizedBox(); : const SizedBox();
} }

@ -1,12 +1,15 @@
import 'dart:developer';
class ChatParticipantModel { class ChatParticipantModel {
int? id; int? id;
String? title; String? title;
String? conversationType; String? conversationType;
List<Participants>? participants; List<Participants>? participants;
String? lastMessage; // String? lastMessage;
String? createdAt; String? createdAt;
int? unreadCount;
ChatParticipantModel({this.id, this.title, this.conversationType, this.participants, this.lastMessage, this.createdAt}); ChatParticipantModel({this.id, this.title, this.conversationType, this.participants, this.createdAt, this.unreadCount});
ChatParticipantModel.fromJson(Map<String, dynamic> json) { ChatParticipantModel.fromJson(Map<String, dynamic> json) {
id = json['id']; id = json['id'];
@ -18,20 +21,22 @@ class ChatParticipantModel {
participants!.add(new Participants.fromJson(v)); participants!.add(new Participants.fromJson(v));
}); });
} }
lastMessage = json['lastMessage']; // lastMessage = json['lastMessage'];
createdAt = json['createdAt']; createdAt = json['createdAt'];
unreadCount = json['unreadCount'];
} }
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>(); final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = this.id; data['id'] = id;
data['title'] = this.title; data['title'] = title;
data['conversationType'] = this.conversationType; data['conversationType'] = conversationType;
if (this.participants != null) { if (participants != null) {
data['participants'] = this.participants!.map((v) => v.toJson()).toList(); data['participants'] = participants!.map((v) => v.toJson()).toList();
} }
data['lastMessage'] = this.lastMessage; // data['lastMessage'] = lastMessage;
data['createdAt'] = this.createdAt; data['createdAt'] = createdAt;
data['unreadCount'] = unreadCount;
return data; return data;
} }
} }
@ -54,12 +59,12 @@ class Participants {
} }
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>(); final Map<String, dynamic> data = <String, dynamic>{};
data['userId'] = this.userId; data['userId'] = userId;
data['userName'] = this.userName; data['userName'] = userName;
data['employeeNumber'] = this.employeeNumber; data['employeeNumber'] = employeeNumber;
data['role'] = this.role; data['role'] = role;
data['userStatus'] = this.userStatus; data['userStatus'] = userStatus;
return data; return data;
} }
} }

@ -5,12 +5,20 @@ import 'package:test_sa/new_views/app_style/app_color.dart';
class CustomBadge extends StatelessWidget { class CustomBadge extends StatelessWidget {
final Widget child; // The widget that the badge will be overlaid on. final Widget child; // The widget that the badge will be overlaid on.
final int value; // The value or text to be displayed in the badge. final int value; // The value or text to be displayed in the badge.
final Color color; // The background color of the badge. final Color color;
final double? positionR;
final double? positionT;
final double? height;
final double? width;
const CustomBadge({ CustomBadge({
Key? key, Key? key,
required this.child, required this.child,
required this.value, required this.value,
this.height,
this.width,
this.positionR,
this.positionT,
this.color = AppColor.red30, // Default color is red this.color = AppColor.red30, // Default color is red
}) : super(key: key); }) : super(key: key);
@ -22,13 +30,14 @@ class CustomBadge extends StatelessWidget {
child, // The main widget child, // The main widget
// if (value > 0) // if (value > 0)
Positioned( Positioned(
right: -6, right: positionR ?? -6,
top: -6, top: positionT ?? -6,
//Need to check why opacity he used here this is not correct need to make this total dynamic and responsive
child: Opacity( child: Opacity(
opacity: value > 0 ? 1 : 0, opacity: value > 0 ? 1 : 0,
child: Container( child: Container(
height: 23, height: height ?? 23,
constraints: const BoxConstraints(minWidth: 23), constraints: BoxConstraints(minWidth: width ?? 23),
padding: const EdgeInsets.all(3), padding: const EdgeInsets.all(3),
alignment: Alignment.center, alignment: Alignment.center,
decoration: BoxDecoration(color: color, borderRadius: BorderRadius.circular(30)), decoration: BoxDecoration(color: color, borderRadius: BorderRadius.circular(30)),
@ -43,3 +52,139 @@ class CustomBadge extends StatelessWidget {
); );
} }
} }
//Need to use this badge every where..
class CustomBadge2 extends StatelessWidget {
final Widget child;
final int value;
final double top;
final double right;
final double left;
final double bottom;
final double minSize;
final Color backgroundColor;
final Color textColor;
final TextStyle? textStyle;
final int maxValue;
final Duration animationDuration;
const CustomBadge2({
super.key,
required this.child,
required this.value,
this.top = -6,
this.right = -6,
this.left = double.nan,
this.bottom = double.nan,
this.minSize = 18,
this.backgroundColor = AppColor.red30,
this.textColor = AppColor.white10,
this.textStyle,
this.maxValue = 99,
this.animationDuration = const Duration(milliseconds: 200),
});
bool get _isVisible => value > 0;
@override
Widget build(BuildContext context) {
return Stack(
clipBehavior: Clip.none,
children: [
child,
if (_isVisible)
Positioned(
top: top.isNaN ? null : top,
right: right.isNaN ? null : right,
left: left.isNaN ? null : left,
bottom: bottom.isNaN ? null : bottom,
child: AnimatedScale(
scale: _isVisible ? 1 : 0,
duration: animationDuration,
curve: Curves.easeOutBack,
child: AnimatedOpacity(
opacity: _isVisible ? 1 : 0,
duration: animationDuration,
child: _Badge(
value: value,
maxValue: maxValue,
minSize: minSize,
backgroundColor: backgroundColor,
textColor: textColor,
textStyle: textStyle ??
Theme.of(context).textTheme.labelSmall?.copyWith(
fontWeight: FontWeight.w700,
),
),
),
),
),
],
);
}
}
class _Badge extends StatelessWidget {
final int value;
final int maxValue;
final double minSize;
final Color backgroundColor;
final Color textColor;
final TextStyle? textStyle;
const _Badge({
required this.value,
required this.maxValue,
required this.minSize,
required this.backgroundColor,
required this.textColor,
this.textStyle,
});
bool get _isOverflow => value > maxValue;
@override
Widget build(BuildContext context) {
final TextStyle baseStyle = (textStyle ?? Theme.of(context).textTheme.labelMedium)!.copyWith(
color: textColor,
fontWeight: FontWeight.w700,
);
final double badgeSize = minSize;
return IgnorePointer(
child: SizedBox(
width: badgeSize,
height: badgeSize,
child: DecoratedBox(
decoration: const BoxDecoration(
shape: BoxShape.circle,
),
child: DecoratedBox(
decoration: BoxDecoration(
color: backgroundColor,
shape: BoxShape.circle,
),
child: Center(
child: _isOverflow
? FittedBox(
child: Text(
'$maxValue+',
style: baseStyle.copyWith(
fontSize: badgeSize * 0.45,
),
),
)
: CounterAnimatedText(
value: value,
style: baseStyle.copyWith(
fontSize: badgeSize * 0.6,
),
),
),
),
),
),
);
}
}

Loading…
Cancel
Save