contactstudiocstools 1.0.224
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/README.md +94 -0
- package/dist/module.cjs +5 -0
- package/dist/module.d.ts +7 -0
- package/dist/module.json +5 -0
- package/dist/module.mjs +72 -0
- package/dist/runtime/components/Atom.Alert.vue +46 -0
- package/dist/runtime/components/Atom.Auth.vue +37 -0
- package/dist/runtime/components/Atom.BannerChatEmpty.vue +18 -0
- package/dist/runtime/components/Atom.BannerPage404.vue +28 -0
- package/dist/runtime/components/Atom.BannerPageUnauthorized.vue +18 -0
- package/dist/runtime/components/Atom.Breadcrumb.vue +26 -0
- package/dist/runtime/components/Atom.ChatContact.vue +136 -0
- package/dist/runtime/components/Atom.ChatContactSchedule.vue +87 -0
- package/dist/runtime/components/Atom.ChatMessageFooter.vue +25 -0
- package/dist/runtime/components/Atom.DarkMode.vue +67 -0
- package/dist/runtime/components/Atom.DraggableWindow.vue +102 -0
- package/dist/runtime/components/Atom.Dropdown.vue +9 -0
- package/dist/runtime/components/Atom.DropdownSearchable.vue +25 -0
- package/dist/runtime/components/Atom.Fetch.vue +46 -0
- package/dist/runtime/components/Atom.Field.vue +43 -0
- package/dist/runtime/components/Atom.FieldDate.vue +19 -0
- package/dist/runtime/components/Atom.FieldNumber.vue +19 -0
- package/dist/runtime/components/Atom.FieldPhone.vue +92 -0
- package/dist/runtime/components/Atom.FieldSelect.vue +28 -0
- package/dist/runtime/components/Atom.FieldSelectMultiple.vue +49 -0
- package/dist/runtime/components/Atom.FieldText.vue +19 -0
- package/dist/runtime/components/Atom.FieldTextarea.vue +41 -0
- package/dist/runtime/components/Atom.Loading.vue +80 -0
- package/dist/runtime/components/Atom.Notification.vue +48 -0
- package/dist/runtime/components/Atom.Ringtone.vue +23 -0
- package/dist/runtime/components/Atom.SelectTreeField.vue +49 -0
- package/dist/runtime/components/Atom.Snapshot.vue +33 -0
- package/dist/runtime/components/Atom.Tabs.vue +60 -0
- package/dist/runtime/components/Molecule.ChatMessageFile.vue +102 -0
- package/dist/runtime/components/Molecule.ChatMessageOption.vue +85 -0
- package/dist/runtime/components/Molecule.ChatMessageText.vue +36 -0
- package/dist/runtime/components/Molecule.ClientHistory.vue +62 -0
- package/dist/runtime/components/Molecule.DropdownDDI.vue +333 -0
- package/dist/runtime/components/Molecule.FieldGroup.vue +73 -0
- package/dist/runtime/components/Molecule.FieldSelectMultiple.vue +19 -0
- package/dist/runtime/components/Molecule.File.vue +84 -0
- package/dist/runtime/components/Molecule.SelectTreeSearchable.vue +126 -0
- package/dist/runtime/components/Molecule.Status.vue +154 -0
- package/dist/runtime/components/Molecule.TimeDaily.vue +9 -0
- package/dist/runtime/components/Organism.Attachments.vue +139 -0
- package/dist/runtime/components/Organism.ChatMessages.vue +31 -0
- package/dist/runtime/components/Organism.ChatRoom.vue +342 -0
- package/dist/runtime/components/Organism.ChatSchedule.vue +110 -0
- package/dist/runtime/components/Organism.ClientHistoryTable.vue +85 -0
- package/dist/runtime/components/Organism.ClientHistoryTimeline.vue +77 -0
- package/dist/runtime/components/Organism.FAQ.vue +88 -0
- package/dist/runtime/components/Organism.Form.vue +67 -0
- package/dist/runtime/components/Organism.FormMailing.vue +112 -0
- package/dist/runtime/components/Organism.HeaderMain.vue +79 -0
- package/dist/runtime/components/Organism.Manifestation.vue +146 -0
- package/dist/runtime/components/Organism.Nav.vue +27 -0
- package/dist/runtime/components/Organism.NavMain.vue +187 -0
- package/dist/runtime/components/Organism.PageContainer.vue +22 -0
- package/dist/runtime/components/Organism.Schedule.vue +170 -0
- package/dist/runtime/components/Organism.Tabulation.vue +237 -0
- package/dist/runtime/components/types/dto.d.ts +16 -0
- package/dist/runtime/components/types/dto.mjs +236 -0
- package/dist/runtime/components/types/helpers.d.ts +39 -0
- package/dist/runtime/components/types/helpers.mjs +295 -0
- package/dist/runtime/components/types/index.d.ts +4 -0
- package/dist/runtime/components/types/index.mjs +4 -0
- package/dist/runtime/components/types/types.d.ts +198 -0
- package/dist/runtime/components/types/types.mjs +35 -0
- package/dist/runtime/index.css +1 -0
- package/dist/runtime/plugins/clickOutside.d.ts +2 -0
- package/dist/runtime/plugins/clickOutside.mjs +16 -0
- package/dist/runtime/plugins/emitter.d.ts +2 -0
- package/dist/runtime/plugins/emitter.mjs +17 -0
- package/dist/runtime/public/192x192.png +0 -0
- package/dist/runtime/public/404.svg +1 -0
- package/dist/runtime/public/512x512.png +0 -0
- package/dist/runtime/public/chat.svg +138 -0
- package/dist/runtime/public/chatbg.png +0 -0
- package/dist/runtime/public/dev-sw.d.ts +0 -0
- package/dist/runtime/public/dev-sw.mjs +0 -0
- package/dist/runtime/public/empty.svg +1 -0
- package/dist/runtime/public/loading.svg +1 -0
- package/dist/runtime/public/messages.svg +1 -0
- package/dist/runtime/public/privacy.svg +1 -0
- package/dist/runtime/public/ringtone.mp3 +0 -0
- package/dist/runtime/public/security.svg +188 -0
- package/dist/runtime/public/snapshot.d.ts +15 -0
- package/dist/runtime/public/snapshot.mjs +77 -0
- package/dist/runtime/public/unauthorized.svg +1 -0
- package/dist/types.d.ts +10 -0
- package/package.json +50 -0
package/README.md
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
Get your module up and running quickly.
|
|
3
|
+
|
|
4
|
+
Find and replace all on all files (CMD+SHIFT+F):
|
|
5
|
+
- Name: CS Tools
|
|
6
|
+
- Package name: @contactstudio/cstools
|
|
7
|
+
- Description: Nuxt Tools Module for ContactStudio
|
|
8
|
+
-->
|
|
9
|
+
|
|
10
|
+
# CS Tools
|
|
11
|
+
|
|
12
|
+
[![npm version][npm-version-src]][npm-version-href]
|
|
13
|
+
[![npm downloads][npm-downloads-src]][npm-downloads-href]
|
|
14
|
+
[![License][license-src]][license-href]
|
|
15
|
+
[![Nuxt][nuxt-src]][nuxt-href]
|
|
16
|
+
|
|
17
|
+
Nuxt Tools Module for ContactStudio for doing amazing things.
|
|
18
|
+
|
|
19
|
+
- [✨ Release Notes](/CHANGELOG.md)
|
|
20
|
+
<!-- - [🏀 Online playground](https://stackblitz.com/github/your-org/@contactstudio/cstools?file=playground%2Fapp.vue) -->
|
|
21
|
+
<!-- - [📖 Documentation](https://example.com) -->
|
|
22
|
+
|
|
23
|
+
## Features
|
|
24
|
+
|
|
25
|
+
<!-- Highlight some of the features your module provide here -->
|
|
26
|
+
|
|
27
|
+
- ⛰ Foo
|
|
28
|
+
- 🚠 Bar
|
|
29
|
+
- 🌲 Baz
|
|
30
|
+
|
|
31
|
+
## Quick Setup
|
|
32
|
+
|
|
33
|
+
1. Add `@contactstudio/cstools` dependency to your project
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
# Using pnpm
|
|
37
|
+
pnpm add -D @contactstudio/cstools
|
|
38
|
+
|
|
39
|
+
# Using yarn
|
|
40
|
+
yarn add --dev @contactstudio/cstools
|
|
41
|
+
|
|
42
|
+
# Using npm
|
|
43
|
+
npm install --save-dev @contactstudio/cstools
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
2. Add `@contactstudio/cstools` to the `modules` section of `nuxt.config.ts`
|
|
47
|
+
|
|
48
|
+
```js
|
|
49
|
+
export default defineNuxtConfig({
|
|
50
|
+
modules: ["@contactstudio/cstools"],
|
|
51
|
+
});
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
That's it! You can now use CS Tools in your Nuxt app ✨
|
|
55
|
+
|
|
56
|
+
## Development
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
# Watch generate CSS
|
|
60
|
+
npx tailwindcss -o ./src/runtime/index.css --minify --watch
|
|
61
|
+
|
|
62
|
+
# Install dependencies
|
|
63
|
+
npm install
|
|
64
|
+
|
|
65
|
+
# Generate type stubs
|
|
66
|
+
npm run dev:prepare
|
|
67
|
+
|
|
68
|
+
# Develop with the playground
|
|
69
|
+
npm run dev
|
|
70
|
+
|
|
71
|
+
# Build the playground
|
|
72
|
+
npm run dev:build
|
|
73
|
+
|
|
74
|
+
# Run ESLint
|
|
75
|
+
npm run lint
|
|
76
|
+
|
|
77
|
+
# Run Vitest
|
|
78
|
+
npm run test
|
|
79
|
+
npm run test:watch
|
|
80
|
+
|
|
81
|
+
# Release new version
|
|
82
|
+
npm run release
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
<!-- Badges -->
|
|
86
|
+
|
|
87
|
+
[npm-version-src]: https://img.shields.io/npm/v/@contactstudio/cstools/latest.svg?style=flat&colorA=18181B&colorB=28CF8D
|
|
88
|
+
[npm-version-href]: https://npmjs.com/package/@contactstudio/cstools
|
|
89
|
+
[npm-downloads-src]: https://img.shields.io/npm/dm/@contactstudio/cstools.svg?style=flat&colorA=18181B&colorB=28CF8D
|
|
90
|
+
[npm-downloads-href]: https://npmjs.com/package/@contactstudio/cstools
|
|
91
|
+
[license-src]: https://img.shields.io/npm/l/@contactstudio/cstools.svg?style=flat&colorA=18181B&colorB=28CF8D
|
|
92
|
+
[license-href]: https://npmjs.com/package/@contactstudio/cstools
|
|
93
|
+
[nuxt-src]: https://img.shields.io/badge/Nuxt-18181B?logo=nuxt.js
|
|
94
|
+
[nuxt-href]: https://nuxt.com
|
package/dist/module.cjs
ADDED
package/dist/module.d.ts
ADDED
package/dist/module.json
ADDED
package/dist/module.mjs
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { defineNuxtModule, createResolver, addPlugin, addComponent } from '@nuxt/kit';
|
|
2
|
+
import { fileURLToPath } from 'url';
|
|
3
|
+
import { readdirSync } from 'fs';
|
|
4
|
+
|
|
5
|
+
const module = defineNuxtModule({
|
|
6
|
+
meta: {
|
|
7
|
+
name: "@contactstudio/cstools",
|
|
8
|
+
configKey: "CSTools"
|
|
9
|
+
},
|
|
10
|
+
// Default configuration options of the Nuxt module
|
|
11
|
+
defaults: {},
|
|
12
|
+
setup(options, nuxt) {
|
|
13
|
+
const { resolve } = createResolver(import.meta.url);
|
|
14
|
+
const runtimeDir = fileURLToPath(new URL("./runtime", import.meta.url));
|
|
15
|
+
const componentsDir = `${runtimeDir}/components`;
|
|
16
|
+
addPlugin(resolve("runtime/plugins/emitter"));
|
|
17
|
+
addPlugin(resolve("runtime/plugins/clickOutside"));
|
|
18
|
+
nuxt.options.css.push(`${runtimeDir}/index.css`);
|
|
19
|
+
setAliases(nuxt);
|
|
20
|
+
setCDNs(nuxt);
|
|
21
|
+
setLibPublic(nuxt);
|
|
22
|
+
const files = readdirSync(componentsDir);
|
|
23
|
+
for (const file of files) {
|
|
24
|
+
addComponent({
|
|
25
|
+
name: getFileName(file),
|
|
26
|
+
filePath: resolve(componentsDir, file)
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
function getFileName(file) {
|
|
32
|
+
const parts = file.split(".");
|
|
33
|
+
parts.pop();
|
|
34
|
+
return parts.join("");
|
|
35
|
+
}
|
|
36
|
+
function setCDNs(nuxt) {
|
|
37
|
+
const MINDBEUI_VERSION = nuxt.options.runtimeConfig.public.MINDBEUI_VERSION;
|
|
38
|
+
nuxt.options.app.head.link?.push({
|
|
39
|
+
rel: "stylesheet",
|
|
40
|
+
href: `https://cdn.jsdelivr.net/gh/lipis/flag-icons@6.11.0/css/flag-icons.min.css`
|
|
41
|
+
});
|
|
42
|
+
nuxt.options.app.head.link?.push({
|
|
43
|
+
rel: "stylesheet",
|
|
44
|
+
href: `https://unpkg.com/@contactstudio/mindbeui@${MINDBEUI_VERSION}/dist/mindbeui.css`
|
|
45
|
+
});
|
|
46
|
+
nuxt.options.app.head.script?.push({
|
|
47
|
+
src: `https://unpkg.com/@contactstudio/mindbeui@${MINDBEUI_VERSION}/dist/mindbeui.js`
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
function setAliases(nuxt) {
|
|
51
|
+
nuxt.options.alias = {
|
|
52
|
+
...nuxt.options.alias,
|
|
53
|
+
types: fileURLToPath(
|
|
54
|
+
new URL("./runtime/components/types", import.meta.url)
|
|
55
|
+
),
|
|
56
|
+
components: fileURLToPath(new URL("./runtime/components", import.meta.url)),
|
|
57
|
+
public: fileURLToPath(new URL("./runtime/public", import.meta.url))
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
function setLibPublic(nuxt) {
|
|
61
|
+
const { resolve } = createResolver(import.meta.url);
|
|
62
|
+
nuxt.hook("nitro:config", async (nitroConfig) => {
|
|
63
|
+
nitroConfig.publicAssets || (nitroConfig.publicAssets = []);
|
|
64
|
+
nitroConfig.publicAssets.push({
|
|
65
|
+
dir: resolve("./runtime/public"),
|
|
66
|
+
maxAge: 60 * 60 * 24 * 365
|
|
67
|
+
// 1 year
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export { module as default };
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div
|
|
3
|
+
class="alert"
|
|
4
|
+
:class="[{ visible }, getType]"
|
|
5
|
+
>
|
|
6
|
+
{{ message }}
|
|
7
|
+
</div>
|
|
8
|
+
</template>
|
|
9
|
+
|
|
10
|
+
<script setup lang="ts">
|
|
11
|
+
import { ref, computed } from "vue";
|
|
12
|
+
|
|
13
|
+
// props
|
|
14
|
+
interface IProps {
|
|
15
|
+
timeout?: number
|
|
16
|
+
}
|
|
17
|
+
const props = defineProps<IProps>()
|
|
18
|
+
|
|
19
|
+
// computed
|
|
20
|
+
const getType = computed<string>(() => {
|
|
21
|
+
return `alert-${type.value}`
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
// data
|
|
25
|
+
const visible = ref<boolean>(false);
|
|
26
|
+
const type = ref<string>("")
|
|
27
|
+
const message = ref<string>("")
|
|
28
|
+
|
|
29
|
+
// methods
|
|
30
|
+
function show(tp: string, msg: string) {
|
|
31
|
+
if (visible.value) return;
|
|
32
|
+
|
|
33
|
+
type.value = tp
|
|
34
|
+
message.value = msg
|
|
35
|
+
visible.value = true;
|
|
36
|
+
|
|
37
|
+
setTimeout(() => {
|
|
38
|
+
visible.value = false;
|
|
39
|
+
}, props.timeout ?? 5000);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// expose
|
|
43
|
+
defineExpose({ show });
|
|
44
|
+
</script>
|
|
45
|
+
|
|
46
|
+
<style scoped></style>
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div />
|
|
3
|
+
</template>
|
|
4
|
+
|
|
5
|
+
<script setup lang="ts">
|
|
6
|
+
import { onMounted, onUpdated } from "vue"
|
|
7
|
+
import { useCookie, useNuxtApp } from "#app";
|
|
8
|
+
|
|
9
|
+
// props
|
|
10
|
+
interface IProps {
|
|
11
|
+
logout: Function
|
|
12
|
+
}
|
|
13
|
+
const props = defineProps<IProps>()
|
|
14
|
+
|
|
15
|
+
// hooks
|
|
16
|
+
onMounted(update)
|
|
17
|
+
onUpdated(update)
|
|
18
|
+
|
|
19
|
+
// emits
|
|
20
|
+
const { $listen } = useNuxtApp();
|
|
21
|
+
$listen("auth:logout", logout)
|
|
22
|
+
$listen("auth:update", update)
|
|
23
|
+
|
|
24
|
+
// methods
|
|
25
|
+
function update(): void {
|
|
26
|
+
const session = useCookie("cssession");
|
|
27
|
+
|
|
28
|
+
if (!session.value) {
|
|
29
|
+
props.logout()
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function logout(): void {
|
|
33
|
+
props.logout()
|
|
34
|
+
}
|
|
35
|
+
</script>
|
|
36
|
+
|
|
37
|
+
<style scoped></style>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="w-full flex flex-col justify-center items-center text-center p-10">
|
|
3
|
+
<img
|
|
4
|
+
src="../public/chat.svg"
|
|
5
|
+
class="max-w-md -mt-44 -mb-10 -ml-5"
|
|
6
|
+
>
|
|
7
|
+
<h4 class="text-lg mt-5 mb-1 text-primary font-medium">
|
|
8
|
+
Nenhuma conversa selecionada
|
|
9
|
+
</h4>
|
|
10
|
+
<p class="opacity-50">
|
|
11
|
+
Para iniciar o atendimento, selecione uma conversa do menu ao lado
|
|
12
|
+
</p>
|
|
13
|
+
</div>
|
|
14
|
+
</template>
|
|
15
|
+
|
|
16
|
+
<script setup lang="ts"></script>
|
|
17
|
+
|
|
18
|
+
<style scoped></style>
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="w-full h-screen relative flex flex-col md:flex-row overflow-hidden text-black dark:text-white">
|
|
3
|
+
<article class="flex-1 p-16">
|
|
4
|
+
<p class="font-bold mb-16 sm:mb-40">
|
|
5
|
+
404 Not Found
|
|
6
|
+
</p>
|
|
7
|
+
<h1 class="text-8xl mb-8 font-bold">
|
|
8
|
+
Ohh não...
|
|
9
|
+
</h1>
|
|
10
|
+
<p class="text-lg opacity-50 mb-16">
|
|
11
|
+
Desculpe, infelizmente a página não pode ser encontrada.
|
|
12
|
+
</p>
|
|
13
|
+
<button
|
|
14
|
+
class="btn btn-outline-secondary text-base max-h-none px-6"
|
|
15
|
+
@click="$router.push('/')"
|
|
16
|
+
>
|
|
17
|
+
Página inicial
|
|
18
|
+
</button>
|
|
19
|
+
</article>
|
|
20
|
+
<aside class="flex">
|
|
21
|
+
<img src="../public/404.svg">
|
|
22
|
+
</aside>
|
|
23
|
+
</div>
|
|
24
|
+
</template>
|
|
25
|
+
|
|
26
|
+
<script setup lang="ts"></script>
|
|
27
|
+
|
|
28
|
+
<style scoped></style>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<article class="flex flex-col justify-center items-center text-center dark:text-white">
|
|
3
|
+
<h4 class="text-xl text-warn font-medium mb-1">
|
|
4
|
+
Área restrita.
|
|
5
|
+
</h4>
|
|
6
|
+
<p class="opacity-50 text-sm mb-10">
|
|
7
|
+
Você não possui permissão para acessar essa página
|
|
8
|
+
</p>
|
|
9
|
+
<img
|
|
10
|
+
src="../public/security.svg"
|
|
11
|
+
class="w-full max-w-sm -mt-10"
|
|
12
|
+
>
|
|
13
|
+
</article>
|
|
14
|
+
</template>
|
|
15
|
+
|
|
16
|
+
<script setup lang="ts"></script>
|
|
17
|
+
|
|
18
|
+
<style scoped></style>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<ul class="breadcrumbs">
|
|
3
|
+
<li
|
|
4
|
+
v-for="({ label, disabled, path }, i) in pages"
|
|
5
|
+
:key="i"
|
|
6
|
+
:disabled="disabled"
|
|
7
|
+
class="breadcrumb"
|
|
8
|
+
>
|
|
9
|
+
<NuxtLink :to="path">
|
|
10
|
+
{{ label }}
|
|
11
|
+
</NuxtLink>
|
|
12
|
+
</li>
|
|
13
|
+
</ul>
|
|
14
|
+
</template>
|
|
15
|
+
|
|
16
|
+
<script setup lang="ts">
|
|
17
|
+
import { IPages } from "./types";
|
|
18
|
+
|
|
19
|
+
// props
|
|
20
|
+
interface IProps {
|
|
21
|
+
pages: IPages;
|
|
22
|
+
}
|
|
23
|
+
defineProps<IProps>();
|
|
24
|
+
</script>
|
|
25
|
+
|
|
26
|
+
<style scoped></style>
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<!-- contact -->
|
|
3
|
+
<li class="item flex items-center max-h-none !px-3 !rounded-none">
|
|
4
|
+
<!-- avatar -->
|
|
5
|
+
<figure
|
|
6
|
+
:class="[getStatusClass]"
|
|
7
|
+
:notifications="contact.notifications"
|
|
8
|
+
class="w-10 h-10 avatar 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-xl"
|
|
18
|
+
/>
|
|
19
|
+
</figure>
|
|
20
|
+
|
|
21
|
+
<!-- info -->
|
|
22
|
+
<div class="flex-1 mx-3 w-24">
|
|
23
|
+
<p class="w-full overflow-hidden text-ellipsis whitespace-nowrap py-1">
|
|
24
|
+
<!-- label -->
|
|
25
|
+
<span class="text-xs">
|
|
26
|
+
{{ contact.label }}
|
|
27
|
+
</span>
|
|
28
|
+
<!-- hours -->
|
|
29
|
+
<span
|
|
30
|
+
v-if="entryDateExists"
|
|
31
|
+
class="badge badge-outline-secondary ml-2"
|
|
32
|
+
tooltip="Tempo em atendimento"
|
|
33
|
+
>
|
|
34
|
+
{{ new Date(milliseconds).toISOString().slice(11, 19) }}
|
|
35
|
+
</span>
|
|
36
|
+
</p>
|
|
37
|
+
<!-- typing -->
|
|
38
|
+
<p
|
|
39
|
+
v-if="contact.typing"
|
|
40
|
+
class="text-2xs text-success"
|
|
41
|
+
>
|
|
42
|
+
Digitando...
|
|
43
|
+
</p>
|
|
44
|
+
<!-- message -->
|
|
45
|
+
<div
|
|
46
|
+
v-else
|
|
47
|
+
class="markdown h-4 text-2xs opacity-50 w-full overflow-hidden text-ellipsis whitespace-nowrap"
|
|
48
|
+
v-html="marked(props.contact.message ?? '')"
|
|
49
|
+
/>
|
|
50
|
+
</div>
|
|
51
|
+
|
|
52
|
+
<!-- date message -->
|
|
53
|
+
<p
|
|
54
|
+
v-if="!expirated"
|
|
55
|
+
class="badge !p-0 text-secondary"
|
|
56
|
+
tooltip="Horário da última mensagem"
|
|
57
|
+
>
|
|
58
|
+
{{ getDate }}
|
|
59
|
+
</p>
|
|
60
|
+
|
|
61
|
+
<!-- expirate -->
|
|
62
|
+
<div
|
|
63
|
+
v-if="expirated"
|
|
64
|
+
tooltip="Envie uma mensagem para o cliente!"
|
|
65
|
+
class="flex justify-center items-center relative mr-2"
|
|
66
|
+
>
|
|
67
|
+
<div class="w-5 h-5 rounded-full bg-error animate-ping absolute" />
|
|
68
|
+
|
|
69
|
+
<i class="bi bi-exclamation-circle-fill text-error text-base" />
|
|
70
|
+
</div>
|
|
71
|
+
</li>
|
|
72
|
+
</template>
|
|
73
|
+
|
|
74
|
+
<script setup lang="ts">
|
|
75
|
+
import { marked } from "marked";
|
|
76
|
+
import { ref, computed, onMounted } from "vue";
|
|
77
|
+
import { getMinutesBetweenDates, getTimeByDate, IChatContact } from "./types";
|
|
78
|
+
|
|
79
|
+
// props
|
|
80
|
+
interface IProps {
|
|
81
|
+
contact: IChatContact;
|
|
82
|
+
timeout: number;
|
|
83
|
+
}
|
|
84
|
+
const props = defineProps<IProps>();
|
|
85
|
+
|
|
86
|
+
// mounted
|
|
87
|
+
onMounted(() => {
|
|
88
|
+
setInterval(validateExpiration, 1000);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
// computed
|
|
92
|
+
const getDate = computed<string>(() => {
|
|
93
|
+
const date = props.contact.date;
|
|
94
|
+
if (!date) return "";
|
|
95
|
+
return getTimeByDate(date);
|
|
96
|
+
});
|
|
97
|
+
const entryDateExists = computed<boolean>(() => !!props.contact.entrydate)
|
|
98
|
+
const getStatusClass = computed<string>(() => {
|
|
99
|
+
if (props.contact.on) return "avatar-status-success";
|
|
100
|
+
return "avatar-status-error";
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
// data
|
|
104
|
+
const expirated = ref<boolean>(false);
|
|
105
|
+
const milliseconds = ref<number>(0)
|
|
106
|
+
|
|
107
|
+
// methods
|
|
108
|
+
function validateExpiration() {
|
|
109
|
+
if (!props.contact.date) return;
|
|
110
|
+
expirated.value =
|
|
111
|
+
getMinutesBetweenDates(new Date(), props.contact.date) >= props.timeout;
|
|
112
|
+
}
|
|
113
|
+
async function setTimerContact(): Promise<void> {
|
|
114
|
+
if (!props.contact.entrydate) return
|
|
115
|
+
|
|
116
|
+
await new Promise(resolve => setTimeout(resolve, 1000))
|
|
117
|
+
|
|
118
|
+
const now = new Date().getTime()
|
|
119
|
+
const entry = props.contact.entrydate.getTime()
|
|
120
|
+
|
|
121
|
+
milliseconds.value = Math.abs(now - entry)
|
|
122
|
+
|
|
123
|
+
setTimerContact()
|
|
124
|
+
}
|
|
125
|
+
setTimerContact()
|
|
126
|
+
</script>
|
|
127
|
+
|
|
128
|
+
<style scoped>
|
|
129
|
+
.min-w-40px {
|
|
130
|
+
min-width: 40px;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
.text-2xs {
|
|
134
|
+
font-size: 0.7rem;
|
|
135
|
+
}
|
|
136
|
+
</style>
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<!-- schedule -->
|
|
3
|
+
<li class="flex flex-wrap gap-2 items-center max-h-none !px-3 !rounded-none">
|
|
4
|
+
<!-- avatar -->
|
|
5
|
+
<figure class="w-10 h-10 avatar avatar-soft-schedule [&::after]:!hidden">
|
|
6
|
+
<img
|
|
7
|
+
v-if="schedule.avatar"
|
|
8
|
+
:src="schedule.avatar"
|
|
9
|
+
class="rounded-md"
|
|
10
|
+
>
|
|
11
|
+
<i
|
|
12
|
+
v-else
|
|
13
|
+
class="bi bi-chat-dots-fill text-xl"
|
|
14
|
+
/>
|
|
15
|
+
</figure>
|
|
16
|
+
|
|
17
|
+
<!-- info -->
|
|
18
|
+
<div class="flex-1 w-24">
|
|
19
|
+
<p class="w-full overflow-hidden text-ellipsis whitespace-nowrap">
|
|
20
|
+
<span class="text-xs">
|
|
21
|
+
{{ schedule.identifier }}
|
|
22
|
+
</span>
|
|
23
|
+
</p>
|
|
24
|
+
<p class="markdown h-4 text-2xs opacity-50 w-full overflow-hidden text-ellipsis whitespace-nowrap">
|
|
25
|
+
{{ schedule.date.toLocaleString() }}
|
|
26
|
+
</p>
|
|
27
|
+
</div>
|
|
28
|
+
|
|
29
|
+
<div
|
|
30
|
+
v-if="slotsExists"
|
|
31
|
+
class="w-full accordion accordion-bordered"
|
|
32
|
+
>
|
|
33
|
+
<details class="item">
|
|
34
|
+
<summary class="text-xs">
|
|
35
|
+
Mais Detalhes
|
|
36
|
+
</summary>
|
|
37
|
+
<article>
|
|
38
|
+
<table class="w-full">
|
|
39
|
+
<tr
|
|
40
|
+
v-for="(value, field) in schedule.slots"
|
|
41
|
+
v-show="value"
|
|
42
|
+
:key="field"
|
|
43
|
+
>
|
|
44
|
+
<td class="pt-2 text-xs">
|
|
45
|
+
{{ field }}
|
|
46
|
+
</td>
|
|
47
|
+
<td
|
|
48
|
+
class="pt-2"
|
|
49
|
+
align="right"
|
|
50
|
+
>
|
|
51
|
+
<span class="badge badge-soft-secondary">{{ value }}</span>
|
|
52
|
+
</td>
|
|
53
|
+
</tr>
|
|
54
|
+
</table>
|
|
55
|
+
</article>
|
|
56
|
+
</details>
|
|
57
|
+
</div>
|
|
58
|
+
</li>
|
|
59
|
+
</template>
|
|
60
|
+
|
|
61
|
+
<script setup lang="ts">
|
|
62
|
+
import { computed } from "vue";
|
|
63
|
+
import { IPortfolioSchedule } from "./types";
|
|
64
|
+
|
|
65
|
+
// props
|
|
66
|
+
interface IProps {
|
|
67
|
+
schedule: IPortfolioSchedule;
|
|
68
|
+
}
|
|
69
|
+
const props = defineProps<IProps>();
|
|
70
|
+
|
|
71
|
+
// computed
|
|
72
|
+
const slotsExists = computed<boolean>(() => {
|
|
73
|
+
if (!props.schedule.slots) return false;
|
|
74
|
+
return !!Object.entries(props.schedule.slots).length;
|
|
75
|
+
});
|
|
76
|
+
</script>
|
|
77
|
+
|
|
78
|
+
<style scoped>
|
|
79
|
+
.avatar-soft-schedule {
|
|
80
|
+
background-color: #f1f5f9;
|
|
81
|
+
color: #7E22CE;
|
|
82
|
+
}
|
|
83
|
+
.dark .avatar-soft-schedule {
|
|
84
|
+
background-color: #1e293b!important;
|
|
85
|
+
color: #A855F7;
|
|
86
|
+
}
|
|
87
|
+
</style>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="flex justify-between opacity-50">
|
|
3
|
+
<span class="text-2xs mr-10">
|
|
4
|
+
{{ message.who }}
|
|
5
|
+
</span>
|
|
6
|
+
<span class="text-2xs">
|
|
7
|
+
{{ getTimeByDate(message.date) }}
|
|
8
|
+
</span>
|
|
9
|
+
</div>
|
|
10
|
+
</template>
|
|
11
|
+
|
|
12
|
+
<script setup lang="ts">
|
|
13
|
+
import { getTimeByDate, IChatMessage } from "./types";
|
|
14
|
+
// props
|
|
15
|
+
interface IProps {
|
|
16
|
+
message: IChatMessage;
|
|
17
|
+
}
|
|
18
|
+
defineProps<IProps>();
|
|
19
|
+
</script>
|
|
20
|
+
|
|
21
|
+
<style scoped>
|
|
22
|
+
.text-2xs {
|
|
23
|
+
font-size: 0.7rem;
|
|
24
|
+
}
|
|
25
|
+
</style>
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<label
|
|
3
|
+
class="flex items-center h-5 w-10 rounded-full cursor-pointer border bg-gray-200 border-gray-400 dark:border-gray-600 dark:bg-gray-700"
|
|
4
|
+
@click="change"
|
|
5
|
+
>
|
|
6
|
+
<figure
|
|
7
|
+
:class="{ 'translate-x-full': dark }"
|
|
8
|
+
class="rounded-full w-1/2 h-full flex justify-center items-center select-none transition-transform bg-white dark:bg-gray-900"
|
|
9
|
+
>
|
|
10
|
+
<!-- darkmode -->
|
|
11
|
+
<i
|
|
12
|
+
v-if="dark"
|
|
13
|
+
class="bi bi-moon-fill leading-none"
|
|
14
|
+
/>
|
|
15
|
+
|
|
16
|
+
<!-- lightmode -->
|
|
17
|
+
<i
|
|
18
|
+
v-else
|
|
19
|
+
class="bi bi-sun leading-none"
|
|
20
|
+
/>
|
|
21
|
+
</figure>
|
|
22
|
+
</label>
|
|
23
|
+
</template>
|
|
24
|
+
|
|
25
|
+
<script setup lang="ts">
|
|
26
|
+
import { useNuxtApp, useCookie } from "#app";
|
|
27
|
+
|
|
28
|
+
// app
|
|
29
|
+
const { $listen } = useNuxtApp();
|
|
30
|
+
|
|
31
|
+
// data
|
|
32
|
+
const dark = useCookie<boolean>("darkmode", {
|
|
33
|
+
default: () => false,
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
// methods
|
|
37
|
+
function change(): void {
|
|
38
|
+
dark.value = !dark.value;
|
|
39
|
+
|
|
40
|
+
update();
|
|
41
|
+
}
|
|
42
|
+
function update(): void {
|
|
43
|
+
if (!process.client) return;
|
|
44
|
+
|
|
45
|
+
if (dark.value) {
|
|
46
|
+
document.body.classList.add("dark");
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
document.body.classList.remove("dark");
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
update();
|
|
54
|
+
|
|
55
|
+
// emits
|
|
56
|
+
$listen("darkmode:change", change);
|
|
57
|
+
</script>
|
|
58
|
+
|
|
59
|
+
<style scoped>
|
|
60
|
+
.right {
|
|
61
|
+
transform: translateX(100%);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
i {
|
|
65
|
+
font-size: 9px;
|
|
66
|
+
}
|
|
67
|
+
</style>
|