@buerokratt-ria/common-gui-components 0.0.16 → 0.0.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -4,18 +4,31 @@ All changes to this project will be documented in this file.
4
4
 
5
5
  ## Template [MajorVersion.MediterraneanVersion.MinorVersion] - DD-MM-YYYY
6
6
 
7
- ## [0.0.16] - 12-05-2025
7
+ ## [0.0.18] - 16-05-2025
8
8
 
9
- - Updating CSA display and filtering.
9
+ - Made title configurable.
10
+ - Made passed dates configurable dynamically.
11
+ - Made searchbar configrable
12
+ - Updated default column data to handle both null and undefined.
10
13
 
11
- ## [0.0.15] - 09-05-2025
14
+ ## [0.0.17] - 13-05-2025
15
+
16
+ - Updated csa display and filtering.
17
+
18
+
19
+ ## [0.0.16] - 09-05-2025
12
20
 
13
21
  - Display feedback rating consistently in history page.
14
22
 
15
- ## [0.0.14] - 05-05-2025
23
+ ## [0.0.15] - 05-05-2025
16
24
 
17
25
  - Updated popup duration to be 5 seconds.
18
26
 
27
+ ## [0.0.14] - 30-04-2025
28
+
29
+ - Added sorting configurable (disabled by default)
30
+ - Added Email display configurable (disabled by default)
31
+
19
32
  ## [0.0.13] - 25-04-2025
20
33
 
21
34
  - Adding double scrollbar to history page when size is small.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@buerokratt-ria/common-gui-components",
3
- "version": "0.0.16",
3
+ "version": "0.0.18",
4
4
  "description": "Common GUI components and pre defined templates.",
5
5
  "main": "index.ts",
6
6
  "author": "ExiRai",
@@ -37,18 +37,38 @@ type HistoryProps = {
37
37
  toastContext: ToastContextType | null;
38
38
  onMessageClick?: (message: any) => void;
39
39
  showComment?: boolean;
40
+ showEmail?: boolean;
41
+ showSortingLabel?: boolean;
40
42
  showStatus?: boolean;
43
+ displayTitle?: boolean;
44
+ displaySearchBar?: boolean;
45
+ displayDateFilter?: boolean;
46
+ delegatedStartDate?: string;
47
+ delegatedEndDate?: string;
41
48
  }
42
49
 
