typescripterror-handlingvuejs3nuxt3.jscomposable

Nuxt keeps showing undefined in my component


I have a dynamic page in my nuxt3 app, it keeps showing undefined mentorshipInfo, whereas, i know it does have mentorshipInfo in the composable.

Here is my code.

<ApplicationProcessWrapper
v-if="!isLoading"
icon="dollar-circle"
header-title="Setup Payment Plan for this Program"
header-subtitle="You will not be charged right now"
header-other-text="If your application is accepted"
>

<div class="plan">
<ApplicationPlanWrapper title="Select Payment Option">
<div class="cards-container">
<PaymentPlanCard
id="first-milestone"
title="First Milestone"
:price="minPrice"
:description="firstMilestone"
/>
<PaymentPlanCard
id="full-program"
title="Full Program"
:price="maxPrice"
:description="mentorshipInfo.title"
:recommended="true"
/>
<PaymentPlanCard
id="custom"
title="Custom"
:price="maxPrice"
:minimum="minPrice"
:custom-amount="true"
icon="settings-04"
/>
</div>
</ApplicationPlanWrapper>

<ApplicationPlanWrapper title="Select Payment Method">
<div class="balance span-2" @click="toggleUseBalance">
<AppRadiobutton :value="useBalanceFirst" class="form-radio" />

<div class="balance__info">
<h3>Use Accomplishr Balance First</h3>
<p>Pay with your Accomplishr Balance and then the deficit (if any) deducted from your payment method</p>
<p>
Available Balance
<span>{{ formatCurrency(balance.availableBalance) }}</span>
</p>
</div>
</div>

<div class="cards-container">
<MyPaymentCards />
</div>
</ApplicationPlanWrapper>
</div>
 
<TheMentorshipAction
:is-ok-disabled="isButtonDisabled"
:is-submit-disabled="false"
:is-loading="isSubmitting"
alt-text="Cancel"
submit-text="Submit Application"
use-custom-submit
@save-draft="onCancel"
@continue="onSubmit"
/>

</ApplicationProcessWrapper>
<AppLoader v-else class="loader" />

And the script part of the document

const router = useRouter();
const route = useRoute();
const { showAPIError, showAPISuccess } = useNotify();
const { getApplicationAPIStore, getApplicationById, getMentorship, mentorshipInfo } = useMentorship();
const { getBalanceAPI } = useBalance();

const mentorshipId = route.params.id as string;
const applicationId = route.params.uuid as string;

const isLoading = ref<boolean>(false);
const isSubmitting = ref<boolean>(false);
const useBalanceFirst = ref<boolean>(false);
const plan = ref<string>(null);
const paymentMethodId = ref<string>(null);

const { balance, profileOtherUser, clearOtherProfile } = useUser();
const { paymentComputation, getCharges } = usePaymentGeneral();
const { loading, isPaymentInfoEmpty } = usePayment();

await getMentorship(true);

const minPrice = computed(() => getMinPrice());
const maxPrice = computed(() => getProductTotalPrice());

const milestones = computed(() => {
return mentorshipInfo.value.milestones?.filter((milestone: IMilestone) => Number(milestone.price) > 0) ?? [];
});
const isButtonDisabled = computed(() => {
return isSubmitting.value || isPaymentInfoEmpty.value || !loading.value;
});
const firstMilestone = computed(() => {
const milestones = sortedMilestones();
return milestones.length === 0 ? '' : milestones[0].description;
});
const notPayedMilestones = computed(() => {
return milestones.value.filter((milestone: IMilestone) => !milestone.isUserPaid && milestone.price && Number(milestone.price) > 0);
});


const application = computed(() => {
return getApplicationById.value(applicationId);
});

function sortedMilestones() {
return notPayedMilestones.value.sort((a, b) => {
return new Date(getDateKey(a)).getTime() - new Date(getDateKey(b)).getTime();
});
}

function getMinPrice() {
const milestones = sortedMilestones();
return milestones.length === 0 ? 0 : Number(milestones[0].price ?? 0);
}

function getDateKey(milestone: IMilestone) {
return format(utcToLocalTime(milestone.due_date), 'yyyy-MM-dd');
}

function getProductTotalPrice() {
return notPayedMilestones.value.reduce((prev, curr) => prev + Number(curr.price ?? 0), 0);
}

function mounted() {
if (application.value?.author) {
profileOtherUser.value = application.value.author;
}
}

const onSubmit =  (data: any) => {
try {
isSubmitting.value = true;


} catch (error) {
} finally {
isSubmitting.value = false;
}
};

watch([mentorshipInfo, application], () => {
if (mentorshipInfo.value && application.value) {
mounted();
}
});

onBeforeMount(async () => {
isLoading.value = true;
await Promise.all([getApplicationAPIStore(mentorshipId, applicationId), getBalanceAPI()]);
isLoading.value = false;
});

onMounted(async () => {
await getCharges();
mounted();
});

onUnmounted(clearOtherProfile);

definePageMeta({
name: 'MentorshipPaymentPlan',
layout: 'new-main',
auth: true,
noScroll: true,
breadcumbs: [
{
text: 'Programs',
to: { name: 'Programs' },
},
{
text: mentorshipInfo.value.title || 'Program Application',
},
],
});

useHead({
title: 'Payment Plan', 
})

And the error i am getting on the terminal is below ERROR [nuxt] [request error] [unhandled] [500] mentorshipInfo is not defined at ./src/pages/program/[id]/plan/[uuid].vue:12:17

I have tried to optionally render, but still could not figure out where the error was coming from or why it is failing as i have used the composable all through in the project and it works fine.


Solution

  • The issue is, you can't access variables defined outside definePageMeta because it's a compiler macro. Please read

    definePageMeta({
    name: 'MentorshipPaymentPlan',
    layout: 'new-main',
    auth: true,
    noScroll: true,
    breadcumbs: [
    {
    text: 'Programs',
    to: { name: 'Programs' },
    },
    {
    text: 'Program Application',
    },
    ],
    });
    

    I removed

    mentorshipInfo.value.title

    As this is likely causing the error