230 lines
6.3 KiB
Vue
230 lines
6.3 KiB
Vue
<template>
|
|
<div>
|
|
<v-card-title class="text-h6 d-flex align-center pb-4">
|
|
<v-icon class="mr-2" color="primary">mdi-file-document-edit</v-icon>
|
|
EOI Management
|
|
</v-card-title>
|
|
<v-card-text class="pt-2">
|
|
|
|
<!-- Generate EOI Button -->
|
|
<div v-if="!hasEOI" class="mb-4">
|
|
<v-btn
|
|
@click="generateEOI"
|
|
:loading="isGenerating"
|
|
color="primary"
|
|
variant="flat"
|
|
prepend-icon="mdi-file-document-plus"
|
|
>
|
|
Generate EOI
|
|
</v-btn>
|
|
</div>
|
|
|
|
<!-- EOI Status Badge -->
|
|
<div v-if="hasEOI" class="mb-4">
|
|
<v-chip
|
|
:color="getStatusColor(interest['EOI Status'])"
|
|
variant="tonal"
|
|
prepend-icon="mdi-file-document-check"
|
|
class="mr-2"
|
|
>
|
|
{{ interest['EOI Status'] }}
|
|
</v-chip>
|
|
<span v-if="interest['EOI Time Sent']" class="text-caption text-grey-darken-1">
|
|
Sent: {{ formatDate(interest['EOI Time Sent']) }}
|
|
</span>
|
|
</div>
|
|
|
|
<!-- Signature Links -->
|
|
<v-list v-if="hasEOI" density="comfortable">
|
|
<v-list-item class="mb-2">
|
|
<template v-slot:prepend>
|
|
<v-avatar color="primary" size="40">
|
|
<v-icon>mdi-account</v-icon>
|
|
</v-avatar>
|
|
</template>
|
|
<v-list-item-title>Client Signature Link</v-list-item-title>
|
|
<v-list-item-subtitle>{{ interest['Full Name'] }}</v-list-item-subtitle>
|
|
<template v-slot:append>
|
|
<v-btn
|
|
icon="mdi-content-copy"
|
|
variant="text"
|
|
@click="copyLink(interest['Signature Link Client'])"
|
|
></v-btn>
|
|
</template>
|
|
</v-list-item>
|
|
|
|
<v-list-item class="mb-2">
|
|
<template v-slot:prepend>
|
|
<v-avatar color="success" size="40">
|
|
<v-icon>mdi-account-check</v-icon>
|
|
</v-avatar>
|
|
</template>
|
|
<v-list-item-title>CC Signature Link</v-list-item-title>
|
|
<v-list-item-subtitle>Oscar Faragher</v-list-item-subtitle>
|
|
<template v-slot:append>
|
|
<v-btn
|
|
icon="mdi-content-copy"
|
|
variant="text"
|
|
@click="copyLink(interest['Signature Link CC'])"
|
|
></v-btn>
|
|
</template>
|
|
</v-list-item>
|
|
|
|
<v-list-item class="mb-2">
|
|
<template v-slot:prepend>
|
|
<v-avatar color="secondary" size="40">
|
|
<v-icon>mdi-account-tie</v-icon>
|
|
</v-avatar>
|
|
</template>
|
|
<v-list-item-title>Developer Signature Link</v-list-item-title>
|
|
<v-list-item-subtitle>David Mizrahi</v-list-item-subtitle>
|
|
<template v-slot:append>
|
|
<v-btn
|
|
icon="mdi-content-copy"
|
|
variant="text"
|
|
@click="copyLink(interest['Signature Link Developer'])"
|
|
></v-btn>
|
|
</template>
|
|
</v-list-item>
|
|
</v-list>
|
|
|
|
<!-- Regenerate Button -->
|
|
<div v-if="hasEOI && interest['EOI Status'] !== 'Signed'" class="mt-4">
|
|
<v-btn
|
|
@click="generateEOI"
|
|
:loading="isGenerating"
|
|
variant="text"
|
|
size="small"
|
|
prepend-icon="mdi-refresh"
|
|
>
|
|
Regenerate EOI
|
|
</v-btn>
|
|
</div>
|
|
</v-card-text>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import type { Interest } from '~/utils/types';
|
|
|
|
const props = defineProps<{
|
|
interest: Interest;
|
|
}>();
|
|
|
|
const emit = defineEmits<{
|
|
'eoi-generated': [data: { signingLinks: Record<string, string> }];
|
|
'update': [];
|
|
}>();
|
|
|
|
const { showToast } = useToast();
|
|
const isGenerating = ref(false);
|
|
|
|
const hasEOI = computed(() => {
|
|
return !!(props.interest['Signature Link Client'] ||
|
|
props.interest['Signature Link CC'] ||
|
|
props.interest['Signature Link Developer']);
|
|
});
|
|
|
|
const generateEOI = async () => {
|
|
isGenerating.value = true;
|
|
|
|
try {
|
|
const response = await $fetch<{
|
|
success: boolean;
|
|
documentId: string | number;
|
|
clientSigningUrl: string;
|
|
signingLinks: Record<string, string>;
|
|
}>('/api/email/generate-eoi-document', {
|
|
method: 'POST',
|
|
headers: {
|
|
'x-tag': '094ut234'
|
|
},
|
|
body: {
|
|
interestId: props.interest.Id.toString()
|
|
}
|
|
});
|
|
|
|
if (response.success) {
|
|
showToast(response.documentId === 'existing'
|
|
? 'EOI already exists - signature links retrieved'
|
|
: 'EOI generated successfully');
|
|
|
|
emit('eoi-generated', { signingLinks: response.signingLinks });
|
|
emit('update'); // Trigger parent to refresh data
|
|
}
|
|
} catch (error: any) {
|
|
console.error('Failed to generate EOI:', error);
|
|
showToast(error.data?.statusMessage || 'Failed to generate EOI');
|
|
} finally {
|
|
isGenerating.value = false;
|
|
}
|
|
};
|
|
|
|
const copyLink = async (link: string | undefined) => {
|
|
if (!link) return;
|
|
|
|
try {
|
|
await navigator.clipboard.writeText(link);
|
|
showToast('Signature link copied to clipboard');
|
|
|
|
// Update EOI Time Sent if not already set
|
|
if (!props.interest['EOI Time Sent']) {
|
|
try {
|
|
await $fetch('/api/update-interest', {
|
|
method: 'POST',
|
|
headers: {
|
|
'x-tag': '094ut234'
|
|
},
|
|
body: {
|
|
id: props.interest.Id.toString(),
|
|
data: {
|
|
'EOI Time Sent': new Date().toISOString()
|
|
}
|
|
}
|
|
});
|
|
emit('update'); // Refresh parent data
|
|
} catch (error) {
|
|
console.error('Failed to update EOI Time Sent:', error);
|
|
}
|
|
}
|
|
} catch (error) {
|
|
showToast('Failed to copy link');
|
|
}
|
|
};
|
|
|
|
const formatDate = (dateString: string) => {
|
|
if (!dateString) return '';
|
|
|
|
try {
|
|
const date = new Date(dateString);
|
|
// Check if date is valid
|
|
if (isNaN(date.getTime())) {
|
|
return dateString; // Return original if parsing fails
|
|
}
|
|
|
|
return date.toLocaleString('en-GB', {
|
|
day: '2-digit',
|
|
month: '2-digit',
|
|
year: 'numeric',
|
|
hour: '2-digit',
|
|
minute: '2-digit',
|
|
hour12: false
|
|
});
|
|
} catch (error) {
|
|
console.error('Date formatting error:', error);
|
|
return dateString;
|
|
}
|
|
};
|
|
|
|
const getStatusColor = (status: string) => {
|
|
switch (status) {
|
|
case 'Waiting for Signatures':
|
|
return 'warning';
|
|
case 'Signed':
|
|
return 'success';
|
|
default:
|
|
return 'grey';
|
|
}
|
|
};
|
|
</script>
|