feat: add interest button
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
<v-container fluid>
|
||||
<!-- Header Section -->
|
||||
<v-row class="mb-6">
|
||||
<v-col cols="12">
|
||||
<v-col cols="12" md="8">
|
||||
<h1 class="text-h4 font-weight-bold mb-2">
|
||||
<v-icon class="mr-2" color="primary">mdi-account-group</v-icon>
|
||||
Interest List
|
||||
@@ -12,6 +12,17 @@
|
||||
Manage and track all potential client interests
|
||||
</p>
|
||||
</v-col>
|
||||
<v-col cols="12" md="4" class="d-flex justify-end align-center">
|
||||
<v-btn
|
||||
color="primary"
|
||||
size="large"
|
||||
@click="showCreateModal = true"
|
||||
prepend-icon="mdi-plus"
|
||||
variant="tonal"
|
||||
>
|
||||
Add Interest
|
||||
</v-btn>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<!-- Search and Filters Section -->
|
||||
@@ -182,6 +193,12 @@
|
||||
:selected-interest="selectedInterest"
|
||||
@save="handleSaveInterest"
|
||||
/>
|
||||
|
||||
<!-- Create Interest Modal -->
|
||||
<CreateInterestModal
|
||||
v-model="showCreateModal"
|
||||
@created="handleInterestCreated"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -189,6 +206,7 @@
|
||||
import LeadCategoryBadge from "~/components/LeadCategoryBadge.vue";
|
||||
import InterestSalesBadge from "~/components/InterestSalesBadge.vue";
|
||||
import InterestDetailsModal from "~/components/InterestDetailsModal.vue";
|
||||
import CreateInterestModal from "~/components/CreateInterestModal.vue";
|
||||
import { useFetch } from "#app";
|
||||
import { ref, computed } from "vue";
|
||||
import type { Interest } from "@/utils/types";
|
||||
@@ -201,6 +219,7 @@ const user = useDirectusUser();
|
||||
const router = useRouter();
|
||||
const loading = ref(true);
|
||||
const showModal = ref(false);
|
||||
const showCreateModal = ref(false);
|
||||
const selectedInterest = ref<Interest | null>(null);
|
||||
const selectedSalesLevel = ref('all');
|
||||
|
||||
@@ -231,6 +250,13 @@ const handleSaveInterest = async (interest: Interest) => {
|
||||
loading.value = false;
|
||||
};
|
||||
|
||||
const handleInterestCreated = async (interest: Interest) => {
|
||||
// Refresh the interests data to include the new interest
|
||||
loading.value = true;
|
||||
await refresh();
|
||||
loading.value = false;
|
||||
};
|
||||
|
||||
const headers = [
|
||||
{ title: "Contact", key: "Full Name", sortable: true, width: "25%" },
|
||||
{ title: "Yacht", key: "Yacht Name", sortable: true },
|
||||
|
||||
@@ -1,8 +1,21 @@
|
||||
<template>
|
||||
<v-container fluid class="pa-4">
|
||||
<!-- Loading Indicator -->
|
||||
<v-overlay
|
||||
v-model="loading"
|
||||
persistent
|
||||
class="align-center justify-center"
|
||||
>
|
||||
<v-progress-circular
|
||||
indeterminate
|
||||
size="64"
|
||||
color="primary"
|
||||
></v-progress-circular>
|
||||
</v-overlay>
|
||||
|
||||
<!-- Header -->
|
||||
<v-row class="mb-4">
|
||||
<v-col cols="12">
|
||||
<v-col cols="12" md="8">
|
||||
<h1 class="text-h4 font-weight-bold mb-2">
|
||||
<v-icon class="mr-2" color="primary">mdi-view-column</v-icon>
|
||||
Interest Status Board
|
||||
@@ -11,6 +24,17 @@
|
||||
Track interests through the sales pipeline
|
||||
</p>
|
||||
</v-col>
|
||||
<v-col cols="12" md="4" class="d-flex justify-end align-center">
|
||||
<v-btn
|
||||
color="primary"
|
||||
size="large"
|
||||
@click="showCreateModal = true"
|
||||
prepend-icon="mdi-plus"
|
||||
variant="tonal"
|
||||
>
|
||||
Add Interest
|
||||
</v-btn>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<!-- Kanban Board -->
|
||||
@@ -148,13 +172,20 @@
|
||||
:selected-interest="selectedInterest"
|
||||
@save="handleSaveInterest"
|
||||
/>
|
||||
|
||||
<!-- Create Interest Modal -->
|
||||
<CreateInterestModal
|
||||
v-model="showCreateModal"
|
||||
@created="handleInterestCreated"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import InterestDetailsModal from "~/components/InterestDetailsModal.vue";
|
||||
import CreateInterestModal from "~/components/CreateInterestModal.vue";
|
||||
import InterestSalesBadge from "~/components/InterestSalesBadge.vue";
|
||||
import { useFetch } from "#app";
|
||||
import { ref, computed } from "vue";
|
||||
import { ref, computed, onMounted } from "vue";
|
||||
import type { Interest, InterestSalesProcessLevel, InterestsResponse } from "@/utils/types";
|
||||
import { InterestSalesProcessLevelFlow } from "@/utils/types";
|
||||
|
||||
@@ -165,11 +196,12 @@ useHead({
|
||||
const user = useDirectusUser();
|
||||
const loading = ref(true);
|
||||
const showModal = ref(false);
|
||||
const showCreateModal = ref(false);
|
||||
const selectedInterest = ref<Interest | null>(null);
|
||||
const draggedInterest = ref<Interest | null>(null);
|
||||
const draggedFromLevel = ref<string | null>(null);
|
||||
|
||||
const { data: interests } = useFetch<InterestsResponse>("/api/get-interests", {
|
||||
const { data: interests, refresh } = useFetch<InterestsResponse>("/api/get-interests", {
|
||||
headers: {
|
||||
"x-tag": user.value?.email ? "094ut234" : "pjnvü1230",
|
||||
},
|
||||
@@ -181,6 +213,11 @@ const { data: interests } = useFetch<InterestsResponse>("/api/get-interests", {
|
||||
},
|
||||
});
|
||||
|
||||
// Set loading to true initially
|
||||
onMounted(() => {
|
||||
loading.value = true;
|
||||
});
|
||||
|
||||
const groupedInterests = computed(() => {
|
||||
const groups: Record<string, Interest[]> = {};
|
||||
|
||||
@@ -279,12 +316,19 @@ const handleInterestClick = (interestId: number) => {
|
||||
};
|
||||
|
||||
// Event handlers for the modal
|
||||
const handleSaveInterest = (interest: Interest) => {
|
||||
const handleSaveInterest = async (interest: Interest) => {
|
||||
// Update the interest in the local list if needed
|
||||
// The modal component already handles the API call and shows success/error messages
|
||||
// You can add additional logic here if needed
|
||||
};
|
||||
|
||||
const handleInterestCreated = async (interest: Interest) => {
|
||||
// Refresh the interests data to include the new interest
|
||||
loading.value = true;
|
||||
await refresh();
|
||||
loading.value = false;
|
||||
};
|
||||
|
||||
// Drag and Drop handlers
|
||||
const handleDragStart = (event: DragEvent, interest: Interest) => {
|
||||
draggedInterest.value = interest;
|
||||
@@ -335,19 +379,37 @@ const handleDrop = async (event: DragEvent, targetLevel: string) => {
|
||||
event.currentTarget.classList.remove('drag-over');
|
||||
}
|
||||
|
||||
if (!draggedInterest.value || draggedFromLevel.value === targetLevel) {
|
||||
// Get the dragged interest data from dataTransfer
|
||||
let draggedData: Interest | null = null;
|
||||
try {
|
||||
const dataString = event.dataTransfer?.getData('text/plain');
|
||||
if (dataString) {
|
||||
draggedData = JSON.parse(dataString);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to parse dragged data:', error);
|
||||
}
|
||||
|
||||
// Use either the parsed data or the ref value
|
||||
const interestToMove = draggedData || draggedInterest.value;
|
||||
const sourceLevel = draggedData?.['Sales Process Level'] || draggedFromLevel.value;
|
||||
|
||||
if (!interestToMove || !interestToMove.Id || sourceLevel === targetLevel) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Store the interest ID before any async operations
|
||||
const interestId = interestToMove.Id;
|
||||
|
||||
try {
|
||||
// Update the interest's sales process level
|
||||
const response = await $fetch('/api/update-interest', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'x-tag': '094ut234'
|
||||
'x-tag': user.value?.email ? "094ut234" : "pjnvü1230"
|
||||
},
|
||||
body: {
|
||||
id: draggedInterest.value.Id,
|
||||
id: interestId,
|
||||
data: {
|
||||
'Sales Process Level': targetLevel
|
||||
}
|
||||
@@ -355,19 +417,19 @@ const handleDrop = async (event: DragEvent, targetLevel: string) => {
|
||||
});
|
||||
|
||||
// Update local data
|
||||
const interestIndex = interests.value?.list.findIndex(i => i.Id === draggedInterest.value!.Id);
|
||||
const interestIndex = interests.value?.list.findIndex(i => i.Id === interestId);
|
||||
if (interestIndex !== undefined && interestIndex !== -1 && interests.value) {
|
||||
interests.value.list[interestIndex]['Sales Process Level'] = targetLevel;
|
||||
}
|
||||
|
||||
// Show success message
|
||||
const { $toast } = useNuxtApp();
|
||||
$toast.success(`Moved to ${targetLevel}`);
|
||||
const toast = useToast();
|
||||
toast.success(`Moved to ${targetLevel}`);
|
||||
|
||||
} catch (error) {
|
||||
console.error('Failed to update interest:', error);
|
||||
const { $toast } = useNuxtApp();
|
||||
$toast.error('Failed to update interest status');
|
||||
const toast = useToast();
|
||||
toast.error('Failed to update interest status');
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user