How to implement imet on a component prop in nuxt

22 views Asked by At

im new to nuxt and i am currently developing a module and I'm having a hard time implementing imet on a component props. That it should carry into the payload for adding something.

the logic is on the request.vue where i used the props, where there is userselector and user_id, where if userselector is true, user_id will be null and the selected user is automatically selected, but if userselector is false, it will have a dropdown of the users list to be selected and then it should be carried to the payload, for now this is my code but when i select on the user list and click on submit im getting error because the one i selected is not on the payload.

this is my pinia store, approvals.ts

import { defineStore } from "pinia"
const { token } = useAuth()
const config = useRuntimeConfig()

export const APPROVAL_MANPOWERREQ = "Manpower Request"

export interface Approver {
    type: string,
    user_id: number | null,
    userselector: boolean
}
export interface Approval {
    id: string | null,
    form: string,
    approvals: Array<Approver>,
}
export const useApprovalStore = defineStore("approvals", {
    state: () => ({
        isEdit: false,
        formApproval: {} as Approval,
        list: [],
        pagination: {},
        getParams: {},
        errorMessage: "",
        successMessage: "",
    }),
    actions: {
        async getApproval () {
            const { data, error } = await useFetch(
                "/api/approvals",
                {
                    baseURL: config.public.HRMS_API_URL,
                    method: "GET",
                    headers: {
                        Authorization: token.value + "",
                        Accept: "application/json"
                    },
                    params: this.getParams,
                    onResponse: ({ response }) => {
                        this.list = response._data.data.data.map((val: any) => {
                            return {
                                id: val.id,
                                form: val.form,
                                approvals: JSON.parse(val.approvals),
                            }
                        })
                        this.pagination = {
                            first_page: response._data.data.first_page_url,
                            pages: response._data.data.links,
                            last_page: response._data.data.last_page_url,
                        }
                    },
                }
            )
            if (data) {
                return data
            } else if (error) {
                return error
            }
        },

        async getApprovalByName (approvalName: String) {
            const { data } = await useFetch(
                "/api/get-form-requests/" + approvalName,
                {
                    baseURL: config.public.HRMS_API_URL,
                    method: "GET",
                    headers: {
                        Authorization: token.value + "",
                        Accept: "application/json"
                    },
                    watch: false,
                    onResponse: ({ response }) => {
                        if (response.status !== 200) {
                            this.errorMessage = response._data.message
                        } else {
                            return response._data.data
                        }
                    },
                }
            )
            return data.value.data.approvals
        },

        async createApproval () {
            this.successMessage = ""
            this.errorMessage = ""
            await useFetch(
                "/api/approvals",
                {
                    baseURL: config.public.HRMS_API_URL,
                    method: "POST",
                    headers: {
                        Authorization: token.value + "",
                        Accept: "application/json"
                    },
                    body: this.formApproval,
                    watch: false,
                    onResponse: ({ response }) => {
                        if (response.status !== 200) {
                            this.errorMessage = response._data.message
                        } else {
                            this.getApproval()
                            this.reset()
                            this.successMessage = response._data.message
                        }
                    },
                }
            )
        },
        clearMessages () {
            this.errorMessage = ""
            this.successMessage = ""
        },
        async editApprovals () {
            this.successMessage = ""
            this.errorMessage = ""
            const { data, error } = await useFetch(
                "/api/approvals/" + this.formApproval.id,
                {
                    baseURL: config.public.HRMS_API_URL,
                    method: "PATCH",
                    headers: {
                        Authorization: token.value + "",
                        Accept: "application/json"
                    },
                    body: this.formApproval,
                    watch: false,
                    onResponse: ({ response }) => {
                        if (response.status !== 200) {
                            this.errorMessage = response._data.message
                        } else {
                            this.getApproval()
                            this.reset()
                            this.successMessage = response._data.message
                        }
                    },
                }
            )
            if (data.value) {
                this.getApproval()
                this.reset()
                this.successMessage = data.value.message
                return data
            } else if (error.value) {
                this.errorMessage = error.value.message
                return error
            }
        },
        async deleteApproval (id: number) {
            await useFetch(
                "/api/approvals/" + id,
                {
                    baseURL: config.public.HRMS_API_URL,
                    method: "DELETE",
                    headers: {
                        Authorization: token.value + "",
                        Accept: "application/json"
                    },
                    watch: false,
                    onResponse: ({ response }) => {
                        this.successMessage = response._data.message
                        this.getApproval()
                    },
                    onResponseError: ({ response }) => {
                        this.errorMessage = response._data.message
                    },
                }
            )
        },

        reset () {
            this.approval = {
                id: null,
                form: null,
                approvals: [],
            }
            this.approvals = []
            this.isEdit = false
            this.successMessage = ""
            this.errorMessage = ""
        },

    },
})

