In the Find Job section, users can create a proposal for the job they want to apply for. We will use and detail the use of function createProposal or updateProposal
Good to Know
In this example, we will use reactJS, Ether.js and formik to handle the form on the frontend. You will find a full code example with all imports at the end of tutorial.
// The interface for the inupt field of your forminterfaceIFormValues { about:string; rateToken:string; rateAmount:number; expirationDate:number; videoUrl:string;}// As we using Formik we use the validationSchema to check all the input value.constvalidationSchema=Yup.object({ about:Yup.string().required('Please provide a description of your service'), rateToken:Yup.string().required('Please select a payment token'), rateAmount:Yup.string().required('Please provide an amount for your service'), expirationDate:Yup.number().integer().required('Please provide an expiration date'),});
Let's create our form
// We set up our input field to get the data to create our IPFS CIDreturn ( <FormikinitialValues={initialValues} onSubmit={onSubmit} validationSchema={validationSchema}> {({ isSubmitting }) => ( <Form> <h2className='mb-2 text-gray-900 font-bold'>For the job:</h2> <ServiceItemservice={service} /> <h2className=' mt-8 mb-2 text-gray-900 font-bold'>Describe your proposal in details:</h2> <divclassName='grid grid-cols-1 gap-6 border border-gray-200 rounded-md p-8'> <labelclassName='block'> <spanclassName='text-gray-700'>about</span> <Fieldas='textarea'id='about'rows={8}name='about' className='mt-1 mb-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50'
placeholder='' /> <spanclassName='text-red-500'> <ErrorMessagename='about' /> </span> </label> .................... .................... /* Formik will catch the submit button and trigger the onSubmit function in the next section */ <SubmitButtonisSubmitting={isSubmitting} label='Post' /> );
② Handle Submit and Post the proposal
On submit, we create a new transaction and call the createProposal or the updateProposal for that we will need our contract instance and all the parameter including the CID (data stored on IPFS)
constonSubmit=async ( values:IFormValues, { setSubmitting, resetForm, }: { setSubmitting: (isSubmitting:boolean) =>void; resetForm: () =>void }, ) => {/*............................. we proceed to different check and date formatting .............................*//* as we using the defender API to manage platform signature we need to get it as it's a parameter of the createProposal function */constsignature=awaitgetProposalSignature({ profileId:Number(user.id), cid, serviceId:Number(service.id), });// We need to create the CID to post some data off-chainconstcid=awaitpostToIPFS(JSON.stringify({ about:values.about, video_url:values.videoUrl, }), );// We need the contract instance to call the functionconstcontract=newethers.Contract(config.contracts.serviceRegistry,// contract addressServiceRegistry.abi,// the contract ABI signer,// the signer );/* If a proposal existingProposal exist we call updateProposal otherwise we call createProposal */consttx= existingProposal?awaitcontract.updateProposal(user.id,service.id,values.rateToken, parsedRateAmountString, cid, convertExpirationDateString, ):awaitcontract.createProposal(user.id,service.id,values.rateToken, parsedRateAmountString,process.env.NEXT_PUBLIC_PLATFORM_ID, cid, convertExpirationDateString, signature, );
③ Get the Proposal by User With Subgraph API
Here is an example of a Graph Query you can use to get the proposal by user
exportconstgetAllProposalsByUser = (id: string): Promise<any> => { const query = ` { proposals(where: {seller: "${id}", status: "Pending"}) { id rateAmount rateToken { address decimals name symbol } status cid createdAt seller { id handle } service { id cid createdAt buyer { id handle } } description { id about expectedHours startDate video_url } expirationDate } } `; return processRequest(query);};gra