Add Ask Mento, customer mood, and Pipecat speech-to-text.
Ship assistant answers, contact moods, voice dictation, and the related CRM UI so these can be deployed to production. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -3,6 +3,7 @@ import { computed, ref, watch } from 'vue';
|
||||
import { RouterLink, useRoute, useRouter } from 'vue-router';
|
||||
import { useAuthStore } from '@/stores/auth';
|
||||
import { api } from '@/lib/api';
|
||||
import type { AskMentoResponse } from '@mento/shared';
|
||||
import { formatCompactMoney } from '@/lib/money';
|
||||
import {
|
||||
calendarDaysBetween,
|
||||
@@ -15,6 +16,7 @@ import { purchaseProbability } from '@/lib/person-insights';
|
||||
import { USER_ROLE_LABELS } from '@/lib/roles';
|
||||
import UiIcon from '@/components/UiIcon.vue';
|
||||
import MentoAiAvatar from '@/components/brand/MentoAiAvatar.vue';
|
||||
import AskMentoPanel from '@/components/AskMentoPanel.vue';
|
||||
import ProfileEmptyState from '@/components/person-profile/ProfileEmptyState.vue';
|
||||
import ProfileMoreMenu from '@/components/person-profile/ProfileMoreMenu.vue';
|
||||
import type { ProfileMoreItem } from '@/components/person-profile/ProfileMoreMenu.vue';
|
||||
@@ -62,6 +64,7 @@ const cards = ref<ProjectCardDto[]>([]);
|
||||
const moreOpen = ref(false);
|
||||
const fabOpen = ref(false);
|
||||
const tab = ref<TabKey>('summary');
|
||||
const aiBrief = ref('');
|
||||
|
||||
const moreItems: ProfileMoreItem[] = [
|
||||
{ key: 'info', label: 'ویرایش اطلاعات', to: { name: 'profile', query: { tab: 'info' } } },
|
||||
@@ -126,6 +129,7 @@ const probability = computed(() =>
|
||||
);
|
||||
|
||||
const smartText = computed(() => {
|
||||
if (aiBrief.value) return aiBrief.value;
|
||||
const overdue = activities.value.filter(
|
||||
(a) => a.status === 'open' && a.dueAt && new Date(a.dueAt).getTime() < Date.now(),
|
||||
).length;
|
||||
@@ -281,6 +285,7 @@ function onSmartCta() {
|
||||
async function load() {
|
||||
loading.value = true;
|
||||
error.value = '';
|
||||
aiBrief.value = '';
|
||||
try {
|
||||
const [actRes, boardRes] = await Promise.all([
|
||||
api.get<PaginatedResponse<ActivityDto>>('/activities', {
|
||||
@@ -296,6 +301,7 @@ async function load() {
|
||||
} catch {
|
||||
cards.value = [];
|
||||
}
|
||||
void loadAiBrief();
|
||||
} catch {
|
||||
error.value = 'بارگذاری پروفایل ناموفق بود.';
|
||||
} finally {
|
||||
@@ -303,6 +309,18 @@ async function load() {
|
||||
}
|
||||
}
|
||||
|
||||
async function loadAiBrief() {
|
||||
try {
|
||||
const { data } = await api.post<AskMentoResponse>('/ai/ask', {
|
||||
question:
|
||||
'وضعیت کاری امروز من را خلاصه کن: فعالیتهای عقبافتاده، معاملات باز و مهمترین پیگیری بعدی.',
|
||||
});
|
||||
aiBrief.value = data.answer;
|
||||
} catch {
|
||||
aiBrief.value = '';
|
||||
}
|
||||
}
|
||||
|
||||
watch(() => route.query.tab, readTab, { immediate: true });
|
||||
watch(() => auth.user?.id, () => void load(), { immediate: true });
|
||||
</script>
|
||||
@@ -364,6 +382,7 @@ watch(() => auth.user?.id, () => void load(), { immediate: true });
|
||||
<p>{{ smartText }}</p>
|
||||
</div>
|
||||
</header>
|
||||
<AskMentoPanel placeholder="از منتو درباره کار امروز بپرس..." />
|
||||
<button class="smart-cta" type="button" @click="onSmartCta">
|
||||
<span>{{ smartCta }}</span>
|
||||
<UiIcon name="chevron" :size="16" />
|
||||
|
||||
Reference in New Issue
Block a user