eleven-solutions-common-website-unique-web 21.0.56 → 22.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/App.d.ts +0 -3
- package/dist/App.js +0 -2
- package/dist/components/admin/Sidebar.d.ts +0 -1
- package/dist/components/admin/Sidebar.js +2 -2
- package/dist/components/admin/UserForm.js +6 -5
- package/dist/components/admin/Users.js +4 -3
- package/dist/components/footer/Footer.d.ts +3 -2
- package/dist/components/footer/Footer.js +2 -3
- package/dist/components/index.d.ts +3 -2
- package/dist/components/index.js +3 -2
- package/dist/components/login/GoogleButton.js +4 -1
- package/dist/components/login/Header.d.ts +3 -1
- package/dist/components/login/Header.js +135 -31
- package/dist/components/login/Login.d.ts +2 -1
- package/dist/components/login/Login.js +15 -65
- package/dist/components/login/Setcookie.d.ts +2 -0
- package/dist/components/login/Setcookie.js +7 -0
- package/dist/components/redux/slices/types/types.d.ts +3 -0
- package/dist/components/redux/slices/types/types.js +1 -0
- package/dist/components/redux/slices/userSlice.d.ts +20 -0
- package/dist/components/redux/slices/userSlice.js +90 -0
- package/dist/components/useraccount/UpdateUserDetails.d.ts +1 -0
- package/dist/components/useraccount/UpdateUserDetails.js +15 -22
- package/package.json +9 -4
- package/.github/workflows/main.yml +0 -22
- package/azure-pipelines.yml +0 -20
- package/dist/components/Navbar.d.ts +0 -6
- package/dist/components/Navbar.js +0 -5
- package/dist/components/login/View.d.ts +0 -2
- package/dist/components/login/View.js +0 -10
- package/dist/components/useraccount/AddMissingDetails.d.ts +0 -9
- package/dist/components/useraccount/AddMissingDetails.js +0 -56
- package/dist/components/useraccount/AddUserDetails.d.ts +0 -9
- package/dist/components/useraccount/AddUserDetails.js +0 -21
- package/src/App.tsx +0 -21
- package/src/components/Navbar.tsx +0 -21
- package/src/components/admin/Dashboard.tsx +0 -7
- package/src/components/admin/Editor.tsx +0 -25
- package/src/components/admin/Sidebar.tsx +0 -102
- package/src/components/admin/Taxionomies.tsx +0 -314
- package/src/components/admin/TaxonomyForm.tsx +0 -744
- package/src/components/admin/Template.tsx +0 -304
- package/src/components/admin/TemplateForm.tsx +0 -141
- package/src/components/admin/UserForm.tsx +0 -231
- package/src/components/admin/Users.tsx +0 -479
- package/src/components/api/api.ts +0 -59
- package/src/components/api/taxonomy.ts +0 -201
- package/src/components/api/template.ts +0 -114
- package/src/components/api/updateuser.ts +0 -53
- package/src/components/api/user.ts +0 -133
- package/src/components/footer/Footer.tsx +0 -128
- package/src/components/footer/Privacy.tsx +0 -82
- package/src/components/footer/Terms.tsx +0 -156
- package/src/components/index.ts +0 -19
- package/src/components/login/GoogleButton.tsx +0 -85
- package/src/components/login/Header.tsx +0 -340
- package/src/components/login/Login.tsx +0 -277
- package/src/components/useraccount/AddUserDetails.tsx +0 -136
- package/src/components/useraccount/UpdateUserDetails.tsx +0 -214
- package/src/index.ts +0 -1
- package/tsconfig.json +0 -15
@@ -1,304 +0,0 @@
|
|
1
|
-
import React from "react";
|
2
|
-
import { useState, useEffect } from "react";
|
3
|
-
import { FaPlus } from "react-icons/fa";
|
4
|
-
import { fetchTemplatesApi, deleteTemplateApi } from "../api/template";
|
5
|
-
|
6
|
-
interface TemplateProps {
|
7
|
-
url: string;
|
8
|
-
}
|
9
|
-
|
10
|
-
const Template = ({ url }: TemplateProps) => {
|
11
|
-
const [templates, setTemplates] = useState<any[]>([]);
|
12
|
-
|
13
|
-
const fetchTemplatesData = async () => {
|
14
|
-
const data = await fetchTemplatesApi(url);
|
15
|
-
if (data) {
|
16
|
-
setTemplates(data as any[]);
|
17
|
-
} else {
|
18
|
-
console.error("Failed to fetch templates");
|
19
|
-
}
|
20
|
-
};
|
21
|
-
|
22
|
-
useEffect(() => {
|
23
|
-
fetchTemplatesData();
|
24
|
-
}, []);
|
25
|
-
|
26
|
-
const handleNavigation = (event: React.MouseEvent, path: string) => {
|
27
|
-
event.preventDefault();
|
28
|
-
window.history.pushState({}, "", path);
|
29
|
-
window.dispatchEvent(new PopStateEvent("popstate"));
|
30
|
-
};
|
31
|
-
|
32
|
-
//Pagination
|
33
|
-
|
34
|
-
const [currentPage, setCurrentPage] = useState(1);
|
35
|
-
const itemsPerPage = 10;
|
36
|
-
|
37
|
-
const totalPages = Math.ceil(templates.length / itemsPerPage);
|
38
|
-
|
39
|
-
const handleNextPage = () => {
|
40
|
-
if (currentPage < totalPages) {
|
41
|
-
setCurrentPage(currentPage + 1);
|
42
|
-
}
|
43
|
-
};
|
44
|
-
|
45
|
-
const handlePreviousPage = () => {
|
46
|
-
if (currentPage > 1) {
|
47
|
-
setCurrentPage(currentPage - 1);
|
48
|
-
}
|
49
|
-
};
|
50
|
-
|
51
|
-
const handlePageClick = (pageNumber: number) => {
|
52
|
-
setCurrentPage(pageNumber);
|
53
|
-
};
|
54
|
-
|
55
|
-
const paginatedTemplates = templates.slice(
|
56
|
-
(currentPage - 1) * itemsPerPage,
|
57
|
-
currentPage * itemsPerPage
|
58
|
-
);
|
59
|
-
|
60
|
-
const handleEditClick = (
|
61
|
-
event: React.MouseEvent,
|
62
|
-
path: string,
|
63
|
-
id: string
|
64
|
-
) => {
|
65
|
-
event.preventDefault();
|
66
|
-
window.history.pushState({}, "", path + id);
|
67
|
-
window.dispatchEvent(new PopStateEvent("popstate"));
|
68
|
-
};
|
69
|
-
|
70
|
-
const handleDeleteClick = async (id: string) => {
|
71
|
-
try {
|
72
|
-
await deleteTemplateApi(url, id);
|
73
|
-
alert("Template deleted successfully");
|
74
|
-
|
75
|
-
fetchTemplatesData();
|
76
|
-
} catch (error) {
|
77
|
-
console.error("Error deleting Template:", error);
|
78
|
-
}
|
79
|
-
};
|
80
|
-
|
81
|
-
return (
|
82
|
-
<div className="container px-4 mx-auto mt-6 h-full">
|
83
|
-
<div className="w-3/4">
|
84
|
-
<h1 className="text-3xl font-bold text-blue-600 mb-5">Template</h1>
|
85
|
-
</div>
|
86
|
-
<div className="flex-grow ml-0 w-full mt-10">
|
87
|
-
<form className="w-full ">
|
88
|
-
<label
|
89
|
-
htmlFor="default-search"
|
90
|
-
className="mb-2 text-sm font-medium text-gray-900 sr-only dark:text-white"
|
91
|
-
>
|
92
|
-
Search
|
93
|
-
</label>
|
94
|
-
<div className="relative w-full">
|
95
|
-
<div className="absolute inset-y-0 start-0 flex items-center ps-3 pointer-events-none">
|
96
|
-
<svg
|
97
|
-
className="w-4 h-4 text-gray-500 dark:text-gray-400"
|
98
|
-
aria-hidden="true"
|
99
|
-
xmlns="http://www.w3.org/2000/svg"
|
100
|
-
fill="none"
|
101
|
-
viewBox="0 0 20 20"
|
102
|
-
>
|
103
|
-
<path
|
104
|
-
stroke="currentColor"
|
105
|
-
stroke-linecap="round"
|
106
|
-
stroke-linejoin="round"
|
107
|
-
stroke-width="2"
|
108
|
-
d="m19 19-4-4m0-7A7 7 0 1 1 1 8a7 7 0 0 1 14 0Z"
|
109
|
-
/>
|
110
|
-
</svg>
|
111
|
-
</div>
|
112
|
-
<input
|
113
|
-
type="search"
|
114
|
-
id="default-search"
|
115
|
-
className="inline-block min-w-full p-3 ps-10 outline-none text-sm text-gray-900 border border-gray-300 rounded-lg bg-gray-50 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
|
116
|
-
placeholder="Search Templates"
|
117
|
-
required
|
118
|
-
/>
|
119
|
-
<button
|
120
|
-
type="submit"
|
121
|
-
className="text-white absolute end-1.5 bottom-1.5 bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-4 py-2 dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800"
|
122
|
-
>
|
123
|
-
Search
|
124
|
-
</button>
|
125
|
-
</div>
|
126
|
-
</form>
|
127
|
-
</div>
|
128
|
-
<div className="flex-grow ml-0 w-3/4">
|
129
|
-
<form className="w-auto">{/* Search Form */}</form>
|
130
|
-
</div>
|
131
|
-
<div className="flex-grow ml-0 mt-4 w-full">
|
132
|
-
<div className="overflow-hidden border border-gray-200 dark:border-gray-700 md:rounded-lg mt-6">
|
133
|
-
<table className="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
|
134
|
-
<thead className="bg-gray-50 dark:bg-gray-800">
|
135
|
-
<tr>
|
136
|
-
<th
|
137
|
-
scope="col"
|
138
|
-
className="px-4 py-3.5 text-md font-normal text-left rtl:text-right text-gray-500 dark:text-gray-400"
|
139
|
-
style={{ width: "200px" }}
|
140
|
-
>
|
141
|
-
Actions
|
142
|
-
</th>
|
143
|
-
<th
|
144
|
-
scope="col"
|
145
|
-
className="py-3.5 px-4 text-md font-normal text-left rtl:text-right text-gray-500 dark:text-gray-400"
|
146
|
-
>
|
147
|
-
<div className="flex items-center gap-x-3">
|
148
|
-
<span>Name</span>
|
149
|
-
</div>
|
150
|
-
</th>
|
151
|
-
</tr>
|
152
|
-
</thead>
|
153
|
-
<tbody className="bg-white divide-y divide-gray-200 dark:divide-gray-700 dark:bg-gray-900">
|
154
|
-
{paginatedTemplates
|
155
|
-
.filter((template) => !template.isDeleted)
|
156
|
-
.map((template, index) => (
|
157
|
-
<tr key={template.id || index}>
|
158
|
-
<td className="px-4 py-4 text-sm whitespace-nowrap">
|
159
|
-
<div className="flex items-center gap-x-6">
|
160
|
-
<button
|
161
|
-
onClick={() => handleDeleteClick(template.id)}
|
162
|
-
className="text-gray-500 transition-colors duration-200 dark:hover:text-red-600 dark:text-gray-300 hover:text-red-500 focus:outline-none"
|
163
|
-
>
|
164
|
-
<svg
|
165
|
-
xmlns="http://www.w3.org/2000/svg"
|
166
|
-
fill="none"
|
167
|
-
viewBox="0 0 24 24"
|
168
|
-
stroke-width="1.5"
|
169
|
-
stroke="currentColor"
|
170
|
-
className="w-5 h-5"
|
171
|
-
>
|
172
|
-
<path
|
173
|
-
stroke-linecap="round"
|
174
|
-
stroke-linejoin="round"
|
175
|
-
d="M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0"
|
176
|
-
/>
|
177
|
-
</svg>
|
178
|
-
</button>
|
179
|
-
|
180
|
-
<button
|
181
|
-
onClick={(event) =>
|
182
|
-
handleEditClick(
|
183
|
-
event,
|
184
|
-
"/admin/template/templateform?id=",
|
185
|
-
template.id
|
186
|
-
)
|
187
|
-
}
|
188
|
-
className="text-gray-500 transition-colors duration-200 dark:hover:text-yellow-500 dark:text-gray-300 hover:text-yellow-500 focus:outline-none"
|
189
|
-
>
|
190
|
-
<svg
|
191
|
-
xmlns="http://www.w3.org/2000/svg"
|
192
|
-
fill="none"
|
193
|
-
viewBox="0 0 24 24"
|
194
|
-
strokeWidth="1.5"
|
195
|
-
stroke="currentColor"
|
196
|
-
className="w-5 h-5"
|
197
|
-
>
|
198
|
-
<path
|
199
|
-
strokeLinecap="round"
|
200
|
-
strokeLinejoin="round"
|
201
|
-
d="M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L10.582 16.07a4.5 4.5 0 01-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 011.13-1.897l8.932-8.931zm0 0L19.5 7.125M18 14v4.75A2.25 2.25 0 0115.75 21H5.25A2.25 2.25 0 013 18.75V8.25A2.25 2.25 0 015.25 6H10"
|
202
|
-
/>
|
203
|
-
</svg>
|
204
|
-
</button>
|
205
|
-
</div>
|
206
|
-
</td>
|
207
|
-
<td className="px-4 py-4 text-sm font-medium text-gray-700 whitespace-nowrap">
|
208
|
-
<div className="inline-flex items-center gap-x-3">
|
209
|
-
<div className="flex items-center gap-x-2">
|
210
|
-
<div>
|
211
|
-
<h2 className=" text-sm font-medium text-gray-800 dark:text-white ">
|
212
|
-
{template.name}
|
213
|
-
</h2>
|
214
|
-
</div>
|
215
|
-
</div>
|
216
|
-
</div>
|
217
|
-
</td>
|
218
|
-
</tr>
|
219
|
-
))}
|
220
|
-
</tbody>
|
221
|
-
</table>
|
222
|
-
</div>
|
223
|
-
|
224
|
-
<div className="flex items-center justify-between mt-6">
|
225
|
-
<button
|
226
|
-
onClick={handlePreviousPage}
|
227
|
-
disabled={currentPage === 1}
|
228
|
-
className="flex items-center px-5 py-2 text-sm text-gray-700 capitalize transition-colors duration-200 bg-white border rounded-md gap-x-2 hover:bg-gray-100 dark:bg-gray-900 dark:text-gray-200 dark:border-gray-700 dark:hover:bg-gray-800"
|
229
|
-
>
|
230
|
-
<svg
|
231
|
-
xmlns="http://www.w3.org/2000/svg"
|
232
|
-
fill="none"
|
233
|
-
viewBox="0 0 24 24"
|
234
|
-
stroke-width="1.5"
|
235
|
-
stroke="currentColor"
|
236
|
-
className="w-5 h-5 rtl:-scale-x-100"
|
237
|
-
>
|
238
|
-
<path
|
239
|
-
stroke-linecap="round"
|
240
|
-
stroke-linejoin="round"
|
241
|
-
d="M6.75 15.75L3 12m0 0l3.75-3.75M3 12h18"
|
242
|
-
/>
|
243
|
-
</svg>
|
244
|
-
|
245
|
-
<span>previous</span>
|
246
|
-
</button>
|
247
|
-
|
248
|
-
<div className="items-center hidden lg:flex gap-x-3">
|
249
|
-
{Array.from({ length: totalPages }, (_, index) => (
|
250
|
-
<button
|
251
|
-
key={index + 1}
|
252
|
-
onClick={() => handlePageClick(index + 1)}
|
253
|
-
className={`px-2 py-1 text-sm ${
|
254
|
-
currentPage === index + 1
|
255
|
-
? "text-blue-500 bg-blue-100"
|
256
|
-
: "text-gray-500 hover:bg-gray-100"
|
257
|
-
} rounded-md`}
|
258
|
-
>
|
259
|
-
{index + 1}
|
260
|
-
</button>
|
261
|
-
))}
|
262
|
-
</div>
|
263
|
-
<button
|
264
|
-
onClick={handleNextPage}
|
265
|
-
disabled={currentPage === totalPages}
|
266
|
-
className="flex items-center px-5 py-2 text-sm text-gray-700 capitalize transition-colors duration-200 bg-white border rounded-md gap-x-2 hover:bg-gray-100 dark:bg-gray-900 dark:text-gray-200 dark:border-gray-700 dark:hover:bg-gray-800"
|
267
|
-
>
|
268
|
-
<span>Next</span>
|
269
|
-
|
270
|
-
<svg
|
271
|
-
xmlns="http://www.w3.org/2000/svg"
|
272
|
-
fill="none"
|
273
|
-
viewBox="0 0 24 24"
|
274
|
-
stroke-width="1.5"
|
275
|
-
stroke="currentColor"
|
276
|
-
className="w-5 h-5 rtl:-scale-x-100"
|
277
|
-
>
|
278
|
-
<path
|
279
|
-
stroke-linecap="round"
|
280
|
-
stroke-linejoin="round"
|
281
|
-
d="M17.25 8.25L21 12m0 0l-3.75 3.75M21 12H3"
|
282
|
-
/>
|
283
|
-
</svg>
|
284
|
-
</button>
|
285
|
-
</div>
|
286
|
-
|
287
|
-
<div className="flex-grow ml-0 mt-4 w-0">
|
288
|
-
<button
|
289
|
-
type="button"
|
290
|
-
onClick={(event) =>
|
291
|
-
handleNavigation(event, "/admin/template/templateform")
|
292
|
-
}
|
293
|
-
className="flex items-center justify-center px-6 py-2 font-medium tracking-wide text-white capitalize transition-colors duration-300 transform bg-blue-600 rounded-lg hover:bg-blue-500 focus:outline-none focus:ring focus:ring-blue-300 focus:ring-opacity-80"
|
294
|
-
>
|
295
|
-
<FaPlus className="mr-2 font-medium" />
|
296
|
-
Template
|
297
|
-
</button>
|
298
|
-
</div>
|
299
|
-
</div>
|
300
|
-
</div>
|
301
|
-
);
|
302
|
-
};
|
303
|
-
|
304
|
-
export default Template;
|
@@ -1,141 +0,0 @@
|
|
1
|
-
import React, { useState, useEffect, useRef, useMemo } from "react";
|
2
|
-
import {
|
3
|
-
addTemplateApi,
|
4
|
-
fetchTemplateByIdApi,
|
5
|
-
updateTemplateApi,
|
6
|
-
} from "../api/template";
|
7
|
-
|
8
|
-
import Editor from "./Editor";
|
9
|
-
|
10
|
-
interface TemplateFormProps {
|
11
|
-
url: string;
|
12
|
-
}
|
13
|
-
|
14
|
-
const TemplateForm = ({ url }: TemplateFormProps) => {
|
15
|
-
const [name, setName] = useState("");
|
16
|
-
const [content, setContent] = useState("");
|
17
|
-
const placeholder = "";
|
18
|
-
|
19
|
-
const [isEditMode, setIsEditMode] = useState<boolean>(false);
|
20
|
-
|
21
|
-
const editor = useRef(null);
|
22
|
-
const config: Record<string, any> = useMemo(
|
23
|
-
() => ({
|
24
|
-
readonly: false,
|
25
|
-
placeholder: placeholder || "",
|
26
|
-
}),
|
27
|
-
[placeholder]
|
28
|
-
);
|
29
|
-
|
30
|
-
const validateForm = () => {
|
31
|
-
if (!name || !content) {
|
32
|
-
alert("Please fill in all required fields: Name and Content.");
|
33
|
-
return false;
|
34
|
-
}
|
35
|
-
return true;
|
36
|
-
};
|
37
|
-
|
38
|
-
const queryParams = new URLSearchParams(window.location.search);
|
39
|
-
const id = queryParams.get("id");
|
40
|
-
|
41
|
-
useEffect(() => {
|
42
|
-
if (id) {
|
43
|
-
const fetchTemplateData = async () => {
|
44
|
-
try {
|
45
|
-
const fetchedUser = await fetchTemplateByIdApi(url, id);
|
46
|
-
if (fetchedUser) {
|
47
|
-
const user = fetchedUser as {
|
48
|
-
name: string;
|
49
|
-
content: string;
|
50
|
-
};
|
51
|
-
setIsEditMode(true);
|
52
|
-
setName(user.name);
|
53
|
-
setContent(user.content);
|
54
|
-
}
|
55
|
-
} catch (error) {
|
56
|
-
console.error("Unable to fetch user data", error);
|
57
|
-
}
|
58
|
-
};
|
59
|
-
fetchTemplateData();
|
60
|
-
}
|
61
|
-
}, [id]);
|
62
|
-
|
63
|
-
const handleSubmit = async (event: React.MouseEvent<HTMLButtonElement>) => {
|
64
|
-
event.preventDefault();
|
65
|
-
if (!validateForm()) return;
|
66
|
-
|
67
|
-
try {
|
68
|
-
if (isEditMode) {
|
69
|
-
await updateTemplateApi(url, id, name, content);
|
70
|
-
alert("Template updated successfully");
|
71
|
-
} else {
|
72
|
-
await addTemplateApi(url, name, content);
|
73
|
-
alert("Template added successfully");
|
74
|
-
}
|
75
|
-
window.history.pushState({}, "", "/admin/template");
|
76
|
-
window.dispatchEvent(new PopStateEvent("popstate"));
|
77
|
-
} catch (error) {
|
78
|
-
console.error("Error adding/updating Template:", error);
|
79
|
-
alert("Failed to add/update Template");
|
80
|
-
}
|
81
|
-
};
|
82
|
-
|
83
|
-
const handleCancelClick = () => {
|
84
|
-
setName("");
|
85
|
-
setContent("");
|
86
|
-
|
87
|
-
window.history.pushState({}, "", "/admin/template");
|
88
|
-
window.dispatchEvent(new PopStateEvent("popstate"));
|
89
|
-
};
|
90
|
-
|
91
|
-
return (
|
92
|
-
<div className="w-full pr-16">
|
93
|
-
<div className="flex-grow p-6">
|
94
|
-
<form>
|
95
|
-
<h1 className="text-3xl font-bold text-center text-blue-600 capitalize dark:text-white mb-4">
|
96
|
-
{isEditMode ? "Edit Template" : "Add Template"}
|
97
|
-
</h1>
|
98
|
-
|
99
|
-
<div className="mb-6 w-full">
|
100
|
-
<label className="text-gray-900 dark:text-gray-200 font-semibold">
|
101
|
-
Name <span className="text-red-500">*</span>
|
102
|
-
</label>
|
103
|
-
<input
|
104
|
-
required
|
105
|
-
type="text"
|
106
|
-
value={name}
|
107
|
-
onChange={(e) => setName(e.target.value)}
|
108
|
-
className="w-full px-4 py-2 mt-2 text-gray-800 bg-white border border-gray-400 rounded-md dark:bg-gray-800 dark:text-gray-300 dark:border-gray-800 focus:border-blue-400 focus:ring-blue-300 focus:ring-opacity-40 dark:focus:border-blue-300 focus:outline-none focus:ring"
|
109
|
-
placeholder="Enter Name"
|
110
|
-
/>
|
111
|
-
</div>
|
112
|
-
<div className="mb-6 w-full">
|
113
|
-
<label className="text-gray-900 dark:text-gray-200 font-semibold">
|
114
|
-
Content <span className="text-red-500">*</span>
|
115
|
-
</label>
|
116
|
-
<Editor content={content} setContent={setContent} config={config} />
|
117
|
-
</div>
|
118
|
-
|
119
|
-
<div className="flex space-x-4 mt-6 justify-end">
|
120
|
-
<button
|
121
|
-
type="submit"
|
122
|
-
onClick={handleSubmit}
|
123
|
-
className="px-8 py-2.5 leading-5 text-white transition-colors duration-300 transform bg-blue-600 rounded-md hover:bg-blue-500 focus:outline-none focus:bg-gray-600"
|
124
|
-
>
|
125
|
-
{isEditMode ? "Edit" : "Add"}
|
126
|
-
</button>
|
127
|
-
<button
|
128
|
-
type="button"
|
129
|
-
onClick={handleCancelClick}
|
130
|
-
className="px-8 py-2.5 leading-5 text-white transition-colors duration-300 transform bg-blue-600 rounded-md hover:bg-blue-500 focus:outline-none focus:bg-gray-600"
|
131
|
-
>
|
132
|
-
Cancel
|
133
|
-
</button>
|
134
|
-
</div>
|
135
|
-
</form>
|
136
|
-
</div>
|
137
|
-
</div>
|
138
|
-
);
|
139
|
-
};
|
140
|
-
|
141
|
-
export default TemplateForm;
|
@@ -1,231 +0,0 @@
|
|
1
|
-
import React from "react";
|
2
|
-
import { useState, useEffect } from "react";
|
3
|
-
|
4
|
-
import { addUserApi, updateUserApi, fetchUserByIdApi } from "../api/user";
|
5
|
-
|
6
|
-
interface UserFormProps {
|
7
|
-
url: string;
|
8
|
-
}
|
9
|
-
|
10
|
-
const UserForm = ({ url }: UserFormProps) => {
|
11
|
-
const [userName, setUserName] = useState("");
|
12
|
-
const [email, setEmail] = useState("");
|
13
|
-
const [mobile, setMobile] = useState("");
|
14
|
-
const [address, setAddress] = useState("");
|
15
|
-
const [roleType, setRoleType] = useState("");
|
16
|
-
const [gender, setGender] = useState("");
|
17
|
-
|
18
|
-
const [isEditMode, setIsEditMode] = useState<boolean>(false);
|
19
|
-
|
20
|
-
const validateForm = () => {
|
21
|
-
if (!userName || !roleType) {
|
22
|
-
alert(
|
23
|
-
"Please fill in all required fields: User Name, Email, and Role Type."
|
24
|
-
);
|
25
|
-
return false;
|
26
|
-
}
|
27
|
-
return true;
|
28
|
-
};
|
29
|
-
|
30
|
-
const queryParams = new URLSearchParams(window.location.search);
|
31
|
-
const id = queryParams.get("id");
|
32
|
-
|
33
|
-
useEffect(() => {
|
34
|
-
if (id) {
|
35
|
-
const fetchUserData = async () => {
|
36
|
-
try {
|
37
|
-
const fetchedUser = await fetchUserByIdApi(url, id);
|
38
|
-
if (fetchedUser) {
|
39
|
-
const user = fetchedUser as {
|
40
|
-
name: string;
|
41
|
-
email: string;
|
42
|
-
mobile: string;
|
43
|
-
address: string;
|
44
|
-
roleType: string;
|
45
|
-
gender: string;
|
46
|
-
};
|
47
|
-
setIsEditMode(true);
|
48
|
-
setUserName(user.name);
|
49
|
-
setEmail(user.email);
|
50
|
-
setMobile(user.mobile);
|
51
|
-
setAddress(user.address);
|
52
|
-
setRoleType(user.roleType);
|
53
|
-
setGender(user.gender);
|
54
|
-
}
|
55
|
-
} catch (error) {
|
56
|
-
console.error("Unable to fetch user data", error);
|
57
|
-
}
|
58
|
-
};
|
59
|
-
fetchUserData();
|
60
|
-
}
|
61
|
-
}, [id]);
|
62
|
-
|
63
|
-
const handleSubmit = async (event: React.MouseEvent<HTMLButtonElement>) => {
|
64
|
-
event.preventDefault();
|
65
|
-
if (!validateForm()) return;
|
66
|
-
|
67
|
-
try {
|
68
|
-
if (isEditMode) {
|
69
|
-
await updateUserApi(
|
70
|
-
url,
|
71
|
-
id,
|
72
|
-
userName,
|
73
|
-
email,
|
74
|
-
mobile,
|
75
|
-
address,
|
76
|
-
roleType,
|
77
|
-
gender
|
78
|
-
);
|
79
|
-
alert("User updated successfully");
|
80
|
-
} else {
|
81
|
-
await addUserApi(
|
82
|
-
url,
|
83
|
-
userName,
|
84
|
-
email,
|
85
|
-
mobile,
|
86
|
-
address,
|
87
|
-
roleType,
|
88
|
-
gender
|
89
|
-
);
|
90
|
-
alert("User added successfully");
|
91
|
-
}
|
92
|
-
window.history.pushState({}, "", "/admin/users");
|
93
|
-
window.dispatchEvent(new PopStateEvent("popstate"));
|
94
|
-
} catch (error) {
|
95
|
-
console.error("Error adding/updating User:", error);
|
96
|
-
alert(
|
97
|
-
isEditMode ? "Failed to Update the User." : "Failed to Add the User."
|
98
|
-
);
|
99
|
-
}
|
100
|
-
};
|
101
|
-
|
102
|
-
const handleCancelClick = () => {
|
103
|
-
setUserName("");
|
104
|
-
setEmail("");
|
105
|
-
setMobile("");
|
106
|
-
setAddress("");
|
107
|
-
setRoleType("");
|
108
|
-
setGender("");
|
109
|
-
|
110
|
-
window.history.pushState({}, "", "/admin/users");
|
111
|
-
window.dispatchEvent(new PopStateEvent("popstate"));
|
112
|
-
};
|
113
|
-
|
114
|
-
return (
|
115
|
-
<div className="max-w-4xl p-6 mx-auto dark:bg-gray-800">
|
116
|
-
<div>
|
117
|
-
<form>
|
118
|
-
<h1 className="text-3xl font-bold text-center text-blue-600 capitalize dark:text-white mb-4">
|
119
|
-
{isEditMode ? "Edit User" : "Add User"}
|
120
|
-
</h1>
|
121
|
-
|
122
|
-
<div className="mb-6 w-full">
|
123
|
-
<label className="text-gray-900 dark:text-gray-200 font-semibold">
|
124
|
-
Name <span className="text-red-500">*</span>
|
125
|
-
</label>
|
126
|
-
<input
|
127
|
-
required
|
128
|
-
value={userName}
|
129
|
-
onChange={(e) => setUserName(e.target.value)}
|
130
|
-
type="text"
|
131
|
-
className="w-full px-4 py-2 mt-2 text-gray-800 bg-white border border-gray-400 rounded-md dark:bg-gray-800 dark:text-gray-300 dark:border-gray-800 focus:border-blue-400 focus:ring-blue-300 focus:ring-opacity-40 dark:focus:border-blue-300 focus:outline-none focus:ring"
|
132
|
-
placeholder="Enter User Name"
|
133
|
-
/>
|
134
|
-
</div>
|
135
|
-
<div className="mb-6 w-full">
|
136
|
-
<label className="text-gray-900 dark:text-gray-200 font-semibold">
|
137
|
-
Email <span className="text-red-500">*</span>
|
138
|
-
</label>
|
139
|
-
<input
|
140
|
-
required
|
141
|
-
value={email}
|
142
|
-
onChange={(e) => setEmail(e.target.value)}
|
143
|
-
type="email"
|
144
|
-
className="w-full px-4 py-2 mt-2 text-gray-800 bg-white border border-gray-400 rounded-md dark:bg-gray-800 dark:text-gray-300 dark:border-gray-800 focus:border-blue-400 focus:ring-blue-300 focus:ring-opacity-40 dark:focus:border-blue-300 focus:outline-none focus:ring"
|
145
|
-
placeholder="Enter Email"
|
146
|
-
/>
|
147
|
-
</div>
|
148
|
-
<div className="mb-6 w-full">
|
149
|
-
<label className="text-gray-900 dark:text-gray-200 font-semibold">
|
150
|
-
Mobile Number
|
151
|
-
</label>
|
152
|
-
<input
|
153
|
-
required
|
154
|
-
value={mobile}
|
155
|
-
onChange={(e) => setMobile(e.target.value)}
|
156
|
-
type="number"
|
157
|
-
className="w-full px-4 py-2 mt-2 text-gray-800 bg-white border border-gray-400 rounded-md dark:bg-gray-800 dark:text-gray-300 dark:border-gray-800 focus:border-blue-400 focus:ring-blue-300 focus:ring-opacity-40 dark:focus:border-blue-300 focus:outline-none focus:ring"
|
158
|
-
placeholder="Enter Mobile Number"
|
159
|
-
/>
|
160
|
-
</div>
|
161
|
-
<div className="mb-6 w-full">
|
162
|
-
<label className="text-gray-900 dark:text-gray-200 font-semibold">
|
163
|
-
Address
|
164
|
-
</label>
|
165
|
-
<input
|
166
|
-
required
|
167
|
-
value={address}
|
168
|
-
onChange={(e) => setAddress(e.target.value)}
|
169
|
-
type="text"
|
170
|
-
className="w-full px-4 py-2 mt-2 text-gray-800 bg-white border border-gray-400 rounded-md dark:bg-gray-800 dark:text-gray-300 dark:border-gray-800 focus:border-blue-400 focus:ring-blue-300 focus:ring-opacity-40 dark:focus:border-blue-300 focus:outline-none focus:ring"
|
171
|
-
placeholder="Address"
|
172
|
-
/>
|
173
|
-
</div>
|
174
|
-
|
175
|
-
<div className="mb-6 w-full">
|
176
|
-
<label className="text-gray-900 dark:text-gray-200 font-semibold">
|
177
|
-
Gender
|
178
|
-
</label>
|
179
|
-
<select
|
180
|
-
required
|
181
|
-
value={gender}
|
182
|
-
onChange={(e) =>
|
183
|
-
setGender(e.target.value === "" ? null : e.target.value)
|
184
|
-
}
|
185
|
-
className="w-full px-4 py-2 mt-2 text-gray-800 bg-white border border-gray-400 rounded-md dark:bg-gray-800 dark:text-gray-300 dark:border-gray-800 focus:border-blue-400 focus:ring-blue-300 focus:ring-opacity-40 dark:focus:border-blue-300 focus:outline-none focus:ring"
|
186
|
-
>
|
187
|
-
<option value="">Select a Gender</option>
|
188
|
-
<option value="1">Male</option>
|
189
|
-
<option value="2">Female</option>
|
190
|
-
</select>
|
191
|
-
</div>
|
192
|
-
|
193
|
-
<div className="mb-6 w-full">
|
194
|
-
<label className="text-gray-900 dark:text-gray-200 font-semibold">
|
195
|
-
Role Type <span className="text-red-500">*</span>
|
196
|
-
</label>
|
197
|
-
<select
|
198
|
-
required
|
199
|
-
value={roleType}
|
200
|
-
onChange={(e) => setRoleType(e.target.value)}
|
201
|
-
className="w-full px-4 py-2 mt-2 text-gray-800 bg-white border border-gray-400 rounded-md dark:bg-gray-800 dark:text-gray-300 dark:border-gray-800 focus:border-blue-400 focus:ring-blue-300 focus:ring-opacity-40 dark:focus:border-blue-300 focus:outline-none focus:ring"
|
202
|
-
>
|
203
|
-
<option value="">Select a Role Type</option>
|
204
|
-
<option value="1">Guest</option>
|
205
|
-
<option value="2">Admin</option>
|
206
|
-
</select>
|
207
|
-
</div>
|
208
|
-
|
209
|
-
<div className="flex space-x-4 mt-6 justify-end">
|
210
|
-
<button
|
211
|
-
type="submit"
|
212
|
-
onClick={handleSubmit}
|
213
|
-
className="px-8 py-2.5 leading-5 text-white transition-colors duration-300 transform bg-blue-600 rounded-md hover:bg-blue-500 focus:outline-none focus:bg-gray-600"
|
214
|
-
>
|
215
|
-
{isEditMode ? "Edit" : "Add"}
|
216
|
-
</button>
|
217
|
-
<button
|
218
|
-
type="button"
|
219
|
-
onClick={handleCancelClick}
|
220
|
-
className="px-8 py-2.5 leading-5 text-white transition-colors duration-300 transform bg-blue-600 rounded-md hover:bg-blue-500 focus:outline-none focus:bg-gray-600"
|
221
|
-
>
|
222
|
-
Cancel
|
223
|
-
</button>
|
224
|
-
</div>
|
225
|
-
</form>
|
226
|
-
</div>
|
227
|
-
</div>
|
228
|
-
);
|
229
|
-
};
|
230
|
-
|
231
|
-
export default UserForm;
|