port-nimara-client-portal/components/EOISection.vue

217 lines
6.0 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) => {
const date = new Date(dateString);
return date.toLocaleString('en-US', {
month: 'short',
day: 'numeric',
year: 'numeric',
hour: '2-digit',
minute: '2-digit'
});
};
const getStatusColor = (status: string) => {
switch (status) {
case 'Waiting for Signatures':
return 'warning';
case 'Signed':
return 'success';
default:
return 'grey';
}
};
</script>