# NodeJS -------------------------------------------------------------------------------- title: "Introduction" description: "Build a React task manager app to create and manage tasks. You can perform CRUD and filter functionality on tasks." last_updated: "2026-03-18T07:41:08.688Z" source: "https://docs.catalyst.zoho.com/en/tutorials/task-manager/nodejs/introduction/" service: "All Services" related: - Project Directory Structure (/en/cli/v1/project-directory-structure/introduction/) - NoSQL Table Keys (/en/cloud-scale/help/nosql/components/#table-keys) - NoSQL SDK (/en/sdk/nodejs/v2/cloud-scale/nosql/get-component-instance/) - NoSQL API (/en/api/code-reference/cloud-scale/nosql/insert-item/#InsertNewItem) -------------------------------------------------------------------------------- # Task Manager App ### Introduction This tutorial will help you build a React web application called **Task Manager**. The application will allow you to perform the following functionalities: * Create a task * Assign statuses to each task you create * Filter tasks * Update the created tasks * Delete tasks when they are no longer required The client side of the application will look like this: <br /> The logic of this application is coded employing the following Catalyst services and its respective components: 1. {{%link href="/en/serverless/" %}}Catalyst Serverless{{%/link%}}: * {{%link href="/en/serverless/help/functions/advanced-io/" %}}Advanced IO Function{{%/link%}}: To code the backend logic of the application in the Node.js environment. 2. {{%link href="/en/cloud-scale/" %}}Catalyst CloudScale{{%/link%}}: * {{%link href="/en/cloud-scale/help/nosql/introduction/" %}}NoSQL{{%/link%}}: To store unstructured or semi-structured data where the data is passed as JSON or JSON arrays. * {{%link href="/en/cloud-scale/help/web-client-hosting/introduction/" %}}Web Client Hosting{{%/link%}}: To host the front-end of the application as a React web app. You will use the {{%link href="https://console.catalyst.zoho.com/" %}}Catalyst web console{{%/link%}} and the {{%link href="/en/cli/v1/cli-command-reference/" %}}Catalyst Command Line Interface{{%/link%}} (CLI) to build the application. {{%note%}}{{%bold%}}Note:{{%/bold%}} You will be given the code for the files to be included in the function and client components in this tutorial. You need to copy the provided code and paste it into the appropriate files as directed.{{%/note%}} ### Featured Concepts Before we dive into the application, it is important you comprehend the following NoSQL table keys: * **Partition Key**: This key is a mandatory attribute as it defines how and where the data should be stored in the distributed NoSQL table. * **Sort Key**: This key is typically an optional attribute and that will help you in referring the required data that shares the same Partition Key. For example, if you have a NoSQL table that contains data on fruits, then the *fruit* itself will be the **Partition Key**, while its specific *variety* will be the **Sort Key**. <table class="content-table"> <thead> <tr> <th class="w30p">Fruit (Partition Key)</th> <th class="w30p">Variety (Sort Key)</th> <th class="w30p">Color (Index)</th> </tr> </thead> <tbody> <tr> <td>Apple</td> <td>Royal Gala</td> <td>Red</td> </tr> <tr> <td>Apple</td> <td>Fuji</td> <td>Red</td> </tr> <tr> <td>Banana</td> <td>Cavendish</td> <td>Yellow</td> </tr> <tr> <td>Banana</td> <td>Red Dacca</td> <td>Red</td> </tr> </tbody> </table> {{%info%}}{{%bold%}}Info:{{%/bold%}}: {{%link href="/en/cloud-scale/help/nosql/components/#table-keys" %}}Learn more about NoSQL Table Keys{{%/link%}}.{{%/info%}} ### Application Workflow The workflow of the application is described below: * You will create a task by populating the input fields present in the client. The {{%badge%}}UserID{{%/badge%}} will act as the **Partition Key**, and the {{%badge%}}Task Name{{%/badge%}} will act as the **Sort Key**. * Once the task is created, the unstructured data will be stored in the NoSQL storage component. * You can filter the created tasks and the required tasks will be referred using its {{%badge%}}UserID{{%/badge%}} (**Partition Key**) and {{%badge%}}Task Name{{%/badge%}} (**Sort Key**). * You can also perform **Edit** and **Delete** operations on the created tasks. The data changes will be reflected in the NoSQL component. * Finally, the React application is hosted on Catalyst using the Web Client Hosting component. -------------------------------------------------------------------------------- title: "Prerequisites" description: "Build a React task manager app to create and manage tasks. You can perform CRUD and filter functionality on tasks." last_updated: "2026-03-18T07:41:08.688Z" source: "https://docs.catalyst.zoho.com/en/tutorials/task-manager/nodejs/prerequisites/" service: "All Services" related: - Catalyst CLI Documentation (/en/cli/v1/cli-command-reference/) - Catalyst VS Code Extension (/en/catalyst-extensions/vs-code-extension/introduction/) -------------------------------------------------------------------------------- # Prerequisites Before you begin building the application, you must have the following prerequisites installed on your system: 1. {{%bold%}}Catalyst CLI{{%/bold%}}: Catalyst CLI contains a host of tools that enable you to initialize, develop, test, and deploy the components of your application from your local machine. We will be working with Catalyst CLI in this tutorial. You must perform the following actions: - **Install Catalyst CLI**: Catalyst CLI is installed through NPM. You must have NPM and Node.js installed on your system before you install the CLI. Refer to the {{%link href="/en/getting-started/installing-catalyst-cli/" %}}{{%bold%}}Install Catalyst CLI help page{{%/bold%}}{{%/link%}} for details on the prerequisites and the steps to install it. - **Login Catalyst CLI**: After you install Catalyst CLI, you must authenticate the CLI with your Catalyst account before using it. Refer to the {{%link href="/en/cli/v1/login/login-from-cli/" %}}{{%bold%}}CLI Login help page{{%/bold%}}{{%/link%}} for the steps to log in from Catalyst CLI and the various options available for it. 2. {{%bold%}}Any IDE tool for Node.js and client code development{{%/bold%}}: You can use any IDE to work with the function and the client code. Some popular choices include Visual Studio Code, IntelliJ IDEA, Eclipse, and Sublime Text. Download and install an IDE of your choice on your system. {{%info%}}{{%bold%}}Info:{{%/bold%}} If you are a Visual Studio Code IDE user, you can install the {{%bold%}}Catalyst Tools{{%/bold%}} extension, and use your IDE itself in place of the CLI. You can find more details about the Catalyst VS Code extension from this {{%link href="/en/catalyst-extensions/vs-code-extension/introduction/" %}}help section{{%/link%}}.{{%/info%}} -------------------------------------------------------------------------------- title: "Create Project" description: "Build a React task manager app to create and manage tasks. You can perform CRUD and filter functionality on tasks." last_updated: "2026-03-18T07:41:08.688Z" source: "https://docs.catalyst.zoho.com/en/tutorials/task-manager/nodejs/create-project/" service: "All Services" related: - Catalyst Projects (/en/getting-started/catalyst-projects/) -------------------------------------------------------------------------------- # Create a Project Let's {{%link href="/en/getting-started/catalyst-projects/#creating-a-catalyst-project" %}}create a project{{%/link%}} in the Catalyst console. 1. Log in to the {{%link href="https://console.catalyst.zoho.com/baas/index" %}}Catalyst console{{%/link%}} and click **Create New Project**. <br /> 2. Enter the project's name as "{{%badge%}}TaskManager{{%/badge%}}" in the pop-up window, and click **Create**. <br /> Your project will be created. You can open the project by clicking **Access Project**. <br /> -------------------------------------------------------------------------------- title: "Create a NoSQL Table" description: "Build a React task manager app to create and manage tasks. You can perform CRUD and filter functionality on tasks." last_updated: "2026-03-18T07:41:08.688Z" source: "https://docs.catalyst.zoho.com/en/tutorials/task-manager/nodejs/config-nosql/" service: "All Services" related: - Catalyst NoSQL Help Documentation (/en/cloud-scale/help/nosql/introduction/) - Catalyst NoSQL NodeJS SDK (/en/sdk/nodejs/v2/cloud-scale/nosql/get-component-instance/) - Catalyst NoSQL API (/en/api/code-reference/cloud-scale/nosql/insert-item/#InsertNewItem) -------------------------------------------------------------------------------- # Create a NoSQL Table Let's create a table in {{%link href="/en/cloud-scale/help/nosql/introduction/" %}}NoSQL{{%/link%}}. This table will be used to store the unstructured or semi-structured JSON data generated in the application through user inputs. To create a NoSQL table: 1. Navigate to the *Catalyst CloudScale* service section in the console and click **Start Exploring**. <br /> 2. Navigate to the **NoSQL** component under *STORAGE*, and click **Create Table**. <br /> 3. Name your table "{{%badge%}}TaskHandler{{%/badge%}}". <br /> 4. Enter "{{%badge%}}UserID{{%/badge%}}" as the **Partition Key**, and select **String** as the **Data Type**. You can use the UserID field to represent an individual who creates and manages their tasks. This should be kept unique for each user. <br /> 5. Select **Yes** to include **Sort Key**. Enter "{{%badge%}}TaskName{{%/badge%}}" as the **Sort Key**, and select **String** as the **Data Type**. <br /> 6. Click **Create**. <br /> {{%note%}}{{%bold%}}Note:{{%/bold%}} * We do not require any additional {{%italics%}}Sort Keys{{%/italics%}} or need to make use of the {{%italics%}}TTL feature{{%/italics%}} for the purposes of this tutorial. * {{%link href="/en/cloud-scale/help/nosql/components/#table-keys" %}}Learn more about Sort Keys and TTL{{%/link%}}.{{%/note%}} The table will be created and a unique {{%link href="/en/cloud-scale/help/nosql/create-manage-tables/#the-overview-section" %}}Table ID{{%/link%}} will be generated by Catalyst to refer to the table. ### Configure Table Indexes Next, we are going to configure indexes for the NoSQL table. Indexes are required to create other attributes that can be used to search for data stored in the table. {{%info%}}{{%bold%}}Info:{{%/bold%}} {{%link href="/en/cloud-scale/help/nosql/indexing/introduction/" %}}Learn more about NoSQL Indexes{{%/link%}}.{{%/info%}} To create an Index: 1. Navigate to the **Indexes** tab, and click **Add Index**. <br /> 2. Enter "{{%badge%}}PrimaryIndex{{%/badge%}}" as the name of the index. <br /> 3. Enter "{{%badge%}}UserID{{%/badge%}}" as the name of the **Partition Key** and select **String** as the **Data Type**. <br /> 4. Select **No**, as no additional *Sort Keys* are required for the index, select **All Attributes** as the **Attribute Type**, and click **Create**. <br /> The required index has been created. <br /> The NoSQL component has been configured for the application. -------------------------------------------------------------------------------- title: "Initialize the Project" description: "Build a React task manager app to create and manage tasks. You can perform CRUD and filter functionality on tasks." last_updated: "2026-03-18T07:41:08.701Z" source: "https://docs.catalyst.zoho.com/en/tutorials/task-manager/nodejs/init-project/" service: "All Services" related: - Catalyst NoSQL Help Documentation (/en/cloud-scale/help/nosql/introduction/) - CLI Help Documentation (/en/cli/v1/cli-command-reference/) - Initialize Resources From CLI (/en/cli/v1/initialize-resources/introduction/) - Project Directory Structure (/en/cli/v1/project-directory-structure/introduction/) - Catalyst Multi-Orgnization Portal (/en/getting-started/catalyst-organizations/#access-the-multi-org-portal) - Catalyst Tools (/en/catalyst-extensions/vs-code-extension/introduction/) -------------------------------------------------------------------------------- # Initialize the Project You can now begin working on your Catalyst project from the CLI. The first step is to initialize the project in an empty directory. This will be the home directory of your project, and all of the project files will be saved in it. {{%info%}}{{%bold%}}Info:{{%/bold%}} * {{%link href="/en/cli/v1/project-directory-structure/introduction/" %}}Learn more about Project Directory Structures{{%/link%}}. * {{%link href="/en/cli/v1/cli-command-reference/" %}}Learn more about Catalyst CLI{{%/link%}}.{{%/info%}} For this application, we will be initializing the project, an Advanced IO function, and React client components. 1. Create a folder for the project on your local machine and navigate to it from the terminal. 2. Initialize the project by executing the following command from that directory: {{%cli%}}catalyst init{{%/cli%}} 3. Navigate using the arrow keys and select your preferred portal and click Enter. If you have no other organizations associated with the account, then the default will be selected automatically. <br /> {{%info%}}{{%bold%}}Info:{{%/bold%}} {{%link href="/en/getting-started/catalyst-organizations/#access-the-multi-org-portal" %}}Learn more about Catalyst’s multi-org portal feature{{%/link%}}.{{%/info%}} 4. The CLI will now ask you to associate a Catalyst project with the directory. Associate it with the project that we created earlier from the console. Select **TaskManager** from the list and click **Enter**. <br /> 5. Navigate using the arrow keys and select **Functions**, **Client** using the space bar. Press **Enter** to initialize. <br /> 6. The CLI will initiate the function setup. Select **Advanced IO** as the function type to code your backend logic. <br /> 7. Select the latest runtime of **Node.js** as the function stack. <br /> 8. Enter "{{%badge%}}task_manager_function{{%/badge%}}" as the package name, "{{%badge%}}index.js{{%/badge%}}" as the entry point, and your email address as the author, then press **Enter**. Alternatively, you can press **Enter** without entering inputs to fill in the default values. The CLI will prompt the initialization of the Node dependencies. Press **Y** to confirm the installation, and press **Enter** to confirm your choice. The Node modules will be installed. <br /> The CLI will now initiate the client setup. 9. Select **React web app** and press **Enter** to initialize your client as a {{%link href="/en/cli/v1/initialize-resources/initialize-client/#react-applications" %}}React web app{{%/link%}}. <br /> 10. Select **JavaScript** as the React app type and press **Enter**. <br /> 11. Enter "{{%badge%}}task-manager-client{{%/badge%}}" as the name of your client package and click **Enter**. You can also provide any name of your choice. All of the required React packages, such as "{{%badge%}}react{{%/badge%}}," "{{%badge%}}react-dom{{%/badge%}}," and "{{%badge%}}react-scripts{{%/badge%}}" will be installed through the **Catalyst React plugin** ({{%link href="https://www.npmjs.com/package/zcatalyst-cli-plugin-react" %}}{{%badge%}}zcatalyst-cli-plugin-react{{%/badge%}}{{%/link%}}). <br /> The client is now successfully initialized as a React web application. <br /> The {{%link href="/en/cli/v1/project-directory-structure/client-directory" %}}client directory{{%/link%}} will be created in the standard structure in the project directory. This is the structure of the *TaskManager* project’s directory if the client is initialized as a React app. <br /> Catalyst initialization is now complete. -------------------------------------------------------------------------------- title: "Configure the Advanced IO Function" description: "Build a React task manager app to create and manage tasks. You can perform CRUD and filter functionality on tasks." last_updated: "2026-03-18T07:41:08.702Z" source: "https://docs.catalyst.zoho.com/en/tutorials/task-manager/nodejs/config-function/" service: "All Services" related: - Catalyst NoSQL Help Documentation (/en/cloud-scale/help/nosql/introduction/) - NoSQL NodeJS SDK (/en/sdk/nodejs/v2/cloud-scale/nosql/get-component-instance/) - Advanced IO Function (/en/serverless/help/functions/advanced-io/) - Function Directory Structure (/en/cli/v1/project-directory-structure/functions-directory) -------------------------------------------------------------------------------- # Configure the Advanced IO Function Now, we will begin coding the task manager application by configuring the function component. The {{%link href="/en/cli/v1/project-directory-structure/functions-directory" %}}function’s directory{{%/link%}}, {{%badge%}}functions/task_manager_function{{%/badge%}} contains: * The {{%badge%}}index.js{{%/badge%}} main function file * The {{%badge%}}catalyst-config.json{{%/badge%}} configuration file * Node modules * {{%link href="https://docs.npmjs.com/files/package.json" %}}{{%badge%}}package.json{{%/badge%}}{{%/link%}} and {{%link href="https://docs.npmjs.com/configuring-npm/package-lock-json.html" %}}{{%badge%}}package-lock.json{{%/badge%}}{{%/link%}} dependency files You will be adding code in the {{%badge%}}index.js{{%/badge%}} file. The Advanced I/O function contains the following functionalities: <table class="content-table"> <thead> <tr> <th class="w25p">Request Method</th> <th class="w25p">Endpoint</th> <th class="w50p">Purpose</th> </tr> </thead> <tbody> <tr> <td>{{%badge%}}{{%bold%}}POST{{%/bold%}}{{%/badge%}}</td> <td>{{%badge%}}/addtask{{%/badge%}}</td> <td>To create a new task.</td> </tr> <tr> <td>{{%badge%}}{{%bold%}}GET{{%/bold%}}{{%/badge%}}</td> <td>{{%badge%}}/filtertask{{%/badge%}}</td> <td>To filter created tasks by {{%italics%}}UserID{{%/italics%}}, {{%italics%}}TaskName{{%/italics%}} or {{%italics%}}Status{{%/italics%}} fields.</td> </tr> <tr> <td>{{%badge%}}{{%bold%}}DELETE{{%/bold%}}{{%/badge%}}</td> <td>{{%badge%}}/deletetask{{%/badge%}}</td> <td>To delete tasks that are no longer required.</td> </tr> <tr> <td>{{%badge%}}{{%bold%}}POST{{%/bold%}}{{%/badge%}}</td> <td>{{%badge%}}/updatetask{{%/badge%}}</td> <td>To update the content of an existing task.</td> </tr> </tbody> </table> ### Install Required Dependencies We will be using the {{%link href="https://expressjs.com/" %}}Express{{%/link%}} and {{%link href="https://www.npmjs.com/package/axios" %}}Axios{{%/link%}} framework to code the Advanced I/O function. To import the **Express** and **Axios** package in your function’s code, you must install the the required dependency in your system. <table class="content-table"> <thead> <tr> <th class="w50p">Package Name</th> <th class="w50p">Purpose</th> </tr> </thead> <tbody> <tr> <td>{{%badge%}}{{%bold%}}Express{{%/bold%}}{{%/badge%}}</td> <td>To route HTTP requests.</td> </tr> <tr> <td>{{%badge%}}{{%bold%}}Axios{{%/bold%}}{{%/badge%}}</td> <td>To send and handle HTTP requests</td> </tr> </tbody> </table> To install them in your local machine, navigate to the function’s home directory ({{%badge%}}functions/task_manager_function{{%/badge%}}) in your terminal and execute the following command: {{%cli%}}npm install express axios --save{{%/cli%}} <br /> This information will also be updated in the {{%badge%}}package.json{{%/badge%}} file. <br /> Now, let’s begin coding the Advanced I/O function. Copy the code given below and paste it in the {{%badge%}}index.js{{%/badge%}} in the {{%badge%}}functions/task_manager_function{{%/badge%}} directory of your project, and save the file. You can use any IDE of your choice to work with the application’s files. {{%note%}}{{%bold%}}Note:{{%/bold%}} Please go through the code in this section to make sure you fully understand it.{{%/note%}} {{% panel_with_adjustment class="language-javascript line-numbers" header="index.js" footer="button" scroll="set-scroll" %}}'use strict'; var express=require('express'); var catalyst=require('zcatalyst-sdk-node'); const{NoSQLItem}=require('zcatalyst-sdk-node/lib/no-sql'); const{NoSQLReturnValue,NoSQLConditionGroupOperator}=require('zcatalyst-sdk-node/lib/no-sql/enum'); const{NoSQLMarshall,NoSQLEnum}=require('zcatalyst-sdk-node/lib/no-sql'); const{NoSQLOperator}=NoSQLEnum; var app=express(); app.use(express.json()); app.use(express.static('public')); // Add a task app.post('/addtask',async(req,res)=>{ let{userID,taskName,dueDate,priority,status}=req.body; var capp=catalyst.initialize(req); const nosql=capp.nosql(); const table=nosql.table('YOUR_TABLE_ID'); try{ await table.insertItems({ item:NoSQLItem.from({UserID:userID,DueDate:dueDate,TaskName:taskName,Priority:priority,Status:status}), return:NoSQLReturnValue.NULL }); res.send({message:"Thanks! Your task has been successfully inserted."}); }catch(error){ res.status(500).send({error:"Internal server error occurred. Please try again in some time."}); } }); // Filter task app.get('/filtertask',async(req,res)=>{ const query=req.query; const parsedData={index_data:{userID:query.userID,taskName:query.taskName,status:query.status}}; const userId=parsedData.index_data.userID; var capp=catalyst.initialize(req); const nosql=capp.nosql(); const table=nosql.table('YOUR_TABLE_ID'); try{ if(userId!=null&&parsedData.index_data.taskName===''){ if(parsedData.index_data.status==='')return res.status(400).json({error:"Oops! You forgot to select a status."}); const groupOpInsert=await table.queryTable({ key_condition:{attribute:'UserID',operator:NoSQLOperator.EQUALS,value:NoSQLMarshall.makeString(parsedData.index_data.userID)}, consistent_read:true, limit:10, forward_scan:true }); let responseData=[]; groupOpInsert.getResponseData().forEach(data=>{ responseData.push({ UserID:data.item.get("UserID"), TaskName:data.item.get("TaskName"), DueDate:data.item.get("DueDate"), Priority:data.item.get("Priority"), Status:data.item.get("Status") }); }); const filteredData=await filterByStatus(responseData,parsedData); res.status(200).send(filteredData); }else if(userId!=null&&parsedData.index_data.taskName!=null){ if(parsedData.index_data.status==='')return res.status(400).json({error:"Oops! You forgot to select a status."}); const groupOpInsert=await table.queryTable({ key_condition:{ group_operator:NoSQLConditionGroupOperator.AND, group:[ {attribute:'UserID',operator:NoSQLOperator.EQUALS,value:NoSQLMarshall.makeString(parsedData.index_data.userID)}, {attribute:'TaskName',operator:NoSQLOperator.EQUALS,value:NoSQLMarshall.makeString(parsedData.index_data.taskName)} ] }, consistent_read:true, limit:10, forward_scan:true }); let responseData=[]; groupOpInsert.getResponseData().forEach(data=>{ responseData.push({ UserID:data.item.get("UserID"), TaskName:data.item.get("TaskName"), DueDate:data.item.get("DueDate"), Priority:data.item.get("Priority"), Status:data.item.get("Status") }); }); const filteredData=await filterByStatus(responseData,parsedData); res.send(filteredData); }else return res.send("Kindly enter partiyion key user ID and sort key Taskname"); }catch(error){ res.status(500).send({error:"Internal server error occurred. Please try again in some time."}); } }); // Delete Task app.delete('/deletetask',async(req,res)=>{ const query=req.query; const parsedData={index_data:{userID:query.userID,taskName:query.taskName}}; var capp=catalyst.initialize(req); const nosql=capp.nosql(); const table=nosql.table('YOUR_TABLE_ID'); try{ await table.deleteItems({keys:NoSQLItem.from({UserID:parsedData.index_data.userID,TaskName:parsedData.index_data.taskName})}); res.status(200).json({message:"Data deleted successfully!"}); }catch(error){ res.status(500).send({error:"Internal server error occurred. Please try again in some time."}); } }); // Update Task app.post('/updatetask',async(req,res)=>{ let{UserID,TaskName,DueDate,Priority,Status}=req.body; var capp=catalyst.initialize(req); const nosql=capp.nosql(); const table=nosql.table('YOUR_TABLE_ID'); try{ await table.insertItems({ item:NoSQLItem.from({UserID:UserID,DueDate:DueDate,TaskName:TaskName,Priority:Priority,Status:Status}), return:NoSQLReturnValue.NULL }); res.send({message:"Items updated successfully!"}); }catch(error){ res.status(500).send({error:"Internal server error occurred. Please try again in some time."}); } }); async function filterByStatus(data,parseData){ return data.filter(task=>task.Status.toLowerCase()===parseData.index_data.status.toLowerCase()); } module.exports=app; {{%/panel_with_adjustment%}} {{%note%}}{{%bold%}}Note:{{%/bold%}} Ensure you provide your table ID in lines {{%bold%}}16{{%/bold%}}, {{%bold%}}34{{%/bold%}}, {{%bold%}}93{{%/bold%}}, and {{%bold%}}106{{%/bold%}}.{{%/note%}} The function directory is now configured. We can now proceed to configuring the client directory. -------------------------------------------------------------------------------- title: "Configure the Client" description: "Build a React task manager app to create and manage tasks. You can perform CRUD and filter functionality on tasks." last_updated: "2026-03-18T07:41:08.703Z" source: "https://docs.catalyst.zoho.com/en/tutorials/task-manager/nodejs/config-client/" service: "All Services" related: - Catalyst NoSQL Help Documentation (/en/cloud-scale/help/nosql/introduction/) - Client Directory Structure (/en/cli/v1/project-directory-structure/client-directory/) - Web Client Hosting (/en/cloud-scale/help/web-client-hosting/introduction/) -------------------------------------------------------------------------------- # Configure the Client Let's configure the client component. The React web {{%link href="/en/cli/v1/project-directory-structure/client-directory" %}}client directory{{%/link%}} contains the following files: - The root directory of the client contains a {{%badge%}}client-package.json{{%/badge%}} file, which is a configuration file defining the name, version, default home page, and redirect page of the client component. - The {{%badge%}}**task-manager-client**{{%/badge%}} client directory contains two subfolders, as per the default project structure of a React app: - The {{%badge%}}**public**{{%/badge%}} folder is generally used to hold files that can be openly accessed by browsers through public URLs, such as icon files of the web app, the {{%badge%}}index.html{{%/badge%}} file, and the {{%badge%}}404.html{{%/badge%}} file. - The {{%badge%}}**src**{{%/badge%}} folder contains the application’s source files that will be included in the build folder when we compile the React app. - The client directory also contains the {{%link href="https://docs.npmjs.com/files/package.json" %}}{{%badge%}}package.json{{%/badge%}}{{%/link%}} dependency file and a hidden {{%link href="https://docs.npmjs.com/files/package.json" %}}{{%badge%}}.gitignore{{%/badge%}}{{%/link%}} file. - The files present in the {{%badge%}}**src**{{%/badge%}} folder include: - {{%link href="https://reactjs.org/docs/getting-started.html#try-react" %}}Native React files{{%/link%}} such as {{%badge%}}index.js{{%/badge%}}, {{%badge%}}index.css{{%/badge%}}, {{%badge%}}setupTests.js{{%/badge%}}, {{%badge%}}reportWebVitals.js{{%/badge%}}, {{%badge%}}logo.svg{{%/badge%}}, and {{%badge%}}App.test.js{{%/badge%}}. - {{%badge%}}**App.css**{{%/badge%}}: Contains the required styling elements for the applications interface. - {{%badge%}}**App.js**{{%/badge%}}: Contains the hash routing logic to define routes for **AddTask** and **FilterTask** files. - You need to add the following files to the {{%badge%}}src/{{%/badge%}} folder: - {{%badge%}}**AddTask.css**{{%/badge%}}: Contains the required styling elements for the task creation action. - {{%badge%}}**AddTask.js**{{%/badge%}}: To collect task details using form inputs. - {{%badge%}}**FilterTask.css**{{%/badge%}}: Contains the required styling for the filter functionality. - {{%badge%}}**FilterTask.js**{{%/badge%}}: To contain the logic of filtering the tasks based on {{%badge%}}UserID{{%/badge%}}, {{%badge%}}TaskName{{%/badge%}}, and {{%badge%}}Status{{%/badge%}}. Also contains the logic to perform edit and delete operations. - {{%badge%}}**Header.css**{{%/badge%}}: Contains the styling elements of the application - {{%badge%}}**Header.js**{{%/badge%}}: Contains the logic that defines the primary aspects of the application such as, application title, navigation buttons, and more. ### Install Additional React Packages To allow our application to behave as a multi-page application, we need to install the {{%badge%}}react-router-dom{{%/badge%}} package. To install the {{%badge%}}react-router-dom{{%/badge%}} package, navigate to the {{%badge%}}TaskManager/task-manager-client/{{%/badge%}} directory and execute the CLI command given below: {{%cli%}}npm install react-router-dom{{%/cli%}} This command will install the {{%badge%}}react-router-dom{{%/badge%}} module, save the dependencies, and allow us to perform the required hash routing in our application. <br /> This is the client directory after you have created the required files. <br /> {{%note%}}{{%bold%}}Note:{{%/bold%}} Please go through the all code given in this section to ensure you fully understand it.{{%/note%}} Copy the code given below and paste it in the respective files. {{%panel_with_adjustment class="language-css line-numbers" header="App.css" footer="button" scroll="set-scroll" %}}.App{ text-align:center; } .App-logo{ height:40vmin; pointer-events:none; } @media(prefers-reduced-motion:no-preference){ .App-logo{ animation:App-logo-spin infinite 20s linear; } } .App-header{ background-color:#282c34; min-height:100vh; display:flex; flex-direction:column; align-items:center; justify-content:center; font-size:calc(10px+2vmin); color:white; } .App-link{ color:#61dafb; } @keyframes App-logo-spin{ from{ transform:rotate(0deg); } to{ transform:rotate(360deg); } } {{%/panel_with_adjustment%}} {{%panel_with_adjustment class="language-javascript line-numbers" header="App.js" footer="button" scroll="set-scroll" %}}import React from 'react' import {HashRouter,Route,Routes,Navigate} from 'react-router-dom' import AddTask from './AddTask' import FilterTask from './FilterTask' import Header from './Header' export default function App() { return ( &lt;div&gt; &lt;HashRouter&gt; &lt;Header /&gt; &lt;div className='router'&gt; &lt;Routes&gt; &lt;Route path='' element={&lt;Navigate to='/AddTask' /&gt;} /&gt; &lt;Route path='/AddTask' element={&lt;AddTask /&gt;} /&gt; &lt;Route path='/FilterTask' element={&lt;FilterTask /&gt;} /&gt; &lt;/Routes&gt; &lt;/div&gt; &lt;/HashRouter&gt; &lt;/div&gt; ) } {{%/panel_with_adjustment%}} {{%panel_with_adjustment class="language-css line-numbers" header="AddTask.css" footer="button" scroll="set-scroll" %}}body { font-family: Arial, sans-serif; background-color: #f8f9fa; margin: 0; padding: 0; } .container { max-width: 800px; margin: 20px auto; padding: 20px; background: #ffffff; box-shadow: 0px 4px 6px rgba(0,0,0,0.1); border-radius: 10px; } h1 { color: #121111; font-size: 2.5rem; font-weight: bold; margin-bottom: 20px; text-align: center; } .card { border: none; background-color: #fdfdfd; box-shadow: 0 2px 5px rgba(0,0,0,0.1); border-radius: 8px; overflow: hidden; } .card-header { background-color: #439600; color: white; padding: 15px; font-size: 1.25rem; font-weight: bold; text-align: center; } .card-body { padding: 20px; } .form-row { display: flex; flex-wrap: wrap; gap: 15px; margin-bottom: 15px; } .col-md-6,.col-md-4 { flex: 1 1 calc(50% - 15px); min-width: 200px; } label { display: block; font-weight: 600; margin-bottom: 5px; color: #495057; } input,select { width: 93%; padding: 10px; font-size: 1rem; border: 1px solid #ced4da; border-radius: 5px; transition: border-color 0.2s; } input:focus,select:focus { border-color: #007bff; outline: none; box-shadow: 0 0 4px rgba(0,123,255,0.25); } .buttons { display: flex; justify-content: space-between; gap: 10px; } button { padding: 10px 20px; font-size: 1rem; border: none; border-radius: 5px; transition: background-color 0.2s; } button.btn-primary { width: 16%; background-color: #000000; color: white; } button.btn-primary:hover { background-color: #34de19; } button.btn-secondary { background-color: #000000; width: 14%; color: white; font-size: 1rem; font-weight: 600; } button.btn-secondary:hover { background-color: #f00000; } #status.form-control { width: 387%; } .card-header h2 { color: white; } {{%/panel_with_adjustment%}} {{%panel_with_adjustment class="language-javascript line-numbers" header="AddTask.js" footer="button" scroll="set-scroll" %}}import React, { useState } from 'react' import './AddTask.css' import axios from 'axios' export default function AddTask() { const [userID, setUserID] = useState('') const [taskName, setTaskName] = useState('') const [dueDate, setDueDate] = useState('') const [priority, setPriority] = useState('High') const [status, setStatus] = useState('Pending') const today = new Date().toISOString().split('T')[0] const addTask = async (event) => { event.preventDefault() const newTask = { userID, taskName, dueDate, priority, status } await axios.post('/server/task_manager_function/addtask', newTask).then(() => { window.confirm('Task added successfully') clearForm() }).catch((error) => { alert(error.message) }) } const clearForm = () => { setUserID('') setTaskName('') setDueDate('') setPriority('High') setStatus('Pending') } return ( &lt;div className="container my-4"&gt; &lt;div className="card my-4"&gt; &lt;div className="card-header"&gt; &lt;h2&gt;Add New Task&lt;/h2&gt; &lt;/div&gt; &lt;div className="card-body"&gt; &lt;form onSubmit={addTask}&gt; &lt;div className="form-row"&gt; &lt;div className="col-md-6 mb-3"&gt; &lt;label htmlFor="userID" className="userID"&gt;User ID&lt;/label&gt; &lt;input type="text" className="form-control" id="userID" value={userID} onChange={(e) => setUserID(e.target.value)} required /&gt; &lt;/div&gt; &lt;div className="col-md-6 mb-3"&gt; &lt;label htmlFor="taskName"&gt;Task Name&lt;/label&gt; &lt;input type="text" className="form-control" id="taskName" value={taskName} onChange={(e) => setTaskName(e.target.value)} required /&gt; &lt;/div&gt; &lt;/div&gt; &lt;div className="form-row align-items-center"&gt; &lt;div className="col-md-4 mb-3"&gt; &lt;label htmlFor="dueDate"&gt;Due Date&lt;/label&gt; &lt;input type="date" className="form-control" id="dueDate" value={dueDate} onChange={(e) => setDueDate(e.target.value)} min={today} required /&gt; &lt;/div&gt; &lt;div className="col-md-4 mb-3"&gt; &lt;label htmlFor="priority"&gt;Priority&lt;/label&gt; &lt;select className="form-control" id="priority" value={priority} onChange={(e) => setPriority(e.target.value)} required&gt; &lt;option value="High"&gt;High&lt;/option&gt; &lt;option value="Medium"&gt;Medium&lt;/option&gt; &lt;option value="Low"&gt;Low&lt;/option&gt; &lt;/select&gt; &lt;/div&gt; &lt;div className="status-cls"&gt; &lt;label htmlFor="status"&gt;Status&lt;/label&gt; &lt;select className="form-control" id="status" value={status} onChange={(e) => setStatus(e.target.value)} required&gt; &lt;option value="Pending"&gt;Pending&lt;/option&gt; &lt;option value="Completed"&gt;Completed&lt;/option&gt; &lt;/select&gt; &lt;/div&gt; &lt;/div&gt; &lt;div className="buttons mt-4"&gt; &lt;button type="submit" className="btn btn-primary"&gt;Add Task&lt;/button&gt; &lt;button type="button" className="btn btn-secondary" onClick={clearForm}&gt;Clear&lt;/button&gt; &lt;/div&gt; &lt;/form&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt; ) } {{%/panel_with_adjustment%}} {{%panel_with_adjustment class="language-css line-numbers" header="FilterTask.css" footer="button" scroll="set-scroll" %}}@import url("https://fonts.googleapis.com/css2?family=Inter:wght@100..900&display=swap"); * { font-family: "Inter", sans-serif; box-sizing: border-box; margin: 0; padding: 0; } h2 { font-size: 38px; font-weight: bold; margin-bottom: 20px; text-align: center; padding: 10px; border-bottom: 1px dashed #ccc; color: #000; } .btn1 { color: white; padding: 8px 10px; border: none; border-radius: 4px; cursor: pointer; background-color: #ccc; } .green { background-color: green; } .container { margin: 30px auto; padding: 20px; max-width: 900px; background-color: #f9f9f9; border-radius: 8px; box-shadow: 0 4px 8px rgba(0,0,0,0.1); } h3 { text-align: center; color: #333; font-family: Arial, sans-serif; } .table { width: 100%; border-collapse: collapse; margin-top: 20px; font-family: Arial, sans-serif; } .table th, .table td { padding: 12px 15px; text-align: left; border-bottom: 1px solid #ddd; } .table th { background-color: #439600; color: white; } .table tbody tr:nth-child(even) { background-color: #f4f4f4; } .table tbody tr:hover { background-color: #e9e9e9; } .btn { padding: 6px 12px; border: none; border-radius: 4px; cursor: pointer; font-size: 14px; font-weight: bold; background-color: #1100ec; color: white; } .btn:hover { background-color: rgb(32,239,0); } .btn:focus { outline: none; } .btn.green { background-color: #28a745; color: white; } .btn.green:hover { background-color: #218838; } td button { margin-right: 8px; } table tr:hover { background-color: #ddd; } .filter-tasks-container { background-color: #ffffff; padding: 25px 30px; border-radius: 10px; box-shadow: 0 8px 15px rgba(0,0,0,0.15); max-width: 650px; margin: 30px auto 59px; } .filter-tasks-header { font-size: 2rem; font-weight: 700; color: #ffffff; text-align: center; padding: 15px; background: #439600; border-radius: 8px 8px 0 0; margin: -30px -30px 20px -30px; position: relative; } .filter-tasks-header::after { content: ''; display: block; width: 50px; height: 4px; margin: 10px auto 0; border-radius: 2px; } .form-row { display: flex; gap: 20px; margin-bottom: 15px; } .filter-label { font-weight: 600; margin-bottom: 5px; display: block; color: #333; font-size: 0.9rem; } .form-control { border: 1px solid #ddd; border-radius: 6px; font-size: 1rem; padding: 3px; transition: all 0.3s ease; color: black; } .form-control:focus { border-color: #007bff; box-shadow: 0 0 8px rgba(0,123,255,0.2); outline: none; } .btn-primary { color: #ffffff; border: none; padding: 12px 24px; font-size: 1rem; font-weight: 600; border-radius: 6px; width: 26%; background-color: black; } .btn-wraper { display: flex; align-items: center; justify-content: space-between; } .cleartask-btn { width: 22%; color: #ffffff; border: none; padding: 12px 24px; font-size: 1rem; font-weight: 600; border-radius: 6px; background-color: black; } .cleartask-btn:hover { background-color: #e80000; transform: translateY(-2px); } .btn-primary:hover { background-color: #60f389; transform: translateY(-2px); } .btn-primary:active { background-color: #141517; transform: translateY(0); } @media (max-width: 768px) { .form-row { flex-direction: column; gap: 15px; } .btn-primary { width: 100%; } } .task-list-container { width: 59%; padding: 5px; background-color: #f9f9f9; border-radius: 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.1); margin-left: 20%; } .task-list-table { width: 100%; border-collapse: collapse; } .task-list-table-striped thead { background-color: #69f086; color: #ffffff; } .task-list-table-striped th, .task-list-table-striped td { padding: 12px 15px; text-align: left; } .task-list-table-striped tbody tr:nth-child(even) { background-color: #f2f2f2; } .task-list-table-striped tbody tr:hover { background-color: #e0e0e0; } .task-list-table-striped th { font-weight: bold; font-size: 16px; } .task-list-table-striped td { font-size: 14px; } .task-list-table-striped td[data-priority="High"] { color: #dc3545; font-weight: bold; } .task-list-table-striped td[data-priority="Medium"] { color: #ffc107; } .task-list-table-striped td[data-priority="Low"] { color: #28a745; } .task-list-table-striped td[data-status="Completed"] { color: #28a745; font-weight: bold; } .task-list-table-striped td[data-status="Pending"] { color: #ffc107; font-weight: bold; } .task-list-table-striped td[data-status="Overdue"] { color: #dc3545; font-weight: bold; text-decoration: underline; } @media (max-width: 768px) { .task-list-table-striped th, .task-list-table-striped td { padding: 10px; } } .modal { display: block; position: fixed; z-index: 1; left: 0; top: 0; width: 100%; height: 100%; background-color: rgba(0,0,0,0.5); overflow: auto; } .modal-content { background-color: white; margin: 10% auto; padding: 20px; text-align: left; width: 56%; height: 62%; border: 1px solid black; } .close { color: #aaa; float: right; font-size: 28px; font-weight: bold; } .close:hover, .close:focus { color: rgb(245,0,0); cursor: pointer; } .updateContent { margin-bottom: 10%; } .modal-content h2 { font-size: 20px; margin-bottom: 20px; text-align: center; } .modal-content div { margin-bottom: 15px; } .modal-content label { display: block; font-weight: bold; margin-bottom: 5px; } .modal-content input[type="text"], .modal-content input[type="date"], .modal-content select { width: 100%; padding: 8px; border: 1px solid #ccc; border-radius: 4px; box-sizing: border-box; } .modal-content select { cursor: pointer; } .modal-content button { display: inline-block; width: 19%; padding: 10px; background-color: #2c2d2e; color: white; font-size: 16px; font-weight: bold; border: none; border-radius: 4px; cursor: pointer; } .modal-content button:hover { background-color: #43c265; } .head { display: flex; } .applyfilter { font-weight: bold; background-color: black; color: white; } .applyfilter:hover { background-color: #00fe19; transform: translateY(-2px); } .btnDelete { padding: 6px 12px; border: none; border-radius: 4px; cursor: pointer; font-size: 14px; font-weight: bold; background-color: rgb(200,26,17); color: white; } .btnDelete:hover { background-color: rgb(255,0,0); } .btnDelete.green { background-color: #ba2929; color: white; } .btnDelete.green:hover { background-color: #218838; } .btnDelete:focus { outline: none; } .placeholder { color: gray; } {{%/panel_with_adjustment%}} {{%panel_with_adjustment class="language-javascript line-numbers" header="FilterTask.js" footer="button" scroll="set-scroll" %}}import React from 'react' import { useState } from 'react' import axios from "axios" import './FilterTask.css' export default function FilterTask() { const [tasks,setTasks]=useState([]) const [isModelopen,setModal]=useState(false) const [userData,setUserdata]=useState({UserID:"",TaskName:"",DueDate:"",Status:""}) const [userID,setUserID]=useState('') const [taskName,setTaskName]=useState('') const [status,setStatus]=useState('') const filterTasks=async()=>{try{const response=await axios.get('/server/task_manager_function/filtertask',{params:{userID,taskName,status}});setTasks(response.data)}catch(error){if(error.response&&error.response.data&&error.response.data.error){console.error('Backend Error:',error.response.data.error);alert(error.response.data.error)}else{alert('Something went wrong. Please try again.')}}} const handleDelete=async(taskData)=>{const isConfirmed=window.confirm("Are you sure you want to delete this task!");const userID=taskData.UserID;const taskName=taskData.TaskName;if(isConfirmed){await axios.delete(`/server/task_manager_function/deleteTask`,{params:{userID,taskName}}).then((response)=>{if(window.confirm(response.data.message)){window.location.reload()}}).catch(function(error){alert(error.message)})}} const handleEdit=async(data)=>{setUserdata(data);setModal(true)} const closeModal=async()=>{setModal(false)} const clearTask=()=>{setUserID('');setTaskName('');setStatus('')} const handleChange=(e)=>{const{name,value}=e.target;setUserdata(prevData=>({...prevData,[name]:value}))} const handleSubmit=async(e)=>{e.preventDefault();await axios.post("/server/task_manager_function/updatetask",userData).then((response)=>{if(window.confirm(response.data.message)){window.location.reload()}}).catch(function(error){alert(error.message)})} return( &lt;&gt; &lt;div className="filter-tasks-container"&gt; &lt;h4 className="filter-tasks-header"&gt;Filter Tasks&lt;/h4&gt; &lt;div className="form-row"&gt; &lt;div className="col-md-4"&gt; &lt;label htmlFor="filterUserID" className="filter-label"&gt;User ID&lt;/label&gt; &lt;input type="text" className="form-control" id="filterUserID" placeholder="Enter User ID" value={userID} onChange={(e)=>setUserID(e.target.value)}/&gt; &lt;/div&gt; &lt;div className="col-md-4"&gt; &lt;label htmlFor="filterTaskName" className="filter-label"&gt;Task Name&lt;/label&gt; &lt;input type="text" className="form-control" id="filterTaskName" placeholder="Enter Task Name" value={taskName} onChange={(e)=>setTaskName(e.target.value)}/&gt; &lt;/div&gt; &lt;div className="col-md-4"&gt; &lt;label htmlFor="filterStatus" className="filter-label"&gt;Status&lt;/label&gt; &lt;select className="form-control" id="filterStatus" value={status} onChange={(e)=>setStatus(e.target.value)}&gt; &lt;option value="" disabled hidden className="placeholder"&gt;Status&lt;/option&gt; &lt;option value="Pending"&gt;Pending&lt;/option&gt; &lt;option value="Completed"&gt;Completed&lt;/option&gt; &lt;/select&gt; &lt;/div&gt; &lt;/div&gt; &lt;div className="btn-wraper mt-3"&gt; &lt;button className="applyfilter" onClick={filterTasks}&gt;Apply Filters&lt;/button&gt; &lt;button className="cleartask-btn" onClick={clearTask}&gt;Clear&lt;/button&gt; &lt;/div&gt; &lt;/div&gt; {tasks.length&gt;0&&( &lt;div className='container'&gt; &lt;h2&gt;Task List&lt;/h2&gt; &lt;table className='table'&gt; &lt;thead&gt; &lt;tr&gt; &lt;th&gt;S. No&lt;/th&gt; &lt;th&gt;User ID&lt;/th&gt; &lt;th&gt;Task Name&lt;/th&gt; &lt;th&gt;Due Date&lt;/th&gt; &lt;th&gt;Status&lt;/th&gt; &lt;th&gt;Update&lt;/th&gt; &lt;th&gt;Delete&lt;/th&gt; &lt;/tr&gt; &lt;/thead&gt; &lt;tbody&gt; {tasks.map((task,index)=&gt;( &lt;tr key={index+1}&gt; &lt;td&gt;{index+1}&lt;/td&gt; &lt;td&gt;{task.UserID}&lt;/td&gt; &lt;td&gt;{task.TaskName}&lt;/td&gt; &lt;td&gt;{task.DueDate}&lt;/td&gt; &lt;td&gt;{task.Status}&lt;/td&gt; &lt;td&gt;&lt;button className='btn' onClick={()=>handleEdit(task)}&gt;Edit&lt;/button&gt;&lt;/td&gt; &lt;td&gt;&lt;button className='btnDelete' onClick={()=>handleDelete(task)}&gt;Delete&lt;/button&gt;&lt;/td&gt; &lt;/tr&gt; ))} &lt;/tbody&gt; &lt;/table&gt; {isModelopen&&( &lt;div className='modal'&gt; &lt;div className='modal-content'&gt; &lt;span className='close' onClick={closeModal}&gt;&times;&lt;/span&gt; &lt;h2&gt;User Details&lt;/h2&gt; &lt;div&gt; &lt;label htmlFor="userID"&gt;UserID:&lt;/label&gt; &lt;input type="text" id="userID" name="UserID" value={userData.UserID} onChange={handleChange} required/&gt; &lt;/div&gt; &lt;div&gt; &lt;label htmlFor="taskName"&gt;TaskName:&lt;/label&gt; &lt;input type="text" id="taskName" name="TaskName" value={userData.TaskName} onChange={handleChange} required/&gt; &lt;/div&gt; &lt;div&gt; &lt;label htmlFor="dueDate"&gt;DueDate:&lt;/label&gt; &lt;input type="date" id="dueDate" name="DueDate" value={userData.DueDate} onChange={handleChange} min={new Date().toISOString().split('T')[0]} required/&gt; &lt;/div&gt; &lt;div&gt; &lt;label htmlFor="status"&gt;Status:&lt;/label&gt; &lt;select id="status" name="Status" value={userData.Status} onChange={handleChange} required&gt; &lt;option value=""&gt;Select Status&lt;/option&gt; &lt;option value="Pending"&gt;Pending&lt;/option&gt; &lt;option value="Completed"&gt;Completed&lt;/option&gt; &lt;/select&gt; &lt;/div&gt; &lt;div&gt; &lt;button onClick={handleSubmit}&gt;Submit&lt;/button&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt; )} &lt;/div&gt; )} &lt;/&gt; ) } {{%/panel_with_adjustment%}} {{%panel_with_adjustment class="language-css line-numbers" header="Header.css" footer="button" scroll="set-scroll" %}}#root{ display:flex; flex-direction:column; height:100vh; } .heading{ align-items:center; background-color:black; box-shadow:0 2px 4px #0000001a; color:#fff; display:flex; justify-content:space-between; padding:10px 20px; } .heading span{ font-size:1.5rem; font-weight:bold; } .heading ul{ list-style:none; display:flex; gap:20px; margin:0; padding:0; } .heading li{ font-size:1rem; } .heading a{ text-decoration:none; color:#ffffff; transition:color 0.3s ease; font-weight:bold; } .heading a:hover{ color:#007bff; } .naviagtion-btn{ height:36px; background-color:white; border:none; border-radius:7px; font-size:13px; font-weight:bold; } .naviagtion-btn:hover{ background-color:blue; color:white; } {{%/panel_with_adjustment%}} {{%panel_with_adjustment class="language-javascript line-numbers" header="Header.js" footer="button" scroll="set-scroll" %}}import React from 'react' import { Link } from 'react-router-dom' import './Header.css' export default function Header() { return ( &lt;div className='heading'&gt; &lt;span&gt;Task Manager&lt;/span&gt; &lt;ul&gt; &lt;li&gt; &lt;Link to='/AddTask'&gt; &lt;button className='naviagtion-btn'&gt;Add task&lt;/button&gt; &lt;/Link&gt; &lt;/li&gt; &lt;li&gt; &lt;Link to='/FilterTask'&gt; &lt;button className='naviagtion-btn'&gt;Filter task&lt;/button&gt; &lt;/Link&gt; &lt;/li&gt; &lt;/ul&gt; &lt;/div&gt; ) } {{%/panel_with_adjustment%}} The client directory is now configured. Let’s go over the working of the application: 1. **Create a Task** - After an end-user submits a new task by entering the {{%badge%}}UserID{{%/badge%}}, {{%badge%}}Task Name{{%/badge%}}, deadline date, and {{%badge%}}Status{{%/badge%}} from the **Add Task** page, a task creation action is initiated. - The details are sent to the backend via an {{%badge%}}Axios **POST**{{%/badge%}} call to the {{%badge%}}/server/task_manager_function/addtask{{%/badge%}} API endpoint. - This API will validate and store the new task in the NoSQL storage. This action will trigger a confirmation message. - Now, the task will be available for retrieval through the operations. 2. **Filter a Task** - In the **Filter Task** page, the filtering operations are handled entirely through the {{%badge%}}/filtertask{{%/badge%}} API endpoint. - An end-user can choose to filter the created tasks by {{%badge%}}UserID{{%/badge%}}, {{%badge%}}Task Name{{%/badge%}}, or {{%badge%}}Status{{%/badge%}}. The tasks that satisfy the filtered requirement is fetched using an {{%badge%}}Axios **GET**{{%/badge%}} call to the {{%badge%}}/server/task_manager_function/filtertask{{%/badge%}} API endpoint. This call will fetch the required details from the NoSQL table. 3. **Edit or Delete a Task** - Along with the filtered task, each of the tasks listed will provide the end-user with the option to edit or delete the listed tasks. - The logic of the edit and delete operations is defined in the {{%badge%}}handleEdit(){{%/badge%}} and {{%badge%}}handleDelete(){{%/badge%}} functions. - If the end-user chooses to **delete a task**, then: - the {{%badge%}}/deleteTask{{%/badge%}} API endpoint is invoked using an {{%badge%}}Axios **DELETE**{{%/badge%}} request. - this will remove the corresponding entry from the NoSQL table. - a success message is displayed in the client once the required task is successfully deleted. - If the end-user chooses to **update a task**, then: - the existing task details are populated into a modal using the {{%badge%}}handleEdit(){{%/badge%}} function. - when the end-user updates and submits the modified task information, the {{%badge%}}/updatetask{{%/badge%}} API endpoint is invoked via an {{%badge%}}Axios **POST**{{%/badge%}} request. - this API updates the task record in the NoSQL table with the newly provided values. - after the update operation is complete, the page will reload to reflect the latest data in the filtered task list. -------------------------------------------------------------------------------- title: "Test the Application" description: "Build a React task manager app to create and manage tasks. You can perform CRUD and filter functionality on tasks." last_updated: "2026-03-18T07:41:08.705Z" source: "https://docs.catalyst.zoho.com/en/tutorials/task-manager/nodejs/test-app/" service: "All Services" related: - Catalyst NoSQL Help Documentation (/en/cloud-scale/help/nosql/introduction/) - CLI Serve Resources (/en/cli/v1/serve-resources/introduction/) -------------------------------------------------------------------------------- # Test the Application Before you deploy the application to the remote console, you can {{%link href="/en/cli/v1/serve-resources/introduction/" %}}test the application{{%/link%}} on a local server and check if everything works using the Catalyst CLI. To serve the Catalyst project locally, execute the following command from your project directory: {{%cli%}}catalyst serve{{%/cli%}} {{%info%}}{{%bold%}}Info:{{%/bold%}} The application will be ideally served on the default port {{%badge%}}3001{{%/badge%}}. If the port happens to be occupied by another process in your local system, it will be served in the next available port.{{%/info%}} <br /> {{%note%}}{{%bold%}}Note:{{%/bold%}} Every time you access the home page or any of the sub-pages of your application, the CLI will display a live log of the URL accessed, along with the HTTP request method.{{%/note%}} <br /> You can now open the application’s localhost URL in a browser to access the Task Manager application. <br /> ### Test Create Functionality 1. Populate the required fields and click **Add Task**, to create a task. <br /> 2. The task will be created. You can verify, if your task has been created by searching for the data in the NoSQL table present in the console. <br /> 3. Choose the table *TaskHandler* from the Index drop-down, and search using either the {{%badge%}}UserID{{%/badge%}} (**Partition Key**), or {{%badge%}}Task Name{{%/badge%}} (**Sort Key**). Provide values for the required attributes to search by. <br /> ### Test Filter Functionality 1. Click the **Filter Task** button in the client app to navigate to the filter operations section. You can search for tasks that match the criteria of the filters you provide. <br /> 2. Enter the required inputs and click **Apply Filters**, to view the filtered results. <br /> ### Test Edit and Delete Operations After you've queried for a task, you can perform edit and delete operations on the task. To edit a task: 1. Click **Edit** to edit the task. <br /> 2. Click **Submit** once you've updated the task. <br /> The task will be updated. To delete a task: 1. Click **Delete** on the task you no longer require. <br /> 2. Click **OK** to confirm the delete operation. <br /> The task will be permanently deleted from the NoSQL table, and from the application. You can open NoSQL in your console to check if these updates were made. If the application is working as defined in this page, then you can deploy the application. -------------------------------------------------------------------------------- title: "Deploy The Application" description: "Build a React task manager app to create and manage tasks. You can perform CRUD and filter functionality on tasks." last_updated: "2026-03-18T07:41:08.706Z" source: "https://docs.catalyst.zoho.com/en/tutorials/task-manager/nodejs/deploy-app/" service: "All Services" related: - Catalyst NoSQL Help Documentation (/en/cloud-scale/help/nosql/introduction/) - Web Client Hosting Help Documentation (/en/cloud-scale/help/web-client-hosting/introduction/) - CLI Deploy Resources (/en/cli/v1/serve-resources/introduction/) -------------------------------------------------------------------------------- # Deploy The Application To {{%link href="/en/cli/v1/deploy-resources/introduction/" %}}deploy your Catalyst project{{%/link%}} from the CLI to the Catalyst console in the cloud, run the following command in your terminal from your project directory: {{%cli%}}catalyst deploy{{%/cli%}} <br /> The function is deployed first, followed by the client component. The URL endpoints of the components will be displayed in the CLI. <br /> You can access the deployed application from the **Web Client Hosting** component present in the *CloudScale* service section under the *HOST & MANAGE* section. <br /> You can now open the client component’s URL in a browser to access the deployed application. The **Task Manager** application can now be accessed from its web app URL. <br /> The Task Manager application is now functional and will work without any errors.