contactstudiocstools 1.0.258 → 1.0.260

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/dist/module.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@contactstudio/cstools",
3
3
  "configKey": "CSTools",
4
- "version": "1.0.258"
4
+ "version": "1.0.260"
5
5
  }
@@ -0,0 +1,186 @@
1
+ <template>
2
+ <!-- contact -->
3
+ <li class="chat-contact flex items-center !pl-3 max-h-none !rounded-none">
4
+ <!-- avatar -->
5
+ <figure
6
+ :class="[getStatusClass]"
7
+ :notifications="contact.notifications"
8
+ class="w-9 h-9 rounded-full avatar-glass avatar-soft-secondary"
9
+ >
10
+ <img
11
+ v-if="contact.avatar"
12
+ :src="contact.avatar"
13
+ class="rounded-md"
14
+ >
15
+ <i
16
+ v-else
17
+ class="bi-person-fill text-2xl"
18
+ />
19
+ </figure>
20
+
21
+ <!-- info -->
22
+ <div
23
+ class="flex-1 ml-3 py-2 !pr-3 w-24 chat-contact-border"
24
+ :class="{'border-t-2': index === 0}"
25
+ >
26
+ <p class="flex justify-between items-center overflow-hidden text-ellipsis whitespace-nowrap mb-1">
27
+ <!-- label -->
28
+ <span class="text-xs">
29
+ {{ contact.label }}
30
+ </span>
31
+
32
+ <!-- hours
33
+ <span
34
+ v-if="entryDateExists"
35
+ class="badge badge-outline-secondary ml-2"
36
+ tooltip="Tempo em atendimento"
37
+ >
38
+ {{ new Date(milliseconds).toISOString().slice(11, 19) }}
39
+ </span>
40
+ -->
41
+
42
+ <div class="flex items-center gap-1">
43
+ <!-- date message -->
44
+ <p
45
+ class="badge !p-0 text-secondary"
46
+ tooltip="Horário da última mensagem"
47
+ >
48
+ {{ getDate }}
49
+ </p>
50
+ <!-- expirate -->
51
+ <div
52
+ v-if="expirated"
53
+ tooltip="Envie uma mensagem para o cliente!"
54
+ class="flex justify-center items-center relative"
55
+ >
56
+ <div class="flex justify-center items-center rounded-full bg-error h-4 w-4">
57
+ <i class="bi bi-bell-fill text-white text-[8.4px] ml-[1px]" />
58
+ </div>
59
+ </div>
60
+ </div>
61
+ </p>
62
+ <!-- typing -->
63
+ <p
64
+ v-if="contact.typing"
65
+ class="text-2xs text-success"
66
+ >
67
+ Digitando...
68
+ </p>
69
+ <!-- message -->
70
+ <div
71
+ v-else
72
+ class="markdown text-2xs opacity-50 w-full overflow-hidden text-ellipsis whitespace-nowrap"
73
+ v-html="marked(props.contact.message ?? '')"
74
+ />
75
+ </div>
76
+ </li>
77
+ </template>
78
+
79
+ <script setup lang="ts">
80
+ import { marked } from "marked";
81
+ import { ref, computed, onMounted } from "vue";
82
+ import { getMinutesBetweenDates, getTimeByDate, IChatContact } from "./types";
83
+
84
+ // props
85
+ interface IProps {
86
+ contact: IChatContact;
87
+ timeout: number;
88
+ index: number;
89
+ }
90
+ const props = defineProps<IProps>();
91
+
92
+ // mounted
93
+ onMounted(() => {
94
+ setInterval(validateExpiration, 1000);
95
+ });
96
+
97
+ // computed
98
+ const getDate = computed<string>(() => {
99
+ const date = props.contact.date;
100
+ if (!date) return "";
101
+ return getTimeByDate(date);
102
+ });
103
+ const entryDateExists = computed<boolean>(() => !!props.contact.entrydate)
104
+ const getStatusClass = computed<string>(() => {
105
+ if (props.contact.on) return "avatar-status-success";
106
+ return "avatar-status-error";
107
+ });
108
+
109
+ // data
110
+ const expirated = ref<boolean>(false);
111
+ const milliseconds = ref<number>(0)
112
+
113
+ // methods
114
+ function validateExpiration() {
115
+ if (!props.contact.date) return;
116
+ expirated.value =
117
+ getMinutesBetweenDates(new Date(), props.contact.date) >= props.timeout;
118
+ }
119
+ async function setTimerContact(): Promise<void> {
120
+ if (!props.contact.entrydate) return
121
+
122
+ await new Promise(resolve => setTimeout(resolve, 1000))
123
+
124
+ const now = new Date().getTime()
125
+ const entry = props.contact.entrydate.getTime()
126
+
127
+ milliseconds.value = Math.abs(now - entry)
128
+
129
+ setTimerContact()
130
+ }
131
+ setTimerContact()
132
+ </script>
133
+
134
+ <style scoped>
135
+ .min-w-40px {
136
+ min-width: 40px;
137
+ }
138
+
139
+ .text-2xs {
140
+ font-size: 0.7rem;
141
+ }
142
+ .avatar-glass {
143
+ align-items: center;
144
+ display: flex;
145
+ font-weight: 500;
146
+ justify-content: center;
147
+ position: relative;
148
+ text-transform: uppercase;
149
+ }
150
+
151
+ .avatar-glass:after,.avatar-glass:not(.avatar-glass[notifications]):after {
152
+ border-radius: 99999px;
153
+ border: 3px solid #ffffff;
154
+ color: #fff;
155
+ font-size: 11px;
156
+ height: 15px;
157
+ width: 15px;
158
+ position: absolute;
159
+ right: 0;
160
+ top: 0;
161
+ transform: translate(40%,-40%)
162
+ }
163
+
164
+ .avatar-glass:not([notifications=""]):after {
165
+ content: attr(notifications);
166
+ width: 25px;
167
+ height: 25px;
168
+ display: flex;
169
+ justify-content: center;
170
+ align-items: center
171
+ }
172
+
173
+ .chat-contact:hover {
174
+ cursor: pointer;
175
+ background-color: rgba(0, 0, 0, 0.05);
176
+ }
177
+ .dark .chat-contact:hover {
178
+ background-color: rgba(255, 255, 255, 0.05);
179
+ }
180
+
181
+ .chat-contact-border {
182
+ border-bottom: 2px;
183
+ border-style: solid;
184
+ border-color: rgba(0, 0, 0, 0.2);
185
+ }
186
+ </style>
@@ -0,0 +1,74 @@
1
+ <template>
2
+ <div>
3
+ <div class="flex items-center text-xs">
4
+ <span class="w-full px-6 py-5 text-xl">
5
+ Conversas
6
+ </span>
7
+ </div>
8
+
9
+ <article class="overflow-auto max-h-full scrollbar pb-24">
10
+ <!-- contacts -->
11
+ <div
12
+ v-for="(contact, i) in contacts"
13
+ v-show="!visibleSchedules"
14
+ :key="i"
15
+ >
16
+ <ul class="list">
17
+ <AtomChatContactGlass
18
+ :timeout="timeout"
19
+ :contact="contact"
20
+ :class="getSelectedClass(contact)"
21
+ :index="i"
22
+ @click="select(contact)"
23
+ />
24
+ </ul>
25
+ </div>
26
+ </article>
27
+ </div>
28
+ </template>
29
+
30
+ <script setup lang="ts">
31
+ import { ref, computed } from "vue";
32
+ import { IChatContact, IChatContacts, IPortfolioSchedules } from "./types";
33
+
34
+ // props
35
+ interface IProps {
36
+ contacts: IChatContacts;
37
+ schedules: IPortfolioSchedules;
38
+ selected?: IChatContact;
39
+ timeout: number;
40
+ }
41
+ const props = defineProps<IProps>();
42
+
43
+ // emits
44
+ interface IEmits {
45
+ (e: "select", contact: IChatContact): void;
46
+ (e: "schedule", schedule: boolean): void;
47
+ }
48
+ const emit = defineEmits<IEmits>();
49
+
50
+ // computed
51
+ const getSelectedClass = computed<Function>(() => (contact: IChatContact) => {
52
+ if (props.selected?.id === contact.id)
53
+ return "bg-slate-100 dark:bg-slate-800";
54
+ return "";
55
+ });
56
+
57
+ // data
58
+ const visibleSchedules = ref<boolean>(false)
59
+
60
+ // methods
61
+ function select(contact: IChatContact): void {
62
+ emit("select", contact);
63
+ }
64
+ function changeSchedule(): void {
65
+ visibleSchedules.value = !visibleSchedules.value
66
+ emit("schedule", visibleSchedules.value);
67
+ }
68
+ </script>
69
+
70
+ <style scoped>
71
+ .text-2xs {
72
+ font-size: 0.7rem;
73
+ }
74
+ </style>
@@ -70,6 +70,7 @@
70
70
  <MoleculeFieldGroup