43
- const ChatHistory: FC<PropsWithChildren<HistoryProps>> = ({user, toastContext, onMessageClick, showComment = true, showStatus = true}) => {
50
+ const ChatHistory: FC<PropsWithChildren<HistoryProps>> = ({
51
+ user,
52
+ toastContext,
53
+ onMessageClick,
54
+ showComment = true,
55
+ showEmail = false,
56
+ showSortingLabel = false,
57
+ showStatus = true,
58
+ displayTitle = true,
59
+ displayDateFilter = true,
60
+ displaySearchBar = true,
61
+ delegatedEndDate = null,
62
+ delegatedStartDate = null
63
+ }) => {
44
64
  const {t, i18n} = useTranslation();
45
65
  const toast = toastContext;
46
66
  const userInfo = user;
47
67
  const routerLocation = useLocation();
48
68
  const params = new URLSearchParams(routerLocation.search);
49
69
  let passedChatId = new URLSearchParams(routerLocation.search).get('chat');
50
- const passedStartDate = params.get('start');
51
- const passedEndDate = params.get('end');
70
+ const passedStartDate = delegatedStartDate ?? params.get('start');
71
+ const passedEndDate = delegatedEndDate ?? params.get('end');
52
72
  const passedCustomerSupportIds = params.getAll('customerSupportIds');
53
73
  const [search, setSearch] = useState('');
54
74
  const [selectedChat, setSelectedChat] = useState<ChatType | null>(null);
@@ -79,7 +99,7 @@ const ChatHistory: FC<PropsWithChildren<HistoryProps>> = ({user, toastContext, o
79
99
  const [customerSupportAgents, setCustomerSupportAgents] = useState<any[]>([]);
80
100
  const [counterKey, setCounterKey] = useState<number>(0)
81
101
 
82
- const {control, watch} = useForm<{
102
+ const {control, setValue, watch} = useForm<{
83
103
  startDate: Date | string;
84
104
  endDate: Date | string;
85
105
  }>({
@@ -122,6 +142,21 @@ const ChatHistory: FC<PropsWithChildren<HistoryProps>> = ({user, toastContext, o
122
142
  }
123
143
  }, [passedChatId]);
124
144
 
145
+ useEffect(() => {
146
+ if (delegatedStartDate) {
147
+ setValue('startDate', unifyDateFromat(delegatedStartDate));
148
+ fetchData()
149
+ }
150
+ }, [delegatedStartDate]);
151
+
152
+ useEffect(() => {
153
+ if (delegatedEndDate) {
154
+ setValue('endDate', unifyDateFromat(delegatedEndDate));
155
+ fetchData()
156
+ }
157
+ }, [delegatedEndDate]);
158
+
159
+
125
160
  const fetchData = async () => {
126
161
  setInitialLoad(false);
127
162
  try {
@@ -137,7 +172,7 @@ const ChatHistory: FC<PropsWithChildren<HistoryProps>> = ({user, toastContext, o
137
172
  const updatedPagination = updatePagePreference(newPageResults);
138
173
 
139
174
  let newSelectedColumns = [];
140
- if(currentColumns !== undefined && currentColumns.length > 0 && currentColumns[0] !== "") {
175
+ if (currentColumns != null && currentColumns.length > 0 && currentColumns[0] !== "") {
141
176
  newSelectedColumns = currentColumns;
142
177
  }
143
178
  setSelectedColumns(newSelectedColumns)
@@ -269,8 +304,8 @@ const ChatHistory: FC<PropsWithChildren<HistoryProps>> = ({user, toastContext, o
269
304
  },
270
305
  });
271
306
 
272
- const visibleColumnOptions = useMemo(
273
- () => [
307
+ const visibleColumnOptions = useMemo(() => {
308
+ const columns = [
274
309
  {label: t('chat.history.startTime'), value: 'created'},
275
310
  {label: t('chat.history.endTime'), value: 'ended'},
276
311
  {label: t('chat.history.csaName'), value: 'customerSupportFullName'},
@@ -283,9 +318,14 @@ const ChatHistory: FC<PropsWithChildren<HistoryProps>> = ({user, toastContext, o
283
318
  {label: t('global.status'), value: 'status'},
284
319
  {label: 'ID', value: 'id'},
285
320
  {label: 'www', value: 'www'},
286
- ],
287
- [t]
288
- );
321
+ ];
322
+
323
+ if (showEmail) {
324
+ columns.splice(4, 0, {label: t('global.email'), value: 'endUserEmail'}); // insert after name
325
+ }
326
+
327
+ return columns;
328
+ }, [t, showEmail])
289
329
 
290
330
  const chatStatusChangeMutation = useMutation({
291
331
  mutationFn: async (data: { chatId: string | number; event: string }) => {
@@ -458,8 +498,8 @@ const ChatHistory: FC<PropsWithChildren<HistoryProps>> = ({user, toastContext, o
458
498
  </Button>
459
499
  );
460
500
 
461
- const endedChatsColumns = useMemo(
462
- () => [
501
+ const endedChatsColumns = useMemo(() => {
502
+ const columns = [
463
503
  columnHelper.accessor('created', {
464
504
  id: 'created',
465
505
  header: t('chat.history.startTime') ?? '',
@@ -527,8 +567,10 @@ const ChatHistory: FC<PropsWithChildren<HistoryProps>> = ({user, toastContext, o
527
567
  columnHelper.accessor('feedbackRating', {
528
568
  id: 'feedbackRating',
529
569
  header: t('chat.history.rating') ?? '',
530
- cell: (props) =>
531
- props.getValue() && <span>{`${props.getValue()}/10`}</span>,
570
+ cell: (props) => {
571
+ const value = props.getValue();
572
+ return value !== null && value !== undefined ? <span>{`${value}/10`}</span> : null;
573
+ }
532
574
  }),
533
575
  columnHelper.accessor('feedbackText', {
534
576
  id: 'feedbackText',
@@ -574,9 +616,62 @@ const ChatHistory: FC<PropsWithChildren<HistoryProps>> = ({user, toastContext, o
574
616
  sticky: 'right',
575
617
  },
576
618
  }),
577
- ],
578
- []
579
- );
619
+ ];
620
+
621
+ if (showEmail) {
622
+ columns.splice(4, 0, columnHelper.accessor('endUserEmail', {
623
+ id: 'endUserEmail',
624
+ header: t('global.email') ?? '',
625
+ }));
626
+ }
627
+
628
+ return columns;
629
+ }, [t, showEmail])
630
+
631
+ const getSortingString = () => {
632
+ if(sorting && sorting.length > 0) {
633
+ const sortingObject = sorting[0];
634
+ const sortingString = t('sorting.sorting');
635
+ const orderingString = t(`sorting.${sortingObject.desc ? 'desc' : 'asc'}`);
636
+ const column = getColumnTranslation(sortingObject.id);
637
+ return sortingString + ' ' + column + ' ' + orderingString;
638
+ } else {
639
+ return '';
640
+ }
641
+ }
642
+
643
+ const getColumnTranslation = (column: string) : string => {
644
+ switch (column) {
645
+ case 'endUserId':
646
+ return t('global.idCode') ?? ''
647
+ case 'created':
648
+ return t('chat.history.startTime') ?? ''
649
+ case 'ended':
650
+ return t('chat.history.endTime') ?? ''
651
+ case 'customerSupportFullName':
652
+ return t('chat.history.csaName') ?? ''
653
+ case 'endUserName':
654
+ return t('global.name') ?? ''
655
+ case 'endUserEmail':
656
+ return t('global.email') ?? ''
657
+ case 'contactsMessage':
658
+ return t('chat.history.contact') ?? ''
659
+ case 'comment':
660
+ return t('chat.history.comment') ?? ''
661
+ case 'feedbackRating':
662
+ return t('chat.history.rating') ?? ''
663
+ case 'feedbackText':
664
+ return t('chat.history.feedback') ?? ''
665
+ case 'status':
666
+ return t('global.status') ?? ''
667
+ case 'endUserUrl':
668
+ return 'www'
669
+ case 'id':
670
+ return 'id';
671
+ default:
672
+ return '';
673
+ }
674
+ }
580
675
 
581
676
  const handleChatStatusChange = (event: string) => {
582
677
  if (!selectedChat) return;
@@ -625,86 +720,94 @@ const ChatHistory: FC<PropsWithChildren<HistoryProps>> = ({user, toastContext, o
625
720
 
626
721
  return (
627
722
  <>
628
- <h1>{t('chat.history.title')}</h1>
723
+ {displayTitle && (
724
+ <h1>{t('chat.history.title')}</h1>
725
+ )}
629
726
 
630
727
  <Card>
631
728
  <Track gap={16}>
632
- <FormInput
633
- className="input-wrapper"
634
- label={t('chat.history.searchChats')}
635
- hideLabel
636
- name="searchChats"
637
- placeholder={t('chat.history.searchChats') + '...'}
638
- onChange={(e) => {
639
- setSearch(e.target.value);
640
- debouncedGetAllEnded(e.target.value);
641
- }}
642
- />
729
+ {displaySearchBar && (
730
+ <FormInput
731
+ className="input-wrapper"
732
+ label={t('chat.history.searchChats')}
733
+ hideLabel
734
+ name="searchChats"
735
+ placeholder={t('chat.history.searchChats') + '...'}
736
+ onChange={(e) => {
737
+ setSearch(e.target.value);
738
+ debouncedGetAllEnded(e.target.value);
739
+ }}
740
+ />)}
741
+
643
742
  <Track style={{width: '100%'}} gap={16}>
644
- <Track gap={10}>
645
- <p>{t('global.from')}</p>
646
- <Controller
647
- name="startDate"
648
- control={control}
649
- render={({field}) => {
650
- return (
651
- <FormDatepicker
652
- {...field}
653
- label={''}
654
- value={field.value ?? new Date()}
655
- onChange={(v) => {
656
- field.onChange(v);
657
- const start = format(new Date(v), 'yyyy-MM-dd');
658
- setSearchParams((params) => {
659
- params.set('start', start);
660
- return params;
661
- });
662
- getAllEndedChats.mutate({
663
- startDate: start,
664
- endDate: format(new Date(endDate), 'yyyy-MM-dd'),
665
- customerSupportIds: passedCustomerSupportIds,
666
- pagination,
667
- sorting,
668
- search,
669
- });
670
- }}
671
- />
672
- );
673
- }}
674
- />
675
- </Track>
676
- <Track gap={10}>
677
- <p>{t('global.to')}</p>
678
- <Controller
679
- name="endDate"
680
- control={control}
681
- render={({field}) => {
682
- return (
683
- <FormDatepicker
684
- {...field}
685
- label={''}
686
- value={field.value ?? new Date()}
687
- onChange={(v) => {
688
- field.onChange(v);
689
- const end = format(new Date(v), 'yyyy-MM-dd');
690
- setSearchParams((params) => {
691
- params.set('end', end);
692
- return params;
693
- });
694
- getAllEndedChats.mutate({
695
- startDate: format(new Date(startDate), 'yyyy-MM-dd'),
696
- endDate: end,
697
- customerSupportIds: passedCustomerSupportIds,
698
- pagination,
699
- sorting,
700
- search,
701
- });
702
- }}
703
- />
704
- );
705
- }}
706
- />
707
- </Track>
743
+ {displayDateFilter && (
744
+ <>
745
+ <Track gap={10}>
746
+ <p>{t('global.from')}</p>
747
+ <Controller
748
+ name="startDate"
749
+ control={control}
750
+ render={({field}) => {
751
+ return (
752
+ <FormDatepicker
753
+ {...field}
754
+ label={''}
755
+ value={field.value ?? new Date()}
756
+ onChange={(v) => {
757
+ field.onChange(v);
758
+ const start = format(new Date(v), 'yyyy-MM-dd');
759
+ setSearchParams((params) => {
760
+ params.set('start', start);
761
+ return params;
762
+ });
763
+ getAllEndedChats.mutate({
764
+ startDate: start,
765
+ endDate: format(new Date(endDate), 'yyyy-MM-dd'),
766
+ customerSupportIds: passedCustomerSupportIds,
767
+ pagination,
768
+ sorting,
769
+ search,
770
+ });
771
+ }}
772
+ />
773
+ );
774
+ }}
775
+ />
776
+ </Track>
777
+ <Track gap={10}>
778
+ <p>{t('global.to')}</p>
779
+ <Controller
780
+ name="endDate"
781
+ control={control}
782
+ render={({field}) => {
783
+ return (
784
+ <FormDatepicker
785
+ {...field}
786
+ label={''}
787
+ value={field.value ?? new Date()}
788
+ onChange={(v) => {
789
+ field.onChange(v);
790
+ const end = format(new Date(v), 'yyyy-MM-dd');
791
+ setSearchParams((params) => {
792
+ params.set('end', end);
793
+ return params;
794
+ });
795
+ getAllEndedChats.mutate({
796
+ startDate: format(new Date(startDate), 'yyyy-MM-dd'),
797
+ endDate: end,
798
+ customerSupportIds: passedCustomerSupportIds,
799
+ pagination,
800
+ sorting,
801
+ search,
802
+ });
803
+ }}
804
+ />
805
+ );
806
+ }}
807
+ />
808
+ </Track>
809
+ </>
810
+ )}
708
811
  <FormMultiselect
709
812
  key={counterKey}
710
813
  name="visibleColumns"
@@ -757,6 +860,13 @@ const ChatHistory: FC<PropsWithChildren<HistoryProps>> = ({user, toastContext, o
757
860
  </Track>
758
861
  </Card>
759
862
 
863
+ {sorting && sorting.length > 0 && showSortingLabel && (
864
+ <div>
865
+ <Button disabled={true} appearance="secondary">
866
+ {getSortingString()}
867
+ </Button>
868
+ </div>)
869
+ }
760
870
  <div className="card-drawer-container" style={{ height: 'auto', overflow: 'auto' }}>
761
871
  <div className="card-wrapper">
762
872
  <Card>
@@ -1,5 +1,6 @@
1
1
  {
2
2
  "global": {
3
+ "email": "Email",
3
4
  "save": "Save",
4
5
  "add": "Add",
5
6
  "edit": "Edit",
@@ -46,6 +47,11 @@
46
47
  "chosen": "Chosen",
47
48
  "read": "Read"
48
49
  },
50
+ "sorting": {
51
+ "des": "descending",
52
+ "asc": "ascending",
53
+ "sorting": "Sorting"
54
+ },
49
55
  "mainMenu": {
50
56
  "menuLabel": "Main navigation",
51
57
  "closeMenu": "Close menu",
@@ -1,5 +1,6 @@
1
1
  {
2
2
  "global": {
3
+ "email": "Email",
3
4
  "save": "Salvesta",
4
5
  "add": "Lisa",
5
6
  "edit": "Muuda",
@@ -46,6 +47,11 @@
46
47
  "chosen": "Valitud",
47
48
  "read": "Loetud"
48
49
  },
50
+ "sorting": {
51
+ "des": "kahanevalt",
52
+ "asc": "Kasvavalt",
53
+ "sorting": "Sorteerimine"
54
+ },
49
55
  "mainMenu": {
50
56
  "menuLabel": "Põhinavigatsioon",
51
57
  "closeMenu": "Kitsenda menüü",