reactapp.js
· 6.4 KiB · JavaScript
Raw
/* eslint-disable jsx-a11y/aria-role */
import React, { useState } from "react";
function App() {
// Default agenda data for testing
const [agenda, setAgenda] = 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"],
},
]);
const [newTitle, setNewTitle] = useState("");
const [newDescription, setNewDescription] = useState("");
const [newTopic, setNewTopic] = useState("");
const [topics, setTopics] = useState([]);
const [showAddAgenda, setShowAddAgenda] = useState(true);
const [errors, setErrors] = useState({
title: "",
description: "",
topic: "",
});
// Form validation
const validateTitle = (title) => (title.trim() === "" ? "Title is required" : "");
const validateDescription = (description) => (description.trim() === "" ? "Description is required" : "");
const validateTopic = (topic) => (topic.trim() === "" ? "Topic is required" : "");
const handleTitleChange = (e) => {
setNewTitle(e.target.value);
setErrors({ ...errors, title: validateTitle(e.target.value) });
};
const handleDescriptionChange = (e) => {
setNewDescription(e.target.value);
setErrors({ ...errors, description: validateDescription(e.target.value) });
};
const handleTopicChange = (e) => {
setNewTopic(e.target.value);
setErrors({ ...errors, topic: validateTopic(e.target.value) });
};
const addTopic = () => {
if (validateTopic(newTopic) === "") {
setTopics([...topics, newTopic.trim()]);
setNewTopic("");
}
};
const submitAgenda = () => {
if (
validateTitle(newTitle) === "" &&
validateDescription(newDescription) === "" &&
topics.length > 0
) {
setAgenda([...agenda, { title: newTitle.trim(), description: newDescription.trim(), topics }]);
setNewTitle("");
setNewDescription("");
setTopics([]);
}
};
return (
<div>
<h1 className="mx-5 mb-5">Agenda Manager</h1>
{/* Add Agenda Template */}
{showAddAgenda && (
<div className="container" role="addAgenda">
<button className="btn btn-info" role="goToView" onClick={() => setShowAddAgenda(false)}>
Click To View Agenda
</button>
<form>
<div className="my-3">
<label className="form-label">Title</label>
<input
type="text"
placeholder="Enter the title"
className="form-control"
role="inputTitle"
value={newTitle}
onChange={handleTitleChange}
/>
<small className="text-danger" data-testid="invalidTitle">
{errors.title}
</small>
</div>
<div className="my-3">
<label className="form-label">Description</label>
<input
type="text"
placeholder="Enter the description"
className="form-control"
role="inputDescription"
value={newDescription}
onChange={handleDescriptionChange}
/>
<small className="text-danger" data-testid="invalidDescription">
{errors.description}
</small>
</div>
<div className="my-3 w-50">
<label className="form-label">Enter topic</label>
<input
type="text"
placeholder="Enter the topic"
className="form-control"
role="inputTopic"
value={newTopic}
onChange={handleTopicChange}
/>
<small className="text-danger" data-testid="invalidTopic">
{errors.topic}
</small>
</div>
<button
type="button"
className="btn btn-success addAlign"
role="addTopicBtn"
onClick={addTopic}
disabled={validateTopic(newTopic) !== ""}
>
+ Add Topic
</button>
<button
type="button"
className="btn btn-success submitAlign"
role="submitAgendaBtn"
onClick={submitAgenda}
disabled={
validateTitle(newTitle) !== "" || validateDescription(newDescription) !== "" || topics.length === 0
}
>
Submit Agenda
</button>
</form>
{topics.length === 0 && (
<div className="text-danger ml-2 mt-5" data-testid="noTopicsMsg">
No Topics Added
</div>
)}
{topics.length > 0 && (
<div className="card my-3">
<div className="card-header">Added Topics</div>
<div className="card-body">
<ul className="list-group">
{topics.map((topic, index) => (
<li className="list-group-item" role="topicList" key={index}>
{topic}
</li>
))}
</ul>
</div>
<div className="card-footer">Refer the topics you added</div>
</div>
)}
</div>
)}
{/* View Agenda Template */}
{!showAddAgenda && (
<div className="container" role="viewAgenda">
<button className="btn btn-info" role="goToAdd" onClick={() => setShowAddAgenda(true)}>
Click To Add Agenda
</button>
{agenda.map((item, index) => (
<div className="card my-3" role="cards" key={index}>
<div className="card-header">{item.title}</div>
<div className="card-body">
<ul className="list-group">
{item.topics.map((topic, idx) => (
<li className="list-group-item" key={idx}>
{topic}
</li>
))}
</ul>
</div>
<div className="card-footer">{item.description}</div>
</div>
))}
</div>
)}
</div>
);
}
export default App;
1 | /* eslint-disable jsx-a11y/aria-role */ |
2 | import React, { useState } from "react"; |
3 | |
4 | function App() { |
5 | // Default agenda data for testing |
6 | const [agenda, setAgenda] = useState([ |
7 | { |
8 | title: "Angular", |
9 | description: "Some description about the angular", |
10 | topics: ["Introduction", "Typescript", "Why Angular?", "Understanding Versions", "Fundamentals"], |
11 | }, |
12 | { |
13 | title: "Vue", |
14 | description: "Some description about the vue", |
15 | topics: ["Introduction", "Javascript", "Why Vue?", "Vue Bindings", "Component Interaction"], |
16 | }, |
17 | ]); |
18 | |
19 | const [newTitle, setNewTitle] = useState(""); |
20 | const [newDescription, setNewDescription] = useState(""); |
21 | const [newTopic, setNewTopic] = useState(""); |
22 | const [topics, setTopics] = useState([]); |
23 | const [showAddAgenda, setShowAddAgenda] = useState(true); |
24 | const [errors, setErrors] = useState({ |
25 | title: "", |
26 | description: "", |
27 | topic: "", |
28 | }); |
29 | |
30 | // Form validation |
31 | const validateTitle = (title) => (title.trim() === "" ? "Title is required" : ""); |
32 | const validateDescription = (description) => (description.trim() === "" ? "Description is required" : ""); |
33 | const validateTopic = (topic) => (topic.trim() === "" ? "Topic is required" : ""); |
34 | |
35 | const handleTitleChange = (e) => { |
36 | setNewTitle(e.target.value); |
37 | setErrors({ ...errors, title: validateTitle(e.target.value) }); |
38 | }; |
39 | |
40 | const handleDescriptionChange = (e) => { |
41 | setNewDescription(e.target.value); |
42 | setErrors({ ...errors, description: validateDescription(e.target.value) }); |
43 | }; |
44 | |
45 | const handleTopicChange = (e) => { |
46 | setNewTopic(e.target.value); |
47 | setErrors({ ...errors, topic: validateTopic(e.target.value) }); |
48 | }; |
49 | |
50 | const addTopic = () => { |
51 | if (validateTopic(newTopic) === "") { |
52 | setTopics([...topics, newTopic.trim()]); |
53 | setNewTopic(""); |
54 | } |
55 | }; |
56 | |
57 | const submitAgenda = () => { |
58 | if ( |
59 | validateTitle(newTitle) === "" && |
60 | validateDescription(newDescription) === "" && |
61 | topics.length > 0 |
62 | ) { |
63 | setAgenda([...agenda, { title: newTitle.trim(), description: newDescription.trim(), topics }]); |
64 | setNewTitle(""); |
65 | setNewDescription(""); |
66 | setTopics([]); |
67 | } |
68 | }; |
69 | |
70 | return ( |
71 | <div> |
72 | <h1 className="mx-5 mb-5">Agenda Manager</h1> |
73 | |
74 | {/* Add Agenda Template */} |
75 | {showAddAgenda && ( |
76 | <div className="container" role="addAgenda"> |
77 | <button className="btn btn-info" role="goToView" onClick={() => setShowAddAgenda(false)}> |
78 | Click To View Agenda |
79 | </button> |
80 | <form> |
81 | <div className="my-3"> |
82 | <label className="form-label">Title</label> |
83 | <input |
84 | type="text" |
85 | placeholder="Enter the title" |
86 | className="form-control" |
87 | role="inputTitle" |
88 | value={newTitle} |
89 | onChange={handleTitleChange} |
90 | /> |
91 | <small className="text-danger" data-testid="invalidTitle"> |
92 | {errors.title} |
93 | </small> |
94 | </div> |
95 | |
96 | <div className="my-3"> |
97 | <label className="form-label">Description</label> |
98 | <input |
99 | type="text" |
100 | placeholder="Enter the description" |
101 | className="form-control" |
102 | role="inputDescription" |
103 | value={newDescription} |
104 | onChange={handleDescriptionChange} |
105 | /> |
106 | <small className="text-danger" data-testid="invalidDescription"> |
107 | {errors.description} |
108 | </small> |
109 | </div> |
110 | |
111 | <div className="my-3 w-50"> |
112 | <label className="form-label">Enter topic</label> |
113 | <input |
114 | type="text" |
115 | placeholder="Enter the topic" |
116 | className="form-control" |
117 | role="inputTopic" |
118 | value={newTopic} |
119 | onChange={handleTopicChange} |
120 | /> |
121 | <small className="text-danger" data-testid="invalidTopic"> |
122 | {errors.topic} |
123 | </small> |
124 | </div> |
125 | |
126 | <button |
127 | type="button" |
128 | className="btn btn-success addAlign" |
129 | role="addTopicBtn" |
130 | onClick={addTopic} |
131 | disabled={validateTopic(newTopic) !== ""} |
132 | > |
133 | + Add Topic |
134 | </button> |
135 | |
136 | <button |
137 | type="button" |
138 | className="btn btn-success submitAlign" |
139 | role="submitAgendaBtn" |
140 | onClick={submitAgenda} |
141 | disabled={ |
142 | validateTitle(newTitle) !== "" || validateDescription(newDescription) !== "" || topics.length === 0 |
143 | } |
144 | > |
145 | Submit Agenda |
146 | </button> |
147 | </form> |
148 | |
149 | {topics.length === 0 && ( |
150 | <div className="text-danger ml-2 mt-5" data-testid="noTopicsMsg"> |
151 | No Topics Added |
152 | </div> |
153 | )} |
154 | |
155 | {topics.length > 0 && ( |
156 | <div className="card my-3"> |
157 | <div className="card-header">Added Topics</div> |
158 | <div className="card-body"> |
159 | <ul className="list-group"> |
160 | {topics.map((topic, index) => ( |
161 | <li className="list-group-item" role="topicList" key={index}> |
162 | {topic} |
163 | </li> |
164 | ))} |
165 | </ul> |
166 | </div> |
167 | <div className="card-footer">Refer the topics you added</div> |
168 | </div> |
169 | )} |
170 | </div> |
171 | )} |
172 | |
173 | {/* View Agenda Template */} |
174 | {!showAddAgenda && ( |
175 | <div className="container" role="viewAgenda"> |
176 | <button className="btn btn-info" role="goToAdd" onClick={() => setShowAddAgenda(true)}> |
177 | Click To Add Agenda |
178 | </button> |
179 | |
180 | {agenda.map((item, index) => ( |
181 | <div className="card my-3" role="cards" key={index}> |
182 | <div className="card-header">{item.title}</div> |
183 | <div className="card-body"> |
184 | <ul className="list-group"> |
185 | {item.topics.map((topic, idx) => ( |
186 | <li className="list-group-item" key={idx}> |
187 | {topic} |
188 | </li> |
189 | ))} |
190 | </ul> |
191 | </div> |
192 | <div className="card-footer">{item.description}</div> |
193 | </div> |
194 | ))} |
195 | </div> |
196 | )} |
197 | </div> |
198 | ); |
199 | } |
200 | |
201 | export default App; |
202 | |
203 | |
204 |