fix: mode

This commit is contained in:
Ron 2025-06-03 20:32:34 +03:00
parent b3651e7f43
commit 0437ba6462
3 changed files with 215 additions and 181 deletions

View File

@ -1,5 +1,10 @@
<template> <template>
<v-dialog v-model="isOpen" fullscreen hide-overlay transition="dialog-bottom-transition"> <v-dialog
v-model="isOpen"
fullscreen
hide-overlay
transition="dialog-bottom-transition"
>
<v-card> <v-card>
<v-toolbar dark color="primary"> <v-toolbar dark color="primary">
<v-btn icon dark @click="closeModal"> <v-btn icon dark @click="closeModal">
@ -15,46 +20,75 @@
@click="requestMoreInfoToSales" @click="requestMoreInfoToSales"
variant="text" variant="text"
:loading="isRequestingMoreInfo" :loading="isRequestingMoreInfo"
:disabled="isRequestingMoreInfo || isRequestingMoreInformation || isSendingEOI" :disabled="
isRequestingMoreInfo ||
isRequestingMoreInformation ||
isSendingEOI
"
:icon="mobile"
> >
<v-icon start>mdi-information-outline</v-icon> <v-icon v-if="mobile">mdi-information-outline</v-icon>
Info to Sales <template v-else>
<v-icon start>mdi-information-outline</v-icon>
Info to Sales
</template>
</v-btn> </v-btn>
<v-btn <v-btn
@click="requestMoreInformation" @click="requestMoreInformation"
variant="text" variant="text"
:loading="isRequestingMoreInformation" :loading="isRequestingMoreInformation"
:disabled="isRequestingMoreInfo || isRequestingMoreInformation || isSendingEOI" :disabled="
isRequestingMoreInfo ||
isRequestingMoreInformation ||
isSendingEOI
"
:icon="mobile"
> >
<v-icon start>mdi-email-outline</v-icon> <v-icon v-if="mobile">mdi-email-outline</v-icon>
Request Info <template v-else>
<v-icon start>mdi-email-outline</v-icon>
Request Info
</template>
</v-btn> </v-btn>
<v-btn <v-btn
@click="eoiSendToSales" @click="eoiSendToSales"
variant="text" variant="text"
:loading="isSendingEOI" :loading="isSendingEOI"
:disabled="isRequestingMoreInfo || isRequestingMoreInformation || isSendingEOI" :disabled="
isRequestingMoreInfo ||
isRequestingMoreInformation ||
isSendingEOI
"
:icon="mobile"
> >
<v-icon start>mdi-send</v-icon> <v-icon v-if="mobile">mdi-send</v-icon>
EOI to Sales <template v-else>
<v-icon start>mdi-send</v-icon>
EOI to Sales
</template>
</v-btn> </v-btn>
<v-btn <v-btn
variant="flat" variant="flat"
color="success" color="success"
size="large" :size="mobile ? 'default' : 'large'"
@click="saveInterest" @click="saveInterest"
:loading="isSaving" :loading="isSaving"
:disabled="isSaving" :disabled="isSaving"
class="ml-2" class="ml-2"
:icon="mobile"
> >
<v-icon start>mdi-content-save</v-icon> <v-icon v-if="mobile">mdi-content-save</v-icon>
Save Changes <template v-else>
<v-icon start>mdi-content-save</v-icon>
Save Changes
</template>
</v-btn> </v-btn>
</v-toolbar-items> </v-toolbar-items>
</v-toolbar> </v-toolbar>
<v-card-text v-if="interest"> <v-card-text v-if="interest">
<v-stepper <v-stepper
v-show="!mobile"
v-model="currentStep" v-model="currentStep"
class="mb-6" class="mb-6"
variant="flat" variant="flat"
@ -91,7 +125,7 @@
variant="tonal" variant="tonal"
prepend-icon="mdi-calendar-clock" prepend-icon="mdi-calendar-clock"
> >
Created: {{ formatDate(interest['Created At']) }} Created: {{ formatDate(interest["Created At"]) }}
</v-chip> </v-chip>
<v-chip <v-chip
v-if="interest['Request Form Sent']" v-if="interest['Request Form Sent']"
@ -99,7 +133,8 @@
variant="tonal" variant="tonal"
prepend-icon="mdi-email-check" prepend-icon="mdi-email-check"
> >
Request Form Sent: {{ formatDate(interest['Request Form Sent']) }} Request Form Sent:
{{ formatDate(interest["Request Form Sent"]) }}
</v-chip> </v-chip>
<v-chip <v-chip
v-if="interest['EOI Time Sent']" v-if="interest['EOI Time Sent']"
@ -107,7 +142,7 @@
variant="tonal" variant="tonal"
prepend-icon="mdi-email-fast" prepend-icon="mdi-email-fast"
> >
EOI Sent: {{ formatDate(interest['EOI Time Sent']) }} EOI Sent: {{ formatDate(interest["EOI Time Sent"]) }}
</v-chip> </v-chip>
<v-chip <v-chip
v-if="interest['Time LOI Sent']" v-if="interest['Time LOI Sent']"
@ -115,7 +150,7 @@
variant="tonal" variant="tonal"
prepend-icon="mdi-file-document-check" prepend-icon="mdi-file-document-check"
> >
LOI Sent: {{ formatDate(interest['Time LOI Sent']) }} LOI Sent: {{ formatDate(interest["Time LOI Sent"]) }}
</v-chip> </v-chip>
</div> </div>
</v-col> </v-col>
@ -277,8 +312,8 @@
<v-autocomplete <v-autocomplete
v-model="selectedBerthRecommendations" v-model="selectedBerthRecommendations"
:items="availableBerths" :items="availableBerths"
:item-title="item => item['Mooring Number']" :item-title="(item) => item['Mooring Number']"
:item-value="item => item.Id" :item-value="(item) => item.Id"
label="Berth Recommendations" label="Berth Recommendations"
variant="outlined" variant="outlined"
density="comfortable" density="comfortable"
@ -302,8 +337,8 @@
<v-autocomplete <v-autocomplete
v-model="selectedBerths" v-model="selectedBerths"
:items="availableBerths" :items="availableBerths"
:item-title="item => item['Mooring Number']" :item-title="(item) => item['Mooring Number']"
:item-value="item => item.Id" :item-value="(item) => item.Id"
label="Berths" label="Berths"
variant="outlined" variant="outlined"
density="comfortable" density="comfortable"
@ -353,9 +388,17 @@
prepend-inner-icon="mdi-comment-text" prepend-inner-icon="mdi-comment-text"
></v-text-field> ></v-text-field>
</v-col> </v-col>
<v-col cols="12" v-if="interest['EOI Document'] && interest['EOI Document'].length > 0"> <v-col
cols="12"
v-if="
interest['EOI Document'] &&
interest['EOI Document'].length > 0
"
>
<div class="d-flex align-center"> <div class="d-flex align-center">
<v-icon class="mr-2" color="primary">mdi-file-document</v-icon> <v-icon class="mr-2" color="primary"
>mdi-file-document</v-icon
>
<span class="text-subtitle-1 mr-3">EOI Documents:</span> <span class="text-subtitle-1 mr-3">EOI Documents:</span>
<div class="d-flex flex-wrap ga-2"> <div class="d-flex flex-wrap ga-2">
<v-chip <v-chip
@ -398,16 +441,18 @@ interface Props {
} }
interface Emits { interface Emits {
(e: 'update:modelValue', value: boolean): void; (e: "update:modelValue", value: boolean): void;
(e: 'save', interest: Interest): void; (e: "save", interest: Interest): void;
(e: 'requestMoreInfoToSales', interest: Interest): void; (e: "requestMoreInfoToSales", interest: Interest): void;
(e: 'requestMoreInformation', interest: Interest): void; (e: "requestMoreInformation", interest: Interest): void;
(e: 'eoiSendToSales', interest: Interest): void; (e: "eoiSendToSales", interest: Interest): void;
} }
const props = defineProps<Props>(); const props = defineProps<Props>();
const emit = defineEmits<Emits>(); const emit = defineEmits<Emits>();
const { mobile } = useDisplay();
const user = useDirectusUser(); const user = useDirectusUser();
// Local copy of the interest for editing // Local copy of the interest for editing
@ -428,24 +473,28 @@ const originalBerths = ref<number[]>([]);
const originalBerthRecommendations = ref<number[]>([]); const originalBerthRecommendations = ref<number[]>([]);
// Sync the local copy with the prop // Sync the local copy with the prop
watch(() => props.selectedInterest, async (newInterest) => { watch(
if (newInterest) { () => props.selectedInterest,
interest.value = { ...newInterest }; async (newInterest) => {
// Load linked berths and recommendations if (newInterest) {
await loadLinkedBerths(); interest.value = { ...newInterest };
} else { // Load linked berths and recommendations
interest.value = null; await loadLinkedBerths();
selectedBerths.value = []; } else {
selectedBerthRecommendations.value = []; interest.value = null;
originalBerths.value = []; selectedBerths.value = [];
originalBerthRecommendations.value = []; selectedBerthRecommendations.value = [];
} originalBerths.value = [];
}, { immediate: true }); originalBerthRecommendations.value = [];
}
},
{ immediate: true }
);
// Computed property for v-model binding // Computed property for v-model binding
const isOpen = computed({ const isOpen = computed({
get: () => props.modelValue, get: () => props.modelValue,
set: (value: boolean) => emit('update:modelValue', value) set: (value: boolean) => emit("update:modelValue", value),
}); });
const currentStep = computed(() => { const currentStep = computed(() => {
@ -465,22 +514,22 @@ const saveInterest = async () => {
// Create a copy of the interest data without the Berths and Berth Recommendations fields // Create a copy of the interest data without the Berths and Berth Recommendations fields
const dataToSave = { ...interest.value }; const dataToSave = { ...interest.value };
delete dataToSave.Berths; delete dataToSave.Berths;
delete dataToSave['Berth Recommendations']; delete dataToSave["Berth Recommendations"];
// Call the update-interest API // Call the update-interest API
await $fetch('/api/update-interest', { await $fetch("/api/update-interest", {
method: 'POST', method: "POST",
headers: { headers: {
"x-tag": !user.value?.email ? "094ut234" : "pjnvü1230", "x-tag": user.value?.email ? "094ut234" : "pjnvü1230",
}, },
body: { body: {
id: interest.value.Id.toString(), id: interest.value.Id.toString(),
data: dataToSave data: dataToSave,
} },
}); });
alert("Interest saved successfully!"); alert("Interest saved successfully!");
emit('save', interest.value); emit("save", interest.value);
closeModal(); closeModal();
} catch (error) { } catch (error) {
console.error("Failed to save interest:", error); console.error("Failed to save interest:", error);
@ -496,18 +545,18 @@ const requestMoreInfoToSales = async () => {
isRequestingMoreInfo.value = true; isRequestingMoreInfo.value = true;
try { try {
// Call the request-more-info-to-sales API // Call the request-more-info-to-sales API
await $fetch('/api/request-more-info-to-sales', { await $fetch("/api/request-more-info-to-sales", {
method: 'POST', method: "POST",
headers: { headers: {
"x-tag": !user.value?.email ? "094ut234" : "pjnvü1230", "x-tag": user.value?.email ? "094ut234" : "pjnvü1230",
}, },
body: { body: {
interestId: interest.value.Id.toString() interestId: interest.value.Id.toString(),
} },
}); });
alert("Request More Info - To Sales sent successfully!"); alert("Request More Info - To Sales sent successfully!");
emit('requestMoreInfoToSales', interest.value); emit("requestMoreInfoToSales", interest.value);
} catch (error) { } catch (error) {
console.error("Failed to send request:", error); console.error("Failed to send request:", error);
alert("Failed to send request. Please try again."); alert("Failed to send request. Please try again.");
@ -522,18 +571,18 @@ const requestMoreInformation = async () => {
isRequestingMoreInformation.value = true; isRequestingMoreInformation.value = true;
try { try {
// Call the request-more-information API // Call the request-more-information API
await $fetch('/api/request-more-information', { await $fetch("/api/request-more-information", {
method: 'POST', method: "POST",
headers: { headers: {
"x-tag": !user.value?.email ? "094ut234" : "pjnvü1230", "x-tag": user.value?.email ? "094ut234" : "pjnvü1230",
}, },
body: { body: {
interestId: interest.value.Id.toString() interestId: interest.value.Id.toString(),
} },
}); });
alert("Request More Information sent successfully!"); alert("Request More Information sent successfully!");
emit('requestMoreInformation', interest.value); emit("requestMoreInformation", interest.value);
} catch (error) { } catch (error) {
console.error("Failed to send request:", error); console.error("Failed to send request:", error);
alert("Failed to send request. Please try again."); alert("Failed to send request. Please try again.");
@ -548,18 +597,18 @@ const eoiSendToSales = async () => {
isSendingEOI.value = true; isSendingEOI.value = true;
try { try {
// Call the eoi-send-to-sales API // Call the eoi-send-to-sales API
await $fetch('/api/eoi-send-to-sales', { await $fetch("/api/eoi-send-to-sales", {
method: 'POST', method: "POST",
headers: { headers: {
"x-tag": !user.value?.email ? "094ut234" : "pjnvü1230", "x-tag": user.value?.email ? "094ut234" : "pjnvü1230",
}, },
body: { body: {
interestId: interest.value.Id.toString() interestId: interest.value.Id.toString(),
} },
}); });
alert("EOI Send to Sales sent successfully!"); alert("EOI Send to Sales sent successfully!");
emit('eoiSendToSales', interest.value); emit("eoiSendToSales", interest.value);
} catch (error) { } catch (error) {
console.error("Failed to send EOI:", error); console.error("Failed to send EOI:", error);
alert("Failed to send EOI. Please try again."); alert("Failed to send EOI. Please try again.");
@ -573,9 +622,9 @@ const eoiSendToSales = async () => {
const loadAvailableBerths = async () => { const loadAvailableBerths = async () => {
loadingBerths.value = true; loadingBerths.value = true;
try { try {
const response = await $fetch<{ list: Berth[] }>('/api/get-berths', { const response = await $fetch<{ list: Berth[] }>("/api/get-berths", {
headers: { headers: {
"x-tag": !user.value?.email ? "094ut234" : "pjnvü1230", "x-tag": user.value?.email ? "094ut234" : "pjnvü1230",
}, },
}); });
availableBerths.value = response.list || []; availableBerths.value = response.list || [];
@ -592,33 +641,42 @@ const loadLinkedBerths = async () => {
try { try {
// Load berths // Load berths
const berthsResponse = await $fetch<{ list: Array<{ Id: number }> }>('/api/get-interest-berths', { const berthsResponse = await $fetch<{ list: Array<{ Id: number }> }>(
headers: { "/api/get-interest-berths",
"x-tag": !user.value?.email ? "094ut234" : "pjnvü1230", {
}, headers: {
params: { "x-tag": user.value?.email ? "094ut234" : "pjnvü1230",
interestId: interest.value.Id, },
linkType: 'berths' params: {
interestId: interest.value.Id,
linkType: "berths",
},
} }
}); );
// Load berth recommendations // Load berth recommendations
const recommendationsResponse = await $fetch<{ list: Array<{ Id: number }> }>('/api/get-interest-berths', { const recommendationsResponse = await $fetch<{
list: Array<{ Id: number }>;
}>("/api/get-interest-berths", {
headers: { headers: {
"x-tag": !user.value?.email ? "094ut234" : "pjnvü1230", "x-tag": user.value?.email ? "094ut234" : "pjnvü1230",
}, },
params: { params: {
interestId: interest.value.Id, interestId: interest.value.Id,
linkType: 'recommendations' linkType: "recommendations",
} },
}); });
selectedBerths.value = (berthsResponse.list || []).map(b => b.Id); selectedBerths.value = (berthsResponse.list || []).map((b) => b.Id);
selectedBerthRecommendations.value = (recommendationsResponse.list || []).map(b => b.Id); selectedBerthRecommendations.value = (
recommendationsResponse.list || []
).map((b) => b.Id);
// Store original values to detect changes // Store original values to detect changes
originalBerths.value = [...selectedBerths.value]; originalBerths.value = [...selectedBerths.value];
originalBerthRecommendations.value = [...selectedBerthRecommendations.value]; originalBerthRecommendations.value = [
...selectedBerthRecommendations.value,
];
} catch (error) { } catch (error) {
console.error("Failed to load linked berths:", error); console.error("Failed to load linked berths:", error);
} }
@ -630,34 +688,36 @@ const updateBerths = async (newBerths: number[]) => {
try { try {
// Find berths to add and remove // Find berths to add and remove
const toAdd = newBerths.filter(id => !originalBerths.value.includes(id)); const toAdd = newBerths.filter((id) => !originalBerths.value.includes(id));
const toRemove = originalBerths.value.filter(id => !newBerths.includes(id)); const toRemove = originalBerths.value.filter(
(id) => !newBerths.includes(id)
);
// Link new berths // Link new berths
if (toAdd.length > 0) { if (toAdd.length > 0) {
await $fetch('/api/link-berths-to-interest', { await $fetch("/api/link-berths-to-interest", {
method: 'POST', method: "POST",
headers: { headers: {
"x-tag": !user.value?.email ? "094ut234" : "pjnvü1230", "x-tag": user.value?.email ? "094ut234" : "pjnvü1230",
}, },
body: { body: {
interestId: interest.value.Id, interestId: interest.value.Id,
berthIds: toAdd berthIds: toAdd,
} },
}); });
} }
// Unlink removed berths // Unlink removed berths
if (toRemove.length > 0) { if (toRemove.length > 0) {
await $fetch('/api/unlink-berths-from-interest', { await $fetch("/api/unlink-berths-from-interest", {
method: 'POST', method: "POST",
headers: { headers: {
"x-tag": !user.value?.email ? "094ut234" : "pjnvü1230", "x-tag": user.value?.email ? "094ut234" : "pjnvü1230",
}, },
body: { body: {
interestId: interest.value.Id, interestId: interest.value.Id,
berthIds: toRemove berthIds: toRemove,
} },
}); });
} }
@ -677,34 +737,38 @@ const updateBerthRecommendations = async (newRecommendations: number[]) => {
try { try {
// Find recommendations to add and remove // Find recommendations to add and remove
const toAdd = newRecommendations.filter(id => !originalBerthRecommendations.value.includes(id)); const toAdd = newRecommendations.filter(
const toRemove = originalBerthRecommendations.value.filter(id => !newRecommendations.includes(id)); (id) => !originalBerthRecommendations.value.includes(id)
);
const toRemove = originalBerthRecommendations.value.filter(
(id) => !newRecommendations.includes(id)
);
// Link new recommendations // Link new recommendations
if (toAdd.length > 0) { if (toAdd.length > 0) {
await $fetch('/api/link-berth-recommendations-to-interest', { await $fetch("/api/link-berth-recommendations-to-interest", {
method: 'POST', method: "POST",
headers: { headers: {
"x-tag": !user.value?.email ? "094ut234" : "pjnvü1230", "x-tag": user.value?.email ? "094ut234" : "pjnvü1230",
}, },
body: { body: {
interestId: interest.value.Id, interestId: interest.value.Id,
berthIds: toAdd berthIds: toAdd,
} },
}); });
} }
// Unlink removed recommendations // Unlink removed recommendations
if (toRemove.length > 0) { if (toRemove.length > 0) {
await $fetch('/api/unlink-berth-recommendations-from-interest', { await $fetch("/api/unlink-berth-recommendations-from-interest", {
method: 'POST', method: "POST",
headers: { headers: {
"x-tag": !user.value?.email ? "094ut234" : "pjnvü1230", "x-tag": user.value?.email ? "094ut234" : "pjnvü1230",
}, },
body: { body: {
interestId: interest.value.Id, interestId: interest.value.Id,
berthIds: toRemove berthIds: toRemove,
} },
}); });
} }
@ -714,34 +778,40 @@ const updateBerthRecommendations = async (newRecommendations: number[]) => {
console.error("Failed to update berth recommendations:", error); console.error("Failed to update berth recommendations:", error);
alert("Failed to update berth recommendations. Please try again."); alert("Failed to update berth recommendations. Please try again.");
// Revert to original values on error // Revert to original values on error
selectedBerthRecommendations.value = [...originalBerthRecommendations.value]; selectedBerthRecommendations.value = [
...originalBerthRecommendations.value,
];
} }
}; };
// Format date helper function // Format date helper function
const formatDate = (dateString: string | null | undefined) => { const formatDate = (dateString: string | null | undefined) => {
if (!dateString) return ''; if (!dateString) return "";
try { try {
// Handle DD-MM-YYYY format // Handle DD-MM-YYYY format
if (dateString.includes('-')) { if (dateString.includes("-")) {
const parts = dateString.split('-'); const parts = dateString.split("-");
if (parts.length === 3) { if (parts.length === 3) {
const [day, month, year] = parts; const [day, month, year] = parts;
const date = new Date(parseInt(year), parseInt(month) - 1, parseInt(day)); const date = new Date(
return date.toLocaleDateString('en-US', { parseInt(year),
year: 'numeric', parseInt(month) - 1,
month: 'short', parseInt(day)
day: 'numeric' );
return date.toLocaleDateString("en-US", {
year: "numeric",
month: "short",
day: "numeric",
}); });
} }
} }
// Fallback to direct date parsing // Fallback to direct date parsing
const date = new Date(dateString); const date = new Date(dateString);
if (!isNaN(date.getTime())) { if (!isNaN(date.getTime())) {
return date.toLocaleDateString('en-US', { return date.toLocaleDateString("en-US", {
year: 'numeric', year: "numeric",
month: 'short', month: "short",
day: 'numeric' day: "numeric",
}); });
} }
return dateString; return dateString;

View File

@ -181,9 +181,6 @@
v-model="showModal" v-model="showModal"
:selected-interest="selectedInterest" :selected-interest="selectedInterest"
@save="handleSaveInterest" @save="handleSaveInterest"
@request-more-info-to-sales="handleRequestMoreInfoToSales"
@request-more-information="handleRequestMoreInformation"
@eoi-send-to-sales="handleEoiSendToSales"
/> />
</div> </div>
</template> </template>
@ -234,21 +231,6 @@ const handleSaveInterest = async (interest: Interest) => {
loading.value = false; loading.value = false;
}; };
const handleRequestMoreInfoToSales = (interest: Interest) => {
// The modal component already handles the API call
// You can add additional logic here if needed
};
const handleRequestMoreInformation = (interest: Interest) => {
// The modal component already handles the API call
// You can add additional logic here if needed
};
const handleEoiSendToSales = (interest: Interest) => {
// The modal component already handles the API call
// You can add additional logic here if needed
};
const headers = [ const headers = [
{ title: "Contact", key: "Full Name", sortable: true, width: "25%" }, { title: "Contact", key: "Full Name", sortable: true, width: "25%" },
{ title: "Yacht", key: "Yacht Name", sortable: true }, { title: "Yacht", key: "Yacht Name", sortable: true },

View File

@ -147,9 +147,6 @@
v-model="showModal" v-model="showModal"
:selected-interest="selectedInterest" :selected-interest="selectedInterest"
@save="handleSaveInterest" @save="handleSaveInterest"
@request-more-info-to-sales="handleRequestMoreInfoToSales"
@request-more-information="handleRequestMoreInformation"
@eoi-send-to-sales="handleEoiSendToSales"
/> />
</template> </template>
@ -288,21 +285,6 @@ const handleSaveInterest = (interest: Interest) => {
// You can add additional logic here if needed // You can add additional logic here if needed
}; };
const handleRequestMoreInfoToSales = (interest: Interest) => {
// The modal component already handles the API call
// You can add additional logic here if needed
};
const handleRequestMoreInformation = (interest: Interest) => {
// The modal component already handles the API call
// You can add additional logic here if needed
};
const handleEoiSendToSales = (interest: Interest) => {
// The modal component already handles the API call
// You can add additional logic here if needed
};
// Drag and Drop handlers // Drag and Drop handlers
const handleDragStart = (event: DragEvent, interest: Interest) => { const handleDragStart = (event: DragEvent, interest: Interest) => {
draggedInterest.value = interest; draggedInterest.value = interest;