updates
This commit is contained in:
parent
cf4af2cbff
commit
09c32ae6cb
|
|
@ -91,7 +91,10 @@
|
|||
<v-icon :size="mobile ? 'small' : 'default'">mdi-account</v-icon>
|
||||
</v-avatar>
|
||||
</template>
|
||||
<v-list-item-title :class="mobile ? 'text-body-2' : ''">Client Signature Link</v-list-item-title>
|
||||
<v-list-item-title :class="mobile ? 'text-body-2' : ''">
|
||||
Client Signature Link
|
||||
<v-icon v-if="signatureStatus.clientSigned" color="success" :size="mobile ? 'small' : 'default'" class="ml-1">mdi-check-circle</v-icon>
|
||||
</v-list-item-title>
|
||||
<v-list-item-subtitle :class="mobile ? 'text-caption' : ''">{{ interest['Full Name'] }}</v-list-item-subtitle>
|
||||
<template v-slot:append>
|
||||
<v-btn-group variant="text" :size="mobile ? 'small' : 'default'">
|
||||
|
|
@ -114,7 +117,10 @@
|
|||
<v-icon :size="mobile ? 'small' : 'default'">mdi-account-check</v-icon>
|
||||
</v-avatar>
|
||||
</template>
|
||||
<v-list-item-title :class="mobile ? 'text-body-2' : ''">CC Signature Link</v-list-item-title>
|
||||
<v-list-item-title :class="mobile ? 'text-body-2' : ''">
|
||||
CC Signature Link
|
||||
<v-icon v-if="isSignedByEmail('sales@portnimara.com')" color="success" :size="mobile ? 'small' : 'default'" class="ml-1">mdi-check-circle</v-icon>
|
||||
</v-list-item-title>
|
||||
<v-list-item-subtitle :class="mobile ? 'text-caption' : ''">Oscar Faragher</v-list-item-subtitle>
|
||||
<template v-slot:append>
|
||||
<v-btn-group variant="text" :size="mobile ? 'small' : 'default'">
|
||||
|
|
@ -137,7 +143,10 @@
|
|||
<v-icon :size="mobile ? 'small' : 'default'">mdi-account-tie</v-icon>
|
||||
</v-avatar>
|
||||
</template>
|
||||
<v-list-item-title :class="mobile ? 'text-body-2' : ''">Developer Signature Link</v-list-item-title>
|
||||
<v-list-item-title :class="mobile ? 'text-body-2' : ''">
|
||||
Developer Signature Link
|
||||
<v-icon v-if="isSignedByEmail('dm@portnimara.com')" color="success" :size="mobile ? 'small' : 'default'" class="ml-1">mdi-check-circle</v-icon>
|
||||
</v-list-item-title>
|
||||
<v-list-item-subtitle :class="mobile ? 'text-caption' : ''">David Mizrahi</v-list-item-subtitle>
|
||||
<template v-slot:append>
|
||||
<v-btn-group variant="text" :size="mobile ? 'small' : 'default'">
|
||||
|
|
@ -313,6 +322,18 @@ const selectedFile = ref<File | null>(null);
|
|||
const showDeleteConfirmDialog = ref(false);
|
||||
const isDeleting = ref(false);
|
||||
|
||||
// Signature status tracking
|
||||
const signatureStatus = ref({
|
||||
documentStatus: '',
|
||||
clientSigned: false,
|
||||
allSigned: false,
|
||||
signedRecipients: [] as any[],
|
||||
unsignedRecipients: [] as any[]
|
||||
});
|
||||
|
||||
// Polling interval for signature status
|
||||
let statusPollingInterval: NodeJS.Timeout | null = null;
|
||||
|
||||
const hasEOI = computed(() => {
|
||||
return !!(props.interest['Signature Link Client'] ||
|
||||
props.interest['Signature Link CC'] ||
|
||||
|
|
@ -520,4 +541,102 @@ const deleteEOI = async () => {
|
|||
isDeleting.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// Check signature status from Documenso
|
||||
const checkSignatureStatus = async () => {
|
||||
if (!hasEOI.value || isEOISigned.value) return;
|
||||
|
||||
try {
|
||||
const response = await $fetch<{
|
||||
success: boolean;
|
||||
documentStatus: string;
|
||||
clientSigned: boolean;
|
||||
allSigned: boolean;
|
||||
signedRecipients: any[];
|
||||
unsignedRecipients: any[];
|
||||
}>('/api/eoi/check-signature-status', {
|
||||
headers: {
|
||||
'x-tag': '094ut234'
|
||||
},
|
||||
query: {
|
||||
interestId: props.interest.Id.toString()
|
||||
}
|
||||
});
|
||||
|
||||
if (response.success) {
|
||||
signatureStatus.value = {
|
||||
documentStatus: response.documentStatus,
|
||||
clientSigned: response.clientSigned,
|
||||
allSigned: response.allSigned,
|
||||
signedRecipients: response.signedRecipients,
|
||||
unsignedRecipients: response.unsignedRecipients
|
||||
};
|
||||
|
||||
// If all signed, update the EOI status
|
||||
if (response.allSigned && props.interest['EOI Status'] !== 'Signed') {
|
||||
try {
|
||||
await $fetch('/api/update-interest', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'x-tag': '094ut234'
|
||||
},
|
||||
body: {
|
||||
id: props.interest.Id.toString(),
|
||||
data: {
|
||||
'EOI Status': 'Signed',
|
||||
'Sales Process Level': 'Made Reservation'
|
||||
}
|
||||
}
|
||||
});
|
||||
emit('update'); // Refresh parent data
|
||||
stopSignaturePolling(); // Stop polling once signed
|
||||
} catch (updateError) {
|
||||
console.error('Failed to update EOI status:', updateError);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to check signature status:', error);
|
||||
}
|
||||
};
|
||||
|
||||
// Check if a specific email has signed
|
||||
const isSignedByEmail = (email: string) => {
|
||||
return signatureStatus.value.signedRecipients.some(
|
||||
recipient => recipient.email === email
|
||||
);
|
||||
};
|
||||
|
||||
// Start polling for signature status
|
||||
const startSignaturePolling = () => {
|
||||
// Initial check
|
||||
checkSignatureStatus();
|
||||
|
||||
// Poll every 30 seconds
|
||||
statusPollingInterval = setInterval(() => {
|
||||
checkSignatureStatus();
|
||||
}, 30000);
|
||||
};
|
||||
|
||||
// Stop polling
|
||||
const stopSignaturePolling = () => {
|
||||
if (statusPollingInterval) {
|
||||
clearInterval(statusPollingInterval);
|
||||
statusPollingInterval = null;
|
||||
}
|
||||
};
|
||||
|
||||
// Watch for changes in EOI status
|
||||
watch(() => hasEOI.value, (newValue) => {
|
||||
if (newValue && !isEOISigned.value) {
|
||||
startSignaturePolling();
|
||||
} else {
|
||||
stopSignaturePolling();
|
||||
}
|
||||
}, { immediate: true });
|
||||
|
||||
// Cleanup on unmount
|
||||
onUnmounted(() => {
|
||||
stopSignaturePolling();
|
||||
});
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ interface EmailMessage {
|
|||
timestamp: string;
|
||||
direction: 'sent' | 'received';
|
||||
threadId?: string;
|
||||
attachments?: any[];
|
||||
}
|
||||
|
||||
export default defineEventHandler(async (event) => {
|
||||
|
|
@ -304,6 +305,15 @@ async function fetchImapEmails(
|
|||
return;
|
||||
}
|
||||
|
||||
// Extract attachments
|
||||
const attachments = parsed.attachments ? parsed.attachments.map((att: any) => ({
|
||||
filename: att.filename || 'attachment',
|
||||
name: att.filename || 'attachment',
|
||||
size: att.size || 0,
|
||||
type: att.contentType || 'application/octet-stream',
|
||||
cid: att.cid || undefined
|
||||
})) : [];
|
||||
|
||||
const email: EmailMessage = {
|
||||
id: parsed.messageId || `${Date.now()}-${seqno}`,
|
||||
from: fromEmail,
|
||||
|
|
@ -312,7 +322,8 @@ async function fetchImapEmails(
|
|||
body: parsed.text || '',
|
||||
html: parsed.html || undefined,
|
||||
timestamp: parsed.date?.toISOString() || new Date().toISOString(),
|
||||
direction: fromEmail.toLowerCase().includes(userEmail.toLowerCase()) ? 'sent' : 'received'
|
||||
direction: fromEmail.toLowerCase().includes(userEmail.toLowerCase()) ? 'sent' : 'received',
|
||||
attachments: attachments
|
||||
};
|
||||
|
||||
if (parsed.headers.has('in-reply-to')) {
|
||||
|
|
|
|||
|
|
@ -181,7 +181,8 @@ export default defineEventHandler(async (event) => {
|
|||
html: htmlBody,
|
||||
timestamp: new Date().toISOString(),
|
||||
direction: 'sent',
|
||||
interestId: interestId
|
||||
interestId: interestId,
|
||||
attachments: attachments // Include attachment info
|
||||
};
|
||||
|
||||
const objectName = `interest-${interestId}/${Date.now()}-sent.json`;
|
||||
|
|
|
|||
Loading…
Reference in New Issue