@weni/unnnic-system 3.25.6 → 3.25.7

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@weni/unnnic-system",
3
- "version": "3.25.6",
3
+ "version": "3.25.7",
4
4
  "type": "commonjs",
5
5
  "files": [
6
6
  "dist",
@@ -67,6 +67,13 @@
67
67
  </p>
68
68
  <template v-else-if="lastMessageMedia.isMedia">
69
69
  <section class="chats-contact__infos__media">
70
+ <p
71
+ v-if="lastMessage.isFromUser"
72
+ class="chats-contact__infos__media__sender-prefix"
73
+ data-testid="media-sender-prefix"
74
+ >
75
+ {{ i18n('you_message_prefix') }}
76
+ </p>
70
77
  <UnnnicIcon
71
78
  :icon="lastMessageMedia.mediaIcon"
72
79
  scheme="fg-base"
@@ -135,6 +142,18 @@
135
142
  :scheme="schemePin"
136
143
  />
137
144
  </button>
145
+ <UnnnicTooltip
146
+ v-else-if="newMessageIndicator"
147
+ class="chats-contact__infos__new-message-indicator-tooltip"
148
+ :enabled="!!newMessageIndicatorTooltip"
149
+ :text="newMessageIndicatorTooltip"
150
+ side="top"
151
+ >
152
+ <span
153
+ class="chats-contact__infos__new-message-indicator"
154
+ data-testid="new-message-indicator"
155
+ />
156
+ </UnnnicTooltip>
138
157
  <p
139
158
  v-else-if="(unreadMessages && !selected) || forceShowUnreadMessages"
140
159
  class="chats-contact__infos__unread-messages"
@@ -259,6 +278,14 @@ export default {
259
278
  type: String,
260
279
  default: '',
261
280
  },
281
+ newMessageIndicator: {
282
+ type: Boolean,
283
+ default: false,
284
+ },
285
+ newMessageIndicatorTooltip: {
286
+ type: String,
287
+ default: '',
288
+ },
262
289
  },
263
290
 
264
291
  emits: ['click', 'clickPin'],
@@ -309,12 +336,18 @@ export default {
309
336
  en: 'Video',
310
337
  es: 'Video',
311
338
  },
339
+ you_message_prefix: {
340
+ 'pt-br': 'Você:',
341
+ en: 'You:',
342
+ es: 'Tú:',
343
+ },
312
344
  },
313
345
  };
314
346
  },
315
347
 
