Last active 1749835442

Revision 68e1738777a7f7b82bc22171de59df29e93e63ee

reactapp.js Raw
1/* eslint-disable jsx-a11y/aria-role */
2import React, { useState } from "react";
3
4function 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
201export default App;
202
203
204