Build a React.js Quiz App with Asp.Net Core API

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
quick demo of this tutorial here we will build a beautiful quiz application with react.js and asp.net core web api with latest material ui5 this project is built from scratch so that you could learn all about full stack web development with react.js and asp.net core web api apart from creating a beautiful material ui interface you could learn best practices in using context api form design routing authentication in small application like this etc so please watch till the end of this tutorial and build your own quiz application so first of all let's start with creating react app inside this project folder here for that we have to open command prompt from this folder directory so you can use the shortcut inside this folder path here just type cmd then hit enter so here we have open the command prompt from the same directory as that of this folder here now to create the react app we can execute this command npx create react app then name the application in small letters now before creating react or dotnet cover api make sure that inside the folder path directory here we don't have any special characters it might cause problems while running the application i had some similar experience in pass so make sure to avoid special characters inside the folder path directory here now let's execute this create react app command it might take a while so please be patient finally we have completed with the app creation command as a result of that here we have a folder with the same name as that of the react application now we have to get into this new folder quiz client now let's open the folder within vs code but that you can execute this code space then period or dot simple hit enter so here we have the brand new react application with default components now let's run this application for that open the terminal we can use this menu item here or you can use the shortcut ctrl shift then backtick then execute this command npm start it will compile and open this application in our default web browser so this is how the fresh react app looks like for designing this application i'll be using material ui components i have already created a material ui tutorial on this channel it was created with previous version of material ui soon i will be uploading a new version of the same the existing tutorial link is given in video description and inside the icard top right corner now let's look how to integrate material ui into our react application for that click on this get started button here first of all we have to install these libraries here so let's copy this command let's open a fresh terminal like this and paste it over here so here we are installing the core package of material ui these are two packages introduced in the latest version which is a styling engine in version 5. so here we have successfully installed the packages this documentation is recommending this roboto font so let's grab corresponding reference and let's paste that inside the index.html here let's paste it just about this head and tag here we also need material icons so let's copy this reference also and let's paste it over here now this index.html file has the html wrapping for the entire application inside this html we have this div with the id root this div is replaced within this index.js here which is the root javascript file for any react application you see the root div is replaced with the components passed here by default app component is shown inside the root div and here we have the app component and whatever we have here is responsible for the default view of the application here so first of all let me remove these default html from here and this logo reference also now let's quickly design a login form for this application first of all i will create a new folder here called components so that i will create this component login to create the component i will be using this snippet rfc react functional component in order to use this snippet first of all you have to install this extension this one here okay now click on this so here we have the corresponding component with the same name as that of this javascript file here login now let's show this component inside this app component here now while tapping the component you will see the suggestions and if you click on that corresponding import statement will be added at the top like this sometimes it may not work as you expected in that case you have to manually add the import statement up here okay now let's design a form for the login operation with name and email address for that first of all we'll be having an html form here to disable default html validation we can have this attribute now we need an input text box for that inside material ui you could see this component text field and components we need a text box that looks like this so we could do this text field i don't know why my auto suggestion is not working for material ui components so i will add the import statement here from material ui material we have to import text field first of all we have email so label will be email the name of the component now in order to look like this box here we have to set this variant property as outlined so here we have the text box inside that you could see the auto suggestion or the previous auto complete from previous posted data if you want to ignore previous posted data like this you could set this attribute auto complete as off like this we need one more text box for name now we need a submit button for that we have a component button you could see the same inside this menu here or you could also search inside this text box for that you can use the shortcut ctrl k so that you can easily find the component that you are searching for so let's search for button hit enter you could easily see the corresponding component document like this so here we have the button component while typing the component here you could see the auto suggestion if you can't like this just use the shortcut hold ctrl then press space then you could see the possible auto suggestion if you select the item corresponding import statement specified here will be added at the top so first of all type is equal to submit the variant will be our contained size will be large all of these properties and attributes are mentioned inside this documentation here inside the button we will show this start so this is how the login form looks like now let's fix everything in proper place but that first suppose we will wrap this form with this material ui component box it is similar to add div now in order to customize any material ui component you can use this property sx for that you can go to the uh corresponding api documentation for button here we have the corresponding link so here we have the available properties for the component and here you could see the sx it will accept these types of data and here this sx page tells how you can customize the component by passing an object like this okay so here we go s6 first of all we want to pass an object with that first so far we have to wrap everything with a pair of curly brackets like this since we have to pass an object we need another pair of curly brackets like this now here we are going to customize these input text boxes here now if you inspect these text boxes you could see that for any media ui component there will be a root css class like this you can use the corresponding class for customizing this specific component and the root css class for this text field component is mui form control hyphen root to see the same let's search for the corresponding api text field api inside this documentation at the end you could see the root css class as mui text field root so in order to customize text field you can make use of this class here now how this customization is done for that let me copy this css root class here you could see the same root class applied to this root outermost div for this component text field here the text field from mui displayed with an html div and the outermost div is having the root class specified inside this documentation here now in order to customize this text field we'll be using the same class like this so first of all i'm pasting the class here now this class is applied to a child component text field when considered to this box component here this is a child component for this box component here so in order to specify that we could do this now this and simple represent this box component itself now when you specify a class with a space in between them it means we are going to apply this css when this class comes as a chart right this is same in css also so this is how we do it whatever styles that we specify here will be applied to the children of this box having this class so first of all i want to specify a margin of the range 1. as per the sx abbreviation you can shorten this like m like this now you can see the margin is applied to this text field now in order to place these text field into multiple lines i will add this with attribute here 90 percentage see both of them are displayed on separate lines so this is how we are going to customize material ui components from now onwards now we need a separate line for this submit button also so i will add this sx attribute we want to apply these styles to this component itself so we can directly pass the style here with is equal to 90 percentage now i want to show this component inside a material ui component card so let's search for card here here we have various samples showing how you can make use of this component now let's quickly add the element inside this application here now with what we have explained now you can easily follow and understand the dli components that i'm going to use inside this application if you have any doubt you can go through this documentation here now let's quickly complete this design here first of all we need a card component the content of the card will be displayed inside this component card content so let's move this form into this code content now let's set the width to 400 pixel now before anything as i want to center this card component here for that i'm going to create a new component called center center.js and here we have the snippet to create the component now in order to center anything i'm going to make use of material ui component grid so here we have the component grid it is similar to the bootstrap 12 grid system first of all we have this component grid which is the container so we have to specify that with this attribute container and inside that we need same component grid marked as item so this is the container for the grid and this is similar to a column and the width of this column is specified with this attribute s6 and i will set it as to one column space now in order to align anything inside this grid at center we could do this direction is equal to column and then set align items and justify content as sender and finally we have to set the mean height so i will use this property sx mean height i will set it as 100bh now we just need to wrap everything inside this login component with this center component here whatever we have wrapped with this sender can be accessed with the props parameter here and it will be the inside this property props children let's check that here sorry we have a typo inside the center component i always makes this mistake instead of this equals simple we need a colon boom that's it now finally we need an h3 header for this login form here so i will add this typography component we need an h3 header so i will set this gradient as h3 and we need some vertical margin so i will do this margin on y axis of the range three inside that will show this quiz app now here we have everything we need we just need to align them properly but then i will add this our css style here text align as sender now there is one thing that i am recently concerned about which is dark themes these live themes cause a lot of eye strains compared to dark themes so i'm gonna quickly switch into dark theme with material ui so you can search for the documentation here we just need to customize the default theme so open this a root javascript file index.js if you want to stick with the light theme we can ignore these steps here so first of all we need a theme object and here we will call the material ui function create theme now we have to pass the object with our customization we just need to change the mode to dark so let me copy this object from here and let's paste that over here now we'll wrap this app component with this theme provider now here we just need to pass the theme that we have just created now finally in order to work this we need to add one more component the asus baseline boom that's it this is more healthy for your eyes in long term now here we have done with the design in a bit we are going to create dotnet cover bpi to store these email and name here before that i just want to validate the form here let me close all of the component except this login component now first for we want to manage the values of this text field inside the state of this component right but that we normally test this will be creating state object like this value then set value and then we'll be initializing it with use state function inside this we will be passing an object with the initial values instead of this i will be creating a separate folder called hooks inside that i will be creating this a hook component used for we have done this same multiple times in previous tutorials i will just paste that same here and let's explain it so here we have a component inside this hook we have two state objects values and errors inside these values state object we'll be saving the values from these text field here and the corresponding text field errors will be saved inside this object this rs object is initialized with the empty object and this values object will be initialized with an object returned from this function this function will be passed as a parameter to this hook we can see that in a bit and here we have the handle input change we don't have to rewrite that in all of the components where we have f4 and finally we will be returning everything that is required for the component with the phone so let me get rid of this now we could do this now we can call the use form hook here now this hook returns an object with these properties now we can restructure the same inside this component here now in order to initialize this state object values we have to pass this function get fresh model object so i'll create the function here get press model this is just a function to retain an object like this so here we go name and email address with the default values is passed now we just need to pass the same inside this hook here now we can assign values from this object to these text field here values dot email the name of the component and the property used inside this state object must be same that's how this hook is created you could see that inside this handle input change here okay i hope you don't need an explanation for this handle input change even method here most of you know how to handle this input change for these uh text fields here now we can provide the on change even function which is already defined inside the hook until input change okay that's it now let me copy this and pasting for name so here we have assigned value for this text field if you want to verify whether it is working properly or not i will add this submit event login so here is the function login with the default parameter e first of all we have to prevent the default behavior of the form which is reloading the form so prevent default now let's print the state object values now here we have the dev console let's enter some random values and submit the form boom that's it so the values from these input text fields are saving into our state object values now finally i want to implement validation inside these form controls that i will be creating a separate function validate first of all we'll be creating an object empty object like this then we'll be saving the errors related to email with this property email now in order to validate email addresses i'll be using this regular expression now we just need to call this test function into that we can pass the values from our state email if email is in proper format then it will return true so we don't have any error message otherwise we will say email is not valid now like this we have to have the uh name validation so values dot name is not equal to empty string then we don't have an error message else we will show this field is required finally we will set these validation error messages into this state object errors return from this scope here so set errors into that we can pass this temp object and finally from this function we need to return a boolean value indicating whether this form as a whole is valid or not for that all of these error messages here should be empty string right but that we can make use of this object method values inside that we can pass this temp object so actually this function returns an array of values inside this object here and on that return array we want to call this array method every inside this we want to check all of the values inside this object are empty string so if all of them are empty string this will retain true otherwise post so that indicate whether this form as a whole is valid or not so inside this submit event here we can call the function validate so this log statement works if the form as a whole is valid and finally if any of these text field is invalid we want to show them inside these corresponding text field here in order to do so in material ui first of all we have to set this up property error as true and the validation error message will be shown with this property helper text now we want to do this dynamically if this field is invalid for conditionally applying those properties first of all we wrap everything with a pair of curly brackets like this and then i will do the d structures index like this inside the state object errors if the value of the property email is empty or not if it is not empty we want to retain an object with corresponding properties like error set as true and then the helper text which is errors dot email if there is a validation or inside this property email this object will be returned from the statement and it will be restructured here and thereby the properties inside this object can be a part of this outer component here so this is how we dynamically apply properties in react components now let me copy this and pasting for name text field now let me save this and back to the application here let's check whether it is working or not let's try to submit the form here let's provide an invalid email pass some random name so validation is working for name now let's make this valid boom it's working properly fine now it's time to create an asp.net cover baby i project to save these informations from these fields and to process other queries related to quiz application for this project i am using visual studio 2022 and the latest.net conversion 6. now let's start with creating the dotnet codeweb api project i will select this template asp.net core web api name of the application quiz api select the location where you want to save this project so i am selecting this project folder where we have already created our react application as i mentioned already make sure to remove special characters from this folder path directory here so select the folder now let's create the project here i'm selecting the latest dotnet course 6 version i will uncheck this configuration for https since we are creating this application for development make sure to enable this open api support it is really helpful to test the api now let's create the project so here we have the brand new asp.net core web api project first of all let's start with db model and db creation using entity framework for that first of all we have to install corresponding npm packages so right click on this project here then manage and you get packages inside this browse tab search for entity framework let's download this our microsoft entity framework core now from this version drop down here select the same version as that of the framework here so six or two so selected the same version here now let's install the package accept the license now along with the package we need to install these two packages sql server and tools select the same version as that of the framework click on install entity framework code tools so here we have done with the installation of these three entity framework core packages now let's create model classes for the db so first of all i'll be creating the folder models so first of all we have question model first of all we have this primary key question id now the column corresponding to this property will be the primary key for this table so we have to mark this with this key attribute now we have to import the corresponding namespace for that you can use this uh shortcut hold ctrl then press period and select this namespace here data annotations then we have the actual question question in words then image name the name of the image required for illustrating this question will be saved inside this api and will be shown along with the question so the image name will be stored inside this column and the actual image will be stored inside the project directory here then we have the four options for this question finally the answer for this question which is the index of the option from these options here since image name is optional i want to make this property as nullable but that we just need to add this question mark as a suffix to this data type string here now if we leave these model string properties as it is when it is converted to the actual db the sequence server columns corresponding to these properties will be having the data type of nvac max which is more than what we need so in order to remove the data type we will specify the required data type here so first of all we have this attribute colon import the namespace here now with this type name we can specify the data type as invoke 250 so this is offset type 50 and work f50 sorry i made a mistake all of these options are off the type string so let me correct that here and all of them will take the type and work at 50. now like this let's create one more model for the participant first of all we have participant id then email name of the participant score time taken to complete the quiz let's mark this property as the primary key now let's specify the column type for the string properties so let me copy this let's add the corresponding namespace so that's all we need as model classes now let's create the db context quiz db context now we have to inherit this from the edit framework class db context now let's use the corresponding namespace entity framework core now we have to specify the constructor for this class and this constructor will have a parameter of the type tb context options of the type quiz db context as options and we want to pass the same parameter to the base constructor now we'll be creating the db and the tables corresponding to these model classes using migration in order to do so inside this db context class here we have to have a reference to those particular model classes here but that i will be creating properties of the type db set with those model classes now in order to use this quiz db context by the framework we have to inject this db context instance into the framework with that open this dot cs file in previous version dot net file we have been doing this in a file called startup.cs but in dot 96 we'll do the dependency injection inside program.cs now for the dependency injection we'll be using this builder instance here builder dot services dot add db context of the type with db context as an argument to this method we'll be passing a lambda expression with this options and here we have to provide the provider for this uh db meaning we are going to specify which database we are going to use for this application it will be sql server so we can call this method here use sql server now let's use the corresponding namespace now into this function we have to pass the connection stream so first of all let's save the connection string inside this app settings.json file here so here we go connection string and inside this i will save the connection string with this name dev connection and now for the sake of explanation let me paste the template for db connection string here so first of all we have to provide the sql server instance name in my case it is local sql express so here i'm using a sql express instance that is installed on my local machine and here we have to provide the adb name so quiz db so there will be adb created with this name quiz db for this connection we'll be using windows authentication so set this trusted connection as true and finally in order to execute multiple queries at a time we have set this property multiple active result sets as true now before going further first of all check whether this instance is already started or not for that first of all open your run a window for that you can use the shortcut windows logo key then r it will open up this run command here and then just type services.msc it will open a window containing all of the services installed on your system so let's search for the sql server instance here so here we have the sql server instance name sql express so you have to use the same name inside this uh portion here and make sure that this sql server service is already running inside your machine if not you can see a start option here now let me close this services here so here we have a proper connection string save this back to this dependency injection here now in order to retrieve the connection string saved inside this json file here we just need to do this builder configuration dot get connection string here we just need to provide the connection name that we have used here so it is dev connection so here we have done with the dependency injection now let's build this project after successful build we are going for migration which is the process of creating the actual physical db with these model classes provided here for that first of all select the project then go to choose then manage a new get packages then package manager console and make sure the same project that we have here quiz api is selected from this drop down now first of all we have to execute this command add migration i will name this migration as initial create it and during this process the actual sql server script will be created according to the model that we have inside this project which is saved inside this new folder migrations now in order to execute the sql script for creating the db we have to execute this command update database you could actually see the sql script inside this a package manager console window itself now once it is done let's check whether it is created or not for that i will open my management studio here now let's connect to the same server instance that we have specified in the connection string so here we successfully made a connection to the sql server instance now let's expand this databases note here boom that's it so here we have the new db with the name quiz db the name of this db is already mentioned inside this connection string here now let's check whether those tables are created as per our model clause so here we have those two tables participants and questions now make sure that these tables are created as per the model clauses that we have provided here the name of these tables questions and participant is taken from this db context property db set now i have prepared 10 questions for this quiz app so let's execute the query here for now i will paste in station query here i have given this sql script inside the github repository let's execute this so here we have installed those 10 questions let's check that inside this table here so here we have the 10 questions that i have prepared the actual question is here inside this column if there is an image for this question the corresponding image name will be saved inside this column here then four options and inside this answer column here the correct option index is saved inside this column for option one the index will be zero then one two three like that like the array index now enough with the db now let's add this image mouse.png inside this project directory here for that i'll be creating a new folder images now here is the image let me move this to the new folder here now it's time to create api controllers for these model classes with that first of all let's build this project after successful build right click on controllers then add controller from this left panel select api then api controller with actions using entity framework model clause will be question context is question db context question controller so here we have successfully created the api controller because of scaffolding mechanism required web methods are already added to this controller here now there is a common error while creating controllers with this scaffolding mechanism which is related to installing code generation design package so let's check that here right click on the project then go to manage and you get packages and let's search for the package here code generation design so here is the package it is already installed in this project if you have an error message related to code generation package if the packet is not installed here install the package with the same version as that of the asp.net core if it is installed and you have the same problem then uninstall the package and install it again okay so in most of the case that will solve the problem now back to this controller here now let's create one more controller for this model participant participant controller now that's also done now let's focus on this controller here for any created controller inside the controller constructor you could see a parameter of the tab with db context now from both the value for this context parameter is passed that's where dependency injection comes so whenever there is a constructor parameter of the type quiz db context the instance for that will be passed from this dependency injection here so that's how dependency injection works an instance of this controller is created whenever we make a request to these web methods here then the framework automatically create an instance of this controller since we have a constructor parameter of the type quiz db context the dependency injection will provide the db context and it is saved to this private parameter underscore context and inside these methods here we underscore context is used to feed or query the database that we have created at this moment we want to feed the participant email and name to this web api here for now let me collapse these methods here and for saving the participant details i will be using this post web method here so this existing post web api method will insert new participants but we want some customization here we will insert the corresponding participant details to the corresponding table but if the combination of name and email is already existing we won't insert it instead of creating a new participant we will be returning the existing participant details back to the client side so first of all i'll be creating a temporary object here now let's check whether we have a participant with given name and email address participant and we can call this verb method and here we have the lambda expression x such that x dot name is equal to participant name and let's compare the email also and finally we have to call this method post or default if there is no such participant we will do the insert operation like this here else we will assign the temporary participant to this participant variable and finally from this method we will return the object participant okay now let's run this application now by default the asp.net cover bp i will open an interface to interact with the api that we have created all of the web methods are here you can test them with these interface here we'll be testing some of the web api methods here now from this login form here we have to submit the email and name so back to the vs code here here we have the login form submit event now in order to make an api request from this react application to the web api method here we need to install the package axios so let's do that here i'll open new terminal and let's do this npm install axios now in order to handle api request i'm gonna create a separate folder api so that we will create this index.js first of all let's import the axios package here now let's create and export this constant base url inside that i will save this base address here so let me copy this okay that's it now i will paste this function here i have been using this pattern in almost all of my react tutorials before we have a function create api endpoint and which is exported from this index.js for this function we have an endpoint and here we have generated the complete url and from this function we have returned an object with functions required for all of the operations to retrieve all of your requests we have this fetch function to retrieve a specific record with a given id we have this function here in both of these case we are making a get request with the corresponding url and with this function we are inserting a new record and here we have the put method to update an existing record and this delete function delete an existing record so these methods get paused put delete methods are from axios and they will make again request these corresponding web api methods of the type post get etc you will understand this better as we go forward so inside this form submit event we have to make a post request to this controller web api method here for that we could do this first of all we recall the method that we have just created into this function we have to pass the end point for the url so the base url is already created base url with the api and we just need to append this up controller name here participant so that's the default route in an api controller which is already mentioned at the top here api forward slash name of the controller in this case participant is the controller name so api 4 slash participant now we just need to pass participant here in order to avoid typo here i will be creating a constant object here endpoints it's an object and here we will do this participant i will save the same inside this property and let's export this constant now we just need to do this endpoints participant now this will retain a collection of objects like this in order to make a post request we can call this function post into this function we just need to pass the object that we want to insert the url is already generated up above here so we'll pass this state object values which contains the p values here now we can handle the response inside this then function here so here we have we call back with the response for now let's print this response in developer console response if there is any error we can handle that inside this callback here now let's save this and back to the application now let's submit this form for creating a new participant now let's submit the form here we have an error so here is the problem there is a security feature in almost all web api project called cross origin resource sharing meaning this web api will block requests from another application which is hosted on a different domain or a different port number like this case here we have different port number so this will be i will block request from the port number 3000 here so first of all we have to enable course for this port number here back to the web api here and let's stop this execution now once again open this program.cs file now let's enable course we can make use of this method use course from this app object here and here we have the lambda expression with options options dot with origins inside that we have to pass the corresponding origin so let me copy paste that from this react application here make sure to remove the forward slash at the end and finally we have to call these two methods allow any method and allow any header now let's run this application without debugging now back to the react application let's clear these existing errors here let's submit this form again boom here we have the response from the post web api method and this property data is having the response that we have sent from this post pbi method here now let's check the participant table that's it so here we have the new participant john smith now in order to check whether it creates a duplicate participant let's reload this page and let's try to make the same participant again in order to make it easy i will enable this option for autocomplete so let's set this as on here save the application reload this time it's not working because previously the autocomplete was off in future the previously posted datas will be shown as an auto suggestion here now i will just copy the details from this table here submit the form we got the response with the same data from this participant id itself we could say there is no new participant the accessing participant must be returned see that's it so login is working perfectly fine now what else now from now on was the real game begins now we need a state management mechanism to store oppressive and share the data inside the application across various components inside the application in previous react applications we were using redex but for this application we'll be using context api so let's integrate context api into this react application here first of all let's create rest of the main components inside the application after login we'll be showing this component here question now here we have the final component for showing the result of this quiz program now let's look how to preserve the state of this application and how to share common data among these components for that i will be creating a new hook here use state context first of all we need a react component so here it is and let's name this as context provider now let's create a context object state context now we just need to call this function create context so the nice thing about this context api that everything is already the inside the react library itself now let's add the corresponding import statement so for this component here we have the default parameter props now we will be wrapping everything within this context provider but we need the data from the context api so whatever we have wrapped with this provider can be accessed with the children property here now from this component we are wrapping everything with the context provider like this state context dot provider and we'll be showing the children here now for this component we'll be creating a state object like this context and set context and let's call this function use state so inside this context object we'll be saving the data that we want to share across these components here now in order to initialize this context object i will be creating a separate function get fresh context from here we will return an object with properties that we want to save inside the context with their default values so first of all we have participant id initialized with 0 then time taken to complete the quiz selected options array so these are the data that we want to share globally across this application if you find anything additional you can add them here now let's call this function here now we'll pass this as a value to this context api here context and the corresponding set context function so the data of this context is saved inside this component state object context and it is shared across the children of the context provider here so here we have created and exported this context provider actually we don't want to export it as default so let me remove this from here now let's wrap everything within this context provider now let's open the index true javascript file context provider now this app component and its children components can access the data from this context provider here let's check how it is done so first of all we have to export this context object here now let's try to access the values from this context inside this question component here first of all we have to call this function use context inside that we can pass the state context object that we have created well let's add the corresponding import statement now this function will retain an object we can restructure the same here the return object will be similar to the object that we have passed here it will contain this context and set context so so while restructuring we can use the same property name so let me copy this and pasting here now this context object contains the values from context api and this set function can be used to update values inside the context here so it is exactly similar to handling a react component state object the only difference is that here we have a context provider and this provider uses to wrap every component inside the application and that's how this context is made available across the children components in order to update the values inside the context api we can do the same thing that we do with a component state object we will restructure whatever we have inside the context now if you want to update the time taken for this quiz program we can just update that property here so this is how context api works now we want to make these steps even more simple because here we have imported the use context function and the context api object and everything is restricted here in order to update the values we need another destructuring here so i would like to show you a best practice that you can reuse in your applications for that we'll be creating a hook here called use state context and let's export this same by default now inside we hope we will destructure everything inside the context api so let me copy paste this now from this hook we will be returning the d structure context and the corresponding set function now we don't need to import the state context object and this use context function here we just need to call the hook that we have just created use escape context now i want to even simplify this set context function here just to avoid this destructuring here for that i will redefine this set context function here so here we have the function for this function we expect a parameter object and this object contains the properties inside the context with the updated values okay now inside the function we'll be calling the original set context function inside that first therefore we will restructure the context object and then we will destroy the object parameter so the redefinition of the set context function is only though inside this return object inside the child component we don't have to restructure the context object again we just need to pass an object like this it will be restructured inside this redefine function here hope you will find this more efficient so this is how we are going to use context api inside the application let me remove these uh statements from here now let me remove this set context function invocation here now back to the login form let me try to login with the same details that we have provided previously so after successful login we have to save this a participant id inside our context api for that let's call this use state context hook that we have created here context and set context let's call the hook use state context now inside this success callback we just need to update the corresponding participant id so we'll call this function set context inside that we just need to pass an object with the updated participant id so the return data from the server can be accessed with this property data inside that we have this property participant id now if you want to check the values inside the contacts api let's print the same here context now let's try to login with the previous participant submit before so right here we have an error set context is not a function so let's start with the context provider itself we have created the state object context and it's set function and we have passed the same here this pair of curly brackets indicate that we have something from javascript since we have to pass this context object and this set function we have to pass them inside an object like this then only it will work as we expected okay so an object with the context object and its set function is passed to the context provider here let me save this and back to the application let's try to login with the previous participant let's check the console window here we have printed the values from the context api and it is showing the initial value itself not the updated participant id because this set context function is asynchronous immediately after invoking this function this function get executed since this function is an asynchronous function it is running in the background and this function will get executed even before updating the value here so if you want to see the context value i will do something else inside this render method we can print the context value participant id reload the app initially you could see that its value is zero now let's try to login with the same participant boom that's it the value of the participant id inside the context is getting updated now after this login operation here we want to show the quiz component where we are planning to show the questions from our db for that first of inside this application i'm going to rename this component as quiz component let's update the name here also now currently inside the default app component app.js we are showing the login component instead of that we need a simple routing configuration inside the application for that first of all we have to install this npm package react router dom so here we have successfully installed the package if you are new to react router don't worry this application is perfect for you to understand how react router works now let's get rid of this login component first of all we need to wrap everything with this component browser router and we have one more container routes now we can specify the routes for this application so first of all we have the default route for the login component for the default component path will be a forward slash with this element property we can specify the component that we want to show inside this route which is login now let me duplicate this forest of the two components quiz and result so here we will be showing the quiz component and here we have the result component sorry we forgot to import routes and route hope you know the shortcut for possible imports hold control then press space now let's do the same for this route reload the application so by default the login component will be navigated with this default route here okay now after the successful login we have to navigate inside this route four slash quiz in order to navigate into the quiz route first of all we have to call the use navigate hook so we could do this navigate is equal to use navigate now inside this successful callback we just need to call the function navigate with the corresponding route forward slash quiz before trying this let me print this participant id inside this quiz component here so we have already restructured the context now let's print the context value inside the dev console context that's it let's login with the previous participant boom so here we have successfully logged in inside the application and here we have the quiz component now here we have the current value from the context api now there is one thing that you must know about context api the values inside the context api will be lost once you reload the application like this here see the participant id is reset to its initial value so how can we preserve the context api value across the application now let's look why it is not working after the page reload and how we can fix the problem first of all we have saved the data inside this component react component state object context so data saved in any react component state object will be lost after the corresponding page reload and this context provider or context api only share the data that is provided here to its children components here so both of these state object and context api does nothing to preserve data across page reloads in order to fix this problem there is a storage facility in web browsers called local storage we can actually see the data saved in local storage through web browser dev tools i will show you that in a bit before that let's briefly discuss how we can make use of this local storage first of all in order to save a data we can make use of this method set item as a first argument we have to pass a key to uniquely identify the data that we have saved and as a second parameter we have to pass a json string corresponding to the data in order to retrieve the data we can make use of the method get item so it will return the data saved inside the key provided here finally in order to remove a data store in local storage we can call this method remove item so that's all you need to know to work with local storage so let's integrate local storage into this application so first for anything that we want to save inside this contact state object we will save that first inside this local storage here so you could do this local storage dot set item i will use this key context now here we have to pass the data in json string format so then we can make use of this method json stringify now let's pass this default data here we only need to initialize the local storage with this default object for the first time so first of all we will check whether we have an existing local storage for the context now with this method get item we can check what is the inside this key context we will only initialize the local storage if this context is not already occupied so we can check that by comparing it with null so basically this function is used to initialize the context object here so we have to return the actual data here so we will provide that from this local storage here and don't forget this the data store inside the local storage is in json string format so we have to convert that into an object with this method json pass so this method will detain existing data from local storage for initializing the state object after each time we reload the application now we have to do one more thing from various parts of the application we can modify this context with this function set context right so whenever that happens we have to make the same changes inside this context here also for that we can make use of this hook use effect as a first parameter we can have this callback function and this function will be invoked whenever there is a change inside the second parameter here so as a second parameter inside this array we will pass this state object context so whenever there is a change inside this context this callback function will be invoked during that time we will update the local storage the updated value will be the inside this context so we'll save the corresponding json string in local storage so throughout the application context api data is saved inside the local storage in real time as per context api configuration here the data or the default context must be saved inside the local storage in order to see the data saved in local storage you can go to this tab application so here we have the key and here we have the json string and you could see the corresponding json object here now participant id is zero now let's try to log in with the existing participant that's it participant id is updated to one and here we are inside the quiz route now enough with the context api or router or login form now let's go ahead with this quiz component which is the meat of this application so first of all inside this quiz component we have to fetch the questions that we have inside our db now using this question controller here we'll be picking random five questions using this get web method here api forward slash question so first of all we need a customized query here the first of all we're creating this variable random five questions and we have to do this through async operations so i will use the prefix avoid underscore context can be used to query the database and here we have the collection of questions now we will make this selection here apart from selecting columns as it is we want some customization here also so question id is equal to the actual question id itself then question in words image name now here is the difference we have four options and i want to return them as an array called options now in order to run them as an array of strings we could do this we'll be creating a separate array with those options so that's it we don't need to return the answer of this question that will be done later now here comes the random selection you can call this method order by and we are going to order this in a random order that we can make use of this class guide we can call this method new guide so the questions inside the table will be ordered in a random order and from that we will take post five questions now finally we have to convert this to a list now let's return the same here random five questions this project is already running without debug mode here now in order to reflect these new changes we just need to build this project so that go to build then build solution or you can use the shortcut ctrl shift b so project is successfully built now in order to check the proper working of this web api method you can use this swagger interface here so here we have the component question and we want to make a request to this web api method so click on try it out now click on execute boom that's it here we have the server response with the code 200 meaning response when successfully and here we can see the random five questions and the options is returned as we expected in an array now we have to make this same request from this component here and we want to do that after completely loading this component but that we can make use of this default hook use effect here we have the callback and as a second parameter we have to pass an empty array so the callback here will be executed once this component is fully loaded and here we have to make the get request now we can make use of this api function create api endpoint as a parameter to this function we have to pass the endpoint so i will save the corresponding here question so this will be concatenated with the base url and this api here now let's pass the same here and points dot question now here we have to make the get request so that we can make use of this function patch here we have the success and error callback now in order to store the random questions returned from the server i'm gonna create a state object questions let's initialize that with an empty array now once we receive the random questions from the server we can update that here response dot data let's print the same into developer console we wrote the application again now let's check the console tab that's it here we have the five random questions now let's look how to show these questions one at a time inside this quiz component here so first of all we'll make sure the questions are is populated with the server response we'll be showing the questions if the length of the array is not equal to zero else we'll be returning null here now for displaying the question i'll be using the material ui component card inside that we have to show the card content here we have the typography component for showing the question in words variant is equal to h6 so it is similar to nh6 header now here we have to show this property question inwards before that we need another variable to represent the current question that we are dealing with inside this response we have five questions in order to identify which question we are currently showing inside the component we need an index to keep track of the current question for that i will be creating a state object question index let's initialize that with zero now we could do this questions and let's pass the index here now here we have to show the property question in words back to the application reload this page that's it here we have the question now we can list options of this question for that i'm going to use material ui component list to learn more about this component you can go through the documentation here so here we have the outer component list now for each option we have we'll be showing this component list item but we have four options i will render them with the map function here so here we have the corresponding question inside that we have an array options now we can call the map function this callback has two parameters first for the item itself and then the index inside the callback we will return this list item button first of all i want to disable the ripple effect so we'll set this property disable ripple since we are rendering this component in a loop we have to set this key property with a unique value i will be passing the index here now here we have to show the option i will show that inside a div html div and the option is the inside the parameter item now let's check that here boom that's it so here we have four options now along with these options i want to show the alphabets a b c and d so i will do that with the unicode first of all i will call this method string method from code now here we have to pass the unicode of capital letter a which is 65 so this function will convert unicode 65 into capital letter a now for second option we need b as a prefix then see so the unicode letter must increment on each iteration here with that i will add the index so it will work as we expect now let's concat a column here now i want to make this prefix in bold so i will be using this b tag here now let's style this card component first of all i will set the width to some fixed value now in order to send them horizontally i will set the horizontal margin mx as auto now we need some top margins so we can do this margin top of the range five now let's show some heading for this card here that we can make use of this component card header here we have the property title and this will be shown inside the header here i want to show question x of five so here we go question let's concat the question number here let's save this back to the application so here we have the card header each time we reload this page here we will get different questions because we are randomly selecting the five questions now along with this title here i want to show a timer but that first of all we're creating a state object time taken let's initialize that with zero now in order to start the timer i will be creating a separate function start timer now we can call this javascript function set interval so as a first parameter we'll be having this callback function and then as a second parameter here we have to pass the uh time in milliseconds thousand millisecond here similar to one second so after each one second this callback function will be invoked and this is where we are incrementing this time taken property it is actually representing the seconds elapsed so we could do this set time taken we just need to increment the time taken like this but there is a problem with this approach here this set function for state object is an asynchronous function and it is getting invoked after each seconds if we try to increment this property on each seconds the previous increment operation might not be completed before the next increment so instead of this it would be better to use the callback function inside the set function like this so here we have the parameter previous value and we will increment the previous value with 1. so this callback parameter previous represent the previous value and i think this will wait for the previous set operation to complete so after each second this time taken property is getting incremented second by second now let's start this timer as soon as we got the question from the server so i will do that here now we need to do one more thing whenever we create or configure a set interval operation here we need to suspend this operation when we done with the counter for that i will be creating a variable called timer the set interval function returns a reference to the created timer and that can be assigned here now as i mentioned before this use effect with this ra empty array as a second parameter is represent component did mount event meaning this callback function is getting invoked once the component is completely loaded now if we return a function here like this this function will get invoked whenever we leave this component for example navigating to next component result or reloading the application etc so this is the perfect place to suspend the timer that we have created for that we can call this function clear interval inside that we just need to pass the timer reference so inside this property we have the seconds taken by the participant now we want to show that inside this card header i will show that with this property action within this typography component instead of showing the time taken in seconds we have to format them in proper time format for that i'm going to create a separate folder called helper inside that let's create this index.js and here i will paste the function for converting into proper time format so this represent the minutes and this represent the seconds in between them we have a colon now let's call this function inside the component here now let's check how it works so it is working as we expected now i want to align this time off with this title here for that we have to add some custom css so let's inspect this element here we can make use of this class mui card header action so let's copy it back to the component here we already have some custom css so let's add the corresponding styles here and represent this outer component that that we have this class representing the typography here now in order to center that element we can do this first so far we'll set the margin as zero now let's set this align self as sender so that's done here we have another problem i think we have misspelled this property basically it was just trying to disable this effect here this ripple effect you know what just don't bother let's remove the property here now in order to separate this card header from this card content here i'm gonna use this material ui component progress we'll be showing a progress bar like this indicating how much questions attended by the participant that in between this card header and this card content first of all we need a box which is similar to the div in plain html now let me copy this component from here now here we have to provide the value in percentage so i will do this first of all we need the question number so question index plus 1 divided by 5 resulting value indicate how much fractions of the total question is completed in order to convert this into percentage we will multiply this numerator with 100 boom that's it now when users select an option from here we want to show the next question right and we want to save the selected option along with the corresponding question id and that's all we need for the final score calculation so first of all let's add a click event to the list item here so here we have the on click event to this event function we have to pass few parameters so i will call the function inside another arrow function here update answer first of all we have to pass the question id so let me copy this and pasting here question id and then the index of the option it's the inside this parameter idx now let's define this function up above we have two parameters question id and option index first of all let's update the selected option with the corresponding question id we can save that inside this array context apira selected options first of all let's do structure what we have inside the context the context object and corresponding set function set context now we can call the hook use state context so inside this context object we have the array selected options into that we can just push an object with the question id and the selected option index so question id is equal to question id parameter we can simplify the syntax like this and then we have the selected index so i will pass the option index here now there is a problem for doing this because this state object is immutable we can't directly update the state object context here it's immutable so instead of doing this first therefore i will copy the array here let's destructure the array and this is how we copy an existing array now let's call this push method from this copied array now finally we can update these context with this function set context into this function we just need to pass an object with updated property value so selected options array must be updated with these new values now along with this we have to increment this question id here that we could do this set question index let's increment it to the next index now inside the context api we have to update the time taken for this quiz program and we will update this property time taken after completing five questions so i'm gonna have this if dog here if question index is less than 4 we will do these operations else here we have the last question so we don't have to increment the index along with these options we have to update the um time taken for this quiz program so time taken is equal to we will pass this state property here time taken we can even simplify that like this so this else blog will be executed for the last question so after the fifth question we have to navigate result component sorry i misspelled this if keyword here before getting into the result component we have to do few more things inside this quiz component here now let's check whether it is working as expected let's see the logger storage side by side now select an answer for this question boom so the question is changed and also the selected option index and the corresponding question id is inserted to the local storage so it's working properly fine now let's complete five questions five options selected by the participant and the time taken for the quiz program is updated inside the local storage of the contacts api so navigation through those questions is working perfectly fine here we have forgot to something for this question we have an image of a mouse we want to show that just about this question and below this card header here so let's do that before moving forward we want to show the image in between the header and the content and we will show the image only when there is an image named property for the question so we can do this image name is not equal to null then we will show the image here else null for showing the image we can make use of this component card media the corresponding html component will be img now with this property image we have to pass the image url so inside this api file here we have the base url right and we have exported the same here now we can make use of that here base url and inside the api we have a folder called uh images inside that we have this image with the name given here now let me save this and back to the application let's reload this page again and again until we find the question sorry image is already showing for questions without image so here so here we have to change the condition to not equal to null let's reload it until we find the question for the mouse so here it is you see it's not working as we expected actually the image is there inside the folder images with the same name that we have saved inside the db in order to solve this problem first of all we have to enable static files for this api here for that we can go to this program.css here now just below this course configuration from the app object call this function use static files now into this method we have to provide the directory where we have saved the static parts so we could do this static file options file provider is equal to new physical file provider let's add the corresponding namespace now inside this we have to pass the directory where we have saved the images so path dot combine method can be called now we can make use of this object builder environment dot content root path will give the path up to this our project directory here into that we just need to append this images which is the name of this folder here now as a second parameter we have to pass this request path so this is the route that we want to use for accessing static files inside the older images here now let's build this project now let's try it again let's try it until we find the question for mouse boom here we go now actually here we have to apply some custom css to place the image properly before that i want to show you the current state of the context api or local storage see here we have lot of questions as a result of reloading this quiz component here so let's fix that first we just need to reset the context api inside this component did mount event here set context let's pass the object with updated values so first of all we have time taken property let's assign it with 0 and then the array selected options so this will do the job now i want to do this similar full reset operation of the context api inside this login component here because we can navigate back to the login component like this in these cases also things might mess up so let's do the full reset inside this logging component also so first of all let's import use effect we can make use of this snippet use effect snippet we just need an empty array and here we can reset the context api and local storage now this same operation can be reused in other components for example if you want to log out from this application this reset operation might be helpful so i'm gonna define the function inside the return object inside this hook here along with the set context i'm gonna define a function reset context and this function will be only available if we restructure the property reset context right okay first of all let's remove the context from local storage now let's reset the state object context we just need to call this function get fresh context now inside this login component we can restructure this property here and let's call this same inside this user effect here from both of these components login and quiz will reset local storage or contact api properties to keep the integrity of data saved from the application now back to the mouse image here so here we have the custom css to properly align the image first of all i will set the width to auto now in order to align the image horizontally in center i will set top and bottom margin 10 pixel horizontally i will set the margin as auto so it is working perfectly fine now before moving to the result component we want to show a top now bar here and inside that number we'll be having a logout button to quit from this quiz application and this now bar must be available inside this result component also how can we do that for that i will create a new component layout.js for the top now but you can make use of this material ui component app bar so first of all i will add the component here app bar i will set the position as sticky now inside this we need this component toolbar let's import this app by component also for this toolbar let's set the width same as that of the card so width is equal to 640 pixel and let's set the margin as auto so that it will align horizontally in center now let's show a heading with the app name quiz app variant is h4 so here we have the title quiz app now in order to show this app bar for both of these components this should act as a parent control right or a layout for these components here that we can easily accomplish with the router so here we have the router configuration inside the app component now let's wrap these two components quiz and result with the route layout component path is set as for slash element is equal to layout component so here we have the corresponding close tag now if you navigate into those two components you could see the app bar see but the actual html from the component is not shown to fix this we can do this just add this stack outlet so whatever we have inside the targeted component according to the current route will be shown in place of this outlet here now this component render method does not allow two outer components so let's enclose them with react fragment like this so here we go you know what when we use react material ui components it's better to enclose everything with this container component so let's do that here now inside this app bar let me show a lockout button here we have the click event logout let's define the same function here during logout operation we just need to clear everything from the contacts api and we want to navigate into the login form right so first of all i will use the hook for the state context we just need to import this uh reset context method use state context now for navigating back to the login form let's create this navigate object first of all let's reset the context navigate back to the login form so here we have the button before trying this out let's align it properly that we just need this custom thesis plex grow is equal to one so this heading will take all of the free space and thereby this logout button will push to the right side now let's check whether it is working or not that's it now let's check the local storage so the reset operation is working as we expected now let's login into the application again now before moving to the result page i want to make one more change here inside this application here by default in react material ui the default font is roboto instead of that i really like this font from this material ui documentation here if you inspect that you could see it's called ibm flex sense so let's grab the same from google fonts so here it is now we'll select these phone weights 300 400 500 and 700. now let's copy this link from here and let's replace the same inside the index.html here so let's replace the link like this now let's change the same inside this global css here index.css i will set this phone as the first option back to the application let's check it is working or not no it's not working if you inspect here still it is using the font row button so this is by default inside the react material ui in order to override this rule we just need to customize the theme like we have done inside the index.js here so here we go typography and let's reset the default family with this font save this back to the application reload this that's it we can skip this step if you are fine with the default font okay now after these five questions let's navigate into the result component here we have the else part and this is where we have to navigate into the result component first of all let's create the navigate object so here we go navigate over slash result let's check that here boom that's it so this is the final component inside the application hope you are happy with the progress that we have made inside this component we have to show the score of this quiz program along with the correct answers so first of all we'll be making a post request to the web api with the question ids and from the web api we have to return the questions along with the correct answers for that inside this question controller here i will customize this post web api method here so into this web api method will be passing an array of integers so i will name this parameter as question ids let's rename this method as retrieve answers and also i want to change the route for this web method here so let's use this attribute route get answers so in order to make a request to this web api method here the corresponding uri will be like this api forward slash question then get answers now let me get rid of everything inside the web api here we'll be retrieving answers into this variable answers here and we'll be returning the same at the end now how can we retrieve the questions for the given ids here so first of all here we have the avoid keyword now we could do this context dot questions contain the collection of questions inside the db now let's filter the records based on the question id x such that we will select the question if the id of this question is present inside the array but that we can make use of this array method contain and let's pass the question id here so that will return the questions that we are looking for now let's select the column properties as we have done before so let me copy this from the get method we already use this x here for this lambda expression here just to avoid the confusion i will rename this parameter as y now along with these properties we need the answer also so answer is equal to y dot answer okay finally let's convert this to a list so we can call this function to list async so here we have selected the questions with the ids inside this array here and here we have selected the properties as we have done before including the answer now let's build this project let's make the post request directly from this result component here we have to make the post request once the component is completely loaded so let's use this user effect hook before making the request first of all we have to create the array of question ids for passing to this uh parameter here so here we go let's import the context context dot selected options contain the question id and selected options we only need the question id so we can call this array method map now here we will just return the question id inside this quiz component we have saved the question id here and the same is written with this map method here now let's make the api request so here we have the api function create api endpoint let's call that here we already have an endpoint for question but this time it's different i will create new property get answers so question over slash get answers now let's pass the same here endpoints dot get answers let's call this method post the data that we want to post can be passed to this function here so here is the collection of ids now here we have the callback function for both success and error inside the successor response for now let's print the data retrieved from the server so response dot data contains the data that we have returned from the api reload and let's check the dev console surprisingly we got eight answers instead of five so there is some bug let me check that and i will be back in a minute finally i found the reason we had a typo inside this quiz component here instead of this we have to provide selected options save this reload this now let's select answers randomly now let's check the dev console to see the return response from the server api boom so here we have the five questions that we have just attended and the proper answers now we have to merge this array with the array that we have saved inside our local storage or the context api here so that we have the selected options index that we have chosen during the quiz program once we merge these two arrays we can calculate the score out of five so first of all we'll create a property score and here we have the array to store the merged result now let's do the merging inside this callback here actually we are going to merge the answers and questions received from the response into the selected options are inside the contacts here and thereby we can preserve the order of questions that we have just attended so here we go context dot selected options contains those attended questions with the selected option index now from this array we want to call this map method let me split this into multiple lines each of the item inside the array is represented with x now from this map method we are returning an object by combining the properties from both of the arrays first of all let's destructure the properties from this array now here we have to find the question from the response for the current question id so inside this response data we have the collection or array of questions from that we can call this method find and here we have the condition y dot question id is equal to x dot question id so this will return the question for the current question id here now we want to merge the properties from this record let's simplify this index here we don't need this return keyword let's wrap this object with a pair of parentheses like this so inside this array we have merged both the answer and the selected options now we can easily find this code so first of all i will update this array to this question answer object here now i will define a separate function to calculate this core this function accept the array of question answers and let's calculate the score inside this function now let me call the function here for calculating this call i will be using the array method reduce we have already discussed this javascript array method in great depth in one of my javascript tutorial i have given the link in video description and inside the i card top right corner you can watch that if you find reduce method a little difficult to understand so here we have the callback function with accumulator and current value in order to initialize this accumulator i will pass 0 here now here we can do this we will compare the correct answer with the selected option so if they match each other we will return the incremented accumulator else the existing accumulator will be returned so in brief this reduce method will iterate through each of your codes inside this array here and these two properties answer and selected will be compared if they match each other this accumulator get incremented initially the accumulator will be having zero and based on the condition here from each iteration the accumulator get incremented and finally this reduced returns number of questions will be have answered correctly so i will save that into this temp variable here now let's update this cop property now i'll be showing this code inside the component using material ui card component so here we have the card documentation and for showing the score i have copied this card ui controls here i don't want to extend this uh tutorial further more so here's my customized card content will be shown on the first half and then we will be having an image and this image is already saved or copied into this public folder here so this is the image that i have copied and i'll be showing along with the card result here okay so this is how it looks like now we want to show this score here now first of all we will show this text or heading congratulations and then here we have the title saying your score and here we have shown the uh score within this typography score will be the inside the state object score so that's what i have shown inside this typography so this will be similar to a span component in html so we got this code out of pipe now finally we have to show the time taken for this quiz program that i will be adding a new typography component here like this here we have called the helper method get format into that we have passed the time taken from the context api so here it is something went wrong let's check that sorry here we have made a major mistake instead of this curly brackets we have to use square brackets so here it is now just beneath this core we need two buttons for submitting this code to the api and one button to restart this quiz program so i will add those two buttons just below this time taken heading so here we have the button for submitting this code that we have received and here we have the button to restart the program now let's implement the click event for this retry button with this function restart first of all we want to reset the context api data like we have done inside this quiz component did mount here so let me copy this and pasting here now we want to navigate into this quiz component here so first of all we need a navigator object so let me copy this and pasting here let's import this hook now we could do this navigate over slash quiz let's try the button here boom that's it let's implement the click event for this submit button here so during the submission we have to update the current participant score and the time taken for this quiz program so let's create an update web method inside this participant controller here so here we have the put web api method now into this web api method we will be passing only these properties question id score and time taken rest of the properties like email name is not saved inside the uh contacts api so it's not possible to pass them and it's not necessary to pass them here so i will be creating a separate class to receive the data from the client side so here's the class participant result with these properties participant id score and time taken now this model will be used for receiving the data inside this method here so participant result i'll rename this parameter as underscore participant result now we will compare the id that we have passed with the id inside this object underscore participant result so the value inside this id parameter it will be passed along with the uri and the id inside this model property must be matched if not a bad request will be written now we have to find the participant record with the given id here so first of all we can call this point function from the participant db set property so this will find the participant record with the given id here now we have to update the participant score and the time taken for the quiz program like this and here we have said this participant stayed as modified and with this save changes method here it will update the new values provided here rest of the value will be as it is since we have retrieved with the find method here only these two properties are getting updated now here we have the catch block to handle concurrency exception and finally everything when successful we won't return anything now in order to reflect these new changes let's build this project again after successful build back to the react application here let's add a click event to this submit button here now let's define this function in order to make the put request we can make use of the api function here let's import into the function we have to pass the corresponding endpoint which is already the in order to make the put request to the web api method we have to make the request to this url api for slash participant then the id so we could do this endpoints dot participant now to make the put request there is a function called put inside this function here to this function we have to pass the id and the object with the updated values so here we have the participant id now we have to pass the object with updated values along with the participant id then score then time taken for this quiz program now here we have the callback for success and error response now inside this success callback here i just want to print the response to check whether this update operation when successful or not reload this submit this call boom that's it we got the response with the status 2 note 4 no content meaning update operation when successful now after this successful operation i just want to show a notification saying uh operation when successful for that we can make use of this material ui component alert so here we have the alert component inside that we will show this submitted successfully and for customizing this component i will add this sx property like this now if you check the component you could always see this alert component here we only want to show this after this successful submit operation here for that i'm gonna create a new state property show alert and let's initialize that with the boolean value false now after the successful submit operation i will set the corresponding property here we only want to show the alert for few seconds so we can do this we can call this function set timeout this callback will be called after three or four seconds so we can pass the seconds in milliseconds here inside this will reset this property here now based on this state property we need to set the visibility of this alert component here so we'll update this visibility property based on the value like this okay so if this property is true we will set the visibility as visible otherwise hidden initially the alert component is hidden now let's try to submit this code again boom that's it now finally we need to show the questions with the correct answers before that i want to highlight this score here for that inside this result component i will be importing this color green from material ui colors now let's pass the same inside this score typography here we could do this color is equal to green with this shade 500 that's it now let's show the questions with the correct answers for that i'm going to create a new component answer now i will show this answer component inside this result component here answer into this component we need to pass the merged question answer array that i will be using this property question answers i can pass the state object question answers here now let's wrap everything inside this uh component with the react fragment now let's restructure the array that we have passed inside this answer component here so here it is now for displaying question answers i'll be using the material ui component accordion it's a really useful component and it's perfectly appropriate inside this quiz application for showing the correct answers the integration of this component is pretty simple you can go through this documentation here so first of all i will wrap everything with this box component with some custom thesis now we will map through this question answer array like this okay for each question we have we'll be showing an accordion component here for this accordion component there is two parts first of all the header part which is the summary and the content inside this documentation this is the header part or summary and here we have the accordion details so inside this summary we'll be showing the question in words property inside this typography title here now inside this according details we'll be showing the image if there is an image for this question we have already discussed these components already in previous quiz components so i'm not going to explain them you already know it now here we have to show the options of this question like we have done in the previous quiz component like this exactly like we have done in previous component now let's save this and back to the application here boom that's it so here we have the accordion now inside this accordion i only want to open one accordion at a time to do so we need a state object here called expanded now inside this property will be saving the currently opened according index so first of all we have to handle this on change event so here we have the function handle change into that we'll pass this according index so here's the function handle change for this function we have the single parameter panel which is actually the index of the accordion now inside this function this nested function will be invoked it has two default parameters for this unchanged event first for the event itself and here we have the property indicating whether this according component is already opened or not now inside this function we just need to set this expanded property here so if it is already expanded that means if we click on an accordion it will get open and this handle even change will be invoked so this is expanded property will be true in that case the current accordion index will be saved to this state property here otherwise false now based on this property we can conditionally apply whether this accordion is opened or not so that we can do this here we have the expanded property of the component accordion if the id inside this expanded state property is equal to the current index j this property will set as true and thereby this accordion will be opened now if we go back to the component here now this time you can only open one accordion at a time see now we need an expanded icon like this here you can search for icons inside the material ui like this icons page or documentation is here now if you go to this link here you can see all of the material ui icons you can select the icon then copy this import statement here for this accordion here i have imported this icon here expanded circle down icon now we can pass this icon to this component according summary like this sorry i forgot to mention this before using middle u icons we have to install this package here let's open a terminal let's execute the command here installation of the package will take some time so please be patient after all let's reload the application now i want to show these icons in green and red color based on whether the participant answered the question correctly or not for that i will be adding this sx property here and here we can set the color property if the selected option index is similar to the answer we store this green color otherwise we will show the red color now make sure to import these two colors green and red here boom that's it i want to show this icon detail here in gray color for that along with these two colors green and red let's import gray and let's set the color for this details component here now inside these options i want to mark the correct answer in green color and the wrong option in red color that can be done for this typography component here recall this function mark correct or not into this function will be passing the question object and this option index and this function will be returning an object and that return object will be restructured here now let's define this function mark correct or not so here we have the function with those two passed parameters question answer object and the option index now here we have the if close first of all i'll be creating an array with those two indices so here we have the correct option answer index and here we have the selected option index we only want to mark the option current option as correct or not if the index is either the selected index here or the correct answer index so we can call the array method includes with the current option index now inside this if clause will be returning an object with the sx property that's what we used to customize material ui components and we will set this property with this object containing this property color inside that we will conditionally apply the colors if the current option is the correct answer then we will return the green color otherwise we will return the red color now let me save this and back to the application boom that's it which of the following is not operating system correct answer is css and the selected option is unix which is wrong answer and here we have the question that participant answered correctly now finally there is one more small topic to be discussed let's log out from this application i want to make these two routes which are quizzed out and result drought as protected meaning without logging into this application if user or the participant directly under the quiz component url here we have to prevent the user from accessing this quiz component without the actual login operation this time the actual participant id will be zero so everything will mess up at the end of the result so let's look how to make these two routes as protected it's very simple we just need to create a component like this authenticate now we just need to wrap these two routes result and quiz with the newly created component authenticate so here is the route and we need to set the element as the new component authenticate now here we have the corresponding close tag now back to the component authenticate now in order to check whether a user is authenticated or not we can make use of the context api property participant id so first of all i will destructure the context here now we just need to do this context dot participant id can be compared with 0. if it is equal to 0 we could say the participant is not logged in in that case we have to redirect the user to the login component but that we can make use of this navigate component from router now with this two property we can specify the targeted route where we want to redirect the unauthenticated participants so it will be the default route which is login form and here we have the else part meaning there is a participant id inside the context in that case everything should happen as per the route that we can just return this outlet component like this sorry here we have a typo let's save this back to the application currently we are not authenticated or logged in now let's try to access this quiz route here that's it the context participant id is zero and thereby we redirected to the login component now let's try after login operation it's working perfectly fine that's it guys hope you found this tutorial helpful you can download or clone this project from the github repository link given in video description for more react and donor core api tutorials like this please consider subscribing to this channel called affection if you haven't yet please like and share this video with your friends and colleagues so that they can also benefit from this see you in next video
Info
Channel: CodAffection
Views: 24,901
Rating: undefined out of 5
Keywords: react quiz app, react projects, .net core web api, react game, react project for beginners, react and asp.net core api, react quiz app with timer, asp.net core web api quiz, material ui quiz app, real world project with react material ui, quiz app, build sample project with react.js and asp.net core, latest material ui, material ui v5
Id: rgrvOtCPS6Y
Channel Id: undefined
Length: 109min 14sec (6554 seconds)
Published: Mon Jun 06 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.