this is my List.vue component which has the props from the pinia store

<script setup>
import { useUserStore } from "@/stores/hrms/users"

const user = useUserStore()
const { employeeUserList } = storeToRefs(user)

const props = defineProps({
    approval: {
        type: Object,
        required: true,
    },
})
const emit = defineEmits(["changeuserId"])

const changeuserId = (event) => {
    emit("changeuserId", props.approval, event.target.value)
}

</script>

<template>
    <div class="grid grid-cols-2 border border-slate-400 p-2">
        <div class="flex flex-col">
            <label class="block text-sm font-medium text-gray-900 dark:text-white">Approval Type</label>
            <div class="font-semibold text-black">
                {{ approval.type }}
            </div>
        </div>

        <div class="flex flex-col">
            <label class="block text-sm font-medium text-gray-900 dark:text-white">Approver</label>

            <div v-if="approval.userselector">
                <select class="w-full" @change="changeuserId">
                    <option disabled selected>
                        --Select--
                    </option>
                    <option v-for="userSelect in employeeUserList" :key="userSelect.id" :value="userSelect.id">
                        {{ userSelect.name }}
                    </option>
                </select>
            </div>
            <div v-else>
                <span class="font-semibold">{{ approval.name }}</span>
            </div>
        </div>
    </div>
</template>

and this is the request.vue(where all the inputs)

<script setup>
import { storeToRefs } from "pinia"
import { useManpowerStore, EMPLOYMENT_TYPE, NATURE_REQUESTS, STATUS, GENDER } from "@/stores/employee/manpower"
import { useDepartmentStore } from "@/stores/departments"
import { useApprovalStore, APPROVAL_MANPOWERREQ } from "@/stores/approvals"

const { data: userData } = useAuth()
const departments = useDepartmentStore()
const { departmentsList } = storeToRefs(departments)
const manpowers = useManpowerStore()
const { manpower, errorMessage, successMessage } = storeToRefs(manpowers)
const approvals = useApprovalStore()
const snackbar = useSnackbar()
const boardLoading = ref(false)

manpower.value.requested_by = userData.value.id
manpower.value.approvals = await approvals.getApprovalByName(APPROVAL_MANPOWERREQ)

const handleFileUpload = (event) => {
    const file = event.target.files[0]
    manpower.value.job_description_attachment = file
}

const addManpwr = async () => {
    try {
        boardLoading.value = true
        await manpowers.createManpower()
        if (manpowers.errorMessage !== "") {
            snackbar.add({
                type: "error",
                text: manpowers.errorMessage
            })
        } else {
            snackbar.add({
                type: "success",
                text: manpowers.successMessage
            })
        }
    } catch {
        snackbar.add({
            type: "error",
            text: manpowers.errorMessage
        })
    } finally {
        manpowers.clearMessages()
        boardLoading.value = false
    }
}
const changeuserId = (approver, userId) => {
    if (approver.userselector === true) {
        approver.user_id = null
    } else {
        approver.user_id = userId
    }
    console.log("approver:", approver)
    console.log("userId:", userId)
}