316
348
  computed: {
317
349
  messageInfoAlign() {
350
+ if (this.newMessageIndicator) return 'space-between';
318
351
  return this.unreadMessages && this.selected ? 'center' : 'flex-start';
319
352
  },
320
353
  messageInfoMarginTop() {
@@ -552,6 +585,10 @@ export default {
552
585
  display: flex;
553
586
  align-items: center;
554
587
  gap: $unnnic-spacing-nano;
588
+
589
+ &__sender-prefix {
590
+ color: $unnnic-color-fg-base;
591
+ }
555
592
  }
556
593
 
557
594
  &__title,
@@ -647,6 +684,27 @@ export default {
647
684
  color: $unnnic-color-weni-700;
648
685
  }
649
686
 
687
+ &__new-message-indicator {
688
+ display: flex;
689
+ justify-content: center;
690
+ align-items: center;
691
+
692
+ width: $unnnic-space-5;
693
+ min-width: $unnnic-space-5;
694
+ height: $unnnic-space-5;
695
+
696
+ &::before {
697
+ content: '';
698
+ display: block;
699
+
700
+ width: $unnnic-space-2;
701
+ height: $unnnic-space-2;
702
+
703
+ border-radius: 50%;
704
+ background-color: $unnnic-color-bg-blue-strong;
705
+ }
706
+ }
707
+
650
708
  .ellipsis {
651
709
  overflow: hidden;
652
710
  text-overflow: ellipsis;
@@ -259,6 +259,125 @@ describe('UnnnicChatsContact', () => {
259
259
  });
260
260
  });
261
261
 
262
+ describe('Media "You:" prefix', () => {
263
+ const imageMedia = {
264
+ media: [
265
+ {
266
+ content_type: 'image/jpeg',
267
+ message: 'a997421d-6238-4bef-912d-e689c1c0db3f',
268
+ url: 'https://example.com/photo.jpg',
269
+ created_on: '2025-04-15T14:58:56.163027-03:00',
270
+ },
271
+ ],
272
+ };
273
+
274
+ it('should not render the prefix on a media message when isFromUser is falsy', async () => {
275
+ await wrapper.setProps({ lastMessage: imageMedia });
276
+
277
+ const prefix = wrapper.find('[data-testid="media-sender-prefix"]');
278
+ expect(prefix.exists()).toBe(false);
279
+ });
280
+
281
+ it('should render the EN "You:" prefix when isFromUser is true', async () => {
282
+ await wrapper.setProps({
283
+ lastMessage: { ...imageMedia, isFromUser: true },
284
+ locale: 'en',
285
+ });
286
+
287
+ const prefix = wrapper.find('[data-testid="media-sender-prefix"]');
288
+ expect(prefix.exists()).toBe(true);
289
+ expect(prefix.text()).toBe('You:');
290
+ });
291
+
292
+ it('should render the PT-BR "Você:" prefix when isFromUser is true', async () => {
293
+ await wrapper.setProps({
294
+ lastMessage: { ...imageMedia, isFromUser: true },
295
+ locale: 'pt-br',
296
+ });
297
+
298
+ const prefix = wrapper.find('[data-testid="media-sender-prefix"]');
299
+ expect(prefix.exists()).toBe(true);
300
+ expect(prefix.text()).toBe('Você:');
301
+ });
302
+
303
+ it('should render the ES "Tú:" prefix when isFromUser is true', async () => {
304
+ await wrapper.setProps({
305
+ lastMessage: { ...imageMedia, isFromUser: true },
306
+ locale: 'es',
307
+ });
308
+
309
+ const prefix = wrapper.find('[data-testid="media-sender-prefix"]');
310
+ expect(prefix.exists()).toBe(true);
311
+ expect(prefix.text()).toBe('Tú:');
312
+ });
313
+
314
+ it('should not render the prefix for non-media messages even when isFromUser is true', async () => {
315
+ await wrapper.setProps({
316
+ lastMessage: { text: 'Hello there', isFromUser: true },
317
+ });
318
+
319
+ const prefix = wrapper.find('[data-testid="media-sender-prefix"]');
320
+ expect(prefix.exists()).toBe(false);
321
+ });
322
+ });
323
+
324
+ describe('New message indicator', () => {
325
+ it('should not render the dot by default', () => {
326
+ const indicator = wrapper.find('[data-testid="new-message-indicator"]');
327
+ expect(indicator.exists()).toBe(false);
328
+ });
329
+
330
+ it('should render the dot when newMessageIndicator is true', async () => {
331
+ await wrapper.setProps({ newMessageIndicator: true });
332
+
333
+ const indicator = wrapper.find('[data-testid="new-message-indicator"]');
334
+ expect(indicator.exists()).toBe(true);
335
+ });
336
+
337
+ it('should hide the unread-count circle when newMessageIndicator and unreadMessages are both set', async () => {
338
+ await wrapper.setProps({
339
+ newMessageIndicator: true,
340
+ unreadMessages: 5,
341
+ });
342
+
343
+ const indicator = wrapper.find('[data-testid="new-message-indicator"]');
344
+ const unreadCount = wrapper.find(
345
+ '.chats-contact__infos__unread-messages',
346
+ );
347
+
348
+ expect(indicator.exists()).toBe(true);
349
+ expect(unreadCount.exists()).toBe(false);
350
+ });
351
+
352
+ it('should keep tooltip disabled when newMessageIndicatorTooltip is empty', async () => {
353
+ await wrapper.setProps({
354
+ newMessageIndicator: true,
355
+ newMessageIndicatorTooltip: '',
356
+ });
357
+
358
+ const tooltip = wrapper.findComponent({ name: 'UnnnicTooltip' });
359
+
360
+ expect(tooltip.exists()).toBe(true);
361
+ expect(tooltip.props('enabled')).toBe(false);
362
+ expect(tooltip.props('text')).toBe('');
363
+ });
364
+
365
+ it('should enable tooltip with the provided text when newMessageIndicatorTooltip is set', async () => {
366
+ const tooltipText = 'New chats received';
367
+
368
+ await wrapper.setProps({
369
+ newMessageIndicator: true,
370
+ newMessageIndicatorTooltip: tooltipText,
371
+ });
372
+
373
+ const tooltip = wrapper.findComponent({ name: 'UnnnicTooltip' });
374
+
375
+ expect(tooltip.exists()).toBe(true);
376
+ expect(tooltip.props('enabled')).toBe(true);
377
+ expect(tooltip.props('text')).toBe(tooltipText);
378
+ });
379
+ });
380
+
262
381
  describe('Pending response', () => {
263
382
  it('should not render the pending response icon by default', () => {
264
383
  const icon = wrapper.find('[data-testid="pending-response-icon"]');
@@ -220,3 +220,56 @@ export const MediaLastMessage = {
220
220
  `,
221
221
  }),
222
222
  };
223
+
224
+ const lastMessageMediaFromUser = Object.fromEntries(
225
+ Object.entries(lastMessageMedia).map(([mediaType, message]) => [
226
+ mediaType,
227
+ { ...message, isFromUser: true },
228
+ ]),
229
+ );
230
+
231
+ export const MediaLastMessageFromUser = {
232
+ args: {
233
+ ...defaultArgs,
234
+ },
235
+ render: (args) => ({
236
+ setup() {
237
+ return { args, lastMessageMediaFromUser };
238
+ },
239
+ components: { unnnicChatsContact },
240
+ template: `
241
+ <div style="display: grid;">
242
+ <unnnic-chats-contact v-for="mediaType in ['geo', 'audio', 'image', 'video', 'document']" v-bind="args" :lastMessage="lastMessageMediaFromUser[mediaType]"/>
243
+ </div>
244
+ `,
245
+ }),
246
+ };
247
+
248
+ export const NewMessageIndicator = {
249
+ args: {
250
+ ...defaultArgs,
251
+ title: 'Aline',
252
+ projectName: 'Sector name',
253
+ lastMessage: {
254
+ text: 'I’d like to know if powdered dishwasher detergent is available',
255
+ },
256
+ lastInteractionTime: new Date().toISOString(),
257
+ unreadMessages: 1,
258
+ newMessageIndicator: true,
259
+ },
260
+ };
261
+
262
+ export const NewMessageIndicatorWithTooltip = {
263
+ args: {
264
+ ...defaultArgs,
265
+ title: 'Aline',
266
+ projectName: 'Sector name',
267
+ lastMessage: {
268
+ text: 'I’d like to know if powdered dishwasher detergent is available',
269
+ },
270
+ lastInteractionTime: new Date().toISOString(),
271
+ unreadMessages: 1,
272
+ newMessageIndicator: true,
273
+ newMessageIndicatorTooltip: 'New chats received',
274
+ },
275
+ };