71
71
  :rules="getRulesNote"
72
72
  :class="{ error: noteIsInvalid }"
73
+ label="Observação de Tabulação"
73
74
  >
74
75
  <AtomFieldTextarea
75
76
  v-model="note"
@@ -108,6 +109,29 @@
108
109
  />
109
110
  </label>
110
111
  </MoleculeFieldGroup>
112
+
113
+ <!-- Exibir quando ter manifestação vinculada -->
114
+ <div
115
+ v-show="!manifestationIsEmpty"
116
+ class="mx-5 !pb-4"
117
+ >
118
+ <div class="divider" />
119
+
120
+ <!-- manifestatio observation -->
121
+ <article>
122
+ <MoleculeFieldGroup
123
+ label="Nota de Manifestação"
124
+ class="mt-3"
125
+ >
126
+ <AtomFieldTextarea
127
+ v-model="manifestationNote"
128
+ rows="5"
129
+ placeholder="Nota de Manifestação"
130
+ @blur="persist"
131
+ />
132
+ </MoleculeFieldGroup>
133
+ </article>
134
+ </div>
111
135
  </details>
112
136
  </div>
113
137
  </article>
@@ -125,7 +149,7 @@ interface IProps {
125
149
  manifestation?: INodes;
126
150
  persist?: Function;
127
151
  disableNode?: (({ nodeValue }: { nodeValue: string }) => boolean) | undefined;
128
- defaults?: { tabulation: INodes[]; note: string };
152
+ defaults?: { tabulation: INodes[]; note: string ; manifestationNote?: string };
129
153
  }