</script>

<template>
    <LayoutBoards title="Manpower Request" :loading="boardLoading" class="w-90">
        <div class="text-gray-500 p-2">
            <form @submit.prevent="addManpwr">
                <!-- {{ manpower }} -->
                <div class="grid grid-cols-2 gap-2 sm:grid-cols-2">
                    <div class="pb-4">
                        <label for="reqDepartment" class="block text-sm font-medium text-gray-900 dark:text-white">Requesting Department</label>
                        <select id="reqDepartment" v-model="manpower.requesting_department" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" required>
                            <option value="" disabled selected>
                                Choose Department
                            </option>
                            <option v-for="dpt, index in departmentsList" :key="index" :value=" dpt.id">
                                {{ dpt.department_name }}
                            </option>
                        </select>
                    </div>
                    <div>
                        <div class="grid grid-cols-1 gap-2 sm:grid-cols-2">
                            <div class="div">
                                <label for="date_requested" class="block text-sm font-medium text-gray-900 dark:text-white">Date Requested</label>
                                <input id="date_requested" v-model="manpower.date_requested" type="date" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" required>
                            </div>
                            <div class="div">
                                <label for="date_required" class="block text-sm font-medium text-gray-900 dark:text-white">Date Required</label>
                                <input id="date_required" v-model="manpower.date_required" type="date" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" required>
                            </div>
                        </div>
                    </div>
                </div>
                <div class=" grid grid-cols-1 gap-2 sm:grid-cols-2">
                    <div class="pb-4">
                        <label for="position_title" class="block text-sm font-medium text-gray-900 dark:text-white">Position/Title</label>
                        <input id="position_title" v-model="manpower.position" type="text" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" required>
                    </div>
                    <div>
                        <label for="employment_type" class="block text-sm font-medium text-gray-900 dark:text-white">Employment Type</label>
                        <select id="employment_type" v-model="manpower.employment_type" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" required>
                            <option value="" disabled selected>
                                Choose Employment Type
                            </option>
                            <option v-for="employmentType, index2 in EMPLOYMENT_TYPE" :key="index2" :value="employmentType">
                                {{ employmentType }}
                            </option>
                        </select>
                    </div>
                </div>
                <div class=" grid grid-cols-1 gap-2 sm:grid-cols-2">
                    <div class="pb-4">
                        <label for="brief_description" class="block  text-sm font-medium text-gray-900 dark:text-white">Brief Description</label>
                        <textarea id="brief_description" v-model="manpower.brief_description" rows="4" class="block p-2.5 w-full text-sm text-gray-900 bg-gray-50 rounded-lg border border-gray-300 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" placeholder="" />
                    </div>
                    <div class="pb-4">
                        <label for="job_description_attachment" class="block  text-sm font-medium text-gray-900 dark:text-white">Job Description Attachment</label>

                        <input
                            id="job_description_attachment"
                            class="block w-full mb-1 text-xs text-gray-900 border border-gray-300 rounded-lg cursor-pointer bg-gray-50 dark:text-gray-400 focus:outline-none dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400"
                            aria-describedby="file_input_help"
                            type="file"
                            accept=".doc,.docx,.pdf"
                            required
                            @change="handleFileUpload"
                        >
                        <p class="flex justify-center mx-auto text-xs text-gray-500 dark:text-gray-300 uppercase">
                            doc/docx/pdf
                        </p>
                    </div>
                </div>
                <div class="pb-4 grid grid-cols-1 gap-2 sm:grid-cols-5">
                    <div class="col-span-2">
                        <label class="block text-sm font-medium text-gray-900 dark:text-white">Nature of Request</label>
                        <select id="natureReqs" v-model="manpower.nature_of_request" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" required>
                            <option value="" disabled selected>
                                Choose Nature of Request
                            </option>
                            <option v-for="natureReqs, request in NATURE_REQUESTS" :key="request" :value="natureReqs">
                                {{ natureReqs }}
                            </option>
                        </select>
                    </div>
                    <div>
                        <label class="block text-sm font-medium text-gray-900 dark:text-white">Age Range</label>
                        <input id="age_range" v-model="manpower.age_range" type="text" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" required>
                    </div>
                    <div>
                        <label class="block  text-sm font-medium text-gray-900 dark:text-white">Status</label>
                        <select id="status" v-model="manpower.status" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" required>
                            <option value="" disabled selected>
                                Choose Status
                            </option>
                            <option v-for="statusType, index3 in STATUS" :key="index3" :value="statusType">
                                {{ statusType }}
                            </option>
                        </select>
                    </div>
                    <div>
                        <label class="block  text-sm font-medium text-gray-900 dark:text-white">Gender</label>
                        <select id="gender" v-model="manpower.gender" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" required>
                            <option value="" disabled selected>
                                Choose Gender
                            </option>
                            <option v-for="genderType, gender in GENDER" :key="gender" :value="genderType">
                                {{ genderType }}
                            </option>
                        </select>
                    </div>
                </div>
                <div class="pb-4 grid grid-cols-1 gap-2 sm:grid-cols-3">
                    <div>
                        <label for="educational_req" class="block  text-sm font-medium text-gray-900 dark:text-white">Educational Requirement</label>
                        <textarea id="educational_req" v-model="manpower.educational_requirement" rows="4" class="block p-2.5 w-full text-sm text-gray-900 bg-gray-50 rounded-lg border border-gray-300 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" placeholder="" />
                    </div>
                    <div class="col-span-2">
                        <label for="pref_qualification" class="block whitespace-normal text-sm font-medium text-gray-900 dark:text-white">Preferred Qualifications / Experience (not mentioned above or in the Job Description)</label>
                        <textarea id="pref_qualification" v-model="manpower.preferred_qualifications" rows="4" class="block p-2.5 w-full text-sm text-gray-900 bg-gray-50 rounded-lg border border-gray-300 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" placeholder="" />
                    </div>
                </div>
                <div class="pb-4">
                    <label for="remarks" class="block  text-sm font-medium text-gray-900 dark:text-white">Additional Remarks (Reason for Request)</label>
                    <textarea id="remarks" v-model="manpower.remarks" rows="4" class="block p-2.5 w-full text-sm text-gray-900 bg-gray-50 rounded-lg border border-gray-300 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" placeholder="" />
                </div>
                <div class="pb-4 grid grid-cols-1 gap-2 sm:grid-cols-2">
                    <div>
                        <label for="requested_by" class="block text-sm font-medium text-gray-900 dark:text-white">Requested by</label>
                        <input
                            id="requested_by"
                            :value="userData.name"
                            type="text"
                            class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg  focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
                            disabled
                        >
                    </div>
                </div>
                <label for="approved_by" class="block text-sm font-medium text-gray-900 dark:text-white">Approvals</label>
                <div>
                    <HrmsSetupApprovalsList
                        v-for="(approv, apr) in manpower.approvals"
                        :key="apr"
                        :approval="approv"
                        @changeuser-id="changeuserId"
                    />
                </div>

                <div class="pt-4">
                    <button type="submit" class=" text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm w-full sm:w-auto px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800">
                        Submit
                    </button>
                </div>
            </form>
            <p hidden class="error-message text-red-600 text-center font-semibold mt-2 italic" :class="{ 'fade-out': !errorMessage }">
                {{ errorMessage }}
            </p>
            <p
                v-show="successMessage"
                hidden
                class="success-message text-green-600 text-center font-semibold italic transition-opacity delay-1000"
            >
                {{ successMessage }}
            </p>
        </div>
    </LayoutBoards>
</template>
0

There are 0 answers