Skip to content

Instantly share code, notes, and snippets.

@HarshalRathore
Created September 28, 2025 15:03
Show Gist options
  • Save HarshalRathore/762ae1fac8c91f4d445fbb982bb42ba7 to your computer and use it in GitHub Desktop.
Save HarshalRathore/762ae1fac8c91f4d445fbb982bb42ba7 to your computer and use it in GitHub Desktop.
React Agenda Manager App.js for ievolve 62636 Assessment - Full Code with Topics and Agenda Management
/* eslint-disable jsx-a11y/aria-role */
import React, { useState } from "react";
function App() {
/**
* keep this following data as default data in agenda details as it is required for testing
* [
{
title: "Angular",
description: "Some description about the angular",
topics: ["Introduction", "Typescript", "Why Angular?", "Understanding Versions", "Fundamentals"]
},
{
title: "Vue",
description: "Some description about the vue",
topics: ["Introduction", "Javascript", "Why Vue?", "Vue Bindings", "Component Interaction"]
},
],
*/
// your data goes here (state)
const [newTitle, setnewTitle] = useState('');
const [newDescription, setnewDescription] = useState('');
const [newTopic, setnewTopic] = useState('');
const [addedTopic, setaddedTopic] = useState([]);
const [showAgendaBlock, setshowAgendaBlock] = useState(false);
const [addedAgenda, setaddedAgenda] = useState([
{
title: "Angular",
description: "Some description about the angular",
topics: ["Introduction", "Typescript", "Why Angular?", "Understanding Versions", "Fundamentals"]
},
{
title: "Vue",
description: "Some description about the vue",
topics: ["Introduction", "Javascript", "Why Vue?", "Vue Bindings", "Component Interaction"]
},
]);
// your methods goes here
const handleChangeFn = (e) => {
const value = e.target.value;
const name = e.target.name;
if (name === 'newTitle') {
setnewTitle(value);
} else if (name === 'newDescription') {
setnewDescription(value);
} else if (name === 'newTopic') {
setnewTopic(value);
}
}
const addTopicFn = (e) => {
e.preventDefault();
setaddedTopic(addedTopic.concat(newTopic));
setnewTopic("");
}
const addAgendaFn = (e) => {
e.preventDefault();
var agenda = {
title: newTitle,
description: newDescription,
topics: addedTopic
}
setnewTitle("");
setnewDescription("");
setnewTopic("");
setaddedTopic([]);
setaddedAgenda(addedAgenda.concat(agenda));
}
const preventSubmit = (e) => {
e.preventDefault();
}
const showAgendaBlockFn = (e) => {
showAgendaBlock === false ? setshowAgendaBlock(true) : setshowAgendaBlock(false);
}
return (
<div>
<h1 className="mx-5 mb-5">Agenda Manager</h1>
{/* show/hide this following add agenda template */}
{!showAgendaBlock &&
<div className="container" role="addAgenda">
<button className="btn btn-info" role="goToView" onClick={showAgendaBlockFn}>
Click To View Agenda
</button>
<form onSubmit={preventSubmit}>
<div className="my-3">
<label className="form-label">Title</label>
{/* title */}
<input
type="text"
name="newTitle"
placeholder="Enter the title"
className="form-control"
role="inputTitle"
value={newTitle} onChange={handleChangeFn}
/>
<small className="text-danger" data-testid="invalidTitle">
{newTitle.trim().length === 0 ? "Title is required" : ""}
</small>
</div>
<div className="my-3">
<label className="form-label">Description</label>
{/* description */}
<input
type="text"
name="newDescription"
placeholder="Enter the description"
className="form-control"
role="inputDescription"
value={newDescription} onChange={handleChangeFn}
/>
<small className="text-danger" data-testid="invalidDescription">
{newDescription.trim().length === 0 ? "Description is required" : ""}
</small>
</div>
<div className="my-3 w-50">
<label className="form-label">Enter topic</label>
{/* topic */}
<input
type="text"
name="newTopic"
placeholder="Enter the topic"
className="form-control"
role="inputTopic"
value={newTopic} onChange={handleChangeFn}
/>
<small className="text-danger" data-testid="invalidTopic">
{newTopic.trim().length === 0 && addedTopic.length === 0 ? "Topic is required" : ""}
</small>
</div>
{/* on click should add topics and disable the button if invalid topic */}
<button className="btn btn-success addAlign" role="addTopicBtn" onClick={addTopicFn} disabled={newTopic.trim().length === 0}>
+ Add Topic
</button>
{/* on click should add agenda details and disable the button if invalid inputs */}
<button
className="btn btn-success submitAlign"
role="submitAgendaBtn"
onClick={addAgendaFn}
disabled={newTitle.trim().length === 0 || newDescription.trim().length === 0 || addedTopic.length === 0}
>
Submit Agenda
</button>
</form>
{/* show if no topics added yet */}
{addedTopic.length === 0 &&
<div className="text-danger ml-2 mt-5" data-testid="noTopicsMsg">
No Topics Added
</div>}
{/* display the list of topics added using li */}
{addedTopic.length !== 0 &&
<div className="card my-3">
<div className="card-header">Added Topics</div>
<div className="card-body">
<ul className="list-group">
{addedTopic.map((topic) => (
<li className="list-group-item" role="topicList" key={topic}>
{topic}
</li>
))}
{/* topics list */}
</ul>
</div>
<div className="card-footer">Refer the topics you added</div>
</div>}
</div>}
{/* show/hide this following view agenda template */}
{showAgendaBlock &&
<div className="container" role="viewAgenda">
<button className="btn btn-info" role="goToAdd" onClick={showAgendaBlockFn}>
Click To Add Agenda
</button>
{/* iterate the agenda details to display */}
{addedAgenda.map((agenda) => (
<div className="card my-3" role="cards" key={agenda.title}>
<div className="card-header">{agenda.title}</div>
<div className="card-body">
<ul className="list-group">
{/* iterate the topics to display */}
{agenda.topics.map((topic) => (
<li className="list-group-item" key={topic}>
{topic}
{/* {topic} */}
</li>
))}
</ul>
</div>
<div className="card-footer">{agenda.description}</div>
</div>
))}
</div>}
</div>
);
}
export default App;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment