what changes should i make to my vuejs code so that the offchain data code in solidity works.
solidity code:
//SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";


contract LoanNFT is ERC721 {
    struct Loan {
        uint256 id;
        uint256 principal;
        uint256 interestRate;
        uint256 term;
        uint256 maturityDate;
        address borrower;
        bool isRepaid;
        uint256 offchainDataId;
    }

    struct OffchainData {
        string dataURL;
        bytes32 dataHash;
    }

    mapping(uint256 => Loan) public loans;
    mapping(uint256 => OffchainData) public offchainData; // mapping for offchain data

    uint256 public loanId;
    uint256 public couponRate;

    constructor(string memory _name, string memory _symbol, uint256 _couponRate) ERC721(_name, _symbol) {
        loanId = 0;
        couponRate = _couponRate;
    }

    function issueLoan(
        address _borrower,
        uint256 _principal,
        uint256 _interestRate,
        uint256 _term,
        uint256 _maturityDate,
        string memory _offchainDataURL, // parameter for offchain data
        bytes32 _offchainDataHash // parameter for offchain data
    ) public {
        loanId++;
        offchainData[loanId] = OffchainData(_offchainDataURL, _offchainDataHash);
        loans[loanId] = Loan(loanId, _principal, _interestRate, _term, _maturityDate, _borrower, false, loanId); // Pass offchain data id to loan
        _mint(msg.sender, loanId);
    }

    function repayLoan(uint256 _loanId) public {
        require(msg.sender == loans[_loanId].borrower, "Only borrower can repay the loan");
        loans[_loanId].isRepaid = true;
    }

    function buyNFT(uint256 _loanId) public payable {
        require(ownerOf(_loanId) != msg.sender, "Cannot buy your own loan NFT");
        require(msg.value >= calculateCouponAmount(_loanId), "Insufficient funds to buy the loan NFT");
        address owner = ownerOf(_loanId);
        _transfer(owner, msg.sender, _loanId);
        payable(owner).transfer(msg.value);
    }

    function calculateCouponAmount(uint256 _loanId) public view returns (uint256) {
        require(ownerOf(_loanId) != address(0), "Invalid loan NFT");
        Loan memory loan = loans[_loanId];
        uint256 couponAmount = loan.principal * loan.interestRate * couponRate / (100 * loan.term);
        if (loan.isRepaid) {
            couponAmount = couponAmount + loan.principal;
        }
        return couponAmount;
    }

    function destroyNFT(uint256 _loanId) public {
        require(ownerOf(_loanId) == msg.sender, "Only owner can destroy the loan NFT");
        _burn(_loanId);
    }
}

VUEJS:
<template>
  <div class=“loan-nft-app”>
    <!-- <h1>Loan NFT Application</h1> -->
    <h2>Issue Loan</h2>
    <form @submit.prevent="onIssueLoan" class=“loan-form”>
      <div class=“field-group”>
        <label for=“borrower”>Borrower Address:</label>
        <input type=“text” id=“borrower” v-model="loanForm.borrower" required />
      </div>
      <br>
      <div class=“field-group”>
        <label for=“principal”>Principal:</label>
        <input type=“number” id=“principal” v-model="loanForm.principal" required />
      </div>
      <br>
      <div class=“field-group”>
        <label for=“interestRate”>Interest Rate:</label>
        <input type=“number” id=“interestRate” v-model="loanForm.interestRate" required />
      </div>
      <br>
      <div class=“field-group”>
        <label for=“term”>Term:</label>
        <input type=“number” id=“term” v-model="loanForm.term" required />
      </div>
      <br>
      <div class=“field-group”>
        <label for=“maturityDate”>Maturity Date:</label>
        <input type=“number” id=“maturityDate” v-model="loanForm.maturityDate" required />
      </div>
      <br>
      <div class=“field-group”>
        <label for=“offchainDataURL”>Offchain Data URL:</label>
        <input type=“text” id=“offchainDataURL” v-model="loanForm.offchainDataURL" required />
      </div>
      <br>
      <div class=“field-group”>
        <label for=“offchainDataHash”>Offchain Data Hash:</label>
        <input type=“text” id=“offchainDataHash” v-model="loanForm.offchainDataHash" required />
      </div>
      <br>
      <button type=“submit”>Issue Loan</button>
    </form>
    <h2>Buy Loan NFT</h2>
    <form @submit.prevent="onBuyNFT" class=“loan-form”>
      <div class=“field-group”>
        <label for=“buy_loan_id”>Loan ID:</label>
        <input type=“number” id=“buy_loan_id” v-model="buyNFTForm.loanId" required />
      </div>
      <button type=“submit”>Buy Loan NFT</button>
    </form>
    <h2>Destroy Loan NFT</h2>
    <form @submit.prevent="onDestroyNFT" class=“loan-form”>
      <div class=“field-group”>
        <label for=“destroy_loan_id”>Loan ID:</label>
        <input type=“number” id=“destroy_loan_id” v-model="destroyNFTForm.loanId" required />
      </div>
      <button type=“submit”>Destroy Loan NFT</button>
    </form>
    <p>{{issueLoanStatus}}</p>
  </div>
