feat: send one SMS from a person or lead and keep the dashboard inside the phone frame
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -228,7 +228,13 @@ onUnmounted(() => {
|
||||
<style scoped>
|
||||
.dashboard {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
gap: 1.15rem;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.dashboard > * {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.mid-grid {
|
||||
|
||||
@@ -19,6 +19,7 @@ import {
|
||||
UiTextarea,
|
||||
} from '@/components/ui';
|
||||
import RelatedTasksPanel from '@/components/routines/RelatedTasksPanel.vue';
|
||||
import SmsComposeModal from '@/components/SmsComposeModal.vue';
|
||||
import type {
|
||||
ActivityDto,
|
||||
ConvertLeadResult,
|
||||
@@ -57,6 +58,7 @@ const followUpAt = ref('');
|
||||
const followUpBody = ref('');
|
||||
const editing = ref(false);
|
||||
const moreOpen = ref(false);
|
||||
const smsOpen = ref(false);
|
||||
const copied = ref(false);
|
||||
const narrow = ref(typeof window !== 'undefined' && window.matchMedia('(max-width: 900px)').matches);
|
||||
let narrowMq: MediaQueryList | null = null;
|
||||
@@ -371,6 +373,15 @@ onBeforeUnmount(() => narrowMq?.removeEventListener('change', syncNarrow));
|
||||
:back-to="{ name: 'leads' }"
|
||||
>
|
||||
<template #actions>
|
||||
<UiButton
|
||||
v-if="lead && !editing"
|
||||
variant="secondary"
|
||||
size="sm"
|
||||
:disabled="busy || !lead.mobile"
|
||||
@click="smsOpen = true"
|
||||
>
|
||||
پیامک
|
||||
</UiButton>
|
||||
<UiButton
|
||||
v-if="lead && !editing"
|
||||
variant="secondary"
|
||||
@@ -444,10 +455,17 @@ onBeforeUnmount(() => narrowMq?.removeEventListener('change', syncNarrow));
|
||||
<UiIcon name="phone" :size="16" />
|
||||
تماس
|
||||
</a>
|
||||
<button class="m-btn" type="button" @click="smsOpen = true">
|
||||
<UiIcon name="chat" :size="16" />
|
||||
پیامک
|
||||
</button>
|
||||
<button class="m-btn" type="button" @click="startEdit">
|
||||
<UiIcon name="pencil" :size="16" />
|
||||
ویرایش
|
||||
</button>
|
||||
<button class="m-btn icon" type="button" aria-label="بیشتر" @click="moreOpen = true">
|
||||
<UiIcon name="dots" :size="18" />
|
||||
</button>
|
||||
<button
|
||||
v-if="!lead.convertedPersonId"
|
||||
class="m-btn solid"
|
||||
@@ -458,9 +476,6 @@ onBeforeUnmount(() => narrowMq?.removeEventListener('change', syncNarrow));
|
||||
<UiIcon name="user-plus" :size="16" />
|
||||
تبدیل به مشتری
|
||||
</button>
|
||||
<button class="m-btn icon" type="button" aria-label="بیشتر" @click="moreOpen = true">
|
||||
<UiIcon name="dots" :size="18" />
|
||||
</button>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
@@ -704,6 +719,11 @@ onBeforeUnmount(() => narrowMq?.removeEventListener('change', syncNarrow));
|
||||
|
||||
<aside class="side">
|
||||
<button class="sheet-close" type="button" @click="moreOpen = false">بستن</button>
|
||||
<UiCard title="پیامک">
|
||||
<UiButton size="sm" :disabled="!lead.mobile" @click="smsOpen = true; moreOpen = false">
|
||||
ارسال پیامک
|
||||
</UiButton>
|
||||
</UiCard>
|
||||
<UiCard title="تغییر وضعیت">
|
||||
<UiField label="وضعیت">
|
||||
<UiSelect v-model="stageId">
|
||||
@@ -764,6 +784,16 @@ onBeforeUnmount(() => narrowMq?.removeEventListener('change', syncNarrow));
|
||||
</UiCard>
|
||||
</aside>
|
||||
</div>
|
||||
<SmsComposeModal
|
||||
:open="smsOpen"
|
||||
title="ارسال پیامک"
|
||||
:endpoint="`/leads/${lead.id}/sms`"
|
||||
:name="lead.contactName || lead.title"
|
||||
:phone="lead.mobile || lead.phone || ''"
|
||||
:record-title="lead.title"
|
||||
:company="lead.contactName ? lead.title : ''"
|
||||
@close="smsOpen = false"
|
||||
/>
|
||||
</template>
|
||||
</section>
|
||||
</template>
|
||||
@@ -1082,14 +1112,15 @@ onBeforeUnmount(() => narrowMq?.removeEventListener('change', syncNarrow));
|
||||
color: #94a3b8;
|
||||
}
|
||||
|
||||
.m-actions {
|
||||
.m-actions,
|
||||
.m-actions.converted {
|
||||
display: grid;
|
||||
grid-template-columns: auto auto minmax(0, 1fr) 36px;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr)) 36px;
|
||||
gap: 0.35rem;
|
||||
}
|
||||
|
||||
.m-actions.converted {
|
||||
grid-template-columns: 1fr 1fr auto;
|
||||
.m-actions .solid {
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
|
||||
.m-btn {
|
||||
|
||||
@@ -19,6 +19,7 @@ import UiIcon from '@/components/UiIcon.vue';
|
||||
import CustomerMoodFace from '@/components/CustomerMoodFace.vue';
|
||||
import MentoAiAvatar from '@/components/brand/MentoAiAvatar.vue';
|
||||
import { brand } from '@mento/shared';
|
||||
import SmsComposeModal from '@/components/SmsComposeModal.vue';
|
||||
import MentoMemoryPanel from '@/components/MentoMemoryPanel.vue';
|
||||
import AskMentoPanel from '@/components/AskMentoPanel.vue';
|
||||
import ProfileEmptyState from '@/components/person-profile/ProfileEmptyState.vue';
|
||||
@@ -104,6 +105,7 @@ const cards = ref<ProjectCardDto[]>([]);
|
||||
const tahesabMoshtariCode = ref<number | null>(null);
|
||||
|
||||
const moreOpen = ref(false);
|
||||
const smsOpen = ref(false);
|
||||
const mobMoreOpen = ref(false);
|
||||
const filterOpen = ref(false);
|
||||
const historyFilter = ref<HistoryFilter>('all');
|
||||
@@ -117,10 +119,12 @@ const moreItems = computed<ProfileMoreItem[]>(() => [
|
||||
{ key: 'quote', label: 'پیشفاکتور جدید', to: { name: 'quote-new', query: { personId: id.value } } },
|
||||
{ key: 'ticket', label: 'تیکت جدید', to: { name: 'ticket-new', query: { personId: id.value } } },
|
||||
{ key: 'note', label: 'یادداشت جدید', to: { name: 'notes', query: { personId: id.value } } },
|
||||
{ key: 'sms', label: 'ارسال پیامک' },
|
||||
{ key: 'delete', label: 'حذف شخص', danger: true },
|
||||
]);
|
||||
|
||||
function onMoreSelect(key: string) {
|
||||
if (key === 'sms') smsOpen.value = true;
|
||||
if (key === 'delete') void removePerson();
|
||||
}
|
||||
|
||||
@@ -676,6 +680,10 @@ watch(() => route.query.tab, readTab, { immediate: true });
|
||||
<UiIcon name="phone" :size="15" />
|
||||
{{ phoneDisplay }}
|
||||
</a>
|
||||
<button class="contact-pill sms" type="button" :disabled="!phoneNumber" @click="smsOpen = true">
|
||||
<UiIcon name="chat" :size="15" />
|
||||
پیامک
|
||||
</button>
|
||||
<a v-if="person.email" class="contact-pill" :href="mailHref || undefined" dir="ltr">
|
||||
<UiIcon name="mail" :size="15" />
|
||||
{{ person.email }}
|
||||
@@ -1033,6 +1041,18 @@ watch(() => route.query.tab, readTab, { immediate: true });
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<SmsComposeModal
|
||||
v-if="person"
|
||||
:open="smsOpen"
|
||||
title="ارسال پیامک"
|
||||
:endpoint="`/people/${id}/sms`"
|
||||
:name="fullName"
|
||||
:phone="phoneNumber"
|
||||
:record-title="fullName"
|
||||
:company="person.company?.name ?? ''"
|
||||
@close="smsOpen = false"
|
||||
/>
|
||||
|
||||
<div v-if="person" class="dock">
|
||||
<button class="fab-item call" type="button" :disabled="!telHref" @click="goCall">
|
||||
<span class="fab-circle">
|
||||
@@ -1275,6 +1295,17 @@ watch(() => route.query.tab, readTab, { immediate: true });
|
||||
background: #f0fdfa;
|
||||
}
|
||||
|
||||
button.contact-pill {
|
||||
font: inherit;
|
||||
font-weight: 700;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
button.contact-pill:disabled {
|
||||
opacity: 0.55;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.facts-grid {
|
||||
margin: 0;
|
||||
display: grid;
|
||||
|
||||
Reference in New Issue
Block a user