|
|
@@ -0,0 +1,282 @@
|
|
|
+import 'package:easy_localization/easy_localization.dart';
|
|
|
+import 'package:flutter/material.dart';
|
|
|
+import 'package:provider/provider.dart';
|
|
|
+import 'package:telnow_mobile_new/src/cubit/menu_history_cubit.dart' hide HistoryTab;
|
|
|
+
|
|
|
+import '../../../cubit/tab_history_cubit.dart';
|
|
|
+import '../../../utils/U.dart';
|
|
|
+import '../../../utils/extensions.dart';
|
|
|
+import '../../../utils/provider.dart';
|
|
|
+import '../../components/rate_mission.dart';
|
|
|
+import '../../components/template.dart';
|
|
|
+import '../history_detail.dart';
|
|
|
+
|
|
|
+class HistoryItemWidget extends StatelessWidget {
|
|
|
+ final Map<String, dynamic> item;
|
|
|
+ final UserModule userModule;
|
|
|
+ final List<dynamic> rating;
|
|
|
+ final AnimationController animationController;
|
|
|
+ final int index;
|
|
|
+ final TabState state;
|
|
|
+ final String tab;
|
|
|
+
|
|
|
+ const HistoryItemWidget({
|
|
|
+ super.key,
|
|
|
+ required this.item,
|
|
|
+ required this.userModule,
|
|
|
+ required this.rating,
|
|
|
+ required this.animationController,
|
|
|
+ required this.index,
|
|
|
+ required this.state,
|
|
|
+ required this.tab,
|
|
|
+ });
|
|
|
+
|
|
|
+ @override
|
|
|
+ Widget build(BuildContext context) {
|
|
|
+ return GestureDetector(
|
|
|
+ onTap: () {
|
|
|
+ if (context.read<MenuHistoryCubit>().state.multiSelectMode && tab == 'done') {
|
|
|
+ context.read<MenuHistoryCubit>().selectIndex(index);
|
|
|
+ } else {
|
|
|
+ navigateTo(
|
|
|
+ context,
|
|
|
+ WebHistoryDetailPage(
|
|
|
+ index: index,
|
|
|
+ locale: context.locale.toString(),
|
|
|
+ ),
|
|
|
+ );
|
|
|
+ }
|
|
|
+ },
|
|
|
+ onLongPress: () => tab == 'done' && !context.read<MenuHistoryCubit>().state.multiSelectMode
|
|
|
+ ? context.read<MenuHistoryCubit>().selectIndex(index) : null,
|
|
|
+ child: Container(
|
|
|
+ width: double.infinity,
|
|
|
+ padding: const EdgeInsets.all(15),
|
|
|
+ margin: const EdgeInsets.only(bottom: 15),
|
|
|
+ decoration: BoxDecoration(
|
|
|
+ color: context.read<MenuHistoryCubit>().state.selectedIndex.contains(index)
|
|
|
+ ? primaryColor.withValues(alpha: 0.15) : Colors.white,
|
|
|
+ border: Border.all(color: textColor.withValues(alpha: 0.15)),
|
|
|
+ borderRadius: const BorderRadius.all(Radius.circular(12)),
|
|
|
+ ),
|
|
|
+ child: Column(
|
|
|
+ spacing: 10,
|
|
|
+ children: [
|
|
|
+ _buildHeader(context),
|
|
|
+ _buildBody(context),
|
|
|
+ _buildFooter(context),
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ ).withHover();
|
|
|
+ }
|
|
|
+
|
|
|
+ Widget _buildHeader(BuildContext context) {
|
|
|
+ return Row(
|
|
|
+ children: [
|
|
|
+ Text(
|
|
|
+ convertDate(item['datetimeRequest'], context.locale.toString()),
|
|
|
+ style: const TextStyle(color: primaryColor, fontSize: 14),
|
|
|
+ ),
|
|
|
+ const SizedBox(width: 15),
|
|
|
+ Expanded(
|
|
|
+ child: Text(
|
|
|
+ '${'ticketNumber'.tr()}: ${item['ticketNo']}',
|
|
|
+ style: const TextStyle(color: textColor, fontSize: 14),
|
|
|
+ overflow: TextOverflow.ellipsis,
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ _renderStatus(item['currentState'])
|
|
|
+ ],
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ Widget _buildBody(BuildContext context) {
|
|
|
+ return Column(
|
|
|
+ children: [
|
|
|
+ divider(),
|
|
|
+ const SizedBox(height: 10),
|
|
|
+ Row(
|
|
|
+ children: [
|
|
|
+ imageTiles(imageUrl: item['_requestImage'] ?? "null", width: 150, height: 120),
|
|
|
+ const SizedBox(width: 25),
|
|
|
+ Expanded(
|
|
|
+ child: Column(
|
|
|
+ crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
+ children: [
|
|
|
+ Text(item[U.langColumn(context, 'requestGroupDescription')],
|
|
|
+ style: const TextStyle(color: textColor, fontSize: 16),
|
|
|
+ overflow: TextOverflow.ellipsis),
|
|
|
+ const SizedBox(height: 10),
|
|
|
+ Text(item[U.langColumn(context, 'requestSubject')],
|
|
|
+ style: const TextStyle(color: textColor, fontWeight: FontWeight.w600),
|
|
|
+ overflow: TextOverflow.ellipsis),
|
|
|
+ const SizedBox(height: 5),
|
|
|
+ Text(item[U.langColumn(context, '_subjectDescription')] ?? '',
|
|
|
+ style: const TextStyle(color: textColor),
|
|
|
+ overflow: TextOverflow.ellipsis),
|
|
|
+ dashed(top: 10, bottom: 10),
|
|
|
+ _renderRequested(userModule, item),
|
|
|
+ Text('${'location'.tr()}: ${item['ipphoneExtLocation']}',
|
|
|
+ style: const TextStyle(color: textColor, fontSize: 14),
|
|
|
+ overflow: TextOverflow.ellipsis),
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ )
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ ],
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ Widget _buildFooter(BuildContext context) {
|
|
|
+ bool doneStatus = item['currentState'] == 'DISELESAIKAN' ||
|
|
|
+ item['currentState'] == 'TUNTAS' ||
|
|
|
+ item['currentState'] == 'DIBATALKAN';
|
|
|
+
|
|
|
+ final rowChildren = <Widget>[
|
|
|
+ if ((item['satisfactionRate'] == 0 && item['servantGroup'] != "#autoresponse") && doneStatus)
|
|
|
+ GestureDetector(
|
|
|
+ child: Container(
|
|
|
+ padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 16),
|
|
|
+ decoration: BoxDecoration(
|
|
|
+ color: Colors.white,
|
|
|
+ border: Border.all(color: secondaryColor),
|
|
|
+ borderRadius: const BorderRadius.all(Radius.circular(50)),
|
|
|
+ ),
|
|
|
+ child: Text('rateReq'.tr(),
|
|
|
+ style: const TextStyle(color: secondaryColor, fontSize: 14),
|
|
|
+ overflow: TextOverflow.ellipsis),
|
|
|
+ ),
|
|
|
+ onTap: () {
|
|
|
+ showDialog(
|
|
|
+ context: context,
|
|
|
+ builder: (_) => RateMission(
|
|
|
+ parentContext: context,
|
|
|
+ list: item,
|
|
|
+ index: index,
|
|
|
+ rating: rating,
|
|
|
+ state: state,
|
|
|
+ ),
|
|
|
+ );
|
|
|
+ },
|
|
|
+ ).withHover()
|
|
|
+ else if (item['satisfactionRate'] > 0)
|
|
|
+ Row(
|
|
|
+ mainAxisAlignment: MainAxisAlignment.end,
|
|
|
+ children: [
|
|
|
+ Text(rating[item['satisfactionRate']-1]['label'].toString(), style: TextStyle(color: textColor, fontSize: 14), overflow: TextOverflow.ellipsis),
|
|
|
+ SizedBox(width: 5),
|
|
|
+ Image(image: AssetImage(rating[item['satisfactionRate']-1]['image'].toString()), width: 25),
|
|
|
+ ],
|
|
|
+ )
|
|
|
+ else
|
|
|
+ SizedBox(),
|
|
|
+
|
|
|
+ if(item['_hasForum']) _message(item['_hasForum'], item['_forumMsg'] ?? "null"),
|
|
|
+
|
|
|
+ if(doneStatus) GestureDetector(
|
|
|
+ child: Container(
|
|
|
+ padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 16),
|
|
|
+ decoration: BoxDecoration(
|
|
|
+ color: Colors.white,
|
|
|
+ border: Border.all(color: primaryColor),
|
|
|
+ borderRadius: const BorderRadius.all(Radius.circular(50)),
|
|
|
+ ),
|
|
|
+ child: Text('reqAgain'.tr(),
|
|
|
+ style: const TextStyle(color: primaryColor, fontSize: 14)),
|
|
|
+ ),
|
|
|
+ onTap: () => context.read<MenuHistoryCubit>().requestAgain(item) //historyFunction.requestAgainAction(index),
|
|
|
+ ).withHover()
|
|
|
+ ];
|
|
|
+
|
|
|
+ // kalau rowChildren kosong → return shrink
|
|
|
+ if (rowChildren.isEmpty) {
|
|
|
+ return const SizedBox.shrink();
|
|
|
+ }
|
|
|
+
|
|
|
+ return Column(
|
|
|
+ children: [
|
|
|
+ divider(),
|
|
|
+ const SizedBox(height: 10),
|
|
|
+ Row(
|
|
|
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
|
+ children: rowChildren,
|
|
|
+ ),
|
|
|
+ ],
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ Widget _renderStatus(String currentState) {
|
|
|
+ Map<String, Map<String, dynamic>> states = {
|
|
|
+ 'DIMULAI': {'text': 'onProgress'.tr(), 'color': Color(0xffCCA600).withValues(alpha: 0.2)},
|
|
|
+ 'HOLD': {'text': 'hold'.tr(), 'color': Color(0xffD3D3D3)},
|
|
|
+ 'DIPROSES': {'text': 'queued'.tr(), 'color': Color(0xff02C539).withValues(alpha: 0.2)},
|
|
|
+ 'DIANTRIKAN': {'text': 'queued'.tr(), 'color': Color(0xff02C539).withValues(alpha: 0.2)},
|
|
|
+ 'DISELESAIKAN': {'text': 'stateFinish'.tr(), 'color': primaryColor.withValues(alpha: 0.4)},
|
|
|
+ 'TUNTAS': {'text': 'stateFinish'.tr(), 'color': primaryColor.withValues(alpha: 0.4)},
|
|
|
+ 'DIBATALKAN': {'text': 'stateCancel'.tr(), 'color': const Color(0xffD81010).withValues(alpha: 0.4)},
|
|
|
+ };
|
|
|
+
|
|
|
+ Color color = states[currentState]?['color'] ?? Colors.transparent;
|
|
|
+ final text = states[currentState]?['text'] ?? '';
|
|
|
+
|
|
|
+ return Container(
|
|
|
+ padding: const EdgeInsets.symmetric(vertical: 3, horizontal: 10),
|
|
|
+ margin: const EdgeInsets.only(left: 10),
|
|
|
+ decoration: BoxDecoration(color: color, borderRadius: const BorderRadius.all(Radius.circular(3))),
|
|
|
+ child: Text(text, style: const TextStyle(fontSize: 12, color: textColor)),
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ Widget _renderRequested(userModule, list) {
|
|
|
+ if (list['receptionistId'] != null) {
|
|
|
+ var user = userModule.user();
|
|
|
+ if (user['roomAttendant'] &&
|
|
|
+ user['userId'] != list['informantUserId'] &&
|
|
|
+ user['userId'] == list['receptionistId']) {
|
|
|
+ return Column(
|
|
|
+ crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
+ children: [
|
|
|
+ Text('${'requestedFor'.tr()}: ${list['informantName'] ?? '-'}',
|
|
|
+ style: const TextStyle(color: textColor, fontSize: 13, fontWeight: FontWeight.w300)),
|
|
|
+ const SizedBox(height: 6),
|
|
|
+ ],
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ if (user['userId'] == list['informantUserId'] &&
|
|
|
+ user['userId'] != list['receptionistId']) {
|
|
|
+ return Column(
|
|
|
+ crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
+ children: [
|
|
|
+ Text('${'requestedBy'.tr()}: ${list['receptionistName'] ?? ''}',
|
|
|
+ style: const TextStyle(color: textColor, fontSize: 13, fontWeight: FontWeight.w300)),
|
|
|
+ const SizedBox(height: 6),
|
|
|
+ ],
|
|
|
+ );
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return Container();
|
|
|
+ }
|
|
|
+
|
|
|
+ Widget _message(bool hasForum, String forumMsg) {
|
|
|
+ if (hasForum) {
|
|
|
+ return Row(
|
|
|
+ children: [
|
|
|
+ FadeTransition(
|
|
|
+ opacity: animationController,
|
|
|
+ child: U.iconsax('messages-3', color: primaryColor),
|
|
|
+ ),
|
|
|
+ const SizedBox(width: 8),
|
|
|
+ Text('“$forumMsg”',
|
|
|
+ style: TextStyle(color: textColor.withValues(alpha: 0.75), fontSize: 14, fontStyle: FontStyle.italic),
|
|
|
+ overflow: TextOverflow.ellipsis),
|
|
|
+ ],
|
|
|
+ );
|
|
|
+ }
|
|
|
+ return const SizedBox();
|
|
|
+ }
|
|
|
+}
|