</template>

<script>
import Web3 from "web3";
//import LoanNFTJson from "@//LoanNFT.json";
import LoanNFT from '@/LoanNFT.js';

export default {
  data() {
    return {
      web3: null,
      contract: null,
      account: null,
      loanForm: {
        borrower: "",
        principal: 0,
        interestRate: 0,
        term: 0,
        maturityDate: 0,
        offchainDataURL: "",
        offchainDataHash: ""
      },
      buyNFTForm: {
      loanId: 0,
      },
      destroyNFTForm: {
      loanId: 0,
      },
      issueLoanStatus: ""
    };
  },
  async mounted() {
    // Connect to Metamask
    if (window.ethereum) {
      window.web3 = new Web3(window.ethereum);
      this.web3 = window.web3;
      await window.ethereum.enable();
    } else {
      alert("Please install Metamask to use this app");
      return;
    }

    // Get user account
    const accounts = await this.web3.eth.getAccounts();
    this.account = accounts[0];

    // Load and create an instance of the smart contract
    const networkId = await this.web3.eth.net.getId();
    const networkData = LoanNFT.networks[networkId];

    if (!networkData) {
      alert("Smart contract is not deployed to the detected network");
      return;
    }

    const contractAddress = networkData.address;
    this.contract = new this.web3.eth.Contract(LoanNFT.abi, contractAddress);
  },
  methods: {
    async onIssueLoan() {
      try {
        this.issueLoanStatus = "Submitting transaction…";
        await this.contract.methods
          .issueLoan(
            this.loanForm.borrower,
            this.loanForm.principal,
            this.loanForm.interestRate,
            this.loanForm.term,
            this.loanForm.maturityDate,
            this.loanForm.offchainDataURL,
            this.loanForm.offchainDataHash
          )
          .send({ from: this.account });

        this.issueLoanStatus = "Loan issued successfully";
      } catch (error) {
        console.error(error);
        this.issueLoanStatus = "Transaction failed!";
      }
    },
    async onBuyNFT() {
    try {
      const couponAmount = await this.contract.methods.calculateCouponAmount(this.buyNFTForm.loanId).call();
      await this.contract.methods.buyNFT(this.buyNFTForm.loanId).send({ from: this.account, value: couponAmount });
      alert('Loan NFT bought successfully');
    } catch (error) {
      console.error(error);
      alert('Buying Loan NFT failed');
    }
  },
  async onDestroyNFT() {
    try {
      await this.contract.methods.destroyNFT(this.destroyNFTForm.loanId).send({ from: this.account });
      alert('Loan NFT destroyed successfully');
    } catch (error) {
      console.error(error);
      alert('Destroying Loan NFT faile');
    }
  },
},
};
</script>

<style scoped>
/* LoanNFTApp styles */
.loan-nft-app {
  max-width: 600px;
  margin: 0 auto;
  padding: 1rem;
  background-color: #f7f7f7;
  border-radius: 10px;
}

h1 {
  font-size: 1.5rem;
  text-align: center;
  margin-bottom: 1.5rem;
}

h2 {
  font-size: 1.25rem;
  margin-bottom: 1rem;
}

.loan-form {
  display: grid;
  gap: 1.5rem;
}

.field-group {
  display: flex;
  flex-direction: column;
}

label {
  margin-bottom: 0.5rem;
  padding-right: 15px;
}

input {
  height: 2rem;
  margin-bottom: 0.5rem;
  padding: 0.25rem;
  border: 1px solid #ccc;
  border-radius: 4px;
  font-size: 1rem;
}

button {
  background-color: #27ae60;
  color: white;
  border: none;
  padding: 0.5rem 1rem;
  border-radius: 4px;
  font-size: 1rem;
  cursor: pointer;
  transition: background-color 0.2s ease;
}

button:hover {
  background-color: #2ecc71;
}
</style>