Files
CRM_Montzar/apps/web/src/components/dashboard/HomeAiAssistant.vue
T

245 lines
5.0 KiB
Vue
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup lang="ts">
import { RouterLink } from 'vue-router';
import UiIcon from '@/components/UiIcon.vue';
import { brand, type AskMentoSourceDto } from '@mento/shared';
defineProps<{
askQuery: string;
asking?: boolean;
answer?: string;
error?: string;
sources?: AskMentoSourceDto[];
}>();
const emit = defineEmits<{
'update:askQuery': [value: string];
ask: [preset?: string];
}>();
const shortcuts = [
{ label: 'معاملات باز و در خطر را بگو', icon: 'warning' as const },
{ label: 'فعالیت‌های عقب‌افتاده چیست؟', icon: 'calendar' as const },
{ label: 'مهم‌ترین پیگیری امروز چیست؟', icon: 'send' as const },
{ label: 'خلاصه وضعیت فروش را بده', icon: 'chart' as const },
];
function sourceTo(source: AskMentoSourceDto) {
if (source.type === 'person') return { name: 'person-detail', params: { id: source.id } };
if (source.type === 'activity') return { name: 'activity-detail', params: { id: source.id } };
if (source.type === 'deal') return { name: 'deal-detail', params: { id: source.id } };
return { name: 'notes' };
}
function pick(label: string) {
emit('update:askQuery', label);
emit('ask', label);
}
</script>
<template>
<article class="panel">
<header class="panel-head">
<h2>
<span class="spark"><UiIcon name="sparkle" :size="15" /></span>
{{ brand.aiNameFa }}
</h2>
</header>
<p class="ai-lead">چه کمکی می‌تونم بکنم؟</p>
<div class="ai-shortcuts">
<button
v-for="item in shortcuts"
:key="item.label"
class="ai-chip"
type="button"
:disabled="asking"
@click="pick(item.label)"
>
<span class="chip-ico"><UiIcon :name="item.icon" :size="14" /></span>
<span>{{ item.label }}</span>
</button>
</div>
<p v-if="error" class="ai-error">{{ error }}</p>
<div v-else-if="answer" class="ai-answer">
<p>{{ answer }}</p>
<div v-if="sources?.length" class="sources">
<RouterLink
v-for="source in sources"
:key="`${source.type}-${source.id}`"
:to="sourceTo(source)"
>
{{ source.label }}
</RouterLink>
</div>
</div>
<form class="ai-input" @submit.prevent="emit('ask')">
<input
:value="askQuery"
type="search"
:placeholder="brand.askPlaceholderFa"
:disabled="asking"
@input="emit('update:askQuery', ($event.target as HTMLInputElement).value)"
/>
<button type="submit" aria-label="ارسال" :disabled="asking">
<UiIcon name="send" :size="15" />
</button>
</form>
</article>
</template>
<style scoped>
.panel {
background: #fff;
border-radius: 20px;
padding: 1rem 1rem 0.95rem;
box-shadow: 0 8px 24px rgba(15, 23, 42, 0.04);
border: 1px solid #eef2f7;
min-width: 0;
display: flex;
flex-direction: column;
}
.panel-head {
margin-bottom: 0.55rem;
}
h2 {
margin: 0;
font-size: 0.92rem;
display: inline-flex;
align-items: center;
gap: 0.4rem;
color: #0f172a;
}
.spark {
color: #eab308;
display: grid;
}
.ai-lead {
margin: 0 0 0.75rem;
padding: 0.55rem 0.75rem;
width: fit-content;
max-width: 100%;
background: #d1fae5;
color: #115e59;
font-size: 0.8rem;
font-weight: 600;
border-radius: 14px 14px 4px 14px;
}
.ai-shortcuts {
display: grid;
gap: 0.4rem;
margin-bottom: 0.8rem;
flex: 1;
}
.ai-chip {
display: flex;
align-items: center;
gap: 0.55rem;
padding: 0.58rem 0.7rem;
border-radius: 12px;
background: #fff;
border: 1px solid #eef2f7;
color: #334155;
font-size: 0.76rem;
text-align: start;
font: inherit;
cursor: pointer;
box-shadow: 0 1px 2px rgba(15, 23, 42, 0.03);
}
.ai-chip:hover:not(:disabled) {
background: #f0fdfa;
border-color: #99f6e4;
}
.ai-chip:disabled {
opacity: 0.6;
cursor: wait;
}
.chip-ico {
width: 26px;
height: 26px;
border-radius: 8px;
background: #ecfdf8;
color: #14b8a6;
display: grid;
place-items: center;
flex-shrink: 0;
}
.ai-input {
display: flex;
gap: 0.4rem;
margin-top: auto;
}
.ai-input input {
flex: 1;
border: 1px solid #e2e8f0;
border-radius: 12px;
padding: 0.58rem 0.75rem;
background: #f8fafc;
font-size: 0.8rem;
}
.ai-input button {
width: 40px;
border: 0;
border-radius: 12px;
background: #14b8a6;
color: #fff;
cursor: pointer;
display: grid;
place-items: center;
}
.ai-input button:disabled {
opacity: 0.55;
}
.ai-answer {
background: #f0fdfa;
border-radius: 12px;
padding: 0.7rem 0.8rem;
margin-bottom: 0.75rem;
}
.ai-answer p {
margin: 0;
color: #134e4a;
font-size: 0.82rem;
line-height: 1.7;
}
.sources {
display: flex;
flex-wrap: wrap;
gap: 0.3rem;
margin-top: 0.5rem;
}
.sources a {
font-size: 0.72rem;
font-weight: 700;
color: #0f766e;
background: #fff;
border-radius: 999px;
padding: 0.15rem 0.5rem;
}
.ai-error {
margin: 0 0 0.7rem;
color: #b91c1c;
font-size: 0.8rem;
}
</style>