130
154
  const props = defineProps<IProps>();
131
155
 
@@ -184,6 +208,7 @@ const MoleculeFieldGroupRef = ref<InstanceType<
184
208
  > | null>(null);
185
209
  const tabulation = reactive<INodes[]>(props.defaults?.tabulation ?? []);
186
210
  const note = ref<string>(props.defaults?.note ?? "");
211
+ const manifestationNote = ref<string>(props.defaults?.manifestationNote ?? "");
187
212
  const additionals = reactive<any>({});
188
213
 
189
214
  // methods
@@ -198,6 +223,7 @@ function persist(): void {
198
223
  props.persist({
199
224
  tabulation: tabulation,
200
225
  note: note.value,
226
+ manifestationNote: manifestationNote.value,
201
227
  additionals,
202
228
  });
203
229
  }
@@ -228,6 +254,7 @@ watch(
228
254
  defineExpose({
229
255
  tabulation,
230
256
  note: getNote,
257
+ manifestationNote,
231
258
  additionals,
232
259
  isValid,
233
260
  isSchedule,
@@ -180,9 +180,15 @@ export function PausesDTO({ lista_pausa }) {
180
180
  return pauses;
181
181
  }
182
182
  export function DoubtsDTO(primitives) {
183
- if (!primitives)
183
+ if (!primitives || !Array.isArray(primitives)) {
184
184
  return [];
185
- return primitives.map((primitive) => primitive.doubt).flat();
185
+ }
186
+ return primitives.reduce((acc, primitive) => {
187
+ if (primitive && Array.isArray(primitive.doubt)) {
188
+ acc.push(...primitive.doubt);
189
+ }
190
+ return acc;
191
+ }, []);
186
192
  }
187
193
  export function UserDTO(primitive) {
188
194
  if (!primitive.info_agente) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "contactstudiocstools",
3
- "version": "1.0.258",
3
+ "version": "1.0.260",
4
4
  "description": "Nuxt Tools Module for ContactStudio",
5
5
  "type": "module",
6
6
  "exports": {