128 Commits
R1 ... yasin

Author SHA1 Message Date
YasinShaikh123
0531684c73 [ update changes ] 2025-06-18 15:34:32 +05:30
YasinShaikh123
021eb6e4db [ update ] 2025-06-06 20:10:40 +05:30
YasinShaikh123
98f0e9dd29 update fav icon 2025-06-05 16:15:45 +05:30
YasinShaikh123
e8f28df886 [ update bugs ] 2025-06-05 15:18:16 +05:30
YasinShaikh123
1fc5756af0 Merge branch 'dev-rohit' of http://git.wdipl.com/Siddhesh.More/SSA-Admin-Panel into yasin 2025-06-03 13:41:24 +05:30
rockyeverlast
4a1a958475 API integration for register user list 2025-05-31 23:53:54 +05:30
rockyeverlast
f1772a7e07 Uploads img url updated 2025-05-05 18:13:33 +05:30
rockyeverlast
57509b2de8 Merge branch 'dev-rohit' of http://git.wdipl.com/Siddhesh.More/SSA-Admin-Panel into testing 2025-05-05 18:07:56 +05:30
rockyeverlast
e6e8f59afa APi call from Manage post completed 2025-05-05 18:04:31 +05:30
rockyeverlast
29f30f9f98 Api integrated for WorkSpace and JobStatus 2025-04-15 20:43:48 +05:30
rockyeverlast
963b85b15f Api integration for Department master completed 2025-04-14 19:34:59 +05:30
rockyeverlast
58e49c0f87 Merge branch 'dev-rohit' of http://git.wdipl.com/Siddhesh.More/SSA-Admin-Panel into testing 2025-04-10 20:14:11 +05:30
rockyeverlast
a1781ade46 Fixed pagination and Master module country updated 2025-04-10 20:13:14 +05:30
rockyeverlast
6856b4b610 Fixed env for testing 2025-04-09 16:47:24 +05:30
YasinShaikh123
7c3b0a52c5 Merge branch 'dev-rohit' of http://git.wdipl.com/Siddhesh.More/SSA-Admin-Panel into yasin 2025-04-09 16:34:27 +05:30
rockyeverlast
3a847d874c Merge branch 'dev-rohit' of http://git.wdipl.com/Siddhesh.More/SSA-Admin-Panel into testing 2025-04-09 16:24:53 +05:30
rockyeverlast
8acc9430b3 Profiule API integrated 2025-04-09 16:23:36 +05:30
rockyeverlast
c9bbae35f9 Bugs fixes for Manage CMS module 2025-04-07 12:16:59 +05:30
YasinShaikh123
0997b16add Merge branch 'dev-rohit' of http://git.wdipl.com/Siddhesh.More/SSA-Admin-Panel into yasin 2025-04-03 15:11:20 +05:30
YasinShaikh123
8b69f2df6a [ env files ] 2025-04-03 15:11:17 +05:30
rockyeverlast
7e8c9c92d0 Faq data fetch fixed 2025-04-03 15:10:28 +05:30
rockyeverlast
f08fdc682b basic auth encoded in base64 2025-04-03 14:58:15 +05:30
rockyeverlast
ab029438fb updated testing .env file 2025-04-03 14:45:48 +05:30
rockyeverlast
ae9df75508 updated EditSubAdmin 2025-03-19 17:59:02 +05:30
rockyeverlast
0192d4be37 update API url in env 2025-03-19 17:50:35 +05:30
rockyeverlast
628ab225ff updated env for Testing 2025-03-19 17:46:16 +05:30
rockyeverlast
3549035672 Initial commit to testing 2025-03-19 17:39:29 +05:30
rockyeverlast
982513c86e Fixed delete modal / PassWord hide show 2025-03-19 12:30:45 +05:30
rockyeverlast
9180076edb updated routes for ForgotPassword 2025-03-18 20:33:16 +05:30
rockyeverlast
2d15461f86 Working on subadmin update and add post 2025-03-17 20:31:52 +05:30
rockyeverlast
940c2a11d0 Added env.testing / Completed Agency master 2025-03-12 20:05:33 +05:30
rockyeverlast
9fb5e230b7 Added search input functionality in FAQ 2025-03-10 20:36:58 +05:30
rockyeverlast
44a6f60868 Faq / JobType / IndustryMaster/TemplateMaster/Pagination data enabled 2025-03-07 20:13:25 +05:30
rockyeverlast
c0b0a5f431 Updated JobType 2025-03-06 14:55:09 +05:30
rockyeverlast
22e5421d95 Fixed Template modal IMage upload 2025-03-06 14:52:14 +05:30
rockyeverlast
ff651461a1 Fixed Template modal button 2025-03-06 13:50:35 +05:30
rockyeverlast
346af173b2 API implementation for CMS and Master module 2025-03-06 13:16:38 +05:30
rockyeverlast
a673ea69d4 Merge branch 'parth' of http://git.wdipl.com/Siddhesh.More/SSA-Admin-Panel into dev-rohit 2025-02-25 14:02:21 +05:30
9b97228ec8 worked on the about 2025-02-25 13:58:13 +05:30
2cb6173b81 worked on the aboutus component edit functionlity 2025-02-14 15:00:43 +05:30
dc1aa2250f Merge branch 'yasin' of http://git.wdipl.com/Siddhesh.More/SSA-Admin-Panel 2025-02-12 20:05:52 +05:30
a554803603 update 2025-02-12 20:04:40 +05:30
YasinShaikh123
0f11dd0019 [ update action ] 2025-02-12 20:03:47 +05:30
83a180354d update 2025-02-12 20:03:19 +05:30
bf938178a4 update 2025-02-12 19:48:05 +05:30
421926a6ff update 2025-02-12 19:47:44 +05:30
097d8bad99 worked on the module of the aboutus and services 2025-02-12 19:00:47 +05:30
e24d48b917 worked on aboutus 2025-02-12 16:38:28 +05:30
cd586ddf1b update 2025-02-12 16:27:49 +05:30
001d346426 update 2025-02-12 15:35:38 +05:30
2ad88f91d4 update 2025-02-12 13:51:41 +05:30
b56710d363 Merge branch 'yasin' of http://git.wdipl.com/Siddhesh.More/SSA-Admin-Panel 2025-02-12 13:51:37 +05:30
22d07519ff update 2025-02-12 13:30:02 +05:30
YasinShaikh123
68fc0bfdf5 [ Update action iocn 😉 ] 2025-02-12 13:25:22 +05:30
1b27fa32ce worked on the aboutus 2025-02-12 13:19:36 +05:30
9579771f98 update 2025-02-12 13:18:18 +05:30
YasinShaikh123
c7de34fda2 Merge branch 'main' of http://git.wdipl.com/Siddhesh.More/SSA-Admin-Panel into yasin 2025-02-12 12:51:28 +05:30
YasinShaikh123
599f320598 [ working Icon ] 2025-02-12 12:50:47 +05:30
6f25a6a234 worked privacypolicy 2025-02-12 12:47:44 +05:30
5db4c3a236 Merge branch 'parth' of http://git.wdipl.com/Siddhesh.More/SSA-Admin-Panel 2025-02-12 12:45:00 +05:30
dc3c861471 worked on the aboutus 2025-02-12 12:35:49 +05:30
066238b334 updsate 2025-02-12 12:34:31 +05:30
0bd8cc6434 update types folder 2025-02-12 12:27:53 +05:30
84a64c9ae6 worked on the aboutus 2025-02-12 12:04:00 +05:30
c5c3ebfedd worked on the aboutus 2025-02-12 12:02:54 +05:30
AnsariTufail
4ab8daaaf8 update 2025-02-12 12:01:08 +05:30
AnsariTufail
dbde49fffa Worked on the manage cms 2025-02-12 11:58:17 +05:30
688f674062 update 2025-02-12 11:54:21 +05:30
b960b116dc Merge branch 'yasin' of http://git.wdipl.com/Siddhesh.More/SSA-Admin-Panel 2025-02-11 20:14:39 +05:30
795643eead updaate 2025-02-11 20:14:29 +05:30
YasinShaikh123
59df59a9d6 Merge branch 'main' of http://git.wdipl.com/Siddhesh.More/SSA-Admin-Panel into yasin 2025-02-11 19:59:54 +05:30
895516977a update 2025-02-11 19:59:38 +05:30
YasinShaikh123
31f1c5005e Merge branch 'main' of http://git.wdipl.com/Siddhesh.More/SSA-Admin-Panel into yasin 2025-02-11 19:54:02 +05:30
2149144d84 [ update edit delete view icon hover ] 2025-02-11 19:52:50 +05:30
YasinShaikh123
768e0ec8ae Merge branch 'main' of http://git.wdipl.com/Siddhesh.More/SSA-Admin-Panel into yasin 2025-02-11 19:48:46 +05:30
YasinShaikh123
90792de1ac [ forget modal ] 2025-02-11 19:48:41 +05:30
YasinShaikh123
8908bacc8a Merge branch 'parth' of http://git.wdipl.com/Siddhesh.More/SSA-Admin-Panel into yasin 2025-02-11 17:32:31 +05:30
AnsariTufail
38e5185d22 update 2025-02-11 17:23:11 +05:30
AnsariTufail
663cdfc297 update 2025-02-11 17:20:36 +05:30
YasinShaikh123
e36c343cbf [ forget modal ] 2025-02-11 17:19:32 +05:30
bc1d1923d2 get called in aboutus 2025-02-11 17:18:28 +05:30
b9b62bb034 udpate 2025-02-11 16:10:48 +05:30
5ae4660507 update 2025-02-11 15:32:37 +05:30
YasinShaikh123
05074b6055 Merge branch 'main' of http://git.wdipl.com/Siddhesh.More/SSA-Admin-Panel into yasin 2025-02-11 14:57:27 +05:30
22f31a76cb updated 2025-02-11 14:56:48 +05:30
AnsariTufail
1041528f1e update 2025-02-11 14:54:12 +05:30
AnsariTufail
6a2c3ba20d update 2025-02-11 14:47:52 +05:30
YasinShaikh123
f898f28deb Merge branch 'main' of http://git.wdipl.com/Siddhesh.More/SSA-Admin-Panel into yasin 2025-02-11 14:47:39 +05:30
YasinShaikh123
a80163d589 'Login chnges' 2025-02-11 14:47:33 +05:30
7a7aeab5b8 Merge branch 'main' of http://git.wdipl.com/Siddhesh.More/SSA-Admin-Panel into parth 2025-02-11 14:00:32 +05:30
e9fe9410ac updaste dashboard 2025-02-11 13:53:51 +05:30
a9cf30252b [ route update ] 2025-02-11 12:44:43 +05:30
6c7d38779a pushed the files which comes after the pull 2025-02-11 12:17:31 +05:30
7dcff8798d Merge branch 'yasin' of http://git.wdipl.com/Siddhesh.More/SSA-Admin-Panel 2025-02-10 20:00:13 +05:30
0d34e1bae7 UPDAATE 2025-02-10 19:54:18 +05:30
YasinShaikh123
4fa87e01b6 [ service ] 2025-02-10 19:36:14 +05:30
YasinShaikh123
943f401e63 working.......... 2025-02-10 19:35:49 +05:30
18c9ff8b78 update 2025-02-10 19:34:29 +05:30
3aa93b358f update 2025-02-10 19:10:04 +05:30
YasinShaikh123
027af5f93e Merge branch 'main' of http://git.wdipl.com/Siddhesh.More/SSA-Admin-Panel into yasin 2025-02-10 12:38:55 +05:30
9822388ca3 Merge branch 'tufail' of http://git.wdipl.com/Siddhesh.More/SSA-Admin-Panel 2025-02-10 12:30:15 +05:30
YasinShaikh123
f7e76c8fc0 [ working ... ] 2025-02-10 12:30:06 +05:30
YasinShaikh123
f0fcdc14ea Merge branch 'main' of http://git.wdipl.com/Siddhesh.More/SSA-Admin-Panel into yasin 2025-02-10 12:29:50 +05:30
d56678786b update api 2025-02-10 12:27:51 +05:30
AnsariTufail
0c219ba1a9 Working on that Fixed alingment 2025-02-10 12:09:15 +05:30
YasinShaikh123
9e3918b2eb [ Insall Redux ] 2025-02-10 12:06:42 +05:30
b9a902507e update warnings 2025-02-10 12:06:34 +05:30
d37c8ed196 update 2025-02-10 12:04:43 +05:30
cd125a5932 worked on the datatable 2025-02-10 12:01:04 +05:30
YasinShaikh123
50078e4cd7 [ update 👍 ] 2025-02-07 19:41:47 +05:30
YasinShaikh123
4cdef1270b Merge branch 'tufail' of http://git.wdipl.com/Siddhesh.More/SSA-Admin-Panel 2025-02-07 17:27:31 +05:30
YasinShaikh123
611d416109 Merge branch 'parth' of http://git.wdipl.com/Siddhesh.More/SSA-Admin-Panel 2025-02-07 17:25:56 +05:30
YasinShaikh123
7fdcab7215 [ update ] 2025-02-07 17:24:33 +05:30
c47236869f worked on the my profile 2025-02-07 16:58:35 +05:30
AnsariTufail
315eaccf50 Working on the Master Module 2025-02-07 16:38:38 +05:30
YasinShaikh123
5029837c1b Merge branch 'yasin' of http://git.wdipl.com/Siddhesh.More/SSA-Admin-Panel 2025-02-06 15:16:52 +05:30
YasinShaikh123
39b16bd6e6 Merge branch 'tufail' of http://git.wdipl.com/Siddhesh.More/SSA-Admin-Panel 2025-02-06 15:16:26 +05:30
YasinShaikh123
0c3ccce916 Merge branch 'tufail' of http://git.wdipl.com/Siddhesh.More/SSA-Admin-Panel into yasin 2025-02-06 15:14:33 +05:30
YasinShaikh123
07a5d4dd52 "Added src/components/ViewDailog.tsx" 2025-02-06 15:12:43 +05:30
YasinShaikh123
aabbbfff8b [ working👷‍♂️ ] 2025-02-06 15:07:42 +05:30
AnsariTufail
a64731f79a Worked on this ContactUs, Manage CMS 2025-02-06 14:48:27 +05:30
7ac9c41556 worked on the managegroup, managepost, subAdmin 2025-02-06 14:43:31 +05:30
YasinShaikh123
127cce73e6 Merge branch 'parth' of http://git.wdipl.com/Siddhesh.More/SSA-Admin-Panel 2025-02-05 12:35:06 +05:30
YasinShaikh123
ea3ae8b621 [ working ] 2025-02-05 12:34:16 +05:30
13e6260ea2 worked on the model of the manage, subadmin and model 2025-02-05 12:33:20 +05:30
e23067bb1b Merge branch 'yasin' of http://git.wdipl.com/Siddhesh.More/SSA-Admin-Panel into parth 2025-02-04 15:05:02 +05:30
6cccadb1a9 first commit 2025-02-04 15:02:56 +05:30
YasinShaikh123
335bd0bddf [ Update UI Tamplate ] 2025-02-04 13:56:43 +05:30
142 changed files with 14814 additions and 5445 deletions

15
.env Normal file
View File

@@ -0,0 +1,15 @@
# VITE_API_URL='https://ssa.betadelivery.com/apia/v1'
# # VITE_API_URL='http://192.16.50.44/seo-backend/apia/v1'
# VITE_USER_NAME="Admin"
# VITE_PASSWORD="71%@L%es^bUX94`J9XT*@bh,._WWM{$%^^&&"
# VITE_APP_NAME=MyViteApp
# VITE_IMG_TEMPLATES='https://ssa.betadelivery.com/storage/app/public/uploads/post_templates/'
VITE_API_URL='https://ssa.betadelivery.com/testing/apia/v1'
# VITE_API_URL='https://ssa.betadelivery.com/apia/v1'
VITE_USER_NAME="Admin"
VITE_PASSWORD="71%@L%es^bUX94`J9XT*@bh,._WWM{$%^^&&"
# VITE_PASSWORD="71%@L%es^bUX94`J9XT*%4&^%tUU^%Q^ffgt"
VITE_APP_NAME=MyViteApp
VITE_IMG_TEMPLATES='https://ssa.betadelivery.com/testing/storage/app/public/uploads/post_templates/'
VITE_MAIN_URL='https://ssa.betadelivery.com/testing'
VITE_POST_IMG=`${VITE_MAIN_URL}/storage/app/public/uploads/post/`

5
.env.testing Normal file
View File

@@ -0,0 +1,5 @@
# VITE_API_URL='https://ssa.betadelivery.com/testing/apia/'
# VITE_USER_NAME="Admin"
# VITE_PASSWORD="71%@L%es^bUX94`J9XT*@bh,._WWM{$%^^&&"
# VITE_APP_NAME=MyViteApp
# VITE_IMG_TEMPLATES='https://ssa.betadelivery.com/storage/app/public/uploads/post_templates/'

1
.gitignore vendored
View File

@@ -22,3 +22,4 @@ dist-ssr
*.njsproj *.njsproj
*.sln *.sln
*.sw? *.sw?
.env

View File

@@ -82,7 +82,7 @@ define(['./workbox-54d0af47'], (function (workbox) { 'use strict';
"revision": "3ca0b8505b4bec776b69afdba2768812" "revision": "3ca0b8505b4bec776b69afdba2768812"
}, { }, {
"url": "index.html", "url": "index.html",
"revision": "0.4goaulr6o2o" "revision": "0.p75md0vraj"
}], {}); }], {});
workbox.cleanupOutdatedCaches(); workbox.cleanupOutdatedCaches();
workbox.registerRoute(new workbox.NavigationRoute(workbox.createHandlerBoundToURL("index.html"), { workbox.registerRoute(new workbox.NavigationRoute(workbox.createHandlerBoundToURL("index.html"), {

View File

@@ -1,13 +1,17 @@
<!doctype html> <!doctype html>
<html lang="en"> <html lang="en">
<head>
<meta charset="UTF-8" /> <head>
<link rel="icon" type="image/svg+xml" href="/src/assets/favicon.png" /> <meta charset="UTF-8" name="referrer" content="strict-origin-when-cross-origin" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <!-- <link rel="icon" type="image/png+xml" href="/src/assets/favicon.png" /> -->
<title>SEO Admin</title> <link rel="icon" type="image/png" href="/favicon.png" />
</head> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<body> <title>SEO Admin</title>
<div id="root"></div> </head>
<script type="module" src="/src/main.tsx"></script>
</body> <body>
</html> <div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>

5513
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -13,18 +13,26 @@
"@chakra-ui/react": "^3.2.3", "@chakra-ui/react": "^3.2.3",
"@emotion/react": "^11.14.0", "@emotion/react": "^11.14.0",
"@emotion/styled": "^11.14.0", "@emotion/styled": "^11.14.0",
"@reduxjs/toolkit": "^2.5.1",
"axios": "^1.7.9",
"chart.js": "^4.4.7",
"framer-motion": "^11.18.0", "framer-motion": "^11.18.0",
"js-cookie": "^3.0.5",
"next-themes": "^0.4.4", "next-themes": "^0.4.4",
"react": "^18.3.1", "react": "^18.3.1",
"react-chartjs-2": "^5.3.0",
"react-dom": "^18.3.1", "react-dom": "^18.3.1",
"react-hook-form": "^7.54.2", "react-hook-form": "^7.54.2",
"react-icons": "^5.4.0", "react-icons": "^5.4.0",
"react-quill": "^2.0.0",
"react-redux": "^9.2.0",
"react-router-dom": "^7.1.1", "react-router-dom": "^7.1.1",
"vite-plugin-pwa": "^0.21.1" "vite-plugin-pwa": "^0.21.1"
}, },
"devDependencies": { "devDependencies": {
"@chakra-ui/cli": "^3.2.3", "@chakra-ui/cli": "^2.4.1",
"@eslint/js": "^9.17.0", "@eslint/js": "^9.17.0",
"@types/js-cookie": "^3.0.6",
"@types/react": "^18.3.18", "@types/react": "^18.3.18",
"@types/react-dom": "^18.3.5", "@types/react-dom": "^18.3.5",
"@vitejs/plugin-react": "^4.3.4", "@vitejs/plugin-react": "^4.3.4",

View File

@@ -1,41 +1,62 @@
import { useContext } from "react"; import { useContext, useEffect } from "react";
import { Route, BrowserRouter as Router, Routes } from "react-router-dom"; import { BrowserRouter as Router, Routes, Route, Navigate } from "react-router-dom";
import GlobalStateContext from "./Contexts/GlobalStateContext"; import GlobalStateContext from "./Contexts/GlobalStateContext";
import DefaultLayout from "./Layouts/DefaultLayout"; import DefaultLayout from "./Layouts/DefaultLayout";
import Login from "./Pages/Login"; import Login from "./Pages/Login";
import { RouteLink } from "./Routes/Routes"; import { RouteLink } from "./Routes/Routes";
import LoginOtp from "./Pages/OnBoarding/LoginOtp"; import ForgotPassword from "./Pages/ForgotPassword";
import CreatePass from "./Pages/OnBoarding/CreatePass"; import VerifyEnterOTP from "./Pages/VerifyEnterOTP";
import SetNewPassword from "./Pages/SetNewPassword";
function App() { function App() {
const context = useContext(GlobalStateContext); const context = useContext(GlobalStateContext);
if (!context) if (!context) throw new Error("App must be used within a GlobalStateProvider");
throw new Error("App must be used within a GlobalStateProvider");
const { isAuthenticate } = context; const { isAuthenticate, setIsAuthenticate } = context;
useEffect(() => {
const token = localStorage.getItem("token");
setIsAuthenticate(!!token); // Converts token to boolean
}, [setIsAuthenticate]);
console.log("Auth Status:", isAuthenticate);
return ( return (
<Router> <Router>
<Routes> <Routes>
<Route path="/login" element={<Login />} /> {/* Redirect logged-in users away from login */}
<Route path="/login/login-otp" element={<LoginOtp />} /> <Route path="/login" element={isAuthenticate && localStorage.getItem("token") ? <Navigate to="/" /> : <Login />} />
<Route path="/login/create-password" element={<CreatePass/>}/> <Route path="/forgot-password" element={<ForgotPassword />} />
<Route path="/forgot-password/verify-otp" element={<VerifyEnterOTP />} />
<Route path="/forgot-password/reset-password" element={<SetNewPassword />} />
{/* Protected Routes */}
<Route <Route
path="/*" path="/*"
element={ element={isAuthenticate && localStorage.getItem("token") ? (
isAuthenticate === true ? ( <DefaultLayout>
<DefaultLayout> <Routes>
<Routes> {RouteLink.map(({ path, Component }, index) => (
{RouteLink.map(({ path, Component }, index) => ( <Route key={index} path={path} element={<Component />} />
<Route key={index} path={path} element={<Component />} /> ))}
))} </Routes>
</Routes> </DefaultLayout>
</DefaultLayout> ) : (
) : ( <Routes>
<Login /> {/* Allow only forgot password flows */}
) <Route path="/forgot-password" element={<ForgotPassword />} />
} <Route path="/forgot-password/verify" element={<VerifyEnterOTP />} /> {/* ✅ Add this line */}
<Route path="/forgot-password/verify-otp" element={<VerifyEnterOTP />} />
<Route path="/forgot-password/reset-password" element={<SetNewPassword />} />
{/* Default to login */}
<Route path="*" element={<Navigate to="/login" />} />
</Routes>
)}
/> />
<Route path="*" element={<Login />} />
{/* Catch-all route to prevent unauthorized access */}
<Route path="*" element={<Navigate to="/login" />} />
</Routes> </Routes>
</Router> </Router>
); );

View File

@@ -1,19 +0,0 @@
export const getTitle = (location: string): string => {
const titles: { [key: string]: string } = {
'/': 'Dashboard',
'/manage-user/register-user': 'Manage User',
'/manage-user/active-user': 'Manage User',
'/manage-post': 'Manage Post',
'/manage-sub-admin': 'Manage Sub Admin',
'/manage-jobs': 'Manage Jobs',
'/manage-contact-us': 'Manage Contact Us',
'/manage-cms/faq': 'Manage CMS',
'/manage-cms/about-us': 'Manage CMS',
'/manage-cms/privacy-policy': 'Manage CMS',
'/manage-cms/terms-and-condition': 'Manage CMS',
'/profile': 'My Profile',
};
return titles[location] || 'Page Not Found';
};

View File

@@ -2,11 +2,12 @@
import { createContext, Dispatch, SetStateAction } from 'react'; import { createContext, Dispatch, SetStateAction } from 'react';
// Define the shape of your context value // Define the shape of your context value
type GlobalStateContextType = { export interface GlobalStateContextType {
isAuthenticate: boolean; isAuthenticate: boolean;
setIsAuthenticate: Dispatch<SetStateAction<boolean>>; setIsAuthenticate: Dispatch<SetStateAction<boolean>>;
}; isBarLoading: boolean;
setIsBarLoading: Dispatch<SetStateAction<boolean>>;
}
// Create the context with a default value of `undefined` // Create the context with a default value of `undefined`
const GlobalStateContext = createContext<GlobalStateContextType | undefined>(undefined); const GlobalStateContext = createContext<GlobalStateContextType | undefined>(undefined);

View File

@@ -1,14 +1,21 @@
import { ReactNode, useState } from 'react'; import { ReactNode, useState } from "react";
import GlobalStateContext from './GlobalStateContext'; import GlobalStateContext from "./GlobalStateContext";
const GlobalStateProvider = ({ children }: { children: ReactNode }) => {
const GlobalStateProvider = ({ children }:{children:ReactNode}) => {
const [isAuthenticate, setIsAuthenticate] = useState<boolean>(true); const [isAuthenticate, setIsAuthenticate] = useState<boolean>(true);
const [isBarLoading, setIsBarLoading] = useState<boolean>(false); // ✅ Fixed typo
return ( return (
<GlobalStateContext.Provider value={{ isAuthenticate, setIsAuthenticate }}> <GlobalStateContext.Provider value={{
isAuthenticate,
setIsAuthenticate,
isBarLoading,
setIsBarLoading, // ✅ Fixed typo
}}>
{children} {children}
</GlobalStateContext.Provider> </GlobalStateContext.Provider>
); );

View File

@@ -1,206 +1,92 @@
import { HStack, Image, Text, VStack } from "@chakra-ui/react"; import { HStack, Image, Text, VStack } from "@chakra-ui/react";
import React, { FC } from "react"; import React, { FC, useContext } from "react";
import { RiNotificationLine } from "react-icons/ri"; import { RiNotificationLine } from "react-icons/ri";
import { NavLink, useLocation, useNavigate } from "react-router-dom"; import { NavLink, useLocation, useNavigate } from "react-router-dom";
import { nav } from "../Routes/Nav"; import { nav } from "../Routes/Nav";
import logo from "../assets/logo.svg"; import logo from '../assets/logo.svg';
import { import { AccordionItem, AccordionItemContent, AccordionItemTrigger, AccordionRoot } from "../components/ui/accordion";
AccordionItem,
AccordionItemContent,
AccordionItemTrigger,
AccordionRoot,
} from "../components/ui/accordion";
import { Avatar } from "../components/ui/avatar"; import { Avatar } from "../components/ui/avatar";
import { getTitle } from "../Constants/Constants"; import { LuLogOut } from "react-icons/lu";
import { logout } from "../Redux/Service/authSlice";
import { useDispatch } from "react-redux";
import GlobalStateContext from "../Contexts/GlobalStateContext";
import { useLogOutMutation } from "../Redux/Service/apiSlice";
import ProgressBar from "../components/ProgressBar/ProgressBar";
import { useGetProfileQuery } from "../Redux/Service/profile.password";
const DefaultLayout: FC<{ children: React.ReactNode }> = ({ children }) => { const DefaultLayout: FC<{ children: React.ReactNode }> = ({ children }) => {
const navigate = useNavigate(); const { data } = useGetProfileQuery()
const location = useLocation(); const dispatch = useDispatch()
const headerTitle = getTitle(location?.pathname); const navigate = useNavigate()
console.log(location); const location = useLocation()
const context = useContext(GlobalStateContext);
if (!context) {
throw new Error('App must be used within a GlobalStateProvider');
}
const { setIsAuthenticate, isBarLoading } = context;
const [logOutAdmin] = useLogOutMutation()
// Logout function
const handleLogout = async () => {
try {
// ✅ Call mutation and wait for the response
const res = await logOutAdmin().unwrap();
console.log("Logout Success:", res);
// ✅ Clear local storage & update authentication state
dispatch(logout());
localStorage.removeItem("token");
setIsAuthenticate(false);
// ✅ Redirect to login page
navigate("/login");
} catch (error) {
console.error("Logout Failed:", error);
}
};
return ( return (
<HStack <VStack gap={0} w="100%" h="100vh" bg="#F2F2F2">
position={"relative"} <ProgressBar isLoading={isBarLoading} />
bg="#F2F2F2" <HStack overflow={'hidden'} position={'relative'} bg="#F2F2F2" backgroundPosition="center" backgroundRepeat="repeat" backgroundSize="cover" gap={0} w="100%" h="calc(100% - 4px)" p={0}>
backgroundPosition="center"
backgroundRepeat="repeat" <VStack pt={0} zIndex={1} gap={0} rounded={'lg'} h="100%" w="15%" overflow={'auto'} >
backgroundSize="cover" <HStack w={'100%'} p={3} h={'7%'} justifyContent={'center'}>
gap={0} <Image w={55} src={logo} />
pt={2} </HStack>
w="100%" <VStack w={'100%'} p={2} pt={0}>
h="100vh" {nav?.map(({ title, path, Icon, type, children, initPath }, index) => type === 'single' ?
> <NavLink className="link" key={index} to={path || ''} style={{ cursor: 'pointer', borderRadius: '8px', padding: '6px', width: '100%', display: 'flex', alignItems: 'center', gap: 6, border: '1px solid #ffffff', backgroundColor: '#fff', color: '#000', boxShadow: 'rgba(99, 99, 99, 0.2) 0px 2px 8px 0px' }} ><Icon style={{ fontSize: '20px' }} /> <Text fontSize={'xs'} w={'100%'}>{title}</Text></NavLink> :
<VStack zIndex={1} gap={0} rounded={"lg"} h="100%" w="15%"> <AccordionRoot border={location?.pathname.startsWith(initPath ?? path) ? "1px solid #02A0A0" : '1px'} key={index} bg={'#fff'} rounded={'lg'} collapsible>
<HStack w={"100%"} p={3} h={"6.5%"} justifyContent={"center"}> <AccordionItem rounded={'lg'} bg={'#fff'} boxShadow={'rgba(99, 99, 99, 0.2) 0px 2px 8px 0px'} borderBottom={'none'} p={0} key={index} value={title}>
<Image w={55} src={logo} /> <AccordionItemTrigger className="Oxygen" color={'#fff'} onClick={() => navigate(path || '')} gap={0} style={{ cursor: 'pointer', borderRadius: '8px', padding: '5px', width: '100%', display: 'flex', alignItems: 'center', border: '1px solid #ffffff', backgroundColor: '#fff', color: '#000', fontSize: '14px', }}> <Text fontSize={'xs'} gap={1} display={'flex'} alignItems={'center'} ><Icon style={{ fontSize: '20px' }} />{title}</Text></AccordionItemTrigger>
</HStack> {children?.map(({ title, path, Icon }, index) => <AccordionItemContent className={`linkChild Oxygen ${location?.pathname === path && 'activeChild'}`} key={index} onClick={() => navigate(path)} style={{ marginTop: 6, cursor: 'pointer', borderRadius: '8px', padding: '6px', width: '100%', display: 'flex', alignItems: 'center', gap: 6, border: '1px solid #ffffff', backgroundColor: '#fff', color: '#919198' }} ><Icon style={{ fontSize: '20px' }} /> <Text fontSize={'xs'} w={'100%'}>{title}</Text></AccordionItemContent>)}
<VStack w={"100%"} p={3}>
{nav?.map(({ title, path, Icon, type, children, initPath }, index) =>
type === "single" ? (
<NavLink
className="link"
key={index}
to={path}
style={{
cursor: "pointer",
borderRadius: "8px",
padding: "6px",
width: "100%",
display: "flex",
alignItems: "center",
gap: 6,
border: "1px solid #ffffff",
backgroundColor: "#fff",
color: "#000",
boxShadow: "rgba(99, 99, 99, 0.2) 0px 2px 8px 0px",
}}
>
<Icon
style={{
fontSize: "20px",
backgroundColor: "#fff",
width: 28,
color: location?.pathname === path ? "#02A0A0" : "#000",
padding: 2,
borderRadius: "50%",
}}
/>{" "}
<Text fontSize={"xs"} w={"100%"}>
{title}
</Text>
</NavLink>
) : (
<AccordionRoot bg={"#fff"} rounded={"lg"} collapsible>
<AccordionItem
boxShadow={"rgba(99, 99, 99, 0.2) 0px 2px 8px 0px"}
rounded={"lg"}
borderBottom={"none"}
p={0}
key={index}
value={title}
>
<AccordionItemTrigger
className={`link ${location?.pathname.startsWith(initPath ?? "") && "active"}`}
color={"#fff"}
onClick={() => navigate(path)}
gap={0}
style={{
cursor: "pointer",
borderRadius: "8px",
padding: "5px",
width: "100%",
display: "flex",
alignItems: "center",
border: "1px solid #ffffff",
backgroundColor: "#fff",
color: "#000",
fontSize: "14px",
fontWeight: "normal",
}}
>
{" "}
<Text
fontSize={"xs"}
gap={1}
display={"flex"}
alignItems={"center"}
>
<Icon
style={{
fontSize: "20px",
backgroundColor: "#fff",
width: 23,
color: location?.pathname.startsWith(initPath ?? "")
? "#02A0A0"
: "#000",
padding: 2,
borderRadius: "50%",
}}
/>
{title}
</Text>
</AccordionItemTrigger>
{children?.map(({ title, path, Icon }, index) => (
<AccordionItemContent
className={`linkChild ${location?.pathname === path && "activeChild"}`}
key={index}
onClick={() => navigate(path)}
style={{
marginTop: 6,
cursor: "pointer",
borderRadius: "8px",
padding: "6px",
width: "100%",
display: "flex",
alignItems: "center",
gap: 6,
border: "1px solid #ffffff",
backgroundColor: "#fff",
color: "#000",
}}
>
<Icon style={{ fontSize: "16px" }} />{" "}
<Text fontSize={"xs"} w={"100%"}>
{title}
</Text>
</AccordionItemContent>
))}
</AccordionItem> </AccordionItem>
</AccordionRoot> </AccordionRoot>)}
) </VStack>
)} <VStack w={'100%'} p={3} pt={0}>
<HStack onClick={handleLogout} className="link" style={{ cursor: 'pointer', borderRadius: '8px', padding: '6px', width: '100%', display: 'flex', alignItems: 'center', gap: 6, border: '1px solid #ffffff', backgroundColor: '#fff', color: '#000', boxShadow: 'rgba(99, 99, 99, 0.2) 0px 2px 8px 0px' }} ><LuLogOut style={{ fontSize: '20px' }} /> <Text fontSize={'xs'} w={'100%'}>Logout</Text></HStack>
</VStack>
</VStack> </VStack>
</VStack> <VStack gap={0} h="100%" w="85%" >
<VStack overflowY="hidden" gap={0} h="100%" w="85%">
<HStack <HStack h={'11%'} w={'100%'} justifyContent={'flex-end'} pe={3} gap={6}>
h={"6.5%"}
w={"100%"} <NavLink to={'/manage-notification'}><RiNotificationLine color="#013e3e" cursor={'pointer'} style={{ fontSize: '22px' }} /></NavLink>
justifyContent={"space-between"} <HStack cursor={'pointer'} onClick={() => navigate('/profile')} >
alignItems={"flex-end"} <Avatar size={'sm'} src="https://i.pinimg.com/736x/d6/cd/0f/d6cd0ffd4634b0763d3958a7325ce26e.jpg" />
pe={3} <VStack color={'#013e3e'} gap={0} alignItems={'flex-start'}>
gap={6} <Text fontSize={'sm'} fontWeight={'bold'}>{`${data?.data?.first_name.charAt(0).toUpperCase()}${data?.data.first_name.slice(1)}`}</Text>
p={4} <Text fontSize={'xs'} >{data?.data?.phone_number}</Text>
>
<Text
mb={1}
fontSize={"sm"}
ms={1}
fontWeight={600}
color={"#013e3e"}
>
{headerTitle}
</Text>
<HStack
// bg={"#fff"}
h={"100%"}
justifyContent={"center"}
p={2}
rounded={"md"}
// boxShadow={"rgba(99, 99, 99, 0.2) 0px 2px 8px 0px"}
>
<RiNotificationLine
color="#013e3e"
cursor={"pointer"}
style={{ fontSize: "22px" }}
/>
<HStack cursor={"pointer"} onClick={() => navigate("/profile")}>
<Avatar
size={"sm"}
src="https://i.pinimg.com/736x/d6/cd/0f/d6cd0ffd4634b0763d3958a7325ce26e.jpg"
/>
<VStack color={"#013e3e"} gap={0} alignItems={"flex-start"}>
<Text fontSize={"sm"} fontWeight={"bold"}>
Ritesh Pandey
</Text>
<Text fontSize={"xs"}>ritesh.pandey@wdimails.com</Text>
</VStack> </VStack>
</HStack> </HStack>
</HStack> </HStack>
</HStack> {children}
{children} </VStack>
</VStack> </HStack>
</HStack> </VStack>
); );
}; };

View File

@@ -1,6 +0,0 @@
const CMS = () => {
return (
<div>CMS</div>
)
}
export default CMS

View File

@@ -1,11 +1,189 @@
import MainFrame from "../../components/MainFrame" import {
Box,
createListCollection,
Heading,
HStack,
Status,
Tabs,
Text,
} from "@chakra-ui/react";
import BarChart from "../../components/Charts/BarChart";
import CircularApp from "../../components/Charts/CircularProgress";
import SemiDoughnutChart from "../../components/Charts/SemiDoughnutChart";
import MainFrame from "../../components/MainFrame";
import {
AccordionItem,
AccordionItemContent,
AccordionItemTrigger,
AccordionRoot,
} from "../../components/ui/accordion";
import { Button } from "../../components/ui/button";
import {
SelectContent,
SelectItem,
SelectRoot,
SelectTrigger,
SelectValueText
} from "../../components/ui/select";
import AgencyName from "./AgencyName";
const Dashboard = () => { const Dashboard = () => {
const frameworks = createListCollection({
items: [
{ label: "Today", value: "Today" },
{ label: "Week", value: "Week" },
{ label: "Month", value: "Month" },
{ label: "Year", value: "Year" },
],
});
const accItems = [
{
value: "1",
title: "How to create new account?",
text: "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since. Lorem Ipsum has been the industry's standard dummy text ever since.",
},
{
value: "2",
title: "How to create new account?",
text: "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since. Lorem Ipsum has been the industry's standard dummy text ever since.",
},
{
value: "3",
title: "How to create new account?",
text: "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since. Lorem Ipsum has been the industry's standard dummy text ever since.",
},
{
value: "4",
title: "How to create new account?",
text: "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since. Lorem Ipsum has been the industry's standard dummy text ever since.",
},
];
return ( return (
<MainFrame> <MainFrame>
<Box display={"flex"} p={"20px"} pe={'20px'} gap={5}>
</MainFrame> <Box rounded={'lg'} w={"30%"} boxShadow={"rgba(99, 99, 99, 0.2) 0px 2px 8px 0px"}>
) <Heading fontSize={"sm"} p={2}>
} Total Users
</Heading>
<Tabs.Root
size={"sm"}
w={"80%"}
m={"auto"}
variant="enclosed"
fitted
defaultValue={"tab-1"}
mb={6}
>
<Tabs.List>
<Tabs.Trigger fontSize={"xs"} value="tab-1">
Past 24 hrs
</Tabs.Trigger>
<Tabs.Trigger fontSize={"xs"} value="tab-2">
Total Users
</Tabs.Trigger>
<Tabs.Trigger fontSize={"xs"} value="tab-3">
New Signups
</Tabs.Trigger>
</Tabs.List>
</Tabs.Root>
<Box>
<SemiDoughnutChart />
</Box>
export default Dashboard <Box
w={"80%"}
m={"auto"}
display={"flex"}
justifyContent={"space-between"}
mt={8}
>
<Status.Root colorPalette="blue">
<Status.Indicator />
Recruiter <Text fontWeight={500}>2554</Text>
</Status.Root>
<Status.Root colorPalette="blue">
<Status.Indicator />
Customer <Text fontWeight={500}>1224</Text>
</Status.Root>
</Box>
</Box>
<Box
p={"20px"}
w={"49%"}
rounded={'lg'}
boxShadow={"rgba(99, 99, 99, 0.2) 0px 2px 8px 0px"}
>
<HStack alignItems={"center"} mb={4}>
<Text fontSize={"sm"}>Item approvals in</Text>
<SelectRoot collection={frameworks} size="xs" width="200px">
<SelectTrigger>
<SelectValueText p={2} placeholder="Select movie" />
</SelectTrigger>
<SelectContent p={2}>
{frameworks.items.map((movie) => (
<SelectItem item={movie} key={movie.value}>
{movie.label}
</SelectItem>
))}
</SelectContent>
</SelectRoot>
</HStack>
<BarChart />
</Box>
<Box
w={"20%"}
boxShadow={"rgba(99, 99, 99, 0.2) 0px 2px 8px 0px"}
p={'10px'}
rounded={'lg'}
>
<Text fontSize={"sm"} fontWeight={500} pt={3}>Number Of Groups created</Text>
<CircularApp />
</Box>
</Box>
<Box p={"20px"} pt={0} display={"flex"} gap={5}>
<Box w={"50%"} rounded={'lg'} bg={"#f2f2f2"} h={'100%'} p={"10px"} overflow={'auto'}>
<HStack justifyContent={"space-between"} mb={5}>
<Text fontSize={"xs"} fontWeight={500}>Faqs</Text>
<Button
bg={"#fff"}
color={"#222222CC"}
px={3}
fontSize={"12px"}
h={"28px"}
>
View ALL
</Button>
</HStack>
<AccordionRoot collapsible defaultValue={["b"]}>
{accItems.map((item, index) => (
<AccordionItem
boxShadow={'rgba(99, 99, 99, 0.2) 0px 2px 8px 0px'}
key={index}
value={item.value}
bg={"#fff"}
mb={2}
p={"12px"}
rounded={5}
borderBottom={0}
>
<AccordionItemTrigger fontSize={"sm"} >
{item.title}
</AccordionItemTrigger>
<AccordionItemContent fontSize={"xs"} color={'#222222CC'} pt={2}>
{item.text}
</AccordionItemContent>
</AccordionItem>
))}
</AccordionRoot>
</Box>
<Box w={"50%"} rounded={'lg'} bg={"#f2f2f2"} h={'100%'} overflow={'auto'}>
<AgencyName />
</Box>
</Box>
</MainFrame>
);
};
export default Dashboard;

View File

@@ -0,0 +1,65 @@
import { Field, Input, Stack, Text } from "@chakra-ui/react";
import { Button } from "../components/ui/button";
import {
DialogBody,
DialogContent,
DialogFooter,
DialogHeader,
DialogRoot,
DialogTitle,
DialogTrigger,
} from "../components/ui/dialog";
function ForgetPassword() {
return (
<DialogRoot placement="center">
<DialogTrigger asChild>
<Text w={"100%"} textAlign={"end"} mt={2} cursor={"pointer"}>
Forgot password?
</Text>
</DialogTrigger>
<DialogContent
bg={"#fff"}
w={{ base: "90%", md: "400px" }}
p={2}
bgSize={"md"}
>
<DialogHeader bg="white" pt={3} pb={2}>
<DialogTitle
alignSelf="center"
color="black"
fontSize="18px"
textAlign={"center"}
>
Forgot Password
</DialogTitle>
</DialogHeader>
<DialogBody bg="white" pt={5}>
<Stack p={2}>
<Field.Root>
<Field.Label color="black" pt={1} fontSize="12px">
Please Enter Email Address
</Field.Label>
<Input
color="black"
p={2}
fontSize="sm"
type="text"
border="1px solid grey"
size={"sm"}
/>
</Field.Root>
</Stack>
</DialogBody>
<DialogFooter display="flex" justifyContent="center" mt={2} p={2}>
<Button w="100%" bg="#02A0A0" color={"#fff"}>
Reset Password
</Button>
</DialogFooter>
</DialogContent>
</DialogRoot>
);
}
export default ForgetPassword;

View File

@@ -0,0 +1,171 @@
import {
Box,
Center,
HStack,
Image,
Input,
Text,
VStack,
} from "@chakra-ui/react";
import axios from "axios";
import { useState } from "react";
import { useForm } from "react-hook-form";
// import { useDispatch } from "react-redux";
import logo from "../assets/logo.svg";
import { Button } from "../components/ui/button";
import { Field } from "../components/ui/field";
import { toaster, Toaster } from "../components/ui/toaster";
import { useNavigate } from "react-router-dom";
interface FormValues {
mobileNumber: number;
}
const ForgotPassword = () => {
const navigate = useNavigate();
const [isLoading, setIsLoading] = useState<boolean>(false);
const {
register,
handleSubmit,
formState: { errors },
} = useForm<FormValues>();
const onSubmit = handleSubmit(async (data) => {
const username = import.meta.env.VITE_USER_NAME || ""; // Replace with actual username
const password = import.meta.env.VITE_PASSWORD || ""; // Replace with actual password
const basicAuth = `${username}:${password}`; // Encode to Base64
setIsLoading(true);
try {
const res = await axios.post(
`${import.meta.env.VITE_API_URL}/send-otp`,
{
mobile_number: Number(data.mobileNumber),
},
{
headers: {
Authorization: `Basic ${basicAuth}`,
"Content-Type": "application/json",
},
}
);
if (res.status === 200) {
navigate(`/forgot-password/verify?phone=${data.mobileNumber}`)
} else {
// alert(res.data.message || "Something went wrong");
toaster.create({
// title: error?.response?.data?.message,
title: res.data.message || "Something went wrong",
type: "error",
})
setIsLoading(false);
}
console.log("============", res);
} catch (error) {
console.log('error', error);
if (error) {
toaster.create({
// title: error?.response?.data?.message,
title: "Something Went Wrong",
type: "info",
})
// console.log("Login failed", error?.response?.data?.message);
setIsLoading(false);
}
}
});
return (
<VStack appearance={'light'} w={"100%"} h={"100vh"} bg={"#ffffff"}>
<HStack
boxShadow={"rgba(99, 99, 99, 0.2) 0px 2px 8px 0px"}
w={"100%"}
ps={8}
h={"7%"}
justifyContent={"flex-start"}
>
<Image w={50} src={logo} />
</HStack>
<HStack w={"100%"} h={"93%"} p={8} gap={8}>
<Center
display={{ base: "none", md: "flex" }}
bg={"#02A0A033"}
w={"50%"}
h={"100%"}
rounded={"3xl"}
>
<Image w={250} src={logo} />
</Center>
<Box
as={"form"}
onSubmit={onSubmit}
p={{ base: 4, md: 16 }}
w={{ base: "100%", md: "50%" }}
h={"100%"}
>
<VStack gap={2} w={"100%"}>
<Text
w={"100%"}
textAlign={"center"}
fontSize={"24px"}
fontWeight={"normal"}
color={"#313039"}
>
Forgot Password
</Text>
<Box mt={6} gap={4} w={"full"}>
<Field
color={"#313039"}
label={"Enter Mobile Number"}
w={"100%"}
invalid={!!errors.mobileNumber}
errorText={errors.mobileNumber?.message}
mb={4}
>
<Input
type="number"
ps={3}
maxLength={10}
{...register("mobileNumber", {
required: "Please enter a 10 digit mobile number",
pattern: {
value: /^[0-9]{10}$/,
message: "Mobile number must be exactly 10 digits"
}
})}
placeholder="Enter Mobile Number"
onInput={(e) => {
const target = e.target as HTMLInputElement;
target.value = target.value.replace(/\D/g, "").slice(0, 10);
}}
/>
</Field>
<Button
loading={isLoading}
mt={4}
size={"sm"}
bg={"#02A0A0"}
rounded={"md"}
w={"100%"}
color={"#ffffff"}
type="submit"
>
Send OTP
</Button>
</Box>
</VStack>
</Box>
<Toaster />
</HStack>
</VStack>
);
};
export default ForgotPassword;

View File

@@ -1,18 +1,34 @@
import { Center, HStack, Image, Input, Text, VStack } from "@chakra-ui/react"; import {
Box,
Center,
HStack,
Image,
Input,
Text,
VStack,
} from "@chakra-ui/react";
import axios from "axios";
import { useContext, useState } from "react"; import { useContext, useState } from "react";
import { useForm } from "react-hook-form"; import { useForm } from "react-hook-form";
import { useDispatch } from "react-redux";
import GlobalStateContext from "../Contexts/GlobalStateContext"; import GlobalStateContext from "../Contexts/GlobalStateContext";
import { setToken } from "../Redux/Service/authSlice";
import logo from "../assets/logo.svg"; import logo from "../assets/logo.svg";
import { Button } from "../components/ui/button"; import { Button } from "../components/ui/button";
import { Field } from "../components/ui/field"; import { Field } from "../components/ui/field";
import { Toaster, toaster } from "../components/ui/toaster"; import { toaster, Toaster } from "../components/ui/toaster";
import { LuUser } from "react-icons/lu"; import { PasswordInput } from "../components/ui/password-input";
import { Link, useNavigate } from "react-router-dom";
// import ForgetPassword from "./ForgetPassword";
interface FormValues { interface FormValues {
mobileNumber: number; mobileNumber: number;
password: string;
} }
const Login = () => { const Login = () => {
const navigate = useNavigate();
const dispatch = useDispatch();
const [isLoading, setIsLoading] = useState<boolean>(false); const [isLoading, setIsLoading] = useState<boolean>(false);
const context = useContext(GlobalStateContext); const context = useContext(GlobalStateContext);
if (!context) { if (!context) {
@@ -25,24 +41,60 @@ const Login = () => {
formState: { errors }, formState: { errors },
} = useForm<FormValues>(); } = useForm<FormValues>();
const onSubmit = handleSubmit((data) => { const onSubmit = handleSubmit(async (data) => {
setIsLoading(true); setIsLoading(true);
if (data?.mobileNumber === 1234567890) { // Encode Basic Auth Credentials
setTimeout(() => { const username = import.meta.env.VITE_USER_NAME || ""; // Replace with actual username
const password = import.meta.env.VITE_PASSWORD || ""; // Replace with actual password
const basicAuth = `${username}:${password}`; // Encode to Base64
try {
const res = await axios.post(
`${import.meta.env.VITE_API_URL}/login`,
{
mobile_number: Number(data.mobileNumber),
password: data.password,
},
{
headers: {
Authorization: `Basic ${basicAuth}`,
"Content-Type": "application/json",
},
}
);
console.log("============", res);
if (res.data) {
setIsAuthenticate(true); setIsAuthenticate(true);
console.log("====================================");
console.log(res.data?.data);
console.log("====================================");
navigate("/dashboard");
dispatch(setToken(String(res.data?.data["access-token"])));
} else {
console.log("====================================");
console.log(res);
console.log("====================================");
}
} catch (error: any) {
console.log('error', error.response.data.message);
if (error) {
toaster.create({
title: error?.response?.data?.message,
// title: "Something Went Wrong",
type: "info",
})
// console.log("Login failed", error?.response?.data?.message);
setIsLoading(false); setIsLoading(false);
}, 3000); // 3-second delay }
} else {
toaster.create({
title: `Invalid Credentials`,
type: "error",
});
setIsLoading(false);
} }
}); });
return ( return (
<VStack w={"100%"} h={"100vh"} bg={"#ffffff"}>
<VStack appearance={'light'} w={"100%"} h={"100vh"} bg={"#ffffff"}>
<HStack <HStack
boxShadow={"rgba(99, 99, 99, 0.2) 0px 2px 8px 0px"} boxShadow={"rgba(99, 99, 99, 0.2) 0px 2px 8px 0px"}
w={"100%"} w={"100%"}
@@ -64,14 +116,14 @@ const Login = () => {
<Image w={250} src={logo} /> <Image w={250} src={logo} />
</Center> </Center>
<Center <Box
as={"form"} as={"form"}
onSubmit={onSubmit} onSubmit={onSubmit}
p={{ base: 4, md: 16 }} p={{ base: 4, md: 16 }}
w={{ base: "100%", md: "50%" }} w={{ base: "100%", md: "50%" }}
h={"100%"} h={"100%"}
> >
<VStack gap={2} w={"100%"} alignItems={"flex-start"}> <VStack gap={2} w={"100%"}>
<Text <Text
w={"100%"} w={"100%"}
textAlign={"center"} textAlign={"center"}
@@ -82,24 +134,39 @@ const Login = () => {
LOGIN LOGIN
</Text> </Text>
<VStack mt={6} gap={4} w={"full"}> <Box mt={6} gap={4} w={"full"}>
<Field <Field
color={"#313039"} color={"#313039"}
label={"Enter Mobile Number"} label={"Enter Mobile Number"}
w={"100%"} w={"100%"}
invalid={!!errors.mobileNumber} invalid={!!errors.mobileNumber}
errorText={errors.mobileNumber?.message} errorText={errors.mobileNumber?.message}
mb={4}
> >
<Input <Input
type="number"
ps={3} ps={3}
{...register("mobileNumber", { {...register("mobileNumber", {
required: "Mobile Number address is required", required: "Mobile Number address is required",
})} })}
placeholder="Mobile Number Address" placeholder="Mobile Number Address"
/> />
{/* <Text as={'span'} w={'100%'} fontSize={'xs'} fontWeight={'normal'} color={'#686677'}>Forget password</Text> */}
</Field>
<Text cursor="pointer" as={'span'} w={'100%'} fontSize={'xs'} fontWeight={'normal'} color={'#686677'}>Forget password</Text> <Field
color={"#313039"}
label={"Enter password."}
w={"100%"}
invalid={!!errors.password}
errorText={errors.password?.message}
mb={2}
>
<PasswordInput
ps={3}
{...register("password", { required: "Pasword is required" })}
placeholder="Enter password"
/>
{/* <Text as={'span'} w={'100%'} fontSize={'xs'} fontWeight={'normal'} color={'#686677'}>Forget password</Text> */}
</Field> </Field>
<Button <Button
loading={isLoading} loading={isLoading}
@@ -111,13 +178,21 @@ const Login = () => {
color={"#ffffff"} color={"#ffffff"}
type="submit" type="submit"
> >
Send OTP Login
</Button> </Button>
<Text>Forgot password</Text> {/* <ForgetPassword /> */}
</VStack> <Box textAlign={"center"} mt={4}>
<Link
to={'/forgot-password'}
style={{ color: "black", fontSize: "16px" }}
>
Forgot Password
</Link>
</Box>
</Box>
</VStack> </VStack>
</Center> </Box>
<Toaster /> <Toaster />
</HStack> </HStack>
</VStack> </VStack>

View File

@@ -1,11 +1,132 @@
import MainFrame from '../../../components/MainFrame' // import { Badge, HStack, Text, VStack } from "@chakra-ui/react";
// import MainFrame from "../../../components/MainFrame"
// import { useGetAboutUsQuery } from "../../../Redux/Service/manage.aboutus.service";
// import { Spinner } from "../../../components/Sipnner/Spinner";
// import GlobalStateContext from "../../../Contexts/GlobalStateContext";
// import { useContext, useEffect } from "react";
// import AboutUsAddModel from "./AboutUsAddModel";
// const AboutUs = () => {
// const { data, isLoading, isFetching } = useGetAboutUsQuery();
// // const content = data?.data
// console.log('====================================');
// console.log(data);
// console.log('====================================');
// const context = useContext(GlobalStateContext);
// if (!context) throw new Error('App must be used within a GlobalStateProvider');
// const { setIsBarLoading } = context;
// useEffect(() => {
// setIsBarLoading(isFetching)
// }, [data])
// return (
// <MainFrame transperant={true}>
// <VStack gap={4} pb={4} pt={0}>
// {isLoading || isFetching ?
// <Spinner /> : data?.data?.map(({ id, content, about_language }) => <VStack bg={'#fff'}
// boxShadow={'rgba(99, 99, 99, 0.2) 0px 2px 8px 0px'} rounded={'lg'} p={3} key={id}>
// <HStack
// w={"100%"}
// justifyContent={"space-between"}
// py={0}
// px={0}
// >
// <Text as={"span"} fontSize={"sm"} fontWeight={500} color={"#000"}>
// About Us <Badge variant={'surface'} colorPalette="cyan" ms={2} size={'sm'} fontSize={'xs'} px={2}>🎓 {about_language?.language_name}</Badge>
// </Text>
// {/* <AboutUsAddModel /> */}
// <AboutUsAddModel/>
// </HStack>
// <Text
// as="p"
// fontSize="sm"
// fontWeight={400}
// color="#1D1D1D"
// >
// {content}
// </Text>
// </VStack>)}
// </VStack>
// </MainFrame>
// )
// }
// export default AboutUs
import { Badge, HStack, Stack, Text, VStack } from "@chakra-ui/react";
import MainFrame from "../../../components/MainFrame";
import { useGetAboutUsQuery } from "../../../Redux/Service/manage.aboutus.service";
import { Spinner } from "../../../components/Sipnner/Spinner";
import GlobalStateContext from "../../../Contexts/GlobalStateContext";
import { useContext, useEffect } from "react";
import AboutUsAddModel from "./AboutUsAddModel";
const AboutUs = () => { const AboutUs = () => {
return ( const { data, isLoading, isFetching } = useGetAboutUsQuery();
<MainFrame>
</MainFrame>
)
}
export default AboutUs console.log("Fetched About Us Data:", data);
const context = useContext(GlobalStateContext);
if (!context) throw new Error("App must be used within a GlobalStateProvider");
const { setIsBarLoading } = context;
useEffect(() => {
setIsBarLoading(isFetching);
}, [isFetching, setIsBarLoading]);
return (
<MainFrame transperant={true}>
<VStack gap={4} pb={4} pt={0}>
<Stack bg={"#fff"} w={"100%"} mt={2} p={4} borderRadius={4}><Text color={"black"} textAlign={"left"} fontWeight={"600"} > About Us
</Text></Stack>
{isLoading || isFetching ? (
<Spinner />
) : (
data?.data?.map(({ id, content, about_language }) => (
<VStack
bg={"#fff"}
boxShadow={"rgba(99, 99, 99, 0.2) 0px 2px 8px 0px"}
rounded={"lg"}
p={3}
key={id}
>
<HStack w={"100%"} justifyContent={"space-between"} py={0} px={0}>
<Text as={"span"} fontSize={"sm"} fontWeight={500} color={"#000"}>
<Badge
variant={"surface"}
colorPalette="cyan"
ms={2}
size={"sm"}
fontSize={"xs"}
px={2}
>
🎓 {about_language?.language_name}
</Badge>
</Text>
{/* Pass Data to AboutUsAddModel */}
<AboutUsAddModel aboutUsData={{ id, content, about_language }} />
</HStack>
<Text as="p" fontSize="sm" fontWeight={400} color="#1D1D1D">
{/* {content} */}
<div dangerouslySetInnerHTML={{ __html: content }} />
</Text>
</VStack>
))
)}
</VStack>
</MainFrame>
);
};
export default AboutUs;

View File

@@ -1,53 +1,142 @@
import { FaRegEdit } from "react-icons/fa" import { FaRegEdit } from "react-icons/fa";
import { DialogBody, DialogCloseTrigger, DialogContent, DialogFooter, DialogHeader, DialogRoot, DialogTitle, DialogTrigger } from "../../../components/ui/dialog" import {
import { Field, Stack, Text, Textarea } from "@chakra-ui/react" DialogBody,
import { Button } from "../../../components/ui/button" DialogCloseTrigger,
DialogContent,
DialogFooter,
DialogHeader,
DialogRoot,
DialogTitle,
DialogTrigger,
} from "../../../components/ui/dialog";
import { Field, Stack, Text } from "@chakra-ui/react";
import { Button } from "../../../components/ui/button";
import ReactQuill from "react-quill";
import "react-quill/dist/quill.snow.css"; // Import the styles
import { useState } from "react";
import { useUpdateAboutUsMutation } from "../../../Redux/Service/manage.aboutus.service";
import { useForm, Controller } from "react-hook-form"; // Import React Hook Form
function AboutUsAddModel({ aboutUsData }: { aboutUsData: any }) {
const [isOpen, setIsOpen] = useState(false);
// RTK Query Mutation Hook
const [updateAboutUs] = useUpdateAboutUsMutation();
// React Hook Form
const {
control,
handleSubmit,
reset,
setValue,
} = useForm({
defaultValues: {
content: "",
languageCode: "",
},
});
// Function to handle edit click (pre-fill the editor)
const handleEditClick = (data: any) => {
setValue("content", data.content); // Pre-fill the content field
setValue("languageCode", data.about_language.language_code); // Pre-fill the language code
setIsOpen(true); // Open dialog
};
// Function to handle update submission
const onSubmit = async (formData: any) => {
if (!formData.content.trim()) return; // Prevent empty updates
try {
await updateAboutUs({
id: aboutUsData.id,
content: formData.content,
language_code: formData.languageCode,
}).unwrap();
setIsOpen(false); // Close dialog on success
reset(); // Reset the form
} catch (error) {
console.error("Update failed:", error);
}
};
function AboutUsAddModel() {
return ( return (
<DialogRoot placement="center" open={isOpen}>
<DialogRoot placement="center">
<DialogTrigger asChild> <DialogTrigger asChild>
{/* <Button bg={"transparent"} size="sm"> <Button
<MdOutlineRemoveRedEye style={{ cursor: "pointer", fontSize: "16px" }} /> bgColor="#EEEEEE"
</Button> */} pl={3}
<Button bgColor={'#EEEEEE'} pl={3} pr={3} size={'xs'} color={'#000'}> <FaRegEdit color="#000" style={{ height: '14px', width: '14px' }} /> <Text color={"#000"} mt={1}>Edit</Text></Button> pr={3}
size="xs"
color="#000"
onClick={() => handleEditClick(aboutUsData)} // Set content before opening modal
>
<FaRegEdit color="#000" style={{ height: "14px", width: "14px" }} />
<Text color="#000" mt={1}>Edit</Text>
</Button>
</DialogTrigger> </DialogTrigger>
<DialogContent <DialogContent bg="#fff" w={{ base: "90%", md: "1200px" }} height="auto" p={3}>
bg={"#fff"} <DialogHeader bg="white">
// w={{ lg: "60%", md: "230px" }} <DialogTitle alignSelf="center" color="black" fontSize="14px">
w={{ base: '90%', md: '400px' }} Edit About Us
height={"auto"} </DialogTitle>
p={3} // Reduced padding
bgSize={'md'}
>
<DialogHeader bg="white" >
<DialogTitle alignSelf="center" color="black" fontSize="14px">Edit</DialogTitle>
</DialogHeader> </DialogHeader>
<DialogBody bg="white"> <DialogBody bg="white">
<Stack py={3} > <Stack py={3} mb={8}>
<Field.Root> <Field.Root>
<Field.Label color="black" pt={1} fontSize="12px">AboutUs</Field.Label> <Field.Label color="black" pt={1} fontSize="12px">
<Textarea placeholder="" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" pt={1.5} /> About Us Content
</Field.Label>
{/* Use Controller to integrate ReactQuill with React Hook Form */}
<Controller
name="content"
control={control}
render={({ field }) => (
<ReactQuill
value={field.value}
onChange={field.onChange}
placeholder="Enter About Us content"
modules={{
toolbar: [
[{ 'header': [1, 2, false] }],
['bold', 'italic', 'underline', 'strike'],
['link', 'image'],
[{ 'list': 'ordered' }, { 'list': 'bullet' }],
['clean']
],
}}
formats={[
'header',
'bold', 'italic', 'underline', 'strike',
'list', 'bullet',
'link', 'image'
]}
style={{ color: "black", border: "none", fontSize: "12px", height: "170px", width: "100%" }}
/>
)}
/>
</Field.Root> </Field.Root>
</Stack> </Stack>
</DialogBody> </DialogBody>
<DialogFooter display="flex" justifyContent="center" pt={"2"}>
<Button w="100%" bg="#02A0A0" color={"#fff"}> <DialogFooter display="flex" justifyContent="center" pt="2">
<Button
w="100%"
bg="#02A0A0"
color="#fff"
// isLoading={isLoading}
onClick={handleSubmit(onSubmit)} // Use handleSubmit to trigger form submission
>
Save Save
</Button> </Button>
</DialogFooter> </DialogFooter>
<DialogCloseTrigger color="black" /> <DialogCloseTrigger color="black" onClick={() => setIsOpen(false)} />
</DialogContent> </DialogContent>
</DialogRoot > </DialogRoot>
);
)
} }
export default AboutUsAddModel export default AboutUsAddModel;

View File

@@ -1,56 +1,161 @@
import { Button } from "../../../components/ui/button" import { Button } from "../../../components/ui/button";
import { DialogBody, DialogCloseTrigger, DialogContent, DialogFooter, DialogHeader, DialogRoot, DialogTitle, DialogTrigger } from "../../../components/ui/dialog" import {
import { Field, Grid, Input, Stack, Text, Textarea } from "@chakra-ui/react" DialogBody,
import { FaRegEdit } from "react-icons/fa"; DialogCloseTrigger,
function EditDetails() { DialogContent,
return ( DialogFooter,
DialogHeader,
DialogRoot,
DialogTitle,
DialogTrigger,
} from "../../../components/ui/dialog";
import { Field, Input, Stack, Textarea } from "@chakra-ui/react";
import Edit from "../../../components/ActionIcons/Edit";
import { useUpdateFaqMutation } from "../../../Redux/Service/faqs.service";
import { useEffect, useState } from "react";
import { Toaster, toaster } from "../../../components/ui/toaster";
<DialogRoot placement="center"> interface RowData {
<DialogTrigger asChild> id: number;
<Button bg={"transparent"} size="sm"> principal_type_xid: number;
<FaRegEdit style={{ cursor: "pointer", }} color="#000" /> question: string;
</Button> answer: string;
{/* <Button><FaRegEdit /></Button> */}
</DialogTrigger>
<DialogContent
bg={"#fff"}
// w={{ lg: "60%", md: "230px" }}
w={{ base: '90%', md: '400px' }}
height={"auto"}
p={3} // Reduced padding
bgSize={'md'}
>
<DialogHeader bg="white" >
<DialogTitle alignSelf="center" color="black" fontSize="14px">Edit Details</DialogTitle>
</DialogHeader>
<DialogBody bg="white">
<Stack py={3} >
<Field.Root>
<Field.Label color="black" pt={1} fontSize="12px">Questions</Field.Label>
<Input placeholder="Questions" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" />
<Field.Label color="black" pt={1} fontSize="12px">Answer</Field.Label>
<Textarea placeholder="Answer" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" pt={1.5} />
</Field.Root>
</Stack>
</DialogBody>
<DialogFooter display="flex" justifyContent="center" pt={"2"}>
<Button w="100%" bg="#02A0A0" color={"#fff"}>
Save
</Button>
</DialogFooter>
<DialogCloseTrigger color="black" />
</DialogContent>
</DialogRoot >
)
} }
export default EditDetails function EditDetails({ rowData, refetch }: {rowData: RowData, refetch: VoidFunction}) {
const [faqQuestion, setFaqQuestion] = useState(rowData?.question);
const [faqAnswer, setFaqAnswer] = useState(rowData?.answer);
const [isOpen, setIsOpen] = useState(false);
const [updateFaq] = useUpdateFaqMutation()
// console.log('ROWDATA', rowData);
useEffect(() => {
if (rowData) {
setFaqQuestion(rowData.question);
setFaqAnswer(rowData.answer);
}
}, [rowData]);
const handleOpenModal = () => {
setIsOpen(true);
};
const handleSubmit = async () => {
if (!faqQuestion.trim() || !faqAnswer.trim()) {
toaster.create({
title: "Error",
description: "Input fields cannot be empty",
type: "error",
});
return;
}
const payload = {
id: rowData?.id,
question: faqQuestion,
answer: faqAnswer,
principal_type_xid: rowData?.principal_type_xid,
};
try {
const response = await updateFaq(payload).unwrap();
if (response?.status === "success") {
toaster.create({
title: "Success",
description: "FAQ updated successfully",
type: "success",
});
refetch()
setIsOpen(false);
} else {
toaster.create({
title: "Error",
description: "Failed to update FAQ",
type: "error",
});
}
} catch (error) {
console.error("Error updating template:", error);
// alert("Failed to update template");
toaster.create({
title: "Error",
description: "Something went wrong",
type: "error",
});
}
};
return (
<DialogRoot placement="center" open={isOpen} onOpenChange={({ open }) => setIsOpen(open)}>
<DialogTrigger asChild>
<Button bg="transparent" color={"black"} h={"18px"} onClick={handleOpenModal}><Edit /></Button>
</DialogTrigger>
<DialogContent
bg={"#fff"}
w={{ base: "90%", md: "400px" }}
height={"auto"}
p={3}
>
<DialogHeader bg="white">
<DialogTitle alignSelf="center" color="black" fontSize="14px">
Edit Details (ID: {rowData?.id})
</DialogTitle>
</DialogHeader>
<DialogBody bg="white">
<Stack py={3}>
<Field.Root>
<Field.Label color="black" pt={1} fontSize="12px">
Question
</Field.Label>
<Input
placeholder="Question"
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
value={faqQuestion}
onChange={(e) => setFaqQuestion(e.target.value)}
/>
<Field.Label color="black" pt={1} fontSize="12px">
Answer
</Field.Label>
<Textarea
placeholder="Answer"
bgColor="#EEEEEE"
color="black"
border="none"
p={2}
fontSize="12px"
height="auto"
pt={1.5}
value={faqAnswer}
onChange={(e) => setFaqAnswer(e.target.value)}
/>
</Field.Root>
</Stack>
</DialogBody>
<DialogFooter display="flex" justifyContent="center" pt={"2"}>
<Button w="100%" bg="#02A0A0" color={"#fff"} onClick={handleSubmit}>
Save
</Button>
</DialogFooter>
<DialogCloseTrigger color="black" onClick={() => setIsOpen(false)} />
</DialogContent>
<Toaster />
</DialogRoot>
);
}
export default EditDetails;

View File

@@ -1,52 +1,194 @@
import { Box, Button, HStack, Image, Input, Text } from "@chakra-ui/react"; import { Box, HStack, Image, Spinner, Text } from "@chakra-ui/react";
import MainFrame from "../../../components/MainFrame" import MainFrame from "../../../components/MainFrame"
import EditDetails from "./EditDetails"; import EditDetails from "./EditDetails";
import { InputGroup } from "../../../components/ui/input-group"; // import { InputGroup } from "../../../components/ui/input-group";
import { LuSearch } from "react-icons/lu"; // import { LuSearch } from "react-icons/lu";
import DataTable from "../../../components/DataTable"; import DataTable from "../../../components/DataTable";
import AlertDailog from "../../../components/AlertDailog"; import AlertDailog from "../../../components/AlertDailog";
import { RiDeleteBin5Line } from "react-icons/ri";
import { Switch } from "../../../components/ui/switch"; import { Switch } from "../../../components/ui/switch";
import FaqAddModel from "./FaqAddModel"; import FaqAddModel from "./FaqAddModel";
import Delete from "../../../components/ActionIcons/Delete";
import { useEffect, useState } from "react";
import { FaqData, useDeleteFaqPostMutation, useFaqToggleMutation, useGetFaqQuery } from "../../../Redux/Service/faqs.service";
import SearchComponent from "../../../components/SearchComponent";
import NoData from "../../../components/NoData";
import { Toaster, toaster } from "../../../components/ui/toaster";
// table data // table data
const tableHeadRow = [ const tableHeadRow = [
"Sr. No", "Sr. No",
'Category',
"Question", "Question",
"Answer", "Answer",
"Action", "Action",
]; ];
const managepost: any[] = [ // const managepost: any[] = [
...Array.from({ length: 12 }, (_, i) => ({ // ...Array.from({ length: 12 }, (_, i) => ({
"Sr. No": i + 1, // "Sr. No": i + 1,
"Question": "Lorem Ipsum", // "Question": "Lorem Ipsum",
"Answer": "Lorem Ipsum", // "Answer": "Lorem Ipsum",
"Action": ( // "Action": (
<HStack justifyContent="center"> // <HStack justifyContent="center">
<Box> // <Box>
<Switch colorPalette={'teal'} size={"xs"}/> // <Switch colorPalette={'teal'} size={"xs"} />
</Box> // </Box>
<EditDetails /> // {/* <EditDetails /> */}
<AlertDailog // <EditDetails id={(i + 1).toString()} question="Lorem Ipsum" answer="Lorem Ipsum" />
AltertTiggerIcon={RiDeleteBin5Line}
alertText="Delete Users" // <AlertDailog
alertIcon={<Image src={"DeleteIcon"} h={"39px"} />} // AltertTiggerIcon={() => <Delete />}
alertCaption="are you sure you want to delete ?" // alertText="Delete Users"
onConfirm={() => { // alertIcon={<Image src={"DeleteIcon"} h={"39px"} />}
console.log("User deleted:", i + 1); // alertCaption="are you sure you want to delete ?"
}} // onConfirm={() => {
/> // console.log("User deleted:", i + 1);
</HStack> // }}
), // />
})), // </HStack>
]; // ),
// })),
// ];
const FAQ = () => { const FAQ = () => {
return ( const [currentPage, setCurrentPage] = useState(1);
const { data, refetch, isLoading, isFetching } = useGetFaqQuery(currentPage)
const [localData, setLocalData] = useState<any[]>([]);
const [faqToggle] = useFaqToggleMutation()
const [deleteFaqPost] = useDeleteFaqPostMutation()
const [searchTerm, setSearchTerm] = useState("");
const [deleteModal, setDeleteModal] = useState(false)
const [selectedFaqId, setSelectedFaqId] = useState<number | null>(null);
console.log('DATA', data?.data.data);
useEffect(() => {
if (data) {
setLocalData(data?.data.data);
}
}, [data]);
const handlePageChange = (page: number) => {
setCurrentPage(page);
};
const handleToggle = async (agencyId: number, currentStatus: string) => {
const newStatus = currentStatus === '1' ? '0' : '1';
setLocalData((prevData) =>
prevData.map((agency) =>
agency.id === agencyId ? { ...agency, is_active: newStatus } : agency
)
);
try {
await faqToggle({ id: agencyId, is_active: newStatus }).unwrap();
refetch()
} catch (error) {
console.error("Error updating privacy policy:", error);
setLocalData((prevData) =>
prevData.map((agency) =>
agency.id === agencyId ? { ...agency, is_active: currentStatus } : agency
)
);
}
};
const handleDeleteFaq = async (faqId: number) => {
try {
const response = await deleteFaqPost({ id: faqId }).unwrap();
if (response?.status === "success") {
toaster.create({
title: "Success",
description: "FAQ deleted successfully",
type: "success",
});
refetch()
console.log("FAQ deleted successfully:", response);
}
// Optionally, refetch data or update state after deletion
} catch (error) {
console.error("Error deleting FAQ:", error);
toaster.create({
title: "Error",
description: "Something went wrong",
type: "error",
});
}
};
const filteredData = localData?.filter((agency) =>
agency.translations.some((translation: any) => {
const searchLower = searchTerm.toLowerCase();
const questionMatch = translation.question?.toLowerCase().includes(searchLower);
const answerMatch = translation.answer?.toLowerCase().includes(searchLower);
return questionMatch || answerMatch;
})
);
console.log("filteredData", filteredData);
const managepost = filteredData?.flatMap((agency: FaqData, index: number) =>
agency.translations.map((translation: any) => ({
'id': translation.id,
"Sr. No": (currentPage - 1) * (data?.data.per_page ?? 0) + index + 1,
"Question": translation.question,
"Answer": translation.answer,
'Category': agency.principal_type_xid === 2 ? "Recruiter" : "Job Seeker",
"Action": (
<HStack justifyContent="center">
<EditDetails rowData={{ id: agency.id, question: translation.question, answer: translation.answer, principal_type_xid: agency.principal_type_xid }} refetch={refetch} />
<AlertDailog
isOpen={deleteModal}
AltertTiggerIcon={() => <Delete onClick={() => {
setSelectedFaqId(agency.id);
setDeleteModal(true)
}} />}
alertText="Delete FAQ"
alertIcon={<Image src={"DeleteIcon"} h={"39px"} />}
alertCaption="are you sure you want to delete ?"
onClose={() => setDeleteModal(false)}
onConfirm={() => {
// console.log("Deleting FAQ with ID:", selectedFaqId); // Correct ID
if (selectedFaqId) {
setDeleteModal(false);
handleDeleteFaq(selectedFaqId);
}
}}
/>
<Box>
<Switch
colorPalette={'teal'}
size={"xs"}
onChange={() => handleToggle(Number(agency.id), agency.is_active.toString())}
checked={Boolean(Number(agency.is_active))}
key={`switch-${agency.id}`}
/>
</Box>
</HStack>
),
})))
if (isFetching) {
return (
<HStack
w={"100%"}
justifyContent={"center"}
mb={4}
py={0}
px={3}
>
<Spinner color={'teal'} />
</HStack>
)
}
return (
<MainFrame> <MainFrame>
<Box> <Box>
<HStack <HStack
@@ -57,40 +199,35 @@ const FAQ = () => {
px={3} px={3}
> >
<Text as={"span"} fontSize={"sm"} fontWeight={500} color={"#000"}> <Text as={"span"} fontSize={"sm"} fontWeight={500} color={"#000"}>
FAQs FAQs
</Text> </Text>
<HStack > <HStack >
<InputGroup <SearchComponent
startElement={ value={searchTerm}
<LuSearch fontSize={"xs"} style={{ position: 'relative', left: '10px' }} /> onChange={setSearchTerm}
} />
color={"#000"}
>
<Input
p={3}
w={300}
bg={"#fff"}
colorPalette={"blue"}
_focus={{ border: "1px solid #02A0A0" }}
rounded={"md"}
size={"2xs"}
fontSize={"2sm"}
placeholder="Search..."
bgColor={'#EEEEEE'}
ps={8}
/>
</InputGroup>
{/* <Button bgColor={'#EEEEEE'} pl={3} pr={3}><IoMdAdd /> <Text>Add</Text></Button> */} {/* <Button bgColor={'#EEEEEE'} pl={3} pr={3}><IoMdAdd /> <Text>Add</Text></Button> */}
<FaqAddModel /> <FaqAddModel refetch={refetch} />
</HStack> </HStack>
</HStack> </HStack>
<DataTable {isFetching && <Spinner />}
sortableColumns={["Name", "Registration Date "]} {!isLoading && !data?.data ? (
<NoData message={'No data found'} text={'Please add new data'} />
) : (<DataTable
sortableColumns={["Name"]}
tableHeadRow={tableHeadRow} tableHeadRow={tableHeadRow}
data={managepost} data={managepost}
/> paginationData={{
</Box> current_page: data?.data.current_page || 1,
last_page: data?.data.last_page || 1,
per_page: data?.data.per_page || 10,
total: data?.data.total || 0
}}
onPageChange={handlePageChange}
/>)}
</Box>
<Toaster />
</MainFrame> </MainFrame>
) )
} }

View File

@@ -1,57 +1,174 @@
import { DialogBody, DialogCloseTrigger, DialogContent, DialogFooter, DialogHeader, DialogRoot, DialogTitle, DialogTrigger } from "../../../components/ui/dialog" import {
import { Field, Input, Stack, Text, Textarea } from "@chakra-ui/react" DialogBody,
import { IoMdAdd } from "react-icons/io" DialogCloseTrigger,
import { Button } from "../../../components/ui/button" DialogContent,
DialogFooter,
DialogHeader,
DialogRoot,
DialogTitle,
DialogTrigger,
} from "../../../components/ui/dialog";
import { Box, Field, Input, Stack, Text, Textarea } from "@chakra-ui/react";
import { IoMdAdd } from "react-icons/io";
import { Button } from "../../../components/ui/button";
import { useState } from "react";
import { Toaster, toaster } from "../../../components/ui/toaster";
import { useCreateFaqPostMutation } from "../../../Redux/Service/faqs.service";
function FaqAddModel() { function FaqAddModel({ refetch }: { refetch: VoidFunction }) {
return ( const [faqQuestion, setFaqQuestion] = useState('');
const [faqAnswer, setFaqAnswer] = useState('');
const [userType, setUserType] = useState("");
const [isOpen, setIsOpen] = useState(false);
const [createFaqPost] = useCreateFaqPostMutation()
<DialogRoot placement="center"> const handleOpenModal = () => {
<DialogTrigger asChild> setIsOpen(true); // Open modal when clicking "Add"
{/* <Button bg={"transparent"} size="sm"> };
<MdOutlineRemoveRedEye style={{ cursor: "pointer", fontSize: "16px" }} />
</Button> */}
<Button px={5} size={"xs"} bg={"#02A0A0"}><IoMdAdd /> <Text>Add</Text></Button>
</DialogTrigger> const handleSubmit = async () => {
if (userType === "" || isNaN(Number(userType))) {
toaster.create({
title: "Error",
description: "Please select a valid user type.",
type: "error",
});
return;
}
<DialogContent if (!faqQuestion.trim() || !faqAnswer.trim()) {
bg={"#fff"} toaster.create({
// w={{ lg: "60%", md: "230px" }} title: "Error",
w={{ base: '90%', md: '400px' }} description: "Please fill in all required fields",
height={"auto"} type: "error",
});
return;
}
p={3} // Reduced padding const payload = {
bgSize={'md'} principal_type_xid: Number(userType),
> language_code: 'en',
<DialogHeader bg="white" > question: faqQuestion,
<DialogTitle alignSelf="center" color="black" fontSize="14px">Add</DialogTitle> answer: faqAnswer
</DialogHeader> };
<DialogBody bg="white"> try {
<Stack py={3} > const response = await createFaqPost(payload).unwrap();
if (response) {
toaster.create({
title: "Success",
description: "FAQ updated successfully",
type: "success",
});
refetch()
setIsOpen(false);
} else {
toaster.create({
title: "Error",
description: "Failed to update FAQ",
type: "error",
});
}
} catch (error) {
console.error("Error updating template:", error);
// alert("Failed to update template");
}
};
<Field.Root> return (
<Field.Label color="black" pt={1} fontSize="12px">Questions</Field.Label> <DialogRoot placement="center" open={isOpen} onOpenChange={({ open }) => setIsOpen(open)}>
<Input placeholder="Questions" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" /> <DialogTrigger asChild>
<Button px={5} size={"xs"} bg={"#02A0A0"} onClick={handleOpenModal}>
<IoMdAdd /> <Text>Add</Text>
</Button>
</DialogTrigger>
<Field.Label color="black" pt={1} fontSize="12px">Answer</Field.Label> <DialogContent
<Textarea placeholder="Answer" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" pt={1.5} /> bg={"#fff"}
// w={{ lg: "60%", md: "230px" }}
w={{ base: "90%", md: "400px" }}
height={"auto"}
p={3} // Reduced padding
bgSize={"md"}
>
<DialogHeader bg="white">
<DialogTitle alignSelf="center" color="black" fontSize="14px">
Add
</DialogTitle>
</DialogHeader>
</Field.Root> <DialogBody bg="white">
</Stack> <Stack py={3}>
</DialogBody> <Field.Root>
<DialogFooter display="flex" justifyContent="center" pt={"2"}> <Field.Label color="black" pt={1} fontSize="12px">Select User Type</Field.Label>
<Button w="100%" bg="#02A0A0" color={"#fff"}> <Box bgColor="#EEEEEE" borderRadius="md" p={1} w={'100%'}>
Save <select
</Button> style={{
</DialogFooter> width: "100%",
background: "transparent",
color: "black",
border: "none",
fontSize: "12px",
height: "30px",
outline: "none",
}}
value={userType}
onChange={(e) => setUserType(e.target.value)}
>
<option value="" disabled>Select User Type</option>
<option value="2">Recruiter</option>
<option value="3">Jobseeker</option>
</select>
</Box>
</Field.Root>
<DialogCloseTrigger color="black" /> <Field.Root>
</DialogContent> <Field.Label color="black" pt={1} fontSize="12px">
</DialogRoot > Questions
</Field.Label>
<Input
placeholder="Questions"
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
_focusVisible={{ outline: 'none' }}
size={'sm'}
value={faqQuestion}
onChange={(e) => setFaqQuestion(e.target.value)}
/>
) <Field.Label color="black" pt={1} fontSize="12px">
Answer
</Field.Label>
<Textarea
placeholder="Answer"
bgColor="#EEEEEE"
color="black"
border="none"
p={2}
fontSize="12px"
height="120px"
resize={'none'}
_focusVisible={{ outline: 'none' }}
value={faqAnswer}
onChange={(e) => setFaqAnswer(e.target.value)}
/>
</Field.Root>
</Stack>
</DialogBody>
<DialogFooter display="flex" justifyContent="center" pt={"2"}>
<Button w="100%" bg="#02A0A0" color={"#fff"} onClick={handleSubmit}>
Save
</Button>
</DialogFooter>
<DialogCloseTrigger color="black" onClick={() => setIsOpen(false)} />
</DialogContent>
<Toaster />
</DialogRoot>
);
} }
export default FaqAddModel export default FaqAddModel;

View File

@@ -1,12 +0,0 @@
import { Text } from '@chakra-ui/react'
import MainFrame from '../../../components/MainFrame'
const FreqAskQuestion = () => {
return (
<MainFrame>
<Text>hello</Text>
</MainFrame>
)
}
export default FreqAskQuestion

View File

@@ -1,11 +1,82 @@
import MainFrame from '../../../components/MainFrame' import { Badge, HStack, Stack, Text, VStack } from "@chakra-ui/react";
import { useGetPrivacyPolicyQuery } from "../../../Redux/Service/privacy.policy.service";
import MainFrame from "../../../components/MainFrame";
import { Spinner } from "../../../components/Sipnner/Spinner";
import PrivacyPolicyAddModel from "./PrivacyPolicyAddModel";
import GlobalStateContext from "../../../Contexts/GlobalStateContext";
import { useContext, useEffect } from "react";
const PrivacyPolicy = () => { const PrivacyPolicy = () => {
return ( const { data, isLoading, isFetching, refetch } = useGetPrivacyPolicyQuery();
<MainFrame>
</MainFrame>
)
}
export default PrivacyPolicy console.log("PRIVACY", data?.data);
const context = useContext(GlobalStateContext);
if (!context)
throw new Error("App must be used within a GlobalStateProvider");
const { setIsBarLoading } = context;
useEffect(() => {
setIsBarLoading(isFetching);
}, [data]);
console.log("Privacy Policy Data:", data?.data);
return (
<MainFrame transperant={true}>
<Stack bg={"#fff"} w={"100%"} p={4} borderRadius={4} mb={4}>
<Text color={"black"} textAlign={"left"} fontWeight={"600"}>
Privacy Policy
</Text>
</Stack>
<VStack gap={4} pb={4} pt={0}>
{isLoading || isFetching ? (
<Spinner />
) : (
data?.data?.map(({ id, content, privacy_language }) => (
<VStack
bg={"#fff"}
boxShadow={"rgba(99, 99, 99, 0.2) 0px 2px 8px 0px"}
rounded={"lg"}
p={3}
key={id}
>
<HStack w={"100%"} justifyContent={"space-between"} py={0} px={0}>
<Text
as={"span"}
fontSize={"sm"}
fontWeight={500}
color={"#000"}
>
<Badge
variant={"surface"}
colorPalette="cyan"
size={"sm"}
fontSize={"xs"}
px={2}
>
🎓 {privacy_language?.language_name}
</Badge>
</Text>
<PrivacyPolicyAddModel
policyData={{ id, content, privacy_language }}
refetch={refetch}
/>
</HStack>
<Text
as="p"
fontSize="sm"
fontWeight={400}
color="#1D1D1D"
dangerouslySetInnerHTML={{ __html: content }}
/>
</VStack>
))
)}
</VStack>
</MainFrame>
);
};
export default PrivacyPolicy;

View File

@@ -1,53 +1,153 @@
import { FaRegEdit } from "react-icons/fa" import { FaRegEdit } from "react-icons/fa";
import { DialogBody, DialogCloseTrigger, DialogContent, DialogFooter, DialogHeader, DialogRoot, DialogTitle, DialogTrigger } from "../../../components/ui/dialog" import {
import { Field, Input, Stack, Text, Textarea } from "@chakra-ui/react" DialogBody,
import { Button } from "../../../components/ui/button" DialogCloseTrigger,
DialogContent,
DialogFooter,
DialogRoot,
DialogTrigger,
} from "../../../components/ui/dialog";
import { Box, Field, Stack, Text } from "@chakra-ui/react";
import { Button } from "../../../components/ui/button";
import { useUpdatePrivacyPolicyMutation } from "../../../Redux/Service/privacy.policy.service";
import { Controller, useForm } from "react-hook-form";
import { useState } from "react";
import ReactQuill from "react-quill";
function PrivacyPolicyAddModel() { function PrivacyPolicyAddModel({ policyData, refetch }: { policyData: any, refetch: VoidFunction }) {
return ( const [isOpen, setIsOpen] = useState(false);
const [updatePrivacyPolicy] = useUpdatePrivacyPolicyMutation()
const {
control,
handleSubmit,
reset,
setValue,
} = useForm({
defaultValues: {
content: "",
languageCode: "",
},
});
<DialogRoot placement="center"> console.log('POLICY', policyData);
<DialogTrigger asChild>
{/* <Button bg={"transparent"} size="sm">
<MdOutlineRemoveRedEye style={{ cursor: "pointer", fontSize: "16px" }} />
</Button> */}
<Button bgColor={'#EEEEEE'} pl={3} pr={3} size={'xs'} color={'#000'}> <FaRegEdit color="#000" style={{ height: '14px', width: '14px' }} /> <Text color={"#000"} mt={1}>Edit</Text></Button>
</DialogTrigger> const handleEditClick = (data: any) => {
setValue("content", data.content); // Pre-fill the content field
setValue("languageCode", data.privacy_language.language_code); // Pre-fill the language code
setIsOpen(true); // Open dialog
};
<DialogContent const onSubmit = async (formData: any) => {
bg={"#fff"} if (!formData.content.trim()) return; // Prevent empty updates
// w={{ lg: "60%", md: "230px" }}
w={{ base: '90%', md: '400px' }}
height={"auto"}
p={3} // Reduced padding try {
bgSize={'md'} await updatePrivacyPolicy({
> id: policyData.id,
<DialogHeader bg="white" > content: formData.content,
<DialogTitle alignSelf="center" color="black" fontSize="14px">Edit</DialogTitle> language_code: formData.languageCode,
</DialogHeader> }).unwrap();
setIsOpen(false); // Close dialog on success
reset(); // Reset the form
refetch()
} catch (error) {
console.error("Update failed:", error);
}
};
<DialogBody bg="white"> return (
<Stack py={3} > <DialogRoot placement="center" open={isOpen}>
<Box key={policyData.id}>
<DialogTrigger asChild>
<Button
bgColor={"#EEEEEE"}
pl={3} pr={3}
size={"xs"}
color={"#000"}
onClick={() => handleEditClick(policyData)}
>
{" "}
<FaRegEdit
color="#000"
style={{ height: "14px", width: "14px" }}
/>{" "}
<Text color={"#000"} mt={1}>
Edit
</Text>
</Button>
</DialogTrigger>
</Box>
<Field.Root> <DialogContent
<Field.Label color="black" pt={1} fontSize="12px">PrivacyPolicy</Field.Label> bg={"#fff"}
<Textarea placeholder="" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" pt={1.5} /> minW={'600px'}
</Field.Root> // w={{ base: "90%", md: "400px" }}
</Stack> height={"auto"}
</DialogBody> p={3} // Reduced padding
<DialogFooter display="flex" justifyContent="center" pt={"2"}> bgSize={"md"}
<Button w="100%" bg="#02A0A0" color={"#fff"}> >
Save {/* <DialogHeader bg="white">
</Button> <DialogTitle alignSelf="center" color="black" fontSize="14px">
</DialogFooter> Edit
</DialogTitle>
</DialogHeader> */}
<DialogCloseTrigger color="black" /> <DialogBody bg="white">
</DialogContent> <Stack py={3}>
</DialogRoot > <Field.Root>
<Field.Label color="black" pt={1} fontSize="12px">
PrivacyPolicy
</Field.Label>
{/* <Textarea
placeholder=""
bgColor="#EEEEEE"
color="black"
border="none"
p={2}
fontSize="12px"
height={'140px'}
_focusVisible={{ outline: 'none' }}
resize={'none'}
/> */}
<Controller
name="content"
control={control}
render={({ field }) => (
<ReactQuill
value={field.value}
onChange={field.onChange}
placeholder="Enter About Us content"
modules={{
toolbar: [
[{ 'header': [1, 2, false] }],
['bold', 'italic', 'underline', 'strike'],
['link', 'image'],
[{ 'list': 'ordered' }, { 'list': 'bullet' }],
['clean']
],
}}
formats={[
'header',
'bold', 'italic', 'underline', 'strike',
'list', 'bullet',
'link', 'image'
]}
style={{ color: "black", border: "none", fontSize: "12px", height: "220px", width: "100%",marginBottom:'20px' }}
/>
)}
/>
</Field.Root>
</Stack>
</DialogBody>
<DialogFooter display="flex" justifyContent="center" pt={"2"}>
<Button w="100%" bg="#02A0A0" color={"#fff"} mt={'4'} onClick={handleSubmit(onSubmit)}>
Save
</Button>
</DialogFooter>
) <DialogCloseTrigger color="black" onClick={() => setIsOpen(false)} />
</DialogContent>
</DialogRoot>
);
} }
export default PrivacyPolicyAddModel export default PrivacyPolicyAddModel;

View File

@@ -0,0 +1,15 @@
import { Box, Skeleton } from '@chakra-ui/react'
const PrivacyPolicySkeleton = () => {
return (
<Box px={3} pb={3} w="90%">
<Skeleton height="20px" mb="10px" width="90%" />
<Skeleton height="20px" mb="15px" width="90%" />
<Skeleton height="20px" mb="10px" width="90%" />
<Skeleton height="20px" mb="10px" width="80%" />
<Skeleton height="20px" width="60%" />
</Box>
)
}
export default PrivacyPolicySkeleton

View File

@@ -1,11 +0,0 @@
import MainFrame from '../../../components/MainFrame'
const TermsAndCondition = () => {
return (
<MainFrame>
</MainFrame>
)
}
export default TermsAndCondition

View File

@@ -1,38 +1,67 @@
import { Box, HStack, Text } from "@chakra-ui/react"; import { Badge, HStack, Spinner, Stack, Text, VStack } from "@chakra-ui/react";
import MainFrame from "../../../components/MainFrame" import MainFrame from "../../../components/MainFrame";
import { p } from "framer-motion/client";
import TermsAndConditionsAddModel from "./TermsAndConditionsAddModel"; import TermsAndConditionsAddModel from "./TermsAndConditionsAddModel";
import { useGetTermsQuery } from "../../../Redux/Service/terms.and.condition.service";
const TermsAndConditions = () => { const TermsAndConditions = () => {
const { data, refetch, isLoading, isFetching } = useGetTermsQuery();
console.log(data);
return ( return (
<MainFrame transperant={true}>
<MainFrame> <VStack gap={4} pb={4} pt={0}>
<Box> <Stack bg={"#fff"} w={"100%"} mt={2} p={4} borderRadius={4}>
<HStack <Text color={"black"} textAlign={"left"} fontWeight={"600"}>
w={"100%"} Terms and Conditions
justifyContent={"space-between"}
mb={4}
py={0}
px={3}
>
<Text as={"span"} fontSize={"sm"} fontWeight={500} color={"#000"}>
Terms And Conditions
</Text> </Text>
</Stack>
<HStack mr={5}> {isLoading || isFetching ? (
<Spinner />
<TermsAndConditionsAddModel /> ) : (
</HStack> data?.data?.map(({ id, content, terms_cond_language }) => (
</HStack> <VStack
<Text as={p} fontSize={"sm"} fontWeight={400} color={"#1D1D1D"} px={3} w={"85%"} mb={"15px"} > bg={"#fff"}
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Numquam soluta doloremque quibusdam facilis quas, unde hic eaque doloribus sed perferendis atque, eos dolores eius consectetur iure sint adipisci itaque tempora fugit quidem culpa provident possimus. Ullam, vitae in voluptatum dignissimos, quos blanditiis sequi aut repellat error eaque veritatis unde quam temporibus adipisci consectetur neque vero exercitationem dolor cum numquam maiores alias, totam minima quas. Possimus, ratione harum. Alias laboriosam nesciunt esse fugit deserunt pariatur corporis tempora quia veniam laborum aliquid enim voluptatibus asperiores minima tempore repudiandae vero quo porro, doloribus explicabo sit beatae et hic natus. Non earum nisi reiciendis? boxShadow={"rgba(99, 99, 99, 0.2) 0px 2px 8px 0px"}
</Text> rounded={"lg"}
<Text as={p} fontSize={"sm"} fontWeight={400} color={"#1D1D1D"} px={3} w={"85%"} > p={3}
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Numquam soluta doloremque quibusdam facilis quas, unde hic eaque doloribus sed perferendis atque, eos dolores eius consectetur iure sint adipisci itaque tempora fugit quidem culpa provident possimus. Ullam, vitae in voluptatum dignissimos, quos blanditiis sequi aut repellat error eaque veritatis unde quam temporibus adipisci consectetur neque vero exercitationem dolor cum numquam maiores alias, totam minima quas. Possimus, ratione harum. Alias laboriosam nesciunt esse fugit deserunt pariatur corporis tempora quia veniam laborum aliquid enim voluptatibus asperiores minima tempore repudiandae vero quo porro, doloribus explicabo sit beatae et hic natus. Non earum nisi reiciendis? key={id}
</Text> >
</Box> <HStack w={"100%"} justifyContent={"space-between"} py={0} px={0}>
<Text
as={"span"}
fontSize={"sm"}
fontWeight={500}
color={"#000"}
>
<Badge
variant={"surface"}
colorPalette="cyan"
ms={2}
size={"sm"}
fontSize={"xs"}
px={2}
>
🎓 {terms_cond_language?.language_name}
</Badge>
</Text>
{/* Pass Data to AboutUsAddModel */}
<TermsAndConditionsAddModel
termsData={{ id, content, terms_cond_language }}
refetch={refetch}
/>
</HStack>
<Text as="p" fontSize="sm" fontWeight={400} color="#1D1D1D">
{/* {content} */}
<div dangerouslySetInnerHTML={{ __html: content }} />
</Text>
</VStack>
))
)}
</VStack>
</MainFrame> </MainFrame>
) );
} };
export default TermsAndConditions export default TermsAndConditions;

View File

@@ -1,53 +1,150 @@
import { FaRegEdit } from "react-icons/fa" import { FaRegEdit } from "react-icons/fa";
import { DialogBody, DialogCloseTrigger, DialogContent, DialogFooter, DialogHeader, DialogRoot, DialogTitle, DialogTrigger } from "../../../components/ui/dialog" import {
import { Field, Stack, Text, Textarea } from "@chakra-ui/react" DialogBody,
import { Button } from "../../../components/ui/button" DialogCloseTrigger,
DialogContent,
DialogFooter,
DialogHeader,
DialogRoot,
DialogTitle,
DialogTrigger,
} from "../../../components/ui/dialog";
import { Field, Stack, Text } from "@chakra-ui/react";
import { Button } from "../../../components/ui/button";
import { Controller, useForm } from "react-hook-form";
import ReactQuill from "react-quill";
import { useState } from "react";
import { useUpdateTermsMutation } from "../../../Redux/Service/terms.and.condition.service";
function TermsAndConditionsAddModel() { function TermsAndConditionsAddModel({ termsData, refetch }: { termsData: any, refetch: VoidFunction }) {
return ( const [isOpen, setIsOpen] = useState(false);
const [updateTerms] = useUpdateTermsMutation()
const {
control,
handleSubmit,
reset,
setValue,
} = useForm({
defaultValues: {
content: "",
languageCode: "",
},
});
<DialogRoot placement="center"> const handleEditClick = (data: any) => {
<DialogTrigger asChild> setValue("content", data.content); // Pre-fill the content field
{/* <Button bg={"transparent"} size="sm"> setValue("languageCode", data.terms_cond_language.language_code); // Pre-fill the language code
<MdOutlineRemoveRedEye style={{ cursor: "pointer", fontSize: "16px" }} /> setIsOpen(true); // Open dialog
</Button> */} };
<Button bgColor={'#EEEEEE'} pl={3} pr={3} size={'xs'} color={'#000'}> <FaRegEdit color="#000" style={{ height: '14px', width: '14px' }} /> <Text color={"#000"} mt={1}>Edit</Text></Button>
</DialogTrigger> const onSubmit = async (formData: any) => {
if (!formData.content.trim()) return; // Prevent empty updates
<DialogContent try {
bg={"#fff"} await updateTerms({
// w={{ lg: "60%", md: "230px" }} id: termsData.id,
w={{ base: '90%', md: '400px' }} content: formData.content,
height={"auto"} language_code: formData.languageCode,
}).unwrap();
setIsOpen(false); // Close dialog on success
reset(); // Reset the form
refetch()
} catch (error) {
console.error("Update failed:", error);
}
};
p={3} // Reduced padding return (
bgSize={'md'} <DialogRoot placement="center" open={isOpen}>
> <DialogTrigger asChild>
<DialogHeader bg="white"> <Button
<DialogTitle alignSelf="center" color="black" fontSize="14px">Edit</DialogTitle> bgColor={"#EEEEEE"}
</DialogHeader> pl={3} pr={3}
size={"xs"}
color={"#000"}
onClick={() => handleEditClick(termsData)}
>
{" "}
<FaRegEdit
color="#000"
style={{ height: "14px", width: "14px" }}
/>{" "}
<Text color={"#000"} mt={1}>
Edit
</Text>
</Button>
</DialogTrigger>
<DialogContent
bg={"#fff"}
maxW={'600px'}
// w={{ base: "90%", md: "600px" }}
height={"auto"}
p={3} // Reduced padding
bgSize={"md"}
>
<DialogHeader bg="white">
<DialogTitle alignSelf="center" color="black" fontSize="14px">
Edit
</DialogTitle>
</DialogHeader>
<DialogBody bg="white"> <DialogBody bg="white">
<Stack py={3}> <Stack py={3}>
<Field.Root>
<Field.Label color="black" pt={1} fontSize="12px">
TermsAndConditions
</Field.Label>
{/* <Textarea
placeholder=""
bgColor="#EEEEEE"
color="black"
border="none"
p={2}
fontSize="12px"
height={'140px'}
_focusVisible={{outline:'none'}}
resize={'none'}
/> */}
<Controller
name="content"
control={control}
render={({ field }) => (
<ReactQuill
value={field.value}
onChange={field.onChange}
placeholder="Enter About Us content"
modules={{
toolbar: [
[{ 'header': [1, 2, false] }],
['bold', 'italic', 'underline', 'strike'],
['link', 'image'],
[{ 'list': 'ordered' }, { 'list': 'bullet' }],
['clean']
],
}}
formats={[
'header',
'bold', 'italic', 'underline', 'strike',
'list', 'bullet',
'link', 'image'
]}
style={{ color: "black", border: "none", fontSize: "12px", height: "220px", width: "100%",marginBottom:'20px' }}
/>
)}
/>
</Field.Root>
</Stack>
</DialogBody>
<DialogFooter display="flex" justifyContent="center" pt={"2"}>
<Button w="100%" bg="#02A0A0" color={"#fff"} mt={'4'} onClick={handleSubmit(onSubmit)}>
Save
</Button>
</DialogFooter>
<Field.Root> <DialogCloseTrigger color="black" onClick={() => setIsOpen(false)} />
<Field.Label color="black" pt={1} fontSize="12px">TermsAndConditions</Field.Label> </DialogContent>
<Textarea placeholder="" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" pt={1.5} /> </DialogRoot>
</Field.Root> );
</Stack>
</DialogBody>
<DialogFooter display="flex" justifyContent="center" pt={"2"}>
<Button w="100%" bg="#02A0A0" color={"#fff"}>
Save
</Button>
</DialogFooter>
<DialogCloseTrigger color="black" />
</DialogContent>
</DialogRoot >
)
} }
export default TermsAndConditionsAddModel export default TermsAndConditionsAddModel;

View File

@@ -1,39 +1,77 @@
import { Box, HStack, Image, Input, Text } from "@chakra-ui/react"; import { Box, HStack, Input, Text } from "@chakra-ui/react";
import MainFrame from "../../components/MainFrame" import MainFrame from "../../components/MainFrame";
import PendingRequests from "../../Pages/ManageContact/PendingRequests" import PendingRequests from "../../Pages/ManageContact/PendingRequests";
import { InputGroup } from "../../components/ui/input-group"; import { InputGroup } from "../../components/ui/input-group";
import { LuSearch } from "react-icons/lu"; import { LuSearch } from "react-icons/lu";
import DataTable from "../../components/DataTable"; import DataTable from "../../components/DataTable";
import { useGetContactQuery } from "../../Redux/Service/manage.contactus.service";
import { useEffect, useState } from "react";
import { Spinner } from "../../components/Sipnner/Spinner";
// table data // table data
const tableHeadRow = ["Sr. No", "Email id", "Name", "Date", "Action"];
const tableHeadRow = [
"Sr. No",
"Email id",
"Name",
"Date",
"Action",
];
const managepost: any[] = [
...Array.from({ length: 12 }, (_, i) => ({
"Sr. No": i + 1,
"Email id": "ABC@gmail.com",
"Name": "Pooja",
"Date": "11/02/1989",
"Action": (
<HStack justifyContent="center">
<PendingRequests />
</HStack>
),
})),
];
const ManageContact = () => { const ManageContact = () => {
return ( const { data, isLoading, isError } = useGetContactQuery();
const [localData, setLocalData] = useState([]);
useEffect(() => {
if (data) {
setLocalData((data as any)?.data?.data || []);
}
}, [data]);
const formatDateOfBirth = (dob: string): string => {
return new Date(dob).toLocaleDateString("en-GB", {
day: "2-digit",
month: "2-digit",
year: "numeric",
});
};
const managepost = localData?.map((agency: any, index: number) => ({
"Sr. No": index + 1, // Typically Sr. No starts from 1, not using id which might not be sequential
"Email id": agency?.email || "-",
Name: agency?.first_name || "-",
Date: formatDateOfBirth(agency?.created_at) || "-",
Action: (
<HStack justifyContent="center">
<PendingRequests />
</HStack>
),
}));
if (isLoading) {
return (
<MainFrame>
<Box
display="flex"
justifyContent="center"
alignItems="center"
height="100%"
>
<Spinner />
</Box>
</MainFrame>
);
}
if (isError) {
return (
<MainFrame>
<Box
display="flex"
justifyContent="center"
alignItems="center"
height="100%"
>
<Text>Error loading data</Text>
</Box>
</MainFrame>
);
}
return (
<MainFrame> <MainFrame>
<Box> <Box>
<HStack <HStack
@@ -44,13 +82,16 @@ const ManageContact = () => {
px={3} px={3}
> >
<Text as={"span"} fontSize={"sm"} fontWeight={500} color={"#000"}> <Text as={"span"} fontSize={"sm"} fontWeight={500} color={"#000"}>
Contact Requests Contact Requests
</Text> </Text>
<HStack mr={5}> <HStack>
<InputGroup marginRight={"1rem"} <InputGroup
startElement={ startElement={
<LuSearch fontSize={"xs"} style={{ position: 'relative', left: '10px' }} /> <LuSearch
fontSize={"xs"}
style={{ position: "relative", left: "10px" }}
/>
} }
color={"#000"} color={"#000"}
> >
@@ -61,23 +102,23 @@ const ManageContact = () => {
colorPalette={"blue"} colorPalette={"blue"}
_focus={{ border: "1px solid #02A0A0" }} _focus={{ border: "1px solid #02A0A0" }}
rounded={"md"} rounded={"md"}
size={"2xs"} size={"xs"}
fontSize={"2sm"} fontSize={"sm"}
placeholder="Search..." placeholder="Search..."
bgColor={'#EEEEEE'} bgColor={"#EEEEEE"}
ps={8} ps={8}
/> />
</InputGroup> </InputGroup>
{/* <Button bgColor={'#EEEEEE'} pl={3} pr={3}><IoMdAdd /> <Text>Add</Text></Button> */}
</HStack> </HStack>
</HStack> </HStack>
<DataTable <DataTable
sortableColumns={["Name", "Registration Date "]} sortableColumns={["Name", "Registration Date "]}
tableHeadRow={tableHeadRow} tableHeadRow={tableHeadRow}
data={managepost} data={managepost || []} // Ensure an empty array is passed if managepost is undefined
/> />
</Box> </Box>
</MainFrame> </MainFrame>
) );
} };
export default ManageContact
export default ManageContact;

View File

@@ -1,77 +1,105 @@
import { Button } from "../../components/ui/button" import { Button } from "../../components/ui/button";
import { DialogBody, DialogCloseTrigger, DialogContent, DialogFooter, DialogHeader, DialogRoot, DialogTitle, DialogTrigger } from "../../components/ui/dialog" import {
import { Field, HStack, Input, Stack, Textarea, } from "@chakra-ui/react" DialogBody,
DialogCloseTrigger,
DialogContent,
DialogFooter,
DialogHeader,
DialogRoot,
DialogTitle,
DialogTrigger,
} from "../../components/ui/dialog";
import { Badge, Field, HStack, Input, Stack, Textarea } from "@chakra-ui/react";
function PendingRequests() { function PendingRequests() {
return ( return (
<DialogRoot placement="center">
<DialogTrigger asChild>
<Badge fontSize={"xs"} px={2} bg={'#02a0a01f'}>
Answer request
</Badge>
</DialogTrigger>
<DialogRoot placement="center"> <DialogContent
<DialogTrigger asChild> bg={"#fff"}
<Button bg={"transparent"} fontSize={"xs"} color="#000000CC" fontWeight="700" textDecoration="underline"> w={{ base: "90%", md: "400px" }}
{/* <MdOutlineRemoveRedEye style={{ cursor: "pointer", }} /> */} height={"auto"}
Answer request p={3} // Reduced padding
</Button> bgSize={"md"}
{/* <Button><FaRegEdit /></Button> */} >
<DialogHeader bg="white">
<DialogTitle alignSelf="center" color="black" fontSize="14px">
Pending Requests
</DialogTitle>
</DialogHeader>
</DialogTrigger> <DialogBody bg="white">
<Stack py={3}>
<Field.Root>
<Field.Label color="black" pt={1} fontSize="12px">
Request Type
</Field.Label>
<Input
placeholder="Message"
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
/>
<DialogContent <Field.Label color="black" pt={1} fontSize="12px">
bg={"#fff"} Solution
w={{ base: '90%', md: '400px' }} </Field.Label>
height={"auto"} <Textarea
p={3} // Reduced padding placeholder=""
bgSize={'md'} bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="80px"
pt={1.5}
/>
</Field.Root>
</Stack>
</DialogBody>
<DialogFooter
display={{ base: "block", md: "flex" }}
justifyContent="center"
gap={1}
pt={2}
>
<HStack mt={2} mb={3} width={"100%"} justifyContent={"space-between"}>
<Button
width={"48%"}
color="black"
_hover={{ bgColor: "white" }}
variant="outline"
borderRadius="sm"
border="1px solid #02A0A0"
size={"xs"}
> >
<DialogHeader bg="white"> Unresolved
<DialogTitle alignSelf="center" color="black" fontSize="14px">Pending Requests</DialogTitle> </Button>
</DialogHeader> <Button
width={"48%"}
borderRadius="sm"
// bgColor="#007F33"
bgColor={"#02A0A0"}
color="white"
// colorPalette="#007F33"
size={"xs"}
>
Resolved
</Button>
</HStack>
</DialogFooter>
<DialogBody bg="white"> <DialogCloseTrigger color="black" />
<Stack py={3}> </DialogContent>
<Field.Root> </DialogRoot>
<Field.Label color="black" pt={1} fontSize="12px">Request Type</Field.Label> );
<Input placeholder="Message" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" />
<Field.Label color="black" pt={1} fontSize="12px">Solution</Field.Label>
<Textarea placeholder="" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="80px" pt={1.5} />
</Field.Root>
</Stack>
</DialogBody>
<DialogFooter display={{ base: 'block', md: 'flex' }} justifyContent="center" gap={1} pt={2}>
<HStack mt={2} width={"100%"}
justifyContent={"space-between"}>
<Button
width={"48%"}
color="black"
_hover={{ bgColor: "white" }}
variant="outline"
borderRadius="sm"
border="1px solid black"
size={"xs"}
>
Unresolved
</Button>
<Button
width={"48%"}
borderRadius="sm"
// bgColor="#007F33"
bgColor={'#02A0A0'}
color="white"
// colorPalette="#007F33"
size={"xs"}
>
Resolved{" "}
</Button>
</HStack>
</DialogFooter>
<DialogCloseTrigger color="black" />
</DialogContent>
</DialogRoot >
)
} }
export default PendingRequests export default PendingRequests;

View File

@@ -1,11 +0,0 @@
import MainFrame from '../../components/MainFrame'
const ManageContactUs = () => {
return (
<MainFrame>
</MainFrame>
)
}
export default ManageContactUs

View File

@@ -1,6 +1,6 @@
import { Button } from "../../components/ui/button" import { Button } from "../../components/ui/button"
import { DialogBody, DialogCloseTrigger, DialogContent, DialogFooter, DialogHeader, DialogRoot, DialogTitle, DialogTrigger } from "../../components/ui/dialog" import { DialogBody, DialogCloseTrigger, DialogContent, DialogFooter, DialogHeader, DialogRoot, DialogTitle, DialogTrigger } from "../../components/ui/dialog"
import { Avatar, Box, Field, Heading, Input, Stack, Text } from "@chakra-ui/react" import { Field, Heading, Input, Stack, Text } from "@chakra-ui/react"
import { Switch } from "../../components/ui/switch"; import { Switch } from "../../components/ui/switch";
import { IoMdAdd } from "react-icons/io"; import { IoMdAdd } from "react-icons/io";
function AddGroup() { function AddGroup() {

View File

@@ -1,85 +1,119 @@
import { Button } from "../../components/ui/button" import { Button } from "../../components/ui/button";
import { DialogBody, DialogCloseTrigger, DialogContent, DialogFooter, DialogHeader, DialogRoot, DialogTitle, DialogTrigger } from "../../components/ui/dialog" import {
import { Avatar, Box, Field, Heading, Input, Stack, Text } from "@chakra-ui/react" DialogBody,
DialogCloseTrigger,
DialogContent,
DialogFooter,
DialogHeader,
DialogRoot,
DialogTitle,
DialogTrigger,
} from "../../components/ui/dialog";
import { Avatar, Box, Field, Heading, Input, Span, Stack } from "@chakra-ui/react";
import { Switch } from "../../components/ui/switch"; import { Switch } from "../../components/ui/switch";
import { FaRegEdit } from "react-icons/fa";
import { AvatarGroup } from "../../components/ui/avatar"; import { AvatarGroup } from "../../components/ui/avatar";
import Edit from "../../components/ActionIcons/Edit";
function EditDetailGroups() { function EditDetailGroups() {
return ( return (
<DialogRoot placement="center">
<DialogTrigger asChild>
<Span><Edit /></Span>
</DialogTrigger>
<DialogRoot placement="center" > <DialogContent
<DialogTrigger asChild> bg={"#fff"}
<Button bg={"transparent"} size="sm"> w={{ base: "90%", md: "400px" }}
<FaRegEdit style={{ cursor: "pointer", }} color="#000"/> height={"auto"}
</Button> p={3} // Reduced padding
{/* <Button><FaRegEdit /></Button> */} >
<DialogHeader bg="white">
<DialogTitle alignSelf="center" color="black" fontSize="14px">
Edit details
</DialogTitle>
</DialogHeader>
<DialogBody bg="white">
<Stack py={3}>
<Field.Root>
<Field.Label color="black" pt={1} fontSize="12px">
Group Name
</Field.Label>
<Input
value="Priyanka"
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
readOnly
/>
</DialogTrigger> <Field.Label color="black" pt={1} fontSize="12px">
Description
</Field.Label>
<Input
value="Joshi"
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
readOnly
/>
<DialogContent <Field.Label color="black" pt={1} fontSize="12px">
bg={"#fff"} Members
w={{ base: '90%', md: '400px' }} </Field.Label>
height={"auto"}
p={3} // Reduced padding
>
<DialogHeader bg="white">
<DialogTitle alignSelf="center" color="black" fontSize="14px">Edit details</DialogTitle>
</DialogHeader>
<DialogBody bg="white"> <Box
<Stack py={3} > bgColor="#EEEEEE"
border="none"
w="100%"
display="flex"
p={1}
rounded={4}
>
<AvatarGroup gap="0" spaceX="-3" size={"xs"}>
<Avatar.Root border={"none"}>
<Avatar.Fallback />
<Avatar.Image src="https://cdn.myanimelist.net/r/84x124/images/characters/9/131317.webp?s=d4b03c7291407bde303bc0758047f6bd" />
</Avatar.Root>
<Field.Root> <Avatar.Root border={"none"}>
<Field.Label color="black" pt={1} fontSize="12px">Group Name</Field.Label> <Avatar.Fallback />
<Input value="Priyanka" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" readOnly /> <Avatar.Image src="https://cdn.myanimelist.net/r/84x124/images/characters/7/284129.webp?s=a8998bf668767de58b33740886ca571c" />
</Avatar.Root>
<Field.Label color="black" pt={1} fontSize="12px">Description</Field.Label> <Avatar.Root border={"none"}>
<Input value="Joshi" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" readOnly /> <Avatar.Fallback />
<Avatar.Image src="https://cdn.myanimelist.net/r/84x124/images/characters/9/105421.webp?s=269ff1b2bb9abe3ac1bc443d3a76e863" />
<Field.Label color="black" pt={1} fontSize="12px">Members</Field.Label> </Avatar.Root>
<Avatar.Root
<Box variant="solid"
bgColor="#EEEEEE" border={"none"}
border="none" backgroundColor={"transparent"}
w="100%" >
display="flex" <Avatar.Fallback ml={5}>+3</Avatar.Fallback>
p={1} </Avatar.Root>
rounded={4} </AvatarGroup>
> </Box>
<AvatarGroup gap="0" spaceX="-3" size={"xs"} > </Field.Root>
<Avatar.Root border={'none'}> <Heading color="black" pt={1} fontSize="12px">
<Avatar.Fallback /> public/Private
<Avatar.Image src="https://cdn.myanimelist.net/r/84x124/images/characters/9/131317.webp?s=d4b03c7291407bde303bc0758047f6bd" /> </Heading>
</Avatar.Root> <Switch />
</Stack>
<Avatar.Root border={'none'}> </DialogBody>
<Avatar.Fallback /> <DialogFooter display="flex" justifyContent="center" pt={"2"}>
<Avatar.Image src="https://cdn.myanimelist.net/r/84x124/images/characters/7/284129.webp?s=a8998bf668767de58b33740886ca571c" /> <Button size={"xs"} w="100%" bg="#02A0A0" color={"#fff"}>
</Avatar.Root> Save
</Button>
<Avatar.Root border={'none'}> </DialogFooter>{" "}
<Avatar.Fallback /> <DialogCloseTrigger color="black" />
<Avatar.Image src="https://cdn.myanimelist.net/r/84x124/images/characters/9/105421.webp?s=269ff1b2bb9abe3ac1bc443d3a76e863" /> </DialogContent>
</Avatar.Root> </DialogRoot>
<Avatar.Root variant="solid" border={'none'} backgroundColor={'transparent'} > );
<Avatar.Fallback ml={5}>+3</Avatar.Fallback>
</Avatar.Root>
</AvatarGroup>
</Box>
</Field.Root>
<Heading color="black" pt={1} fontSize="12px">public/Private</Heading>
<Switch />
</Stack>
</DialogBody>
<DialogFooter display="flex" justifyContent="center" pt={"2"}>
<Button size={'xs'} w="100%" bg="#02A0A0" color={"#fff"}>
Save
</Button>
</DialogFooter> <DialogCloseTrigger color="black" />
</DialogContent>
</DialogRoot >
)
} }
export default EditDetailGroups export default EditDetailGroups;

View File

@@ -1,16 +1,18 @@
import { Box, HStack, Image, Input, Text } from "@chakra-ui/react" import { Box, HStack,
import MainFrame from "../../components/MainFrame" // Image,
import { InputGroup } from "../../components/ui/input-group" Input, Text } from "@chakra-ui/react";
import { LuSearch } from "react-icons/lu" import MainFrame from "../../components/MainFrame";
import DataTable from "../../components/DataTable" import { InputGroup } from "../../components/ui/input-group";
import AlertDailog from "../../components/AlertDailog" import { LuSearch } from "react-icons/lu";
import { RiDeleteBin5Line } from "react-icons/ri"; import DataTable from "../../components/DataTable";
import ViewManageGroup from "./ViewManageGroup" // import AlertDailog from "../../components/AlertDailog";
import EditDetailGroups from "./EditDetailGroup" // import { RiDeleteBin5Line } from "react-icons/ri";
import AddGroup from "./AddGroup" import ViewManageGroup from "./ViewManageGroup";
import EditDetailGroups from "./EditDetailGroup";
import AddGroup from "./AddGroup";
// import Delete from "../../components/ActionIcons/Delete";
// import ViewSubAdmin from "./ViewSubAdmin" // import ViewSubAdmin from "./ViewSubAdmin"
// table data // table data
const tableHeadRow = [ const tableHeadRow = [
@@ -26,36 +28,32 @@ const managepost: any[] = [
...Array.from({ length: 12 }, (_, i) => ({ ...Array.from({ length: 12 }, (_, i) => ({
"Sr. No": i + 1, "Sr. No": i + 1,
"Group Name": "ABC", "Group Name": "ABC",
"Description": "Lorem ipsum", Description: "Lorem ipsum",
"Date": "12/01/1987", Date: "12/01/1987",
"Group type": "Private", "Group type": "Private",
"Action": ( Action: (
<HStack justifyContent="center"> <HStack justifyContent="center">
{/* <MdOutlineRemoveRedEye
style={{ cursor: "pointer", fontSize: "16px" }}
/> */}
<ViewManageGroup /> <ViewManageGroup />
<EditDetailGroups /> <EditDetailGroups />
{/* <AlertDailog
{/* <RiDeleteBin5Line style={{ cursor: "pointer" }} /> */} AltertTiggerIcon={() => <Delete />}
<AlertDailog
AltertTiggerIcon={RiDeleteBin5Line}
alertText="Delete Users" alertText="Delete Users"
alertIcon={<Image src={"DeleteIcon"} h={"39px"} />} alertIcon={<Image src={"DeleteIcon"} h={"39px"} />}
alertCaption="are you sure you want to delete ?" alertCaption="are you sure you want to delete ?"
onConfirm={() => { onConfirm={() => {
console.log("User deleted:", i + 1); console.log("User deleted:", i + 1);
}} }}
/> /> */}
</HStack> </HStack>
), ),
})), })),
]; ];
const ManageGroups = () => { const ManageGroups = () => {
return ( return (
<MainFrame>
<MainFrame >
<Box> <Box>
<HStack <HStack
w={"100%"} w={"100%"}
@@ -68,10 +66,13 @@ const ManageGroups = () => {
Manage Groups Manage Groups
</Text> </Text>
<HStack > <HStack>
<InputGroup <InputGroup
startElement={ startElement={
<LuSearch fontSize={"xs"} style={{ position: 'relative', left: '10px' }} /> <LuSearch
fontSize={"xs"}
style={{ position: "relative", left: "10px" }}
/>
} }
color={"#000"} color={"#000"}
> >
@@ -82,12 +83,12 @@ const ManageGroups = () => {
colorPalette={"blue"} colorPalette={"blue"}
_focus={{ border: "1px solid #02A0A0" }} _focus={{ border: "1px solid #02A0A0" }}
rounded={"md"} rounded={"md"}
size={"2xs"} size={"xs"}
fontSize={"2sm"} fontSize={"sm"}
placeholder="Search..." placeholder="Search..."
bgColor={'#EEEEEE'} bgColor={"#EEEEEE"}
ps={8} ps={8}
border={'none'} border={"none"}
/> />
</InputGroup> </InputGroup>
{/* <Button bgColor={'#EEEEEE'} pl={3} pr={3}><IoMdAdd /> <Text>Add</Text></Button> */} {/* <Button bgColor={'#EEEEEE'} pl={3} pr={3}><IoMdAdd /> <Text>Add</Text></Button> */}
@@ -99,7 +100,8 @@ const ManageGroups = () => {
tableHeadRow={tableHeadRow} tableHeadRow={tableHeadRow}
data={managepost} data={managepost}
/> />
</Box> </MainFrame> </Box>{" "}
) </MainFrame>
} );
export default ManageGroups };
export default ManageGroups;

View File

@@ -1,86 +1,116 @@
import { Button } from "../../components/ui/button" import {
import { DialogBody, DialogCloseTrigger, DialogContent, DialogFooter, DialogHeader, DialogRoot, DialogTitle, DialogTrigger } from "../../components/ui/dialog" DialogBody,
import { Avatar, Box, Field, Grid, Heading, Input, Stack, Text } from "@chakra-ui/react" DialogCloseTrigger,
import { Checkbox } from "../../components/ui/checkbox" DialogContent,
import { MdOutlineRemoveRedEye } from "react-icons/md"; DialogHeader,
DialogRoot,
DialogTitle,
DialogTrigger,
} from "../../components/ui/dialog";
import { Avatar, Box, Field, Heading, Input, Span, Stack } from "@chakra-ui/react";
import { Switch } from "../../components/ui/switch"; import { Switch } from "../../components/ui/switch";
import { AvatarGroup } from "../../components/ui/avatar"; import { AvatarGroup } from "../../components/ui/avatar";
import View from "../../components/ActionIcons/View";
function ViewManageGroup() { function ViewManageGroup() {
return ( return (
<DialogRoot placement="center">
<DialogTrigger asChild>
<Span><View /></Span>
</DialogTrigger>
<DialogRoot placement="center" > <DialogContent
<DialogTrigger asChild> bg={"#fff"}
<Button bg={"transparent"} size="sm"> // w={{ lg: "60%", md: "230px" }}
<MdOutlineRemoveRedEye style={{ cursor: "pointer", }} color="#000"/> w={{ base: "90%", md: "400px" }}
</Button> height={"auto"}
{/* <Button><FaRegEdit /></Button> */} p={3} // Reduced padding
bgSize={"md"}
>
<DialogHeader bg="white">
<DialogTitle alignSelf="center" color="black" fontSize="14px">
View details
</DialogTitle>
</DialogHeader>
</DialogTrigger> <DialogBody bg="white">
<Stack py={3}>
<Field.Root>
<Field.Label color="black" pt={1} fontSize="12px">
Group Name
</Field.Label>
<Input
value="Priyanka"
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
readOnly
/>
<DialogContent <Field.Label color="black" pt={1} fontSize="12px">
bg={"#fff"} Description
// w={{ lg: "60%", md: "230px" }} </Field.Label>
w={{ base: '90%', md: '400px' }} <Input
height={"auto"} value="Joshi"
p={3} // Reduced padding bgColor="#EEEEEE"
bgSize={'md'} color="black"
> border="none"
<DialogHeader bg="white" > pl={1}
<DialogTitle alignSelf="center" color="black" fontSize="14px">View details</DialogTitle> fontSize="12px"
</DialogHeader> height="30px"
readOnly
/>
<DialogBody bg="white"> <Field.Label color="black" pt={1} fontSize="12px">
<Stack py={3} > Members
</Field.Label>
<Field.Root> <Box
<Field.Label color="black" pt={1} fontSize="12px">Group Name</Field.Label> bgColor="#EEEEEE"
<Input value="Priyanka" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" readOnly /> border="none"
w="100%"
display="flex"
p={1}
rounded={4}
>
<AvatarGroup gap="0" spaceX="-3" size={"xs"}>
<Avatar.Root border={"none"}>
<Avatar.Fallback />
<Avatar.Image src="https://cdn.myanimelist.net/r/84x124/images/characters/9/131317.webp?s=d4b03c7291407bde303bc0758047f6bd" />
</Avatar.Root>
<Field.Label color="black" pt={1} fontSize="12px">Description</Field.Label> <Avatar.Root border={"none"}>
<Input value="Joshi" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" readOnly /> <Avatar.Fallback />
<Avatar.Image src="https://cdn.myanimelist.net/r/84x124/images/characters/7/284129.webp?s=a8998bf668767de58b33740886ca571c" />
</Avatar.Root>
<Field.Label color="black" pt={1} fontSize="12px">Members</Field.Label> <Avatar.Root border={"none"}>
<Avatar.Fallback />
<Avatar.Image src="https://cdn.myanimelist.net/r/84x124/images/characters/9/105421.webp?s=269ff1b2bb9abe3ac1bc443d3a76e863" />
</Avatar.Root>
<Avatar.Root
variant="solid"
border={"none"}
backgroundColor={"transparent"}
>
<Avatar.Fallback ml={5}>+3</Avatar.Fallback>
</Avatar.Root>
</AvatarGroup>
</Box>
</Field.Root>
<Heading color="black" pt={1} fontSize="12px">
public/Private
</Heading>
<Switch />
</Stack>
</DialogBody>
<Box <DialogCloseTrigger color="black" />
bgColor="#EEEEEE" </DialogContent>
border="none" </DialogRoot>
w="100%" );
display="flex"
p={1}
rounded={4}
>
<AvatarGroup gap="0" spaceX="-3" size={"xs"} >
<Avatar.Root border={'none'}>
<Avatar.Fallback />
<Avatar.Image src="https://cdn.myanimelist.net/r/84x124/images/characters/9/131317.webp?s=d4b03c7291407bde303bc0758047f6bd" />
</Avatar.Root>
<Avatar.Root border={'none'}>
<Avatar.Fallback />
<Avatar.Image src="https://cdn.myanimelist.net/r/84x124/images/characters/7/284129.webp?s=a8998bf668767de58b33740886ca571c" />
</Avatar.Root>
<Avatar.Root border={'none'}>
<Avatar.Fallback />
<Avatar.Image src="https://cdn.myanimelist.net/r/84x124/images/characters/9/105421.webp?s=269ff1b2bb9abe3ac1bc443d3a76e863" />
</Avatar.Root>
<Avatar.Root variant="solid" border={'none'} backgroundColor={'transparent'} >
<Avatar.Fallback ml={5}>+3</Avatar.Fallback>
</Avatar.Root>
</AvatarGroup>
</Box>
</Field.Root>
<Heading color="black" pt={1} fontSize="12px">public/Private</Heading>
<Switch />
</Stack>
</DialogBody>
<DialogCloseTrigger color="black" />
</DialogContent>
</DialogRoot >
)
} }
export default ViewManageGroup export default ViewManageGroup;

View File

@@ -1,11 +1,180 @@
import MainFrame from "../../components/MainFrame" import {
Box,
HStack,
Image,
// Image,
Input,
Text,
} from "@chakra-ui/react";
import { LuSearch } from "react-icons/lu";
// import { RiDeleteBin5Line } from "react-icons/ri";
// import AlertDailog from "../../components/AlertDailog";
import DataTable from "../../components/DataTable";
import MainFrame from "../../components/MainFrame";
import { InputGroup } from "../../components/ui/input-group";
import ManageJobsAdd from "./ManageJobsAdd";
import ViewManageJob from "./ViewManageJob";
import {
useDeleteJobsPostMutation,
useGetManageJobsQuery,
} from "../../Redux/Service/manage.jobs.service";
import { useEffect, useState } from "react";
import { Spinner } from "../../components/Sipnner/Spinner";
import Delete from "../../components/ActionIcons/Delete";
import { toaster } from "../../components/ui/toaster";
import AlertDailog from "../../components/AlertDailog";
// import { useState } from "react";
// import { useGetManageJobsQuery } from "../../Redux/Service/manage.jobs.service";
// import Delete from "../../components/ActionIcons/Delete";
// table data
const tableHeadRow = [
"Sr. No",
"Job Title",
"Workspace mode",
"Category",
"Sub-category",
"Salary",
"Action",
];
const ManageJobs = () => { const ManageJobs = () => {
const [currentPage] = useState(1);
const [localData, setLocalData] = useState([]);
const { data, refetch, isLoading } = useGetManageJobsQuery(currentPage);
const [deleteJobsPost] = useDeleteJobsPostMutation();
const [deleteModal, setDeleteModal] = useState(false);
const [selectedJobsId, setSelectedJobsId] = useState<number | null>(null);
useEffect(() => {
if (data) {
setLocalData((data as any)?.data?.data || []);
}
}, [data]);
console.log(data?.data.data);
const handleDeleteJobs = async (jobsId: number) => {
try {
const response = await deleteJobsPost({ id: jobsId }).unwrap();
if (response?.status === "success") {
toaster.create({
title: "Success",
description: "Jobs deleted successfully",
type: "Success",
});
refetch();
}
} catch (error) {
console.error("Error deleting FAQ:", error);
toaster.create({
title: "Error",
description: "Something went wrong",
type: "error",
});
}
};
const managepost = localData?.map((agency: any, index: number) => ({
"Sr. No": index + 1,
"Job Title": agency?.job_title,
"Workspace mode": agency?.workspace?.en_name,
Category: agency?.industry?.en_name,
"Sub-category": agency?.department?.en_name,
Salary: agency?.ctc_amount,
Action: (
<HStack justifyContent="center">
<ViewManageJob />
<ManageJobsAdd />
<AlertDailog
isOpen={deleteModal}
AltertTiggerIcon={() => (
<Delete
onClick={() => {
setSelectedJobsId(agency.id);
setDeleteModal(true);
}}
/>
)}
alertText="Delete FAQ"
alertIcon={<Image src={"DeleteIcon"} h={"39px"} />}
alertCaption="are you sure you want to delete ?"
onClose={() => setDeleteModal(false)}
onConfirm={() => {
// console.log("Deleting FAQ with ID:", selectedFaqId); // Correct ID
if (selectedJobsId) {
setDeleteModal(false);
handleDeleteJobs(selectedJobsId);
}
}}
/>
</HStack>
),
}));
if (isLoading) {
return (
<MainFrame>
<Box
display="flex"
justifyContent="center"
alignItems="center"
height="100%"
>
<Spinner />
</Box>
</MainFrame>
);
}
return ( return (
<MainFrame> <MainFrame>
<Box>
</MainFrame> <HStack
) w={"100%"}
} justifyContent={"space-between"}
mb={4}
py={0}
px={3}
>
<Text as={"span"} fontSize={"sm"} fontWeight={500} color={"#000"}>
View job Posting
</Text>
export default ManageJobs <HStack>
<InputGroup
startElement={
<LuSearch
fontSize={"xs"}
style={{ position: "relative", left: "10px" }}
/>
}
color={"#000"}
>
<Input
p={3}
w={300}
bg={"#fff"}
colorPalette={"blue"}
_focus={{ border: "1px solid #02A0A0" }}
rounded={"md"}
size={"xs"}
fontSize={"sm"}
placeholder="Search..."
bgColor={"#EEEEEE"}
ps={8}
/>
</InputGroup>
{/* <Button bgColor={'#EEEEEE'} pl={3} pr={3}><IoMdAdd /> <Text>Add</Text></Button> */}
</HStack>
</HStack>
<DataTable
sortableColumns={["Name", "Registration Date "]}
tableHeadRow={tableHeadRow}
data={managepost}
/>
</Box>
</MainFrame>
);
};
export default ManageJobs;

View File

@@ -1,118 +1,261 @@
import { Button } from "../../components/ui/button" import {
import { DialogBody, DialogCloseTrigger, DialogContent, DialogFooter, DialogHeader, DialogRoot, DialogTitle, DialogTrigger } from "../../components/ui/dialog" Field,
import { createListCollection, Field, Input, SelectValueText, Stack } from "@chakra-ui/react" Input,
SelectValueText,
Span,
Stack,
createListCollection,
} from "@chakra-ui/react";
import { Button } from "../../components/ui/button";
import {
DialogBody,
DialogCloseTrigger,
DialogContent,
DialogFooter,
DialogHeader,
DialogRoot,
DialogTitle,
DialogTrigger,
} from "../../components/ui/dialog";
import { FaRegEdit } from "react-icons/fa" // import { TbEdit } from "react-icons/tb";
import { SelectContent, SelectItem, SelectLabel, SelectRoot, SelectTrigger } from "../../components/ui/select" import {
SelectContent,
SelectItem,
SelectLabel,
SelectRoot,
SelectTrigger,
} from "../../components/ui/select";
import Edit from "../../components/ActionIcons/Edit";
const frameworks = createListCollection({ const frameworks = createListCollection({
items: [ items: [
{ label: "React.js", value: "react" }, { label: "React.js", value: "react" },
{ label: "Vue.js", value: "vue" }, { label: "Vue.js", value: "vue" },
{ label: "Angular", value: "angular" }, { label: "Angular", value: "angular" },
{ label: "Svelte", value: "svelte" }, { label: "Svelte", value: "svelte" },
], ],
}) });
function ManageJobsAdd() { function ManageJobsAdd() {
return ( return (
<DialogRoot placement="center">
<DialogTrigger asChild>
<Span><Edit /></Span>
</DialogTrigger>
<DialogContent
bg={"#fff"}
// w={{ lg: "60%", md: "230px" }}
w={{ base: "90%", md: "400px" }}
height={"80vh"}
overflow={"scroll"}
overflowX="hidden"
p={3} // Reduced padding
bgSize={"md"}
>
<DialogHeader bg="white">
<DialogTitle alignSelf="center" color="black" fontSize="14px">
Add Details
</DialogTitle>
</DialogHeader>
<DialogRoot placement="center"> <DialogBody bg="white">
<DialogTrigger asChild> <Stack py={3}>
<Button bg={"transparent"} size="sm"> <Field.Root>
<FaRegEdit style={{ cursor: "pointer", fontSize: "14px" }} color="#000" /> <Field.Label color="black" pt={1} fontSize="12px">
</Button> Job title
</DialogTrigger> </Field.Label>
<Input
<DialogContent placeholder="Enter the Job Title"
bg={"#fff"} bgColor="#EEEEEE"
// w={{ lg: "60%", md: "230px" }} color="black"
w={{ base: '90%', md: '400px' }} border="none"
height={'80vh'} pl={1}
overflow={'scroll'} fontSize="12px"
overflowX="hidden" height="30px"
p={3} // Reduced padding />
bgSize={'md'} </Field.Root>
> <Field.Root>
<DialogHeader bg="white"> <Field.Label color="black" pt={1} fontSize="12px">
<DialogTitle alignSelf="center" color="black" fontSize="14px">Add Details</DialogTitle> Workspace mode
</DialogHeader> </Field.Label>
<Input
<DialogBody bg="white"> placeholder="Enter the Workspace Mode"
<Stack py={3}> bgColor="#EEEEEE"
<Field.Root> color="black"
<Field.Label color="black" pt={1} fontSize="12px">Job title</Field.Label> border="none"
<Input placeholder="Enter the Job Title" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" /> pl={1}
</Field.Root> fontSize="12px"
<Field.Root> height="30px"
/>
<Field.Label color="black" pt={1} fontSize="12px">Workspace mode</Field.Label> </Field.Root>
<Input placeholder="Enter the Workspace Mode" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" /> <Field.Root>
</Field.Root> <Field.Label pt={1} color="black" fontSize="12px">
<Field.Root> Category
<Field.Label pt={1} color="black" fontSize="12px">Category</Field.Label> </Field.Label>
<Input placeholder="Enter the Category" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" /> <Input
</Field.Root> placeholder="Enter the Category"
<Field.Root> bgColor="#EEEEEE"
<Field.Label pt={1} color="black" fontSize="12px">Sub-Category</Field.Label> color="black"
<Input placeholder="Enter the Sub-Category" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" /> border="none"
</Field.Root> pl={1}
<Field.Root> fontSize="12px"
<Field.Label pt={1} color="black" fontSize="12px">Salary</Field.Label> height="30px"
<Input placeholder="Enter the Salary" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" /> />
</Field.Root> </Field.Root>
<Field.Root> <Field.Root>
<Field.Label pt={1} color="black" fontSize="12px">Experience</Field.Label> <Field.Label pt={1} color="black" fontSize="12px">
<Input placeholder="Enter the Experience" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" /> Sub-Category
</Field.Root> </Field.Label>
<Field.Root> <Input
<Field.Label pt={1} color="black" fontSize="12px">Job Location</Field.Label> placeholder="Enter the Sub-Category"
<Input placeholder="Enter the Job Location" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" /> bgColor="#EEEEEE"
</Field.Root> color="black"
{/* <Field.Label pt={1} color="black" fontSize="12px">Country Selection</Field.Label> border="none"
pl={1}
fontSize="12px"
height="30px"
/>
</Field.Root>
<Field.Root>
<Field.Label pt={1} color="black" fontSize="12px">
Salary
</Field.Label>
<Input
placeholder="Enter the Salary"
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
/>
</Field.Root>
<Field.Root>
<Field.Label pt={1} color="black" fontSize="12px">
Experience
</Field.Label>
<Input
placeholder="Enter the Experience"
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
/>
</Field.Root>
<Field.Root>
<Field.Label pt={1} color="black" fontSize="12px">
Job Location
</Field.Label>
<Input
placeholder="Enter the Job Location"
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
/>
</Field.Root>
{/* <Field.Label pt={1} color="black" fontSize="12px">Country Selection</Field.Label>
<Input placeholder="Enter the Country Selection" /> */} <Input placeholder="Enter the Country Selection" /> */}
<SelectRoot collection={frameworks} size="sm" w={'100%'}> <SelectRoot collection={frameworks} size="sm" w={"100%"}>
<SelectLabel pt={1} color="black" fontSize="12px">Country Selection</SelectLabel> <SelectLabel pt={1} color="black" fontSize="12px">
<SelectTrigger bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" Country Selection
borderRadius={"5px"}> </SelectLabel>
<SelectValueText placeholder="Enter the Country Selection" pb={"6px"} fontSize={"12px"} /> <SelectTrigger
</SelectTrigger> bgColor="#EEEEEE"
<SelectContent position={'relative'} zIndex={'9999'} bg={"#fff"}> color="black"
{frameworks.items.map((movie) => ( border="none"
<SelectItem item={movie} key={movie.value} color={"black"} pl={2} p={1} _hover={{ bg: "#F0F0F0" }} // Light grey background on hover pl={1}
fontSize="12px" > fontSize="12px"
{movie.label} height="30px"
</SelectItem> borderRadius={"5px"}
))} >
</SelectContent> <SelectValueText
</SelectRoot> placeholder="Enter the Country Selection"
<Field.Root> pb={"6px"}
fontSize={"12px"}
/>
</SelectTrigger>
<SelectContent position={"relative"} zIndex={"9999"} bg={"#fff"}>
{frameworks.items.map((movie) => (
<SelectItem
item={movie}
key={movie.value}
color={"black"}
pl={2}
p={1}
_hover={{ bg: "#F0F0F0" }} // Light grey background on hover
fontSize="12px"
>
{movie.label}
</SelectItem>
))}
</SelectContent>
</SelectRoot>
<Field.Root>
<Field.Label pt={1} color="black" fontSize="12px">
Job type
</Field.Label>
<Input
placeholder="Enter the Job Type"
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
/>
</Field.Root>
<Field.Root>
<Field.Label pt={1} color="black" fontSize="12px">
Skills required
</Field.Label>
<Input
placeholder="Enter the Skills Required"
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
/>
</Field.Root>
<Field.Root>
<Field.Label pt={1} color="black" fontSize="12px">
Job Description*
</Field.Label>
<Input
placeholder="Enter the Job Description"
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
/>
</Field.Root>
</Stack>
</DialogBody>
<DialogFooter display="flex" justifyContent="center" pt={"2"}>
<Button
w="100%"
bg="#02A0A0"
color={"#fff"}
fontSize="12px"
height="30px"
>
Save
</Button>
</DialogFooter>
<Field.Label pt={1} color="black" fontSize="12px">Job type</Field.Label> <DialogCloseTrigger color="black" />
<Input placeholder="Enter the Job Type" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" /> </DialogContent>
</Field.Root> </DialogRoot>
<Field.Root> );
<Field.Label pt={1} color="black" fontSize="12px">Skills required</Field.Label>
<Input placeholder="Enter the Skills Required" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" />
</Field.Root>
<Field.Root>
<Field.Label pt={1} color="black" fontSize="12px">Job Description*</Field.Label>
<Input placeholder="Enter the Job Description" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" />
</Field.Root>
</Stack>
</DialogBody>
<DialogFooter display="flex" justifyContent="center" pt={"2"}>
<Button w="100%" bg="#02A0A0" color={"#fff"} fontSize="12px" height="30px">
Save
</Button>
</DialogFooter>
<DialogCloseTrigger color="black" />
</DialogContent>
</DialogRoot>
)
} }
export default ManageJobsAdd export default ManageJobsAdd;

View File

@@ -1,113 +1,297 @@
import { Button } from "../../components/ui/button" import {
import { DialogBody, DialogCloseTrigger, DialogContent, DialogFooter, DialogHeader, DialogRoot, DialogTitle, DialogTrigger } from "../../components/ui/dialog" Field,
import { createListCollection, Field, Input, SelectValueText, Stack, } from "@chakra-ui/react" Input,
SelectValueText,
Span,
Stack,
createListCollection,
} from "@chakra-ui/react";
import { Button } from "../../components/ui/button";
import {
DialogBody,
DialogCloseTrigger,
DialogContent,
DialogFooter,
DialogHeader,
DialogRoot,
DialogTitle,
DialogTrigger,
} from "../../components/ui/dialog";
import { FaRegEdit } from "react-icons/fa" // import { MdOutlineRemoveRedEye } from "react-icons/md";
import { SelectContent, SelectItem, SelectLabel, SelectRoot, SelectTrigger } from "../../components/ui/select" import {
import { MdOutlineRemoveRedEye } from "react-icons/md" SelectContent,
SelectItem,
SelectLabel,
SelectRoot,
SelectTrigger,
} from "../../components/ui/select";
import View from "../../components/ActionIcons/View";
import { useLazyViewJobsQuery } from "../../Redux/Service/manage.jobs.service";
const frameworks = createListCollection({ const frameworks = createListCollection({
items: [ items: [
{ label: "React.js", value: "react" }, { label: "React.js", value: "react" },
{ label: "Vue.js", value: "vue" }, { label: "Vue.js", value: "vue" },
{ label: "Angular", value: "angular" }, { label: "Angular", value: "angular" },
{ label: "Svelte", value: "svelte" }, { label: "Svelte", value: "svelte" },
], ],
}) });
function ViewManageJob() { function ViewManageJob() {
return ( const [trigger, { data }] = useLazyViewJobsQuery();
console.log(data);
<DialogRoot placement="center"> // const handleView = () => {
<DialogTrigger asChild> // trigger(id);
<Button bg={"transparent"} size="sm"> // };
<MdOutlineRemoveRedEye style={{ cursor: "pointer", fontSize: "14px" }} color="#000"/>
</Button>
</DialogTrigger>
<DialogContent const viewJobs = data;
bg={"#fff"}
// w={{ lg: "60%", md: "230px" }}
w={{ base: '90%', md: '400px' }}
height={'80vh'}
overflow={'scroll'}
overflowX="hidden"
p={3} // Reduced padding
bgSize={'md'}
>
<DialogHeader bg="white" >
<DialogTitle alignSelf="center" color="black" fontSize="14px">Add Details</DialogTitle>
</DialogHeader>
<DialogBody bg="white"> console.log();
<Stack py={3}>
<Field.Root> return (
<Field.Label color="black" pt={1} fontSize="12px">Job title</Field.Label> <DialogRoot placement="center">
<Input placeholder="Enter the Job Title" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" /> <DialogTrigger asChild>
</Field.Root><Field.Root> <Span>
<Field.Label color="black" pt={1} fontSize="12px">Workspace mode</Field.Label> <View />
<Input placeholder="Enter the Workspace Mode" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" /> </Span>
</Field.Root><Field.Root> </DialogTrigger>
<Field.Label pt={1} color="black" fontSize="12px">Category</Field.Label>
<Input placeholder="Enter the Category" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" /> {/* {viewJobs?.map((data: any) => ( */}
</Field.Root><Field.Root> <DialogContent
<Field.Label pt={1} color="black" fontSize="12px">Sub-Category</Field.Label> bg={"#fff"}
<Input placeholder="Enter the Sub-Category" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" /> // w={{ lg: "60%", md: "230px" }}
</Field.Root><Field.Root> w={{ base: "90%", md: "400px" }}
<Field.Label pt={1} color="black" fontSize="12px">Salary</Field.Label> height={"80vh"}
<Input placeholder="Enter the Salary" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" /> overflow={"scroll"}
</Field.Root><Field.Root> overflowX="hidden"
<Field.Label pt={1} color="black" fontSize="12px">Experience</Field.Label> p={3} // Reduced padding
<Input placeholder="Enter the Experience" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" /> bgSize={"md"}
</Field.Root><Field.Root> >
<Field.Label pt={1} color="black" fontSize="12px">Job Location</Field.Label> <DialogHeader bg="white">
<Input placeholder="Enter the Job Location" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" /> <DialogTitle alignSelf="center" color="black" fontSize="14px">
</Field.Root> Add Details
{/* <Field.Label pt={1} color="black" fontSize="12px">Country Selection</Field.Label> </DialogTitle>
</DialogHeader>
<DialogBody bg="white">
<Stack py={3}>
<Field.Root>
<Field.Label color="black" pt={1} fontSize="12px">
Job title
</Field.Label>
<Input
placeholder="Enter the Job Title"
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
/>
</Field.Root>
<Field.Root>
<Field.Label color="black" pt={1} fontSize="12px">
Workspace mode
</Field.Label>
<Input
placeholder="Enter the Workspace Mode"
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
/>
</Field.Root>
<Field.Root>
<Field.Label pt={1} color="black" fontSize="12px">
Category
</Field.Label>
<Input
placeholder="Enter the Category"
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
/>
</Field.Root>
<Field.Root>
<Field.Label pt={1} color="black" fontSize="12px">
Sub-Category
</Field.Label>
<Input
placeholder="Enter the Sub-Category"
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
/>
</Field.Root>
<Field.Root>
<Field.Label pt={1} color="black" fontSize="12px">
Salary
</Field.Label>
<Input
placeholder="Enter the Salary"
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
/>
</Field.Root>
<Field.Root>
<Field.Label pt={1} color="black" fontSize="12px">
Experience
</Field.Label>
<Input
placeholder="Enter the Experience"
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
/>
</Field.Root>
<Field.Root>
<Field.Label pt={1} color="black" fontSize="12px">
Job Location
</Field.Label>
<Input
placeholder="Enter the Job Location"
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
/>
</Field.Root>
{/* <Field.Label pt={1} color="black" fontSize="12px">Country Selection</Field.Label>
<Input placeholder="Enter the Country Selection" /> */} <Input placeholder="Enter the Country Selection" /> */}
<SelectRoot collection={frameworks} size="sm" w={'100%'}> <SelectRoot collection={frameworks} size="sm" w={"100%"}>
<SelectLabel pt={1} color="black" fontSize="12px">Country Selection</SelectLabel> <SelectLabel pt={1} color="black" fontSize="12px">
<SelectTrigger bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" Country Selection
borderRadius={"5px"}> </SelectLabel>
<SelectValueText placeholder="Enter the Country Selection" pb={"6px"} fontSize={"12px"} /> <SelectTrigger
</SelectTrigger> bgColor="#EEEEEE"
<SelectContent position={'relative'} zIndex={'9999'} bg={"#fff"}> color="black"
{frameworks.items.map((movie) => ( border="none"
<SelectItem item={movie} key={movie.value} color={"black"} pl={2} p={1} _hover={{ bg: "#F0F0F0" }} // Light grey background on hover pl={1}
fontSize="12px" > fontSize="12px"
{movie.label} height="30px"
</SelectItem> borderRadius={"5px"}
))} >
</SelectContent> <SelectValueText
</SelectRoot> placeholder="Enter the Country Selection"
pb={"6px"}
fontSize={"12px"}
/>
</SelectTrigger>
<SelectContent
position={"relative"}
zIndex={"9999"}
bg={"#fff"}
>
{frameworks.items.map((movie) => (
<SelectItem
item={movie}
key={movie.value}
color={"black"}
pl={2}
p={1}
_hover={{ bg: "#F0F0F0" }} // Light grey background on hover
fontSize="12px"
>
{movie.label}
</SelectItem>
))}
</SelectContent>
</SelectRoot>
<Field.Root> <Field.Root>
<Field.Label pt={1} color="black" fontSize="12px">Job type</Field.Label> <Field.Label pt={1} color="black" fontSize="12px">
<Input placeholder="Enter the Job Type" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" /> Job type
</Field.Root><Field.Root> </Field.Label>
<Field.Label pt={1} color="black" fontSize="12px">Skills required</Field.Label> <Input
<Input placeholder="Enter the Skills Required" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" /> placeholder="Enter the Job Type"
</Field.Root><Field.Root> bgColor="#EEEEEE"
<Field.Label pt={1} color="black" fontSize="12px">Job Description*</Field.Label> color="black"
<Input placeholder="Enter the Job Description" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" /> border="none"
</Field.Root><Field.Root> pl={1}
<Field.Label pt={1} color="black" fontSize="12px">Upload Image</Field.Label> fontSize="12px"
<Input placeholder="Upload Image" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" /> height="30px"
</Field.Root> />
</Stack> </Field.Root>
</DialogBody> <Field.Root>
<DialogFooter display="flex" justifyContent="center" pt={"2"}> <Field.Label pt={1} color="black" fontSize="12px">
<Button w="100%" bg="#02A0A0" color={"#fff"} fontSize="12px" height="30px"> Skills required
Save </Field.Label>
</Button> <Input
</DialogFooter> placeholder="Enter the Skills Required"
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
/>
</Field.Root>
<Field.Root>
<Field.Label pt={1} color="black" fontSize="12px">
Job Description*
</Field.Label>
<Input
placeholder="Enter the Job Description"
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
/>
</Field.Root>
<Field.Root>
<Field.Label pt={1} color="black" fontSize="12px">
Upload Image
</Field.Label>
<Input
placeholder="Upload Image"
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
/>
</Field.Root>
</Stack>
</DialogBody>
<DialogFooter display="flex" justifyContent="center" pt={"2"}>
<Button
w="100%"
bg="#02A0A0"
color={"#fff"}
fontSize="12px"
height="30px"
>
Save
</Button>
</DialogFooter>
<DialogCloseTrigger color="black" /> <DialogCloseTrigger color="black" />
</DialogContent> </DialogContent>
</DialogRoot> {/* ))} */}
</DialogRoot>
);
)
} }
export default ViewManageJob export default ViewManageJob;

View File

@@ -1,11 +1,245 @@
import MainFrame from "../../components/MainFrame" import {
Box, HStack, Icon, Image,
// Span,
Text
} from "@chakra-ui/react";
import MainFrame from "../../components/MainFrame";
// import { InputGroup } from "../../components/ui/input-group";
// import { LuSearch } from "react-icons/lu";
import DataTable from "../../components/DataTable";
// import AlertDailog from "../../components/AlertDailog";
import { Switch } from "../../components/ui/switch";
// import img from "../../assets/waterfall.jpg";
// import { RiDeleteBin5Line } from "react-icons/ri";
import ViewDailog from "./ViewDailog";
import { useGetManagePostsQuery, usePostStatusToggleMutation } from "../../Redux/Service/manage.post.service";
import { useEffect, useState } from "react";
import { toaster } from "../../components/ui/toaster";
import { FaVideo } from "react-icons/fa";
import SearchComponent from "../../components/SearchComponent";
// import Delete from "../../components/ActionIcons/Delete";
// import ViewDailog from './ViewDailog'
const APIURL = import.meta.env.VITE_POST_IMG
const tableHeadRow = [
"Sr. No",
"Images",
"Description",
"Publish Data",
// "Activate/Deactivate",
"Action",
];
// const managepost: any[] = [
// ...Array.from({ length: 12 }, (_, i) => ({
// "Sr. No": i + 1,
// Images: (
// // <Image w={50} src={img} />
// <Image rounded={"lg"} w={100} h={50} src={img} />
// ),
// Description: (
// <Text>
// {`Lorem ipsum dolor, sit amet consectetur adipisicing elit.}`.slice(
// 0,
// 30
// ) + "..."}
// </Text>
// ),
// "Publish Data": "12/01/2025",
// "Activate/Deactivate": (
// <Box w={"100%"}>
// <Switch size={"sm"} colorPalette={"teal"} />
// </Box>
// ),
// Action: (
// <HStack justifyContent="center">
// <ViewDailog />
// {/* <AlertDailog
// AltertTiggerIcon={() => <Span><Delete /> </Span>}
// alertText="Delete Users"
// alertIcon={<Image src={"DeleteIcon"} h={"39px"} />}
// alertCaption="are you sure you want to delete ?"
// onConfirm={() => {
// console.log("User deleted:", i + 1);
// }}
// /> */}
// </HStack>
// ),
// })),
// ];
const ManagePost = () => { const ManagePost = () => {
const [currentPage, setCurrentPage] = useState(1);
const { data, refetch } = useGetManagePostsQuery(currentPage)
const [localData, setLocalData] = useState<any[]>([]);
const [searchTerm, setSearchTerm] = useState("");
const [postStatusToggle] = usePostStatusToggleMutation()
console.log('POSTS', data?.data.data);
useEffect(() => {
if (data?.data?.data) {
setLocalData(data?.data.data);
}
}, [data]);
const handlePageChange = (page: number) => {
setCurrentPage(page);
};
const handleToggle = async (agencyId: string, currentStatus: number) => {
const newStatus = currentStatus ? 0 : 1;
setLocalData((prevData) =>
prevData.map((agency) =>
agency.id === agencyId ? { ...agency, is_active: newStatus } : agency
)
);
try {
await postStatusToggle({ id: agencyId, is_active: newStatus }).unwrap();
refetch()
} catch (error) {
console.error("Error updating:", error);
toaster.create({
title: "Error",
description: "Someting went wrong.",
type: "error",
});
setLocalData((prevData) =>
prevData.map((agency) =>
agency.id === agencyId ? { ...agency, is_active: currentStatus } : agency
)
);
}
};
function formatAPIDate(apiDateString: any) {
const date = new Date(apiDateString);
// Get month, day, and year
const month = date.getMonth() + 1; // Months are 0-indexed
const day = date.getDate();
const year = date.getFullYear();
// Pad with leading zeros if needed
const formattedMonth = month.toString().padStart(2, '0');
const formattedDay = day.toString().padStart(2, '0');
return `${formattedMonth}/${formattedDay}/${year}`;
}
const filteredData = localData?.filter((agency) => {
return (agency.post_content_translation.some((item: any) => {
const searchLower = searchTerm.toLowerCase();
const title = item.content?.toLowerCase().includes(searchLower);
return title;
}))
});
const managepost = filteredData?.flatMap((agency: any, index: number) => (agency.post_content_translation.map((translation: any) => ({
'id': agency.id,
"Sr. No": (currentPage - 1) * (data?.data.per_page ?? 0) + index + 1,
Images: (
agency.images.length > 0 ?
agency.images[0].type === "image" ? (
<HStack>
<Image
rounded={"lg"}
w={100}
h={50}
src={`${APIURL}${agency.images[0].image_name}`}
/>
<Text fontSize="xs" color={'lightgray'}>
{`${Number(agency.images.length) > 1 ? '+' + (Number(agency.images.length) - 1) : ''}`}
</Text>
</HStack>
) : (
<HStack>
<Box
rounded={"lg"}
w={100}
h={50}
bg="gray.200"
display="flex"
alignItems="center"
justifyContent="center"
>
<Icon as={FaVideo} color="gray.500" />
</Box>
<Text fontSize="xs" color={'lightgray'}>
{`${Number(agency.images.length) > 1 ? '+' + (Number(agency.images.length) - 1) : ''}`}
</Text>
</HStack>
) : ''
// <Image rounded={"lg"} w={100} h={50} src={img} />
),
Description: (
<Text>
{`${translation?.content}`.slice(
0,
30
) + "..."}
</Text>
),
"Publish Data": formatAPIDate(agency.created_at),
"is_active": agency.is_active,
"Action": (
<HStack justifyContent="center">
{/* <ViewAgencyMaster agency={localData} id={agency.id} /> */}
<ViewDailog localData={{ ...agency, translation }} refetch={refetch} />
<Box>
<Switch
colorPalette={"teal"}
size={"xs"}
onChange={() => handleToggle(agency.id, Number(agency.is_active))}
checked={Boolean(Number(agency.is_active))}
/>
</Box>
</HStack>
),
}))));
return ( return (
<MainFrame> <MainFrame>
<Box>
</MainFrame> <HStack
) w={"100%"}
} justifyContent={"space-between"}
mb={4}
py={0}
px={3}
>
<Text as={"span"} fontSize={"sm"} fontWeight={500} color={"#000"}>
{/* Manage Post */}
</Text>
export default ManagePost <HStack>
<SearchComponent
value={searchTerm}
onChange={(value) => {
setSearchTerm(value);
// setCurrentPage(1);
refetch()
}}
/>
</HStack>
</HStack>
<DataTable
sortableColumns={["Name", "Registration Date "]}
tableHeadRow={tableHeadRow}
data={managepost}
paginationData={{
current_page: data?.data.current_page || 1,
last_page: data?.data.last_page || 1,
per_page: data?.data.per_page || 10,
total: data?.data.total || 0
}}
onPageChange={handlePageChange}
/>
</Box>
</MainFrame>
);
};
export default ManagePost;

View File

@@ -1,16 +1,18 @@
import { MdOutlineRemoveRedEye } from "react-icons/md" import { Field, HStack, Image, Input, Stack } from "@chakra-ui/react"
import { Button } from "../../components/ui/button" // import { TbEdit } from "react-icons/tb"
// import img from "../../assets/waterfall.jpg"
import { DialogBody, DialogCloseTrigger, DialogContent, DialogHeader, DialogRoot, DialogTitle, DialogTrigger } from "../../components/ui/dialog" import { DialogBody, DialogCloseTrigger, DialogContent, DialogHeader, DialogRoot, DialogTitle, DialogTrigger } from "../../components/ui/dialog"
import { Field, Image, Input, Stack } from "@chakra-ui/react" // import Edit from "../../components/ActionIcons/Edit"
import img from "../../assets/waterfall.jpg" import { LuEye } from "react-icons/lu"
function ViewDailog() {
return (
const APIURL = import.meta.env.VITE_POST_IMG
function ViewDailog({ localData }: { localData: any, refetch: VoidFunction }) {
return (
<DialogRoot placement="center"> <DialogRoot placement="center">
<DialogTrigger asChild> <DialogTrigger asChild>
<Button bg={"transparent"} size="sm"> {/* <Span><Edit /></Span> */}
<MdOutlineRemoveRedEye style={{ cursor: "pointer", fontSize: "16px" }} color="#000" /> <LuEye fontSize={"xm"} cursor={'pointer'} />
</Button>
</DialogTrigger> </DialogTrigger>
<DialogContent <DialogContent
@@ -26,17 +28,49 @@ function ViewDailog() {
<DialogBody bg="white"> <DialogBody bg="white">
<Stack py={3} > <Stack py={3} >
<Field.Root> <Field.Root>
<Field.Label color="black" pt={1} fontSize="12px">Title</Field.Label>
<Input placeholder="Enter the Title" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" readOnly />
<Field.Label color="black" pt={1} fontSize="12px">Subtitle</Field.Label>
<Input placeholder="Enter the Subtitle" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" readOnly />
<Field.Label color="black" pt={1} fontSize="12px">Description</Field.Label> <Field.Label color="black" pt={1} fontSize="12px">Description</Field.Label>
<Input placeholder="Enter the Description" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" readOnly /> <Input
// placeholder="Enter the Title"
value={localData.translation.content}
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
readOnly
/>
{/* <Field.Label color="black" pt={1} fontSize="12px">Subtitle</Field.Label>
<Input placeholder="Enter the Subtitle" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" readOnly /> */}
{/* <Field.Label color="black" pt={1} fontSize="12px">Description</Field.Label>
<Input placeholder="Enter the Description" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" readOnly /> */}
<Field.Label color="black" pt={1} fontSize="12px">Image</Field.Label> <Field.Label color="black" pt={1} fontSize="12px">Image</Field.Label>
<Image src={img} w="100%" maxH="150px" objectFit="contain" /> <HStack w="fit-content" flexWrap={'wrap'}>
{localData.images.map((img: any) => (
img.type === 'image' ? (
<Image
key={img.id}
src={`${APIURL}${img.image_name}`}
w="30%"
maxH="150px"
objectFit="contain"
/>
) : (
<video
key={img.id}
width="45%"
height="50"
controls
>
<source src={`${APIURL}${img.image_name}`} type="video/mp4" />
</video>
)
))}
</HStack>
{/* <Image src={img} w="100%" maxH="150px" objectFit="contain" /> */}
</Field.Root> </Field.Root>
</Stack> </Stack>
</DialogBody> </DialogBody>

View File

@@ -1,11 +0,0 @@
import MainFrame from '../../components/MainFrame'
const ManageSubAdmin = () => {
return (
<MainFrame>
</MainFrame>
)
}
export default ManageSubAdmin

View File

@@ -1,11 +0,0 @@
import MainFrame from '../../../components/MainFrame'
const DeactivatedAccounts = () => {
return (
<MainFrame>
</MainFrame>
)
}
export default DeactivatedAccounts

View File

@@ -1,233 +0,0 @@
import { Box, HStack, Input, Stack, Table, Text } from "@chakra-ui/react";
import MainFrame from "../../../components/MainFrame";
import { InputGroup } from "../../../components/ui/input-group";
import { LuSearch } from "react-icons/lu";
import DataTable from "../../../components/DataTable";
// Table setup
const tableHeadRow = [
"Sr. No",
"First Name",
"Mobile number",
"Gender",
"DOB",
"Type of User",
"Language",
"Status",
"Action",
];
const usersData: any[] = [
{
"Sr. No": 1,
"First Name": "Ritesh",
"Mobile number": "9876543210",
Gender: "Male",
DOB: "15-01-1990",
"Type of User": "Admin",
Language: "English",
Status: "Active",
Action: "Edit/Delete",
},
{
"Sr. No": 2,
"First Name": "Anjali",
"Mobile number": "9123456789",
Gender: "Female",
DOB: "21-06-1995",
"Type of User": "Customer",
Language: "Hindi",
Status: "Inactive",
Action: "Edit/Delete",
},
{
"Sr. No": 3,
"First Name": "Rajesh",
"Mobile number": "9871234560",
Gender: "Male",
DOB: "12-12-1985",
"Type of User": "Vendor",
Language: "English",
Status: "Active",
Action: "Edit/Delete",
},
{
"Sr. No": 4,
"First Name": "Priya",
"Mobile number": "9988776655",
Gender: "Female",
DOB: "05-05-1998",
"Type of User": "Customer",
Language: "Tamil",
Status: "Active",
Action: "Edit/Delete",
},
{
"Sr. No": 5,
"First Name": "Amit",
"Mobile number": "8899665544",
Gender: "Male",
DOB: "03-03-1992",
"Type of User": "Admin",
Language: "Gujarati",
Status: "Inactive",
Action: "Edit/Delete",
},
{
"Sr. No": 6,
"First Name": "Amit",
"Mobile number": "8899665544",
Gender: "Male",
DOB: "03-03-1992",
"Type of User": "Admin",
Language: "Gujarati",
Status: "Inactive",
Action: "Edit/Delete",
},
{
"Sr. No": 7,
"First Name": "Amit",
"Mobile number": "8899665544",
Gender: "Male",
DOB: "03-03-1992",
"Type of User": "Admin",
Language: "Gujarati",
Status: "Inactive",
Action: "Edit/Delete",
},
{
"Sr. No": 5,
"First Name": "Amit",
"Mobile number": "8899665544",
Gender: "Male",
DOB: "03-03-1992",
"Type of User": "Admin",
Language: "Gujarati",
Status: "Inactive",
Action: "Edit/Delete",
},
{
"Sr. No": 6,
"First Name": "Amit",
"Mobile number": "8899665544",
Gender: "Male",
DOB: "03-03-1992",
"Type of User": "Admin",
Language: "Gujarati",
Status: "Inactive",
Action: "Edit/Delete",
},
{
"Sr. No": 7,
"First Name": "Amit",
"Mobile number": "8899665544",
Gender: "Male",
DOB: "03-03-1992",
"Type of User": "Admin",
Language: "Gujarati",
Status: "Inactive",
Action: "Edit/Delete",
},
{
"Sr. No": 8,
"First Name": "Amit",
"Mobile number": "8899665544",
Gender: "Male",
DOB: "03-03-1992",
"Type of User": "Admin",
Language: "Gujarati",
Status: "Inactive",
Action: "Edit/Delete",
},
{
"Sr. No": 9,
"First Name": "Amit",
"Mobile number": "8899665544",
Gender: "Male",
DOB: "03-03-1992",
"Type of User": "Admin",
Language: "Gujarati",
Status: "Inactive",
Action: "Edit/Delete",
},
{
"Sr. No": 10,
"First Name": "Amit",
"Mobile number": "8899665544",
Gender: "Male",
DOB: "03-03-1992",
"Type of User": "Admin",
Language: "Gujarati",
Status: "Inactive",
Action: "Edit/Delete",
},
{
"Sr. No": 11,
"First Name": "Amit",
"Mobile number": "8899665544",
Gender: "Male",
DOB: "03-03-1992",
"Type of User": "Admin",
Language: "Gujarati",
Status: "Inactive",
Action: "Edit/Delete",
},
{
"Sr. No": 12,
"First Name": "Amit",
"Mobile number": "8899665544",
Gender: "Male",
DOB: "03-03-1992",
"Type of User": "Admin",
Language: "Gujarati",
Status: "Inactive",
Action: "Edit/Delete",
},
{
"Sr. No": 13,
"First Name": "Amit",
"Mobile number": "8899665544",
Gender: "Male",
DOB: "03-03-1992",
"Type of User": "Admin",
Language: "Gujarati",
Status: "Inactive",
Action: "Edit/Delete",
},
];
const RegisterUsers = () => {
return (
<MainFrame>
<HStack w={"100%"} justifyContent={"space-between"} p={3}>
<Text as={"span"} fontSize={"sm"} fontWeight={"bolder"} color={"#000"}>
Register User
</Text>
<Box w={"30%"}>
<InputGroup
bgSize={"xs"}
flex="1"
startElement={<LuSearch />}
w={"100%"}
color={"#000"}
>
<Input
w={"100%"}
bg={"#EEEEEE"}
_focus={{ border: "1px #02A0A0 solid" }}
border={"1px #EEEEEE solid"}
rounded={"full"}
size={"sm"}
placeholder="Search..."
/>
</InputGroup>
</Box>
</HStack>
<DataTable tableHeadRow={tableHeadRow} data={usersData} />
</MainFrame>
);
};
export default RegisterUsers;

View File

@@ -4,34 +4,80 @@ import DataTable from "../../../components/DataTable";
import { Switch } from "../../../components/ui/switch"; import { Switch } from "../../../components/ui/switch";
import { InputGroup } from "../../../components/ui/input-group"; import { InputGroup } from "../../../components/ui/input-group";
import { LuSearch } from "react-icons/lu"; import { LuSearch } from "react-icons/lu";
import { useGetContactQuery } from "../../../Redux/Service/deactivated.account.service";
import { useEffect, useState } from "react";
import { Spinner } from "../../../components/Sipnner/Spinner";
const tableHeadRow = [ const tableHeadRow = [
"Sr. No", "Sr. No",
"First Name", "First Name",
"Last Name", "Last Name",
"Company name", "User Type",
"Activate/Deactivate", "Activate/Deactivate",
]; ];
const manageUser: any[] = [ const DeactivatedAccounts = () => {
...Array.from({ length: 12 }, (_, i) => ({ const { data ,isLoading} = useGetContactQuery();
"Sr. No": i + 1, const [localData, setLocalData] = useState([]);
"First Name": "Ritesh",
"Last Name": "akanksha@gmail.com", useEffect(() => {
"Company name": "9876543210", if (data) {
setLocalData((data as any)?.data?.data || []);
}
}, [data]);
const manageUser = localData?.map((agency: any, index: number) => ({
"Sr. No": index + 1,
"First Name": agency?.first_name,
"Last Name": agency?.last_name,
"User Type": agency?.principal_type_xid === 3 ? "JobSeeker" : "Recruiter",
"Activate/Deactivate": ( "Activate/Deactivate": (
<Box display={'flex'} justifyContent={'center'}> <Box display={"flex"} justifyContent={"center"}>
<Switch colorPalette={'teal'} /> <Switch
size={"sm"}
colorPalette={"teal"}
checked={agency.is_active === true}
// onChange={() => handleToggle(agency.id, agency.is_active ? "1" : "0")}
/>
</Box> </Box>
), ),
})), }));
];
if (isLoading) {
return (
<MainFrame>
<Box
display="flex"
justifyContent="center"
alignItems="center"
height="100%"
>
<Spinner />
</Box>
</MainFrame>
);
}
// if (isError) {
// return (
// <MainFrame>
// <Box
// display="flex"
// justifyContent="center"
// alignItems="center"
// height="100%"
// >
// <Text>Error loading data</Text>
// </Box>
// </MainFrame>
// );
// }
const DeactivatedAccounts = () => {
return ( return (
<MainFrame> <MainFrame>
<Box> <Box>
<HStack <HStack
w={"100%"} w={"100%"}
justifyContent={"space-between"} justifyContent={"space-between"}
mb={4} mb={4}
@@ -39,13 +85,16 @@ const DeactivatedAccounts = () => {
px={3} px={3}
> >
<Text as={"span"} fontSize={"sm"} fontWeight={500} color={"#000"}> <Text as={"span"} fontSize={"sm"} fontWeight={500} color={"#000"}>
Deactivated User Accounts Deactivated User Accounts
</Text> </Text>
<HStack> <HStack>
<InputGroup <InputGroup
startElement={ startElement={
<LuSearch fontSize={"xs"} style={{position:'relative',left:'10px'}} /> <LuSearch
fontSize={"xs"}
style={{ position: "relative", left: "10px" }}
/>
} }
color={"#000"} color={"#000"}
> >
@@ -57,9 +106,9 @@ const DeactivatedAccounts = () => {
_focus={{ border: "1px solid #02A0A0" }} _focus={{ border: "1px solid #02A0A0" }}
rounded={"md"} rounded={"md"}
size={"2xs"} size={"2xs"}
fontSize={"2sm"} fontSize={"sm"}
placeholder="Search..." placeholder="Search..."
bgColor={'#EEEEEE'} bgColor={"#EEEEEE"}
ps={8} ps={8}
/> />
</InputGroup> </InputGroup>

View File

@@ -1,5 +1,5 @@
import { MdOutlineRemoveRedEye } from "react-icons/md"; // import { MdOutlineRemoveRedEye } from "react-icons/md";
import { Field, Input, Stack } from "@chakra-ui/react"; import { Field, Input, Span, Stack } from "@chakra-ui/react";
import { import {
DialogActionTrigger, DialogActionTrigger,
DialogBody, DialogBody,
@@ -11,24 +11,28 @@ import {
DialogTitle, DialogTitle,
DialogTrigger, DialogTrigger,
} from "../../../components/ui/dialog"; } from "../../../components/ui/dialog";
import { BiEdit } from "react-icons/bi"; // import { BiEdit } from "react-icons/bi";
import { Button } from "../../../components/ui/button"; import { Button } from "../../../components/ui/button";
// import { TbEdit } from "react-icons/tb";
import Edit from "../../../components/ActionIcons/Edit";
function EditRegisterUsers() { function EditRegisterUsers() {
return ( return (
<DialogRoot placement="center"> <DialogRoot placement="center">
<DialogTrigger asChild> <DialogTrigger asChild>
<BiEdit style={{ cursor: "pointer", fontSize: "16px" }} /> <Span>
<Edit />
</Span>
</DialogTrigger> </DialogTrigger>
<DialogContent <DialogContent
bg={"#fff"} bg={"#fff"}
w={{ base: '90%', md: '400px' }} w={{ base: "90%", md: "400px" }}
height={'80vh'} height={"80vh"}
overflow={'scroll'} overflow={"scroll"}
overflowX="hidden" overflowX="hidden"
p={3} // Reduced padding p={3} // Reduced padding
bgSize={'md'} bgSize={"md"}
> >
<DialogHeader bg="white" p={0}> <DialogHeader bg="white" p={0}>
<DialogTitle alignSelf="center" color="black" fontSize="14px"> <DialogTitle alignSelf="center" color="black" fontSize="14px">
@@ -43,49 +47,81 @@ function EditRegisterUsers() {
First Name First Name
</Field.Label> </Field.Label>
<Input <Input
bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
/> />
<Field.Label color="black" pt={1} fontSize="12px"> <Field.Label color="black" pt={1} fontSize="12px">
Last Name Last Name
</Field.Label> </Field.Label>
<Input <Input
bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
/> />
<Field.Label color="black" pt={1} fontSize="12px"> <Field.Label color="black" pt={1} fontSize="12px">
Gender Gender
</Field.Label> </Field.Label>
<Input <Input
bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
/> />
<Field.Label color="black" pt={1} fontSize="12px"> <Field.Label color="black" pt={1} fontSize="12px">
DOB DOB
</Field.Label> </Field.Label>
<Input <Input
bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
/> />
<Field.Label color="black" pt={1} fontSize="12px"> <Field.Label color="black" pt={1} fontSize="12px">
OTP Verified OTP Verified
</Field.Label> </Field.Label>
<Input <Input
bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
/> />
<Field.Label color="black" pt={1} fontSize="12px"> <Field.Label color="black" pt={1} fontSize="12px">
Language Language
</Field.Label> </Field.Label>
<Input <Input
bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
/> />
</Field.Root> </Field.Root>
</Stack> </Stack>
</DialogBody> </DialogBody>
<DialogFooter mt={5}> <DialogFooter mt={5}>
<DialogActionTrigger asChild> <DialogActionTrigger asChild>
<Button rounded={'md'} w={"100%"} size={'sm'} bg={'#02A0A0'}>Save</Button> <Button rounded={"md"} w={"100%"} size={"sm"} bg={"#02A0A0"}>
Save
</Button>
</DialogActionTrigger> </DialogActionTrigger>
</DialogFooter> </DialogFooter>
<DialogCloseTrigger color="black" /> <DialogCloseTrigger color="black" />

View File

@@ -1,18 +1,20 @@
import { Box, HStack, Image, Input, Text } from "@chakra-ui/react"; import {
Box, HStack,
// Image,
Text
} from "@chakra-ui/react";
import MainFrame from "../../../components/MainFrame"; import MainFrame from "../../../components/MainFrame";
import AlertDailog from "../../../components/AlertDailog"; // import AlertDailog from "../../../components/AlertDailog";
import { NavLink } from "react-router-dom"; // import { RiDeleteBin5Line } from "react-icons/ri";
import { RiDeleteBin5Line } from "react-icons/ri";
import DataTable from "../../../components/DataTable"; import DataTable from "../../../components/DataTable";
import { Switch } from "../../../components/ui/switch"; import { Switch } from "../../../components/ui/switch";
import { InputGroup } from "../../../components/ui/input-group";
import { LuSearch } from "react-icons/lu";
import { BiEdit } from "react-icons/bi";
import ViewRegisterUsers from "./ViewRegisterUsers"; import ViewRegisterUsers from "./ViewRegisterUsers";
import EditRegisterUsers from "./EditRegisterUsers"; import EditRegisterUsers from "./EditRegisterUsers";
import { Button } from "../../../components/ui/button";
import { IoMdAdd } from "react-icons/io";
import AddRegisterUsers from "./AddRegisterUsers"; import AddRegisterUsers from "./AddRegisterUsers";
import { useEffect, useState } from "react";
import { useGetManageUserQuery, UserData, useUserToggleMutation } from "../../../Redux/Service/manage.user";
import SearchComponent from "../../../components/SearchComponent";
// import Delete from "../../../components/ActionIcons/Delete";
const tableHeadRow = [ const tableHeadRow = [
"Sr. No", "Sr. No",
@@ -26,40 +28,113 @@ const tableHeadRow = [
"Action", "Action",
]; ];
const registerUser: any[] = [ // const registerUser: any[] = [
...Array.from({ length: 12 }, (_, i) => ({ // ...Array.from({ length: 12 }, (_, i) => ({
"Sr. No": i + 1, // "Sr. No": i + 1,
"First Name": "Ritesh", // "First Name": "Ritesh",
"Mobile Number": "akanksha@gmail.com", // "Mobile Number": "akanksha@gmail.com",
"Gender": "9876543210", // "Gender": "9876543210",
"DOB": "Female", // "DOB": "Female",
"Type Of User": "15-01-1990", // "Type Of User": "15-01-1990",
"Language": "Mumbai", // "Language": "Mumbai",
"Activate/Deactivate": ( // "Activate/Deactivate": (
<Box> // <Box>
<Switch colorPalette={'teal'} /> // <Switch size={'sm'} colorPalette={'teal'} />
</Box> // </Box>
), // ),
"Action": ( // "Action": (
<HStack justifyContent="center"> // <HStack justifyContent="center">
<ViewRegisterUsers /> // <ViewRegisterUsers />
<EditRegisterUsers /> // <EditRegisterUsers />
{/* <RiDeleteBin5Line style={{ cursor: "pointer" }} /> */} // {/* <RiDeleteBin5Line style={{ cursor: "pointer" }} /> */}
<AlertDailog // {/* <AlertDailog
AltertTiggerIcon={RiDeleteBin5Line} // AltertTiggerIcon={() =><Delete /> } // Pass as function
alertText="Delete Users" // alertText="Delete Users"
alertIcon={<Image src={"DeleteIcon"} h={"39px"} />} // alertIcon={<Image src={"DeleteIcon"} h={"39px"} />}
alertCaption="Are You Sure You Want To Delete This User ?" // alertCaption="Are You Sure You Want To Delete This User ?"
onConfirm={() => { // onConfirm={() => {
console.log("User deleted:", i + 1); // console.log("User deleted:", i + 1);
}} // }}
/> // /> */}
</HStack> // </HStack>
), // ),
})), // })),
]; // ];
const RegisterUsers = () => { const RegisterUsers = () => {
const [currentPage, setCurrentPage] = useState(1);
const { data, refetch } = useGetManageUserQuery(currentPage)
const [localData, setLocalData] = useState<any[]>([]);
const [searchTerm, setSearchTerm] = useState("");
const [userToggle] = useUserToggleMutation()
console.log("Register Users Data", data?.data.data);
useEffect(() => {
if (data) {
setLocalData(data?.data.data);
}
}, [data]);
const handlePageChange = (page: number) => {
setCurrentPage(page);
}
const filteredData = localData?.filter((agency) => {
const searchLower = searchTerm.toLowerCase();
const firstName = agency.first_name?.toLowerCase().includes(searchLower);
// const email = agency.capital?.toLowerCase().includes(searchLower);
return firstName;
});
const handleToggle = async (agencyId: number, currentStatus: string) => {
const newStatus = currentStatus === '1' ? '0' : '1';
setLocalData((prevData) =>
prevData.map((agency) =>
agency.id === agencyId ? { ...agency, is_active: newStatus } : agency
)
);
try {
await userToggle({ id: agencyId, is_active: newStatus }).unwrap();
refetch()
} catch (error) {
console.error("Error updating privacy policy:", error);
setLocalData((prevData) =>
prevData.map((agency) =>
agency.id === agencyId ? { ...agency, is_active: currentStatus } : agency
)
);
}
}
const managepost = filteredData?.flatMap((agency: UserData, index: number) => ({
"Sr. No": (currentPage - 1) * (data?.data.per_page ?? 0) + index + 1,
"First Name": agency.first_name,
"Mobile Number": agency.phone_number,
"Gender": agency.gender,
"DOB": agency.date_of_birth ? new Date(agency.date_of_birth).toLocaleDateString('en-GB').replace(/\//g, '-') : 'N/A',
"Type Of User": agency.principal_type?.principal_type_title || 'N/A',
// "Language": agency.principle_language_links.map(lang => lang.language_name).join(', ') || 'N/A',
"Action": (
<HStack justifyContent="center">
<EditRegisterUsers
// rowData={{ id: agency.id, en_name: agency.en_name, country_code: agency.country_code, phonecode: agency.phonecode, capital: agency.capital, currency: agency.currency, currency_name: agency.currency_name, currency_symbol: agency.currency_symbol }}
// refetch={refetch}
/>
<ViewRegisterUsers />
<Box>
<Switch
colorPalette={'teal'}
size={"xs"}
checked={agency.is_active === true}
onChange={() => handleToggle(agency.id, agency.is_active ? '1' : '0')}
/>
</Box>
</HStack>
),
}))
return ( return (
<MainFrame> <MainFrame>
<Box> <Box>
@@ -75,33 +150,28 @@ const RegisterUsers = () => {
</Text> </Text>
<HStack> <HStack>
<InputGroup <SearchComponent
startElement={ value={searchTerm}
<LuSearch fontSize={"xs"} style={{ position: 'relative', left: '10px' }} /> onChange={(value) => {
} setSearchTerm(value);
color={"#000"} // setCurrentPage(1);
> refetch()
<Input }}
p={3} />
w={300}
bg={"#fff"}
colorPalette={"blue"}
_focus={{ border: "1px solid #02A0A0" }}
rounded={"md"}
size={"2xs"}
fontSize={"2sm"}
placeholder="Search..."
bgColor={'#EEEEEE'}
ps={8}
/>
</InputGroup>
<AddRegisterUsers /> <AddRegisterUsers />
</HStack> </HStack>
</HStack> </HStack>
<DataTable <DataTable
sortableColumns={["Name", "Registration Date "]} sortableColumns={["Name", "Registration Date "]}
tableHeadRow={tableHeadRow} tableHeadRow={tableHeadRow}
data={registerUser} data={managepost}
paginationData={{
current_page: data?.data.current_page || 1,
last_page: data?.data.last_page || 1,
per_page: data?.data.per_page || 10,
total: data?.data.total || 0
}}
onPageChange={handlePageChange}
/> />
</Box> </Box>
</MainFrame> </MainFrame>

View File

@@ -1,5 +1,5 @@
import { MdOutlineRemoveRedEye } from "react-icons/md"; import { Field, Input, Span, Stack } from "@chakra-ui/react";
import { Field, Input, Stack } from "@chakra-ui/react"; import View from "../../../components/ActionIcons/View";
import { import {
DialogBody, DialogBody,
DialogCloseTrigger, DialogCloseTrigger,
@@ -14,10 +14,7 @@ function ViewRegisterUsers() {
return ( return (
<DialogRoot placement="center"> <DialogRoot placement="center">
<DialogTrigger asChild> <DialogTrigger asChild>
<MdOutlineRemoveRedEye <Span><View /></Span>
color="#000"
style={{ cursor: "pointer", fontSize: "16px" }}
/>
</DialogTrigger> </DialogTrigger>
<DialogContent <DialogContent

View File

@@ -1,13 +1,13 @@
import { Box, HStack, Image, Input, Text } from "@chakra-ui/react"; import { Box, HStack, Text } from "@chakra-ui/react";
import MainFrame from "../../../components/MainFrame" import MainFrame from "../../../components/MainFrame"
import { InputGroup } from "../../../components/ui/input-group";
import { LuSearch } from "react-icons/lu";
import DataTable from "../../../components/DataTable"; import DataTable from "../../../components/DataTable";
import { Switch } from "../../../components/ui/switch"; import { Switch } from "../../../components/ui/switch";
import EditAgencyMaster from "./EditAgencyMaster"; // import EditAgencyMaster from "./EditAgencyMaster";
import ViewAgencyAddModel from "./ViewAgencyAddModel"; // import ViewAgencyAddModel from "./ViewAgencyAddModel";
import ViewAgencyMaster from "./ViewAgencyMaster"; import ViewAgencyMaster from "./ViewAgencyMaster";
import { useAgencyMasterToggleMutation, useGetAgencyMasterQuery } from "../../../Redux/Service/agency.master.module.service";
import { useEffect, useState } from "react";
import SearchComponent from "../../../components/SearchComponent";
// table data // table data
@@ -21,32 +21,105 @@ const tableHeadRow = [
"Website/Domain", "Website/Domain",
"GST no.", "GST no.",
"Action" "Action"
]; ];
const managepost: any[] = [ // const managepost: any[] = [
...Array.from({ length: 12 }, (_, i) => ({ // ...Array.from({ length: 12 }, (_, i) => ({
"Sr. No": i + 1, // "Sr. No": i + 1,
"Agency Name": "Lorem Ipsum", // "Agency Name": "Lorem Ipsum",
"RC no.": "Lorem Ipsum", // "RC no.": "Lorem Ipsum",
"State": "Lorem Ipsum", // "State": "Lorem Ipsum",
"RC Status": "Active", // "RC Status": "Active",
"Registered Office Address": "Lorem Ipsum", // "Registered Office Address": "Lorem Ipsum",
"Website/Domain": "Lorem Ipsum", // "Website/Domain": "Lorem Ipsum",
"GST no.": "Lorem Ipsum", // "GST no.": "Lorem Ipsum",
// "Action": (
// <HStack justifyContent="center">
// <ViewAgencyMaster/>
// <EditAgencyMaster />
// <Box>
// <Switch colorPalette={'teal'} size={"xs"}/>
// </Box>
// </HStack>
// ),
// })),
// ];
const AgencyMaster = () => {
const [currentPage, setCurrentPage] = useState(1);
const { data, refetch } = useGetAgencyMasterQuery(currentPage)
const [agencyMasterToggle] = useAgencyMasterToggleMutation()
const [localData, setLocalData] = useState<any[]>([]);
const [searchTerm, setSearchTerm] = useState("");
const handleToggle = async (agencyId: string, currentStatus: number) => {
const newStatus = currentStatus ? 0 : 1;
setLocalData((prevData) =>
prevData.map((agency) =>
agency.id === agencyId ? { ...agency, is_active: newStatus } : agency
)
);
try {
await agencyMasterToggle({ id: agencyId, is_active: newStatus }).unwrap();
refetch()
} catch (error) {
console.error("Error updating privacy policy:", error);
setLocalData((prevData) =>
prevData.map((agency) =>
agency.id === agencyId ? { ...agency, is_active: currentStatus } : agency
)
);
}
};
const handlePageChange = (page: number) => {
setCurrentPage(page);
};
const filteredData = localData?.filter((agency) =>
agency?.name.toLowerCase().includes(searchTerm.toLowerCase())
);
const managepost = filteredData?.map((agency: any, index: number) => ({
'id': agency.id,
"Sr. No": (currentPage - 1) * (data?.data.per_page ?? 0) + index + 1,
"Agency Name": agency.name,
"RC no.": agency.rc_number,
"State": agency.state,
"RC Status": agency.rc_status,
"Registered Office Address": agency.registered_office,
"Website/Domain": agency.domain_name,
"GST no.": agency.gst_number,
"is_active": agency.is_active,
"Action": ( "Action": (
<HStack justifyContent="center"> <HStack justifyContent="center">
<ViewAgencyMaster/> <ViewAgencyMaster agency={localData} id={agency.id} />
<EditAgencyMaster /> {/* <EditAgencyMaster editData={{ id: agency.id, name: agency.name, domain_name: agency.domain_name, gst_number: agency.gst_number, rc_number: agency.rc_number, rc_status: agency.rc_status, registered_office: agency.registered_office, state: agency.state }} refetch={refetch} /> */}
<Box> <Box>
<Switch colorPalette={'teal'} size={"xs"}/> <Switch
colorPalette={"teal"}
size={"xs"}
onChange={() => handleToggle(agency.id.toString(), Number(agency.is_active))}
checked={Boolean(Number(agency.is_active))}
/>
</Box> </Box>
</HStack> </HStack>
), ),
})), }));
];
useEffect(() => {
if (data?.data?.data) {
setLocalData(data?.data?.data);
}
}, [data, localData, managepost]);
// useEffect(() => {
// console.log("Fetched data:", data);
// console.log("Local data:", localData);
// console.log("Managepost data:", managepost);
// }, [data, localData, managepost]);
const AgencyMaster = () => {
return ( return (
<MainFrame> <MainFrame>
@@ -59,11 +132,11 @@ const AgencyMaster = () => {
px={3} px={3}
> >
<Text as={"span"} fontSize={"sm"} fontWeight={500} color={"#000"}> <Text as={"span"} fontSize={"sm"} fontWeight={500} color={"#000"}>
Agency Master Agency Master
</Text> </Text>
<HStack mr={5}> <HStack >
<InputGroup marginRight={"1rem"} {/* <InputGroup
startElement={ startElement={
<LuSearch fontSize={"xs"} style={{ position: 'relative', left: '10px' }} /> <LuSearch fontSize={"xs"} style={{ position: 'relative', left: '10px' }} />
} }
@@ -76,23 +149,33 @@ const AgencyMaster = () => {
colorPalette={"blue"} colorPalette={"blue"}
_focus={{ border: "1px solid #02A0A0" }} _focus={{ border: "1px solid #02A0A0" }}
rounded={"md"} rounded={"md"}
size={"2xs"} size={"xs"}
fontSize={"2sm"} fontSize={"sm"}
placeholder="Search..." placeholder="Search..."
bgColor={'#EEEEEE'} bgColor={'#EEEEEE'}
ps={8} ps={8}
/> />
</InputGroup> </InputGroup> */}
{/* <Button bgColor={'#EEEEEE'} pl={3} pr={3}><IoMdAdd /> <Text>Add</Text></Button> */} <SearchComponent
<ViewAgencyAddModel /> value={searchTerm}
onChange={setSearchTerm}
/>
{/* <ViewAgencyAddModel refetch={refetch} /> */}
</HStack> </HStack>
</HStack> </HStack>
<DataTable <DataTable
sortableColumns={["Name", "Registration Date "]} sortableColumns={["Name", "Registration Date "]}
tableHeadRow={tableHeadRow} tableHeadRow={tableHeadRow}
data={managepost} data={managepost || []}
paginationData={{
current_page: data?.data.current_page || 1,
last_page: data?.data.last_page || 1,
per_page: data?.data.per_page || 10,
total: data?.data.total || 0
}}
onPageChange={handlePageChange}
/> />
</Box> </Box>
</MainFrame> </MainFrame>
) )
} }

View File

@@ -1,75 +1,269 @@
import { FaRegEdit } from "react-icons/fa" import { Button } from "../../../components/ui/button";
import { Button } from "../../../components/ui/button" import {
import { DialogBody, DialogCloseTrigger, DialogContent, DialogFooter, DialogHeader, DialogRoot, DialogTitle, DialogTrigger } from "../../../components/ui/dialog" DialogBody,
import { Field, Input, Stack, } from "@chakra-ui/react" DialogCloseTrigger,
DialogContent,
DialogFooter,
DialogHeader,
DialogRoot,
DialogTitle,
DialogTrigger,
} from "../../../components/ui/dialog";
import { Field, Input, Stack } from "@chakra-ui/react";
import Edit from "../../../components/ActionIcons/Edit";
import { useEffect, useState } from "react";
import { useUpdateAgencyMasterMutation } from "../../../Redux/Service/agency.master.module.service";
import { Toaster, toaster } from "../../../components/ui/toaster";
interface Organization {
function EditAgencyMaster() { id: number;
return ( raid?: string;
name: string;
auth_signatory?: string;
<DialogRoot placement="center"> state: string;
<DialogTrigger asChild> district?: string;
<Button bg={"transparent"} size="sm"> rc_number: number;
<FaRegEdit style={{ cursor: "pointer", fontSize: "14px" }} color="#000"/> contact_details?: string;
</Button> registered_office: string;
</DialogTrigger> branch_office?: string;
registered_email?: string;
<DialogContent other_email?: string;
bg={"#fff"} registered_contact?: string;
// w={{ lg: "60%", md: "230px" }} website?: string;
w={{ base: '90%', md: '400px' }} domain_name: string;
staff_domain_name?: string;
height={'80vh'} gst_number: string;
overflow={'scroll'} rc_status?: "Active" | "Inactive"; // Assuming it's a status with limited values
overflowX="hidden"
p={3} // Reduced padding
bgSize={'md'}
>
<DialogHeader bg="white">
<DialogTitle alignSelf="center" color="black" fontSize="14px">Edit</DialogTitle>
</DialogHeader>
<DialogBody bg="white">
<Stack py={3}>
<Field.Root>
<Field.Label color="black" pt={1} fontSize="12px">Agency name</Field.Label>
<Input value="Lorem Ipsum" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" />
<Field.Label color="black" pt={1} fontSize="12px">RC No.</Field.Label>
<Input value="Lorem Ipsum" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" />
<Field.Label color="black" pt={1} fontSize="12px">State</Field.Label>
<Input value="Lorem Ipsum" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" />
<Field.Label color="black" pt={1} fontSize="12px">Registered Office Address</Field.Label>
<Input value="Active" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" />
<Field.Label color="black" pt={1} fontSize="12px">Website/Domain</Field.Label>
<Input value="Lorem Ipsum" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" />
<Field.Label color="black" pt={1} fontSize="12px">GST no.</Field.Label>
<Input value="Lorem Ipsum" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" />
<Field.Label color="black" pt={1} fontSize="12px">Action</Field.Label>
<Input value="Lorem Ipsum" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" />
</Field.Root>
</Stack>
</DialogBody>
<DialogFooter display="flex" justifyContent="center" pt={"2"}>
<Button w="100%" bg="#02A0A0" color={"#fff"} fontSize="12px" height="30px">
Save
</Button>
</DialogFooter>
<DialogCloseTrigger color="black" />
</DialogContent>
</DialogRoot>
)
} }
export default EditAgencyMaster
function EditAgencyMaster({ editData, refetch }: { editData: Organization, refetch: VoidFunction }) {
const [formData, setFormData] = useState(editData);
const [isOpen, setIsOpen] = useState(false);
const [updateAgencyMaster] = useUpdateAgencyMasterMutation()
useEffect(() => {
setFormData(editData);
}, [editData]);
const handleOpenModal = () => {
setIsOpen(true);
};
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const { name, value } = e.target;
setFormData((prev: any) => ({
...prev,
[name]: value,
}));
}
const handleSubmit = async () => {
// console.log("Updated Data:", formData);
if (!formData.name.trim() ||
!formData.rc_number ||
!formData.state.trim() ||
!formData.registered_office.trim() ||
!formData.domain_name.trim() ||
!formData.gst_number.trim()) {
// console.log("Validation failed: Some fields are empty.");
toaster.create({
title: "Error",
description: "Input fields cannot be empty",
type: "error",
});
return;
}
setIsOpen(false);
// Handle API call or further processing here
const payload = {
id: formData?.id,
name: formData?.name,
state: formData?.state,
rc_number: formData?.rc_number,
registered_office: formData?.registered_office,
domain_name: formData?.domain_name,
gst_number:formData?.gst_number,
};
try {
const response = await updateAgencyMaster(payload).unwrap();
if (response?.status === "success") {
toaster.create({
title: "Success",
description: "Data updated successfully",
type: "success",
});
refetch()
setIsOpen(false);
} else {
toaster.create({
title: "Error",
description: "Failed to update",
type: "error",
});
}
} catch (error) {
console.error("Error updating template:", error);
toaster.create({
title: "Error",
description: "Something went wrong.",
type: "error",
});
// alert("Failed to update template");
}
};
return (
<DialogRoot placement="center" open={isOpen} onOpenChange={({ open }) => setIsOpen(open)}>
<DialogTrigger asChild>
<Button bg="transparent" color={"black"} h={"18px"} onClick={handleOpenModal}><Edit /></Button>
</DialogTrigger>
<DialogContent
bg={"#fff"}
// w={{ lg: "60%", md: "230px" }}
w={{ base: "90%", md: "400px" }}
height={"80vh"}
overflow={"scroll"}
overflowX="hidden"
p={3} // Reduced padding
bgSize={"md"}
>
<DialogHeader bg="white">
<DialogTitle alignSelf="center" color="black" fontSize="14px">
Edit
</DialogTitle>
</DialogHeader>
<DialogBody bg="white">
<Stack py={3}>
<Field.Root>
<Field.Label color="black" pt={1} fontSize="12px">
Agency name
</Field.Label>
<Input
name="name"
value={formData?.name}
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
onChange={handleChange}
/>
<Field.Label color="black" pt={1} fontSize="12px">
RC No.
</Field.Label>
<Input
name='rc_number'
value={formData.rc_number}
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
onChange={handleChange}
/>
<Field.Label color="black" pt={1} fontSize="12px">
State
</Field.Label>
<Input
name="state"
value={formData.state}
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
onChange={handleChange}
/>
<Field.Label color="black" pt={1} fontSize="12px">
Registered Office Address
</Field.Label>
<Input
name="registered_office"
value={formData.registered_office}
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
onChange={handleChange}
/>
<Field.Label color="black" pt={1} fontSize="12px">
Website/Domain
</Field.Label>
<Input
name="domain_name"
value={formData.domain_name}
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
onChange={handleChange}
/>
<Field.Label color="black" pt={1} fontSize="12px">
GST no.
</Field.Label>
<Input
name="gst_number"
value={formData.gst_number}
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
onChange={handleChange}
/>
{/* <Field.Label color="black" pt={1} fontSize="12px">
RC Status
</Field.Label>
<Input
value={formData.rc_status}
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
onChange={handleChange}
/> */}
</Field.Root>
</Stack>
</DialogBody>
<DialogFooter display="flex" justifyContent="center" pt={"2"}>
<Button
w="100%"
bg="#02A0A0"
color={"#fff"}
fontSize="12px"
height="30px"
onClick={handleSubmit}
>
Save
</Button>
</DialogFooter>
<DialogCloseTrigger color="black" onClick={() => setIsOpen(false)} />
</DialogContent>
<Toaster />
</DialogRoot>
);
}
export default EditAgencyMaster;

View File

@@ -1,31 +1,100 @@
import { DialogBody, DialogCloseTrigger, DialogContent, DialogFooter, DialogHeader, DialogRoot, DialogTitle, DialogTrigger } from "../../../components/ui/dialog" import { DialogBody, DialogCloseTrigger, DialogContent, DialogFooter, DialogHeader, DialogRoot, DialogTitle, DialogTrigger } from "../../../components/ui/dialog"
import { Field, Input, Stack, Text, Textarea } from "@chakra-ui/react" import { Field, Input, Stack, Text } from "@chakra-ui/react"
import { IoMdAdd } from "react-icons/io" import { IoMdAdd } from "react-icons/io"
import { Button } from "../../../components/ui/button" import { Button } from "../../../components/ui/button"
import { AgencyPost, useCreateAgencyMasterPostMutation } from "../../../Redux/Service/agency.master.module.service"
import { useState } from "react"
import { Toaster, toaster } from "../../../components/ui/toaster"
function ViewAgencyAddModel({ refetch }: { refetch: VoidFunction }) {
const [formData, setFormData] = useState<AgencyPost>({
name: "",
rc_number: "",
state: "",
registered_office: "",
domain_name: "",
gst_number: "",
});
const [isOpen, setIsOpen] = useState(false);
const [createAgencyMasterPost] = useCreateAgencyMasterPostMutation()
const handleOpenModal = () => {
setIsOpen(true); // Open modal when clicking "Add"
};
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const { name, value } = e.target;
setFormData((prev: any) => ({
...prev,
[name]: value,
}));
}
const handleSubmit = async () => {
console.log("New Data:", formData);
const requiredFields: (keyof AgencyPost)[] = ["name", "rc_number", "state", "registered_office", "domain_name", "gst_number"];
const isEmptyField = requiredFields.some(field => !formData[field]?.trim());
if (isEmptyField) {
console.log("Validation failed: Some fields are empty.");
toaster.create({
title: "Error",
description: "All required fields must be filled.",
type: "error",
});
return;
}
const payload = {
name: formData.name
};
try {
const response = await createAgencyMasterPost(payload).unwrap();
if (response) {
toaster.create({
title: "Success",
description: "Added successfully",
type: "success",
});
refetch()
setIsOpen(false);
} else {
toaster.create({
title: "Error",
description: "Failed to add data.",
type: "error",
});
}
} catch (error) {
console.error("Error updating template:", error);
toaster.create({
title: "Error",
description: "Something went wrong",
type: "error",
});
}
};
function ViewAgencyAddModel() {
return ( return (
<DialogRoot placement="center"> <DialogRoot placement="center" open={isOpen} onOpenChange={({ open }) => setIsOpen(open)}>
<DialogTrigger asChild> <DialogTrigger asChild>
{/* <Button bg={"transparent"} size="sm"> <Button px={5} size={"xs"} bg={"#02A0A0"} onClick={handleOpenModal}>
<MdOutlineRemoveRedEye style={{ cursor: "pointer", fontSize: "16px" }} /> <IoMdAdd /> <Text >Add</Text>
</Button> */}
<Button px={5} size={"xs"} bg={"#02A0A0"}>
<IoMdAdd /> <Text >Add</Text>
</Button> </Button>
</DialogTrigger> </DialogTrigger>
<DialogContent <DialogContent
bg={"#fff"} bg={"#fff"}
// w={{ lg: "60%", md: "230px" }} // w={{ lg: "60%", md: "230px" }}
w={{ base: '90%', md: '400px' }} w={{ base: '90%', md: '400px' }}
height={'80vh'} height={'80vh'}
overflow={'scroll'} overflow={'scroll'}
overflowX="hidden" overflowX="hidden"
p={3} // Reduced padding p={3} // Reduced padding
bgSize={'md'} bgSize={'md'}
> >
<DialogHeader bg="white" > <DialogHeader bg="white" >
<DialogTitle alignSelf="center" color="black" fontSize="14px">Add</DialogTitle> <DialogTitle alignSelf="center" color="black" fontSize="14px">Add</DialogTitle>
@@ -36,38 +105,97 @@ function ViewAgencyAddModel() {
<Field.Root> <Field.Root>
<Field.Label color="black" pt={1} fontSize="12px">Agency Name</Field.Label> <Field.Label color="black" pt={1} fontSize="12px">Agency Name</Field.Label>
<Input placeholder="" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" /> <Input
name="name"
value={formData.name}
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
onChange={handleChange}
/>
<Field.Label color="black" pt={1} fontSize="12px">RC No.</Field.Label> <Field.Label color="black" pt={1} fontSize="12px">RC No.</Field.Label>
<Input placeholder="" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" /> <Input
name='rc_number'
value={formData.rc_number}
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
onChange={handleChange}
/>
<Field.Label color="black" pt={1} fontSize="12px">State</Field.Label> <Field.Label color="black" pt={1} fontSize="12px">State</Field.Label>
<Input placeholder="" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" /> <Input
name="state"
value={formData.state}
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
onChange={handleChange}
/>
<Field.Label color="black" pt={1} fontSize="12px">Registered Office Address</Field.Label> <Field.Label color="black" pt={1} fontSize="12px">Registered Office Address</Field.Label>
<Input placeholder="" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" /> <Input
name="registered_office"
value={formData.registered_office}
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
onChange={handleChange}
/>
<Field.Label color="black" pt={1} fontSize="12px">Website/Domain</Field.Label> <Field.Label color="black" pt={1} fontSize="12px">Website/Domain</Field.Label>
<Input placeholder="" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" /> <Input
name="domain_name"
value={formData.domain_name}
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
onChange={handleChange}
/>
<Field.Label color="black" pt={1} fontSize="12px">GST no.</Field.Label> <Field.Label color="black" pt={1} fontSize="12px">GST no.</Field.Label>
<Input placeholder="" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" /> <Input
name="gst_number"
<Field.Label color="black" pt={1} fontSize="12px">Action</Field.Label> value={formData.gst_number}
<Input placeholder="" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" /> bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
onChange={handleChange}
/>
{/* <Field.Label color="black" pt={1} fontSize="12px">Action</Field.Label>
<Input placeholder="" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" /> */}
</Field.Root> </Field.Root>
</Stack> </Stack>
</DialogBody> </DialogBody>
<DialogFooter display="flex" justifyContent="center" pt={"2"}> <DialogFooter display="flex" justifyContent="center" pt={"2"}>
<Button w="100%" bg="#02A0A0" color={"#fff"}> <Button w="100%" bg="#02A0A0" color={"#fff"} onClick={handleSubmit}>
Save Save
</Button> </Button>
</DialogFooter> </DialogFooter>
<DialogCloseTrigger color="black" /> <DialogCloseTrigger color="black" onClick={() => setIsOpen(false)} />
</DialogContent> </DialogContent>
<Toaster />
</DialogRoot > </DialogRoot >
) )

View File

@@ -1,75 +1,178 @@
import { DialogBody, DialogCloseTrigger, DialogContent, DialogFooter, DialogHeader, DialogRoot, DialogTitle, DialogTrigger } from "../../../components/ui/dialog" import {
import { Field, Input, Stack, } from "@chakra-ui/react" DialogBody,
import { MdOutlineRemoveRedEye } from "react-icons/md" DialogCloseTrigger,
import { Button } from "../../../components/ui/button" DialogContent,
// DialogFooter,
DialogHeader,
DialogRoot,
DialogTitle,
DialogTrigger,
} from "../../../components/ui/dialog";
import { Field, Input, Span, Stack } from "@chakra-ui/react";
// import { MdOutlineRemoveRedEye } from "react-icons/md";
// import { Button } from "../../../components/ui/button";
import View from "../../../components/ActionIcons/View";
import { Agency } from "../../../Redux/Service/agency.master.module.service";
function ViewAgencyMaster({ agency, id }: { agency: Agency[], id:number }) {
function ViewAgencyMaster() { return (
return ( <DialogRoot placement="center">
<DialogTrigger asChild>
<Span><View /></Span>
</DialogTrigger>
<DialogContent
bg={"#fff"}
// w={{ lg: "60%", md: "230px" }}
w={{ base: "90%", md: "400px" }}
height={"80vh"}
overflow={"scroll"}
overflowX="hidden"
p={3} // Reduced padding
bgSize={"md"}
>
<DialogHeader bg="white">
<DialogTitle alignSelf="center" color="black" fontSize="14px">
View
</DialogTitle>
</DialogHeader>
{agency.map((data) => (
<DialogBody bg="white">
{data.id === id && <Stack py={3}>
<Field.Root>
<Field.Label color="black" pt={1} fontSize="12px">
Agency name
</Field.Label>
<Input
value={data.name}
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
disabled
/>
<DialogRoot placement="center"> <Field.Label color="black" pt={1} fontSize="12px">
<DialogTrigger asChild> RC No.
<Button bg={"transparent"} size="sm"> </Field.Label>
<MdOutlineRemoveRedEye style={{ cursor: "pointer", fontSize: "14px" }} color="#000"/> <Input
</Button> value={data.rc_number}
</DialogTrigger> bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
disabled
/>
<DialogContent <Field.Label color="black" pt={1} fontSize="12px">
bg={"#fff"} State
// w={{ lg: "60%", md: "230px" }} </Field.Label>
w={{ base: '90%', md: '400px' }} <Input
value={data.state}
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
disabled
/>
height={'80vh'} <Field.Label color="black" pt={1} fontSize="12px">
overflow={'scroll'} RC Status
overflowX="hidden" </Field.Label>
p={3} // Reduced padding <Input
bgSize={'md'} value={data.rc_status}
> bgColor="#EEEEEE"
<DialogHeader bg="white"> color="black"
<DialogTitle alignSelf="center" color="black" fontSize="14px">Add</DialogTitle> border="none"
</DialogHeader> pl={1}
fontSize="12px"
height="30px"
disabled
/>
<DialogBody bg="white"> <Field.Label color="black" pt={1} fontSize="12px">
<Stack py={3}> Registered Office Address
<Field.Root> </Field.Label>
<Field.Label color="black" pt={1} fontSize="12px">Agency name</Field.Label> <Input
<Input value="Lorem Ipsum" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" /> value={data.registered_office}
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
disabled
/>
<Field.Label color="black" pt={1} fontSize="12px">RC No.</Field.Label> <Field.Label color="black" pt={1} fontSize="12px">
<Input value="Lorem Ipsum" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" /> Website/Domain
</Field.Label>
<Input
value={data.domain_name}
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
disabled
/>
<Field.Label color="black" pt={1} fontSize="12px">State</Field.Label> <Field.Label color="black" pt={1} fontSize="12px">
<Input value="Lorem Ipsum" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" /> GST no.
</Field.Label>
<Input
value={data.gst_number}
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
disabled
/>
<Field.Label color="black" pt={1} fontSize="12px">Registered Office Address</Field.Label> {/* <Field.Label color="black" pt={1} fontSize="12px">
<Input value="Active" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" /> Action
</Field.Label>
<Field.Label color="black" pt={1} fontSize="12px">Website/Domain</Field.Label> <Input
<Input value="Lorem Ipsum" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" /> value={data}
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
disabled
/> */}
</Field.Root>
</Stack>}
</DialogBody>
))}
<Field.Label color="black" pt={1} fontSize="12px">GST no.</Field.Label> {/* <DialogFooter display="flex" justifyContent="center" pt={"2"}>
<Input value="Lorem Ipsum" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" /> <Button
w="100%"
<Field.Label color="black" pt={1} fontSize="12px">Action</Field.Label> bg="#02A0A0"
<Input value="Lorem Ipsum" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" /> color={"#fff"}
fontSize="12px"
height="30px"
>
Save
</Button>
</DialogFooter> */}
<DialogCloseTrigger color="black" />
</Field.Root> </DialogContent>
</Stack> </DialogRoot>
</DialogBody> );
<DialogFooter display="flex" justifyContent="center" pt={"2"}>
<Button w="100%" bg="#02A0A0" color={"#fff"} fontSize="12px" height="30px">
Save
</Button>
</DialogFooter>
<DialogCloseTrigger color="black" />
</DialogContent>
</DialogRoot>
)
} }
export default ViewAgencyMaster export default ViewAgencyMaster;

View File

@@ -1,11 +1,12 @@
import { Box, HStack, Image, Input, Text } from "@chakra-ui/react"; import { Box, HStack, Text } from "@chakra-ui/react";
import MainFrame from "../../../components/MainFrame" import MainFrame from "../../../components/MainFrame"
import { InputGroup } from "../../../components/ui/input-group";
import { LuSearch } from "react-icons/lu";
import DataTable from "../../../components/DataTable"; import DataTable from "../../../components/DataTable";
import { Switch } from "../../../components/ui/switch"; import { Switch } from "../../../components/ui/switch";
import CountryAddModel from "./CountryAddModel"; import CountryAddModel from "./CountryAddModel";
import EditCountryModel from "./EditCountryModel"; import EditCountryModel from "./EditCountryModel";
import { CountryData, useCountryToggleMutation, useGetCountryMasterQuery } from "../../../Redux/Service/country.master";
import { useEffect, useState } from "react";
import SearchComponent from "../../../components/SearchComponent";
@@ -15,25 +16,89 @@ const tableHeadRow = [
"Sr. No", "Sr. No",
"Title", "Title",
"Action" "Action"
]; ];
const managepost: any[] = [ // const managepost: any[] = [
...Array.from({ length: 12 }, (_, i) => ({ // ...Array.from({ length: 12 }, (_, i) => ({
"Sr. No": i + 1, // "Sr. No": i + 1,
"Title": "Lorem Ipsum", // "Title": "Lorem Ipsum",
// "Action": (
// <HStack justifyContent="center">
// <EditCountryModel />
// <Box>
// <Switch colorPalette={'teal'} size={"xs"} />
// </Box>
// </HStack>
// ),
// })),
// ];
const Country = () => {
const [currentPage, setCurrentPage] = useState(1);
const { data, refetch } = useGetCountryMasterQuery(currentPage)
const [countryToggle] = useCountryToggleMutation()
const [localData, setLocalData] = useState<any[]>([]);
const [searchTerm, setSearchTerm] = useState("");
console.log("Country Data", data?.data.data)
useEffect(() => {
if (data) {
setLocalData(data?.data.data);
}
}, [data]);
const handlePageChange = (page: number) => {
setCurrentPage(page);
};
const filteredData = localData?.filter((agency) => {
const searchLower = searchTerm.toLowerCase();
const countryName = agency.en_name?.toLowerCase().includes(searchLower);
const capitalName = agency.capital?.toLowerCase().includes(searchLower);
return countryName || capitalName;
});
const handleToggle = async (agencyId: number, currentStatus: string) => {
const newStatus = currentStatus === '1' ? '0' : '1';
setLocalData((prevData) =>
prevData.map((agency) =>
agency.id === agencyId ? { ...agency, is_active: newStatus } : agency
)
);
try {
await countryToggle({ id: agencyId, is_active: newStatus }).unwrap();
refetch()
} catch (error) {
console.error("Error updating privacy policy:", error);
setLocalData((prevData) =>
prevData.map((agency) =>
agency.id === agencyId ? { ...agency, is_active: currentStatus } : agency
)
);
}
}
const managepost = filteredData?.flatMap((agency: CountryData, index: number) => ({
"Sr. No": (currentPage - 1) * (data?.data.per_page ?? 0) + index + 1,
"Title": agency.en_name,
"Action": ( "Action": (
<HStack justifyContent="center"> <HStack justifyContent="center">
<EditCountryModel /> <EditCountryModel rowData={{ id: agency.id, en_name: agency.en_name, country_code: agency.country_code, phonecode: agency.phonecode, capital: agency.capital, currency: agency.currency, currency_name: agency.currency_name, currency_symbol: agency.currency_symbol }} refetch={refetch} />
<Box> <Box>
<Switch colorPalette={'teal'} size={"xs"}/> <Switch
colorPalette={'teal'}
size={"xs"}
checked={agency.is_active === '1'}
onChange={() => handleToggle(agency.id, agency.is_active)}
/>
</Box> </Box>
</HStack> </HStack>
), ),
})), }))
];
const Country = () => {
return ( return (
<MainFrame> <MainFrame>
@@ -46,11 +111,11 @@ const Country = () => {
px={3} px={3}
> >
<Text as={"span"} fontSize={"sm"} fontWeight={500} color={"#000"}> <Text as={"span"} fontSize={"sm"} fontWeight={500} color={"#000"}>
Country Country
</Text> </Text>
<HStack mr={5}> <HStack >
<InputGroup marginRight={"1rem"} {/* <InputGroup
startElement={ startElement={
<LuSearch fontSize={"xs"} style={{ position: 'relative', left: '10px' }} /> <LuSearch fontSize={"xs"} style={{ position: 'relative', left: '10px' }} />
} }
@@ -63,13 +128,21 @@ const Country = () => {
colorPalette={"blue"} colorPalette={"blue"}
_focus={{ border: "1px solid #02A0A0" }} _focus={{ border: "1px solid #02A0A0" }}
rounded={"md"} rounded={"md"}
size={"2xs"} size={"xs"}
fontSize={"2sm"} fontSize={"sm"}
placeholder="Search..." placeholder="Search..."
bgColor={'#EEEEEE'} bgColor={'#EEEEEE'}
ps={8} ps={8}
/> />
</InputGroup> </InputGroup> */}
<SearchComponent
value={searchTerm}
onChange={(value) => {
setSearchTerm(value);
// setCurrentPage(1);
refetch()
}}
/>
{/* <Button bgColor={'#EEEEEE'} pl={3} pr={3}><IoMdAdd /> <Text>Add</Text></Button> */} {/* <Button bgColor={'#EEEEEE'} pl={3} pr={3}><IoMdAdd /> <Text>Add</Text></Button> */}
<CountryAddModel /> <CountryAddModel />
</HStack> </HStack>
@@ -78,8 +151,15 @@ const Country = () => {
sortableColumns={["Name", "Registration Date "]} sortableColumns={["Name", "Registration Date "]}
tableHeadRow={tableHeadRow} tableHeadRow={tableHeadRow}
data={managepost} data={managepost}
paginationData={{
current_page: data?.data.current_page || 1,
last_page: data?.data.last_page || 1,
per_page: data?.data.per_page || 10,
total: data?.data.total || 0
}}
onPageChange={handlePageChange}
/> />
</Box> </Box>
</MainFrame> </MainFrame>
) )
} }

View File

@@ -1,56 +1,202 @@
import { DialogBody, DialogCloseTrigger, DialogContent, DialogFooter, DialogHeader, DialogRoot, DialogTitle, DialogTrigger } from "../../../components/ui/dialog" import { DialogBody, DialogCloseTrigger, DialogContent, DialogFooter, DialogHeader, DialogRoot, DialogTitle, DialogTrigger } from "../../../components/ui/dialog"
import { Box, Field, IconButton, Input, Stack, Text, Textarea } from "@chakra-ui/react" import { Field, Input, Stack, Text } from "@chakra-ui/react"
import { IoMdAdd } from "react-icons/io" import { IoMdAdd } from "react-icons/io"
import { Button } from "../../../components/ui/button" import { Button } from "../../../components/ui/button"
import { useState } from "react";
import { PostCountry, useCreateCountryPostMutation } from "../../../Redux/Service/country.master";
import { Toaster, toaster } from "../../../components/ui/toaster";
function CountryAddModel() { function CountryAddModel() {
const [createCountryPost] = useCreateCountryPostMutation()
return ( const [isOpen, setIsOpen] = useState(false);
const [countryName, setCountryName] = useState<PostCountry>({
en_name: '',
country_code: '',
phonecode: '',
capital: '',
currency: '',
currency_name: '',
currency_symbol: '',
});
<DialogRoot placement="center"> const handleOpenModal = () => {
<DialogTrigger asChild> setIsOpen(true); // Open modal when clicking "Add"
{/* <Button bg={"transparent"} size="sm"> };
const handleSubmit = async () => {
if (countryName.en_name === "") {
toaster.create({
title: "Error",
description: "Input fields cannot be empty",
type: "error",
});
return;
}
const payload: PostCountry = {
en_name: countryName.en_name,
country_code: countryName.country_code,
phonecode: countryName.phonecode,
capital: countryName.capital,
currency: countryName.currency,
currency_name: countryName.currency_name,
currency_symbol: countryName.currency_symbol,
};
try {
const response = await createCountryPost(payload).unwrap();
if (response) {
toaster.create({
title: "Success",
description: "Country added successfully",
type: "success",
});
setIsOpen(false);
} else {
toaster.create({
title: "Error",
description: "Failed to add Country",
type: "error",
});
}
} catch (error) {
console.error("Error updating template:", error);
// alert("Failed to update template");
}
};
return (
<>
<DialogRoot placement="center" open={isOpen} onOpenChange={({ open }) => setIsOpen(open)}>
<DialogTrigger asChild>
{/* <Button bg={"transparent"} size="sm">
<MdOutlineRemoveRedEye style={{ cursor: "pointer", fontSize: "16px" }} /> <MdOutlineRemoveRedEye style={{ cursor: "pointer", fontSize: "16px" }} />
</Button> */} </Button> */}
<Button px={5} size={"xs"} bg={"#02A0A0"}> <Button px={5} size={"xs"} bg={"#02A0A0"} onClick={handleOpenModal}>
<IoMdAdd /> <Text>Add</Text> <IoMdAdd /> <Text>Add</Text>
</Button>
</DialogTrigger>
<DialogContent
bg={"#fff"}
// w={{ lg: "60%", md: "230px" }}
w={{ base: '90%', md: '400px' }}
height={'auto'}
overflowX="hidden"
p={3} // Reduced padding
bgSize={'md'}
>
<DialogHeader bg="white" >
<DialogTitle alignSelf="center" color="black" fontSize="14px">Add</DialogTitle>
</DialogHeader>
<DialogBody bg="white">
<Stack py={3}>
<Field.Root>
<Field.Label color="black" pt={1} fontSize="12px">Country</Field.Label>
<Input placeholder="" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" />
</Field.Root>
</Stack>
</DialogBody>
<DialogFooter display="flex" justifyContent="center" pt={"2"}>
<Button w="100%" bg="#02A0A0" color={"#fff"}>
Save
</Button> </Button>
</DialogFooter>
<DialogCloseTrigger color="black" /> </DialogTrigger>
</DialogContent>
</DialogRoot > <DialogContent
bg={"#fff"}
// w={{ lg: "60%", md: "230px" }}
w={{ base: '90%', md: '400px' }}
height={'auto'}
overflowX="hidden"
p={3} // Reduced padding
bgSize={'md'}
>
<DialogHeader bg="white" >
<DialogTitle alignSelf="center" color="black" fontSize="14px">Add</DialogTitle>
</DialogHeader>
<DialogBody bg="white">
<Stack py={3}>
<Field.Root>
<Field.Label color="black" pt={1} fontSize="12px">Country</Field.Label>
<Input
placeholder=""
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
value={countryName.en_name}
onChange={(e) => setCountryName({ ...countryName, en_name: e.target.value })}
/>
<Field.Label color="black" pt={1} fontSize="12px">Country Code</Field.Label>
<Input
placeholder=""
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
value={countryName.country_code}
onChange={(e) => setCountryName({ ...countryName, country_code: e.target.value })}
/>
<Field.Label color="black" pt={1} fontSize="12px">Phone Code</Field.Label>
<Input
placeholder=""
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
value={countryName.phonecode}
onChange={(e) => setCountryName({ ...countryName, phonecode: e.target.value })}
/>
<Field.Label color="black" pt={1} fontSize="12px">Capital</Field.Label>
<Input
placeholder=""
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
value={countryName.capital}
onChange={(e) => setCountryName({ ...countryName, capital: e.target.value })}
/>
<Field.Label color="black" pt={1} fontSize="12px">Currency</Field.Label>
<Input
placeholder=""
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
value={countryName.currency}
onChange={(e) => setCountryName({ ...countryName, currency: e.target.value })}
/>
<Field.Label color="black" pt={1} fontSize="12px">Currency name</Field.Label>
<Input
placeholder=""
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
value={countryName.currency_name}
onChange={(e) => setCountryName({ ...countryName, currency_name: e.target.value })}
/>
<Field.Label color="black" pt={1} fontSize="12px">Currency Symbol</Field.Label>
<Input
placeholder=""
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
value={countryName.currency_symbol}
onChange={(e) => setCountryName({ ...countryName, currency_symbol: e.target.value })}
/>
</Field.Root>
</Stack>
</DialogBody>
<DialogFooter display="flex" justifyContent="center" pt={"2"}>
<Button w="100%" bg="#02A0A0" color={"#fff"} onClick={handleSubmit}>
Save
</Button>
</DialogFooter>
<DialogCloseTrigger color="black" />
</DialogContent>
</DialogRoot >
<Toaster />
</>
) )
} }

View File

@@ -1,61 +1,161 @@
import { DialogBody, DialogCloseTrigger, DialogContent, DialogFooter, DialogHeader, DialogRoot, DialogTitle, DialogTrigger } from "../../../components/ui/dialog" import {
import { Box, Field, IconButton, Input, Stack, Text, Textarea } from "@chakra-ui/react" DialogBody,
import { Button } from "../../../components/ui/button" DialogCloseTrigger,
import { FaRegEdit } from "react-icons/fa"; DialogContent,
DialogFooter,
DialogHeader,
DialogRoot,
DialogTitle,
DialogTrigger,
} from "../../../components/ui/dialog";
import { Field, Input, Stack } from "@chakra-ui/react";
import { Button } from "../../../components/ui/button";
import Edit from "../../../components/ActionIcons/Edit";
import { useUpdateCountryMutation } from "../../../Redux/Service/country.master";
import { Toaster, toaster } from "../../../components/ui/toaster";
import { useEffect, useState } from "react";
export interface EditCountryModelProps {
function EditCountryModel() { id?: number;
en_name?: string;
hi_name?: string;
mr_name?: string;
return ( te_name?: string;
ta_name?: string;
<DialogRoot placement="center"> bn_name?: string;
<DialogTrigger asChild> or_name?: string;
{/* <Button bg={"transparent"} size="sm"> country_code?: string;
<MdOutlineRemoveRedEye style={{ cursor: "pointer", fontSize: "16px" }} /> phonecode?: string;
</Button> */} capital?: string;
<Button bg={"transparent"} size="sm"> currency?: string;
<FaRegEdit style={{ cursor: "pointer", fontSize: "14px" }} color="#000"/> currency_name?: string;
</Button> currency_symbol?: string;
</DialogTrigger>
<DialogContent
bg={"#fff"}
// w={{ lg: "60%", md: "230px" }}
w={{ base: '90%', md: '400px' }}
height={'auto'}
overflowX="hidden"
p={3} // Reduced padding
bgSize={'md'}
>
<DialogHeader bg="white" >
<DialogTitle alignSelf="center" color="black" fontSize="14px">Edit</DialogTitle>
</DialogHeader>
<DialogBody bg="white">
<Stack py={3}>
<Field.Root>
<Field.Label color="black" pt={1} fontSize="12px">Country</Field.Label>
<Input value="Lorem Ipsum" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" />
</Field.Root>
</Stack>
</DialogBody>
<DialogFooter display="flex" justifyContent="center" pt={"2"}>
<Button w="100%" bg="#02A0A0" color={"#fff"}>
Save
</Button>
</DialogFooter>
<DialogCloseTrigger color="black" />
</DialogContent>
</DialogRoot >
)
} }
export default EditCountryModel
function EditCountryModel({ rowData, refetch }: { rowData: EditCountryModelProps, refetch: VoidFunction }) {
const [updateCountry] = useUpdateCountryMutation()
const [editData, setEditData] = useState(rowData)
const [isOpen, setIsOpen] = useState(false);
useEffect(() => {
if(rowData){
setEditData(rowData)
}
}, [rowData])
const handleOpenModal = () => {
setIsOpen(true);
};
const handleSubmit = async () => {
if (editData?.en_name === '') {
toaster.create({
title: "Error",
description: "Input fields cannot be empty",
type: "error",
});
return;
}
// Only en_name is editable, so we only need to send that in the payload.
const payload = {
id: rowData?.id,
en_name: editData?.en_name,
country_code: rowData?.country_code,
phonecode: rowData?.phonecode,
capital: rowData?.capital,
currency: rowData?.currency,
currency_name: rowData?.currency_name,
currency_symbol: rowData?.currency_symbol,
};
// console.log('payload', payload)
try {
const response = await updateCountry(payload).unwrap();
if (response?.status === "success") {
toaster.create({
title: "Success",
description: "Country updated successfully",
type: "success",
});
setIsOpen(false);
refetch()
} else {
toaster.create({
title: "Error",
description: "Failed to update Country",
type: "error",
});
}
} catch (error) {
console.error("Error updating template:", error);
// alert("Failed to update template");
toaster.create({
title: "Error",
description: "Something went wrong",
type: "error",
});
}
};
return (
<>
<DialogRoot placement="center" key={editData.id} open={isOpen} onOpenChange={({ open }) => setIsOpen(open)}>
<DialogTrigger asChild>
<Button bg="transparent" color={"black"} h={"18px"} onClick={handleOpenModal}><Edit /></Button>
</DialogTrigger>
<DialogContent
bg={"#fff"}
// w={{ lg: "60%", md: "230px" }}
w={{ base: "90%", md: "400px" }}
height={"auto"}
overflowX="hidden"
p={3} // Reduced padding
bgSize={"md"}
>
<DialogHeader bg="white">
<DialogTitle alignSelf="center" color="black" fontSize="14px">
Edit
</DialogTitle>
</DialogHeader>
<DialogBody bg="white">
<Stack py={3}>
<Field.Root>
<Field.Label color="black" pt={1} fontSize="12px">
Country
</Field.Label>
<Input
value={editData.en_name}
onChange={(e) => setEditData({ ...editData, en_name: e.target.value })}
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
/>
</Field.Root>
</Stack>
</DialogBody>
<DialogFooter display="flex" justifyContent="center" pt={"2"}>
<Button w="100%" bg="#02A0A0" color={"#fff"} onClick={handleSubmit}>
Save
</Button>
</DialogFooter>
<DialogCloseTrigger color="black" />
</DialogContent>
</DialogRoot>
<Toaster />
</>
);
}
export default EditCountryModel;

View File

@@ -0,0 +1,155 @@
import { DialogBody, DialogCloseTrigger, DialogContent, DialogFooter, DialogHeader, DialogRoot, DialogTitle, DialogTrigger } from "../../../components/ui/dialog"
import { Field, Input, Stack, Text } from "@chakra-ui/react"
import { IoMdAdd } from "react-icons/io"
import { Button } from "../../../components/ui/button"
import { useState } from "react";
import { toaster } from "../../../components/ui/toaster";
import { useCreateDepartmentPostMutation, useGetDepartmentMasterDropDownQuery } from "../../../Redux/Service/department.master";
function AddDepartmentMaster({ refetch }: { refetch: VoidFunction }) {
const [jobType, setJobType] = useState("");
const [isOpen, setIsOpen] = useState(false);
const [createDepartmentPost] = useCreateDepartmentPostMutation()
const { data } = useGetDepartmentMasterDropDownQuery()
const [selectdDep, setSelectdDep] = useState<any>({
id: '',
en_name: '',
});
const handleOpenModal = () => {
setIsOpen(true); // Open modal when clicking "Add"
};
const handleSubmit = async () => {
if (!jobType.trim() || !selectdDep.id) {
toaster.create({
title: "Error",
description: "Title and Subtitle cannot be empty.",
type: "error",
});
return;
}
const payload = {
en_name: jobType,
industry_masters_xid: selectdDep.id,
};
try {
await createDepartmentPost(payload);
refetch()
setIsOpen(false);
setJobType("");
setSelectdDep({
id: '',
en_name: '',
})
} catch (error) {
console.error("Error updating template:", error);
alert("Failed to update template");
}
};
console.log("Selected Department", selectdDep);
return (
<DialogRoot placement="center" open={isOpen}>
<DialogTrigger asChild>
{/* <Button bg={"transparent"} size="sm">
<MdOutlineRemoveRedEye style={{ cursor: "pointer", fontSize: "16px" }} />
</Button> */}
<Button px={5} size={"xs"} bg={"#02A0A0"} onClick={handleOpenModal}>
<IoMdAdd /> <Text>Add</Text>
</Button>
</DialogTrigger>
<DialogContent
bg={"#fff"}
// w={{ lg: "60%", md: "230px" }}
w={{ base: '90%', md: '400px' }}
height={'auto'}
overflowX="hidden"
p={3} // Reduced padding
bgSize={'md'}
>
<DialogHeader bg="white" >
<DialogTitle alignSelf="center" color="black" fontSize="14px">Add</DialogTitle>
</DialogHeader>
<DialogBody bg="white">
<Stack py={3}>
<Field.Root>
<Field.Label color="black" pt={1} fontSize="12px">
Select Industry
</Field.Label>
<select
value={selectdDep.id}
onChange={(e) => {
const selectedId = e.target.value;
const selectedIndustry = data?.data.find((item: any) => item.id.toString() === selectedId);
if (selectedIndustry) {
setSelectdDep({
id: selectedIndustry.id,
en_name: selectedIndustry.en_name,
});
}
}}
style={{
backgroundColor: "#EEEEEE",
color: "black",
border: "none",
height: "30px",
fontSize: "12px",
padding: "4px",
borderRadius: "4px",
width: "100%",
}}
>
<option value="" disabled>
Select department
</option>
{data?.data.map((item: any) => (
<option value={item.id} key={item.id}>
{item.en_name}
</option>
))}
</select>
</Field.Root>
<Field.Root>
<Field.Label color="black" pt={1} fontSize="12px">Department</Field.Label>
<Input
placeholder=""
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
value={jobType}
onChange={(e) => setJobType(e.target.value)}
/>
</Field.Root>
</Stack>
</DialogBody>
<DialogFooter display="flex" justifyContent="center" pt={"2"}>
<Button w="100%" bg="#02A0A0" color={"#fff"} onClick={handleSubmit}>
Save
</Button>
</DialogFooter>
<DialogCloseTrigger color="black" onClick={() => setIsOpen(false)} />
</DialogContent>
</DialogRoot >
)
}
export default AddDepartmentMaster

View File

@@ -0,0 +1,142 @@
import { Box, HStack, Text } from "@chakra-ui/react";
import MainFrame from "../../../components/MainFrame"
// import { InputGroup } from "../../../components/ui/input-group";
// import { LuSearch } from "react-icons/lu";
import DataTable from "../../../components/DataTable";
import { Switch } from "../../../components/ui/switch";
import { useEffect, useState } from "react";
import SearchComponent from "../../../components/SearchComponent";
import { useDepartmentToggleMutation, useGetDepartmentMasterQuery } from "../../../Redux/Service/department.master";
import AddDepartmentMaster from "./AddDepartmentMaster";
import EditDepartmentMaster from "./EditDepartmentMaster";
// table data
const tableHeadRow = [
"Sr. No",
"Title",
"Action"
];
const DepartmentMasterList = () => {
const [currentPage, setCurrentPage] = useState(1);
const { data, refetch } = useGetDepartmentMasterQuery(currentPage)
const [departmentToggle] = useDepartmentToggleMutation()
const [localData, setLocalData] = useState<any[]>([]);
const [searchTerm, setSearchTerm] = useState("");
console.log("Department Data", data?.data.data)
useEffect(() => {
if (data?.data?.data) {
setLocalData(data?.data.data);
}
}, [data]);
const handlePageChange = (page: number) => {
setCurrentPage(page);
};
const handleToggle = async (agencyId: string, currentStatus: number) => {
const newStatus = currentStatus ? 0 : 1;
setLocalData((prevData) =>
prevData.map((agency) =>
agency.id === agencyId ? { ...agency, is_active: newStatus } : agency
)
);
try {
await departmentToggle({ id: agencyId, is_active: newStatus }).unwrap();
refetch()
} catch (error) {
console.error("Error updating privacy policy:", error);
setLocalData((prevData) =>
prevData.map((agency) =>
agency.id === agencyId ? { ...agency, is_active: currentStatus } : agency
)
);
}
};
const filteredData = localData?.filter((agency) => {
const searchLower = searchTerm.toLowerCase();
const title = agency.en_name?.toLowerCase().includes(searchLower);
return title;
});
const managepost = filteredData?.map((agency: any, index: number) => ({
'id': agency.id,
"Sr. No": (currentPage - 1) * (data?.data.per_page ?? 0) + index + 1,
"Title": agency.en_name,
"is_active": agency.is_active,
"Action": (
<HStack justifyContent="center">
{/* <ViewAgencyMaster agency={localData} id={agency.id} /> */}
<EditDepartmentMaster localData={agency} refetch={refetch} />
<Box>
<Switch
colorPalette={"teal"}
size={"xs"}
onChange={() => handleToggle(agency.id, Number(agency.is_active))}
checked={Boolean(Number(agency.is_active))}
/>
</Box>
</HStack>
),
}));
// useEffect(() => {
// console.log("Fetched data:", data);
// console.log("Local data:", localData);
// console.log("Managepost data:", managepost);
// }, [data, localData, managepost]);
return (
<MainFrame>
<Box>
<HStack
w={"100%"}
justifyContent={"space-between"}
mb={4}
py={0}
px={3}
>
<Text as={"span"} fontSize={"sm"} fontWeight={500} color={"#000"}>
Department Master
</Text>
<HStack >
<SearchComponent
value={searchTerm}
onChange={(value) => {
setSearchTerm(value);
// setCurrentPage(1);
refetch()
}}
/>
{/* <Button bgColor={'#EEEEEE'} pl={3} pr={3}><IoMdAdd /> <Text>Add</Text></Button> */}
{/* <ViewAgencyAddModel /> */}
<AddDepartmentMaster refetch={refetch} />
</HStack>
</HStack>
<DataTable
sortableColumns={["Name"]}
tableHeadRow={tableHeadRow}
data={managepost || []}
paginationData={{
current_page: data?.data.current_page || 1,
last_page: data?.data.last_page || 1,
per_page: data?.data.per_page || 10,
total: data?.data.total || 0
}}
onPageChange={handlePageChange}
/>
</Box>
</MainFrame>
)
}
export default DepartmentMasterList

View File

@@ -0,0 +1,160 @@
import {
DialogBody,
DialogCloseTrigger,
DialogContent,
DialogFooter,
DialogHeader,
DialogRoot,
DialogTitle,
DialogTrigger,
} from "../../../components/ui/dialog";
import { Box, Field, Input, Stack } from "@chakra-ui/react";
import { Button } from "../../../components/ui/button";
import Edit from "../../../components/ActionIcons/Edit";
import { useState } from "react";
import { Toaster, toaster } from "../../../components/ui/toaster";
import { useGetDepartmentMasterDropDownQuery, useUpdateDepartmentMutation } from "../../../Redux/Service/department.master";
function EditDepartmentMaster({ localData, refetch }: { localData: any, refetch: VoidFunction }) {
const [jobtype, setJobType] = useState("");
const [updateDepartment] = useUpdateDepartmentMutation()
const { data } = useGetDepartmentMasterDropDownQuery()
const [isOpen, setIsOpen] = useState(false);
const [selectdDep, setSelectdDep] = useState<any>({
id: localData.industry_master.id,
en_name: localData.industry_master.en_name,
});
const handleOpenModal = () => {
// const template = localData?.find((item: any) => item.id === id);
if (localData) {
setJobType(localData.en_name);
setSelectdDep({
id: localData.industry_master.id,
en_name: localData.industry_master.en_name,
})
setIsOpen(true);
}
};
const handleSubmit = async () => {
if (!jobtype.trim()) {
toaster.create({
title: "Error",
description: "Title and Subtitle cannot be empty.",
type: "error",
});
return;
}
const payload = {
id: localData.id,
industry_masters_xid: selectdDep.id != null ? selectdDep.id : localData.industry_master.id,
en_name: jobtype
};
try {
await updateDepartment(payload).unwrap();
refetch()
setIsOpen(false);
} catch (error) {
console.error("Error updating template:", error);
alert("Failed to update template");
}
};
console.log("Dropdown Data", selectdDep);
console.log("Dep Data", localData)
return (
<DialogRoot placement="center" open={isOpen} onOpenChange={({ open }) => setIsOpen(open)}>
<DialogTrigger asChild>
<Box bg={"transparent"} onClick={handleOpenModal}>
<Edit />
</Box>
</DialogTrigger>
<DialogContent
bg={"#fff"}
// w={{ lg: "60%", md: "230px" }}
w={{ base: "90%", md: "400px" }}
height={"auto"}
overflowX="hidden"
p={3} // Reduced padding
bgSize={"md"}
>
<DialogHeader bg="white">
<DialogTitle alignSelf="center" color="black" fontSize="14px">
Edit Title
</DialogTitle>
</DialogHeader>
<DialogBody bg="white">
<Stack py={3}>
<Field.Root>
<Field.Label color="black" pt={1} fontSize="12px">
Select Industry
</Field.Label>
<select
value={selectdDep.id}
onChange={(e) => {
const selected = data?.data.find((item: any) => item.id === Number(e.target.value));
if (selected) {
setSelectdDep({ id: selected.id, en_name: selected.en_name });
}
}}
style={{
backgroundColor: "#EEEEEE",
color: "black",
border: "none",
height: "30px",
fontSize: "12px",
padding: "4px",
borderRadius: "4px",
width: "100%",
}}
>
<option value="" disabled>
Select department
</option>
{data?.data.map((item: any) => (
<option value={item.id} key={item.id}>
{item.en_name}
</option>
))}
</select>
</Field.Root>
<Field.Root>
<Field.Label color="black" pt={1} fontSize="12px">
Department
</Field.Label>
<Input
value={jobtype}
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
onChange={(e) => setJobType(e.target.value)}
/>
</Field.Root>
</Stack>
</DialogBody>
<DialogFooter display="flex" justifyContent="center" pt={"2"}>
<Button w="100%" bg="#02A0A0" color={"#fff"} onClick={handleSubmit}>
Save
</Button>
</DialogFooter>
<DialogCloseTrigger color="black" onClick={() => setIsOpen(false)} />
</DialogContent>
<Toaster />
</DialogRoot>
);
}
export default EditDepartmentMaster;

View File

@@ -0,0 +1,103 @@
import { DialogBody, DialogCloseTrigger, DialogContent, DialogFooter, DialogHeader, DialogRoot, DialogTitle, DialogTrigger } from "../../../components/ui/dialog"
import { Field, Input, Stack, Text } from "@chakra-ui/react"
import { IoMdAdd } from "react-icons/io"
import { Button } from "../../../components/ui/button"
import { useState } from "react";
import { toaster } from "../../../components/ui/toaster";
import { useCreateIndustryMasterPostMutation } from "../../../Redux/Service/industry.master.service";
function AddIndustryMaster({ refetch }: { refetch: VoidFunction }) {
const [jobType, setJobType] = useState("");
const [isOpen, setIsOpen] = useState(false);
const [createIndustryMasterPost] = useCreateIndustryMasterPostMutation()
const handleOpenModal = () => {
setIsOpen(true); // Open modal when clicking "Add"
};
const handleSubmit = async () => {
if (!jobType.trim()) {
toaster.create({
title: "Error",
description: "Title and Subtitle cannot be empty.",
type: "error",
});
return;
}
const payload = {
en_name: jobType,
categories_masters_xid:4
};
try {
await createIndustryMasterPost(payload);
refetch()
setIsOpen(false);
} catch (error) {
console.error("Error updating template:", error);
alert("Failed to update template");
}
};
return (
<DialogRoot placement="center" open={isOpen}>
<DialogTrigger asChild>
{/* <Button bg={"transparent"} size="sm">
<MdOutlineRemoveRedEye style={{ cursor: "pointer", fontSize: "16px" }} />
</Button> */}
<Button px={5} size={"xs"} bg={"#02A0A0"} onClick={handleOpenModal}>
<IoMdAdd /> <Text>Add</Text>
</Button>
</DialogTrigger>
<DialogContent
bg={"#fff"}
// w={{ lg: "60%", md: "230px" }}
w={{ base: '90%', md: '400px' }}
height={'auto'}
overflowX="hidden"
p={3} // Reduced padding
bgSize={'md'}
>
<DialogHeader bg="white" >
<DialogTitle alignSelf="center" color="black" fontSize="14px">Add</DialogTitle>
</DialogHeader>
<DialogBody bg="white">
<Stack py={3}>
<Field.Root>
<Field.Label color="black" pt={1} fontSize="12px">Job Type</Field.Label>
<Input
placeholder=""
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
value={jobType}
onChange={(e) => setJobType(e.target.value)}
/>
</Field.Root>
</Stack>
</DialogBody>
<DialogFooter display="flex" justifyContent="center" pt={"2"}>
<Button w="100%" bg="#02A0A0" color={"#fff"} onClick={handleSubmit}>
Save
</Button>
</DialogFooter>
<DialogCloseTrigger color="black" onClick={() => setIsOpen(false)} />
</DialogContent>
</DialogRoot >
)
}
export default AddIndustryMaster

View File

@@ -0,0 +1,112 @@
import {
DialogBody,
DialogCloseTrigger,
DialogContent,
DialogFooter,
DialogHeader,
DialogRoot,
DialogTitle,
DialogTrigger,
} from "../../../components/ui/dialog";
import { Box, Field, Input, Stack } from "@chakra-ui/react";
import { Button } from "../../../components/ui/button";
import Edit from "../../../components/ActionIcons/Edit";
import { useState } from "react";
import { toaster } from "../../../components/ui/toaster";
import { useUpdateIndustryMasterMutation } from "../../../Redux/Service/industry.master.service";
function EditIndustryMaster({ id, localData, refetch, categories }: { id: number, localData: any, refetch: VoidFunction, categories: any }) {
const [jobtype, setJobType] = useState("");
const [updateIndustryMaster] = useUpdateIndustryMasterMutation()
const [isOpen, setIsOpen] = useState(false);
const handleOpenModal = () => {
const template = localData?.find((item: any) => item.id === id);
if (template) {
setJobType(template.en_name);
setIsOpen(true);
}
};
const handleSubmit = async () => {
if (!jobtype.trim()) {
toaster.create({
title: "Error",
description: "Title and Subtitle cannot be empty.",
type: "error",
});
return;
}
const payload = {
id: id,
en_name: jobtype,
categories_masters_xid: categories
};
try {
await updateIndustryMaster(payload);
refetch()
setIsOpen(false);
} catch (error) {
console.error("Error updating template:", error);
alert("Failed to update template");
}
};
return (
<DialogRoot placement="center" open={isOpen} onOpenChange={({ open }) => setIsOpen(open)}>
<DialogTrigger asChild>
<Box bg={"transparent"} onClick={handleOpenModal}>
<Edit />
</Box>
</DialogTrigger>
<DialogContent
bg={"#fff"}
// w={{ lg: "60%", md: "230px" }}
w={{ base: "90%", md: "400px" }}
height={"auto"}
overflowX="hidden"
p={3} // Reduced padding
bgSize={"md"}
>
<DialogHeader bg="white">
<DialogTitle alignSelf="center" color="black" fontSize="14px">
Edit
</DialogTitle>
</DialogHeader>
<DialogBody bg="white">
<Stack py={3}>
<Field.Root>
<Field.Label color="black" pt={1} fontSize="12px">
Job Type
</Field.Label>
<Input
value={jobtype}
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
onChange={(e) => setJobType(e.target.value)}
/>
</Field.Root>
</Stack>
</DialogBody>
<DialogFooter display="flex" justifyContent="center" pt={"2"}>
<Button w="100%" bg="#02A0A0" color={"#fff"} onClick={handleSubmit}>
Save
</Button>
</DialogFooter>
<DialogCloseTrigger color="black" onClick={() => setIsOpen(false)} />
</DialogContent>
</DialogRoot>
);
}
export default EditIndustryMaster;

View File

@@ -0,0 +1,160 @@
import { Box, HStack, Text } from "@chakra-ui/react";
import MainFrame from "../../../components/MainFrame"
// import { InputGroup } from "../../../components/ui/input-group";
// import { LuSearch } from "react-icons/lu";
import DataTable from "../../../components/DataTable";
import { Switch } from "../../../components/ui/switch";
import { useEffect, useState } from "react";
import { useGetIndustryMasterQuery, useIndustryMasterToggleMutation } from "../../../Redux/Service/industry.master.service";
import EditIndustryMaster from "./EditIndustryMaster";
import AddIndustryMaster from "./AddIndustryMaster";
import SearchComponent from "../../../components/SearchComponent";
// table data
const tableHeadRow = [
"Sr. No",
"Title",
"Action"
];
// const managepost: any[] = [
// ...Array.from({ length: 12 }, (_, i) => ({
// "Sr. No": i + 1,
// "Agency Name": "Lorem Ipsum",
// "RC no.": "Lorem Ipsum",
// "State": "Lorem Ipsum",
// "RC Status": "Active",
// "Registered Office Address": "Lorem Ipsum",
// "Website/Domain": "Lorem Ipsum",
// "GST no.": "Lorem Ipsum",
// "Action": (
// <HStack justifyContent="center">
// <ViewAgencyMaster/>
// <EditAgencyMaster />
// <Box>
// <Switch colorPalette={'teal'} size={"xs"}/>
// </Box>
// </HStack>
// ),
// })),
// ];
const IndustryMasterList = () => {
const [currentPage, setCurrentPage] = useState(1);
const { data, refetch } = useGetIndustryMasterQuery(currentPage)
const [industryMasterToggle] = useIndustryMasterToggleMutation()
const [localData, setLocalData] = useState<any[]>([]);
const [searchTerm, setSearchTerm] = useState("");
useEffect(() => {
if (data?.data?.data) {
setLocalData(data?.data.data);
}
}, [data]);
const handlePageChange = (page: number) => {
setCurrentPage(page);
};
const handleToggle = async (agencyId: string, currentStatus: number) => {
const newStatus = currentStatus ? 0 : 1;
setLocalData((prevData) =>
prevData.map((agency) =>
agency.id === agencyId ? { ...agency, is_active: newStatus } : agency
)
);
try {
await industryMasterToggle({ id: agencyId, is_active: newStatus }).unwrap();
refetch()
} catch (error) {
console.error("Error updating privacy policy:", error);
setLocalData((prevData) =>
prevData.map((agency) =>
agency.id === agencyId ? { ...agency, is_active: currentStatus } : agency
)
);
}
};
const filteredData = localData?.filter((agency) => {
const searchLower = searchTerm.toLowerCase();
const title = agency.en_name?.toLowerCase().includes(searchLower);
return title;
});
const managepost = filteredData?.map((agency: any, index: number) => ({
'id': agency.id,
"Sr. No": (currentPage - 1) * (data?.data.per_page ?? 0) + index + 1,
"Title": agency.en_name,
"is_active": agency.is_active,
"Action": (
<HStack justifyContent="center">
{/* <ViewAgencyMaster agency={localData} id={agency.id} /> */}
<EditIndustryMaster id={agency.id} localData={localData} refetch={refetch} categories={agency.categories_masters_xid} />
<Box>
<Switch
colorPalette={"teal"}
size={"xs"}
onChange={() => handleToggle(agency.id, Number(agency.is_active))}
checked={Boolean(Number(agency.is_active))}
/>
</Box>
</HStack>
),
}));
// useEffect(() => {
// console.log("Fetched data:", data);
// console.log("Local data:", localData);
// console.log("Managepost data:", managepost);
// }, [data, localData, managepost]);
return (
<MainFrame>
<Box>
<HStack
w={"100%"}
justifyContent={"space-between"}
mb={4}
py={0}
px={3}
>
<Text as={"span"} fontSize={"sm"} fontWeight={500} color={"#000"}>
Industry Master
</Text>
<HStack >
<SearchComponent
value={searchTerm}
onChange={(value) => {
setSearchTerm(value);
// setCurrentPage(1);
refetch()
}}
/>
{/* <Button bgColor={'#EEEEEE'} pl={3} pr={3}><IoMdAdd /> <Text>Add</Text></Button> */}
{/* <ViewAgencyAddModel /> */}
<AddIndustryMaster refetch={refetch} />
</HStack>
</HStack>
<DataTable
sortableColumns={["Name"]}
tableHeadRow={tableHeadRow}
data={managepost || []}
paginationData={{
current_page: data?.data.current_page || 1,
last_page: data?.data.last_page || 1,
per_page: data?.data.per_page || 10,
total: data?.data.total || 0
}}
onPageChange={handlePageChange}
/>
</Box>
</MainFrame>
)
}
export default IndustryMasterList

View File

@@ -1,35 +1,69 @@
import { DialogBody, DialogCloseTrigger, DialogContent, DialogFooter, DialogHeader, DialogRoot, DialogTitle, DialogTrigger } from "../../../components/ui/dialog" import { DialogBody, DialogCloseTrigger, DialogContent, DialogFooter, DialogHeader, DialogRoot, DialogTitle, DialogTrigger } from "../../../components/ui/dialog"
import { Box, Field, IconButton, Input, Stack, Text, Textarea } from "@chakra-ui/react" import { Box, Field, Input, Stack } from "@chakra-ui/react"
import { Button } from "../../../components/ui/button" import { Button } from "../../../components/ui/button"
import { FaRegEdit } from "react-icons/fa"; // import { FaRegEdit } from "react-icons/fa";
import Edit from "../../../components/ActionIcons/Edit";
import { useState } from "react";
import { useUpdateJobStatusMutation } from "../../../Redux/Service/job.status";
import { Toaster, toaster } from "../../../components/ui/toaster";
function EditJobStatusModel() { function EditJobStatusModel({ localData, refetch }: { localData: any, refetch: VoidFunction }) {
const [updateJobStatus] = useUpdateJobStatusMutation()
const [title, setTitle] = useState(localData.translation.title);
const [isOpen, setIsOpen] = useState(false);
console.log(localData);
const handleOpenModal = () => {
if (localData) {
setIsOpen(true);
}
};
const handleSubmit = async () => {
if (!title.trim()) {
toaster.create({
title: "Error",
description: "Title field cannot be empty.",
type: "error",
});
return;
}
const payload = {
id: localData?.id,
title: title
};
try {
await updateJobStatus(payload).unwrap();
refetch()
setIsOpen(false);
} catch (error) {
console.error("Error updating template:", error);
alert("Failed to update template");
}
};
return ( return (
<DialogRoot placement="center"> <DialogRoot placement="center" open={isOpen} onOpenChange={({ open }) => setIsOpen(open)}>
<DialogTrigger asChild> <DialogTrigger asChild>
{/* <Button bg={"transparent"} size="sm"> <Box bg={"transparent"} onClick={handleOpenModal}>
<MdOutlineRemoveRedEye style={{ cursor: "pointer", fontSize: "16px" }} /> <Edit />
</Button> */} </Box>
<Button bg={"transparent"} size="sm">
<FaRegEdit style={{ cursor: "pointer", fontSize: "14px" }} color="#000"/>
</Button>
</DialogTrigger> </DialogTrigger>
<DialogContent <DialogContent
bg={"#fff"} bg={"#fff"}
// w={{ lg: "60%", md: "230px" }} // w={{ lg: "60%", md: "230px" }}
w={{ base: '90%', md: '400px' }} w={{ base: '90%', md: '400px' }}
height={'auto'} height={'auto'}
overflowX="hidden" overflowX="hidden"
p={3} // Reduced padding p={3} // Reduced padding
bgSize={'md'} bgSize={'md'}
> >
<DialogHeader bg="white" > <DialogHeader bg="white" >
<DialogTitle alignSelf="center" color="black" fontSize="14px">Edit</DialogTitle> <DialogTitle alignSelf="center" color="black" fontSize="14px">Edit</DialogTitle>
@@ -40,21 +74,30 @@ function EditJobStatusModel() {
<Field.Root> <Field.Root>
<Field.Label color="black" pt={1} fontSize="12px">Job Status</Field.Label> <Field.Label color="black" pt={1} fontSize="12px">Job Status</Field.Label>
<Input value="Lorem Ipsum" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" /> <Input
value={title}
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
onChange={(e) => setTitle(e.target.value)}
/>
</Field.Root> </Field.Root>
</Stack> </Stack>
</DialogBody> </DialogBody>
<DialogFooter display="flex" justifyContent="center" pt={"2"}> <DialogFooter display="flex" justifyContent="center" pt={"2"}>
<Button w="100%" bg="#02A0A0" color={"#fff"}> <Button w="100%" bg="#02A0A0" color={"#fff"} onClick={handleSubmit}>
Save Save
</Button> </Button>
</DialogFooter> </DialogFooter>
<DialogCloseTrigger color="black" /> <DialogCloseTrigger color="black" />
</DialogContent> </DialogContent>
<Toaster />
</DialogRoot > </DialogRoot >
) )
} }

View File

@@ -1,11 +1,13 @@
import { Box, HStack, Image, Input, Text } from "@chakra-ui/react"; import { Box, HStack, Text } from "@chakra-ui/react";
import MainFrame from "../../../components/MainFrame" import MainFrame from "../../../components/MainFrame"
import { InputGroup } from "../../../components/ui/input-group";
import { LuSearch } from "react-icons/lu";
import DataTable from "../../../components/DataTable"; import DataTable from "../../../components/DataTable";
import { Switch } from "../../../components/ui/switch"; import { Switch } from "../../../components/ui/switch";
import JobStatusAddModel from "./JobStatusAddModel"; import JobStatusAddModel from "./JobStatusAddModel";
import EditJobStatusModel from "./EditJobStatusModel"; import EditJobStatusModel from "./EditJobStatusModel";
import { useGetJobStatusQuery, useJobStatusToggleMutation } from "../../../Redux/Service/job.status";
import { useEffect, useState } from "react";
import SearchComponent from "../../../components/SearchComponent";
import { toaster } from "../../../components/ui/toaster";
@@ -15,25 +17,96 @@ const tableHeadRow = [
"Sr. No", "Sr. No",
"Title", "Title",
"Action" "Action"
]; ];
const managepost: any[] = [ // const managepost: any[] = [
...Array.from({ length: 12 }, (_, i) => ({ // ...Array.from({ length: 12 }, (_, i) => ({
"Sr. No": i + 1, // "Sr. No": i + 1,
"Title": "Lorem Ipsum", // "Title": "Lorem Ipsum",
// "Action": (
// <HStack justifyContent="center">
// <EditJobStatusModel />
// <Box>
// <Switch colorPalette={'teal'} size={"xs"} />
// </Box>
// </HStack>
// ),
// })),
// ];
const JobStatus = () => {
const [currentPage, setCurrentPage] = useState(1);
const { data, refetch } = useGetJobStatusQuery(currentPage)
const [localData, setLocalData] = useState<any[]>([]);
const [searchTerm, setSearchTerm] = useState("");
const [jobStatusToggle] = useJobStatusToggleMutation()
console.log(data?.data.data)
useEffect(() => {
if (data?.data?.data) {
setLocalData(data?.data.data);
}
}, [data]);
const handlePageChange = (page: number) => {
setCurrentPage(page);
};
const handleToggle = async (agencyId: string, currentStatus: number) => {
const newStatus = currentStatus ? 0 : 1;
setLocalData((prevData) =>
prevData.map((agency) =>
agency.id === agencyId ? { ...agency, is_active: newStatus } : agency
)
);
try {
await jobStatusToggle({ id: agencyId, is_active: newStatus }).unwrap();
refetch()
} catch (error) {
console.error("Error updating:", error);
toaster.create({
title: "Error",
description: "Someting went wrong.",
type: "error",
});
setLocalData((prevData) =>
prevData.map((agency) =>
agency.id === agencyId ? { ...agency, is_active: currentStatus } : agency
)
);
}
};
const filteredData = localData?.filter((agency) => {
return (agency.job_status_translation.map((item: any) => {
const searchLower = searchTerm.toLowerCase();
const title = item.title?.toLowerCase().includes(searchLower);
return title;
}))
});
const managepost = filteredData?.flatMap((agency: any, index: number) => (agency.job_status_translation.map((translation: any) => ({
'id': agency.id,
"Sr. No": (currentPage - 1) * (data?.data.per_page ?? 0) + index + 1,
"Title": translation.title,
"is_active": agency.is_active,
"Action": ( "Action": (
<HStack justifyContent="center"> <HStack justifyContent="center">
<EditJobStatusModel /> {/* <ViewAgencyMaster agency={localData} id={agency.id} /> */}
<EditJobStatusModel localData={{ ...agency, translation }} refetch={refetch} />
<Box> <Box>
<Switch colorPalette={'teal'} size={"xs"}/> <Switch
colorPalette={"teal"}
size={"xs"}
onChange={() => handleToggle(agency.id, Number(agency.is_active))}
checked={Boolean(Number(agency.is_active))}
/>
</Box> </Box>
</HStack> </HStack>
), ),
})), }))));
];
const JobStatus = () => {
return ( return (
<MainFrame> <MainFrame>
@@ -46,40 +119,35 @@ const JobStatus = () => {
px={3} px={3}
> >
<Text as={"span"} fontSize={"sm"} fontWeight={500} color={"#000"}> <Text as={"span"} fontSize={"sm"} fontWeight={500} color={"#000"}>
Job Status Job Status
</Text> </Text>
<HStack mr={5}> <HStack >
<InputGroup marginRight={"1rem"} <SearchComponent
startElement={ value={searchTerm}
<LuSearch fontSize={"xs"} style={{ position: 'relative', left: '10px' }} /> onChange={(value) => {
} setSearchTerm(value);
color={"#000"} // setCurrentPage(1);
> refetch()
<Input }}
p={3} />
w={300}
bg={"#fff"}
colorPalette={"blue"}
_focus={{ border: "1px solid #02A0A0" }}
rounded={"md"}
size={"2xs"}
fontSize={"2sm"}
placeholder="Search..."
bgColor={'#EEEEEE'}
ps={8}
/>
</InputGroup>
{/* <Button bgColor={'#EEEEEE'} pl={3} pr={3}><IoMdAdd /> <Text>Add</Text></Button> */} {/* <Button bgColor={'#EEEEEE'} pl={3} pr={3}><IoMdAdd /> <Text>Add</Text></Button> */}
<JobStatusAddModel /> <JobStatusAddModel refetch={refetch} />
</HStack> </HStack>
</HStack> </HStack>
<DataTable <DataTable
sortableColumns={["Name", "Registration Date "]} sortableColumns={["Name", "Registration Date "]}
tableHeadRow={tableHeadRow} tableHeadRow={tableHeadRow}
data={managepost} data={managepost}
paginationData={{
current_page: data?.data.current_page || 1,
last_page: data?.data.last_page || 1,
per_page: data?.data.per_page || 10,
total: data?.data.total || 0
}}
onPageChange={handlePageChange}
/> />
</Box> </Box>
</MainFrame> </MainFrame>
) )
} }

View File

@@ -1,32 +1,67 @@
import { DialogBody, DialogCloseTrigger, DialogContent, DialogFooter, DialogHeader, DialogRoot, DialogTitle, DialogTrigger } from "../../../components/ui/dialog" import { DialogBody, DialogCloseTrigger, DialogContent, DialogFooter, DialogHeader, DialogRoot, DialogTitle, DialogTrigger } from "../../../components/ui/dialog"
import { Box, Field, IconButton, Input, Stack, Text, Textarea } from "@chakra-ui/react" import { Field, Input, Stack, Text } from "@chakra-ui/react"
import { IoMdAdd } from "react-icons/io" import { IoMdAdd } from "react-icons/io"
import { Button } from "../../../components/ui/button" import { Button } from "../../../components/ui/button"
import { useCreateJobStatusPostMutation } from "../../../Redux/Service/job.status"
import { toaster } from "../../../components/ui/toaster"
import { useState } from "react"
function JobStatusAddModel({ refetch }: { refetch: VoidFunction }) {
const [title, setTitle] = useState('')
const [isOpen, setIsOpen] = useState(false);
const [createJobStatusPost] = useCreateJobStatusPostMutation()
const handleOpenModal = () => {
setIsOpen(true);
};
const handleSubmit = async () => {
if (!title.trim()) {
toaster.create({
title: "Error",
description: "Title field cannot be empty.",
type: "error",
});
return;
}
const payload = {
title: title,
};
try {
await createJobStatusPost(payload).unwrap();
refetch()
setIsOpen(false);
setTitle('')
} catch (error) {
console.error("Error updating template:", error);
alert("Failed to update template");
}
};
function JobStatusAddModel() {
return ( return (
<DialogRoot placement="center"> <DialogRoot placement="center" open={isOpen}>
<DialogTrigger asChild> <DialogTrigger asChild>
{/* <Button bg={"transparent"} size="sm"> {/* <Button bg={"transparent"} size="sm">
<MdOutlineRemoveRedEye style={{ cursor: "pointer", fontSize: "16px" }} /> <MdOutlineRemoveRedEye style={{ cursor: "pointer", fontSize: "16px" }} />
</Button> */} </Button> */}
<Button px={5} size={"xs"} bg={"#02A0A0"}> <Button px={5} size={"xs"} bg={"#02A0A0"} onClick={handleOpenModal}>
<IoMdAdd /> <Text>Add</Text> <IoMdAdd /> <Text>Add</Text>
</Button> </Button>
</DialogTrigger> </DialogTrigger>
<DialogContent <DialogContent
bg={"#fff"} bg={"#fff"}
// w={{ lg: "60%", md: "230px" }} // w={{ lg: "60%", md: "230px" }}
w={{ base: '90%', md: '400px' }} w={{ base: '90%', md: '400px' }}
height={'auto'} height={'auto'}
overflowX="hidden" overflowX="hidden"
p={3} // Reduced padding p={3} // Reduced padding
bgSize={'md'} bgSize={'md'}
> >
<DialogHeader bg="white" > <DialogHeader bg="white" >
<DialogTitle alignSelf="center" color="black" fontSize="14px">Add</DialogTitle> <DialogTitle alignSelf="center" color="black" fontSize="14px">Add</DialogTitle>
@@ -37,18 +72,28 @@ function JobStatusAddModel() {
<Field.Root> <Field.Root>
<Field.Label color="black" pt={1} fontSize="12px">Job Status</Field.Label> <Field.Label color="black" pt={1} fontSize="12px">Job Status</Field.Label>
<Input placeholder="" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" /> <Input
placeholder=""
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
value={title}
onChange={(e) => setTitle(e.target.value)}
/>
</Field.Root> </Field.Root>
</Stack> </Stack>
</DialogBody> </DialogBody>
<DialogFooter display="flex" justifyContent="center" pt={"2"}> <DialogFooter display="flex" justifyContent="center" pt={"2"}>
<Button w="100%" bg="#02A0A0" color={"#fff"}> <Button w="100%" bg="#02A0A0" color={"#fff"} onClick={handleSubmit}>
Save Save
</Button> </Button>
</DialogFooter> </DialogFooter>
<DialogCloseTrigger color="black" /> <DialogCloseTrigger color="black" onClick={() => setIsOpen(false)} />
</DialogContent> </DialogContent>
</DialogRoot > </DialogRoot >

View File

@@ -1,62 +1,111 @@
import { DialogBody, DialogCloseTrigger, DialogContent, DialogFooter, DialogHeader, DialogRoot, DialogTitle, DialogTrigger } from "../../../components/ui/dialog" import {
import { Box, Field, IconButton, Input, Stack, Text, Textarea } from "@chakra-ui/react" DialogBody,
import { Button } from "../../../components/ui/button" DialogCloseTrigger,
import { FiUpload } from "react-icons/fi"; DialogContent,
import { FaRegEdit } from "react-icons/fa"; DialogFooter,
DialogHeader,
DialogRoot,
DialogTitle,
DialogTrigger,
} from "../../../components/ui/dialog";
import { Box, Field, Input, Stack } from "@chakra-ui/react";
import { Button } from "../../../components/ui/button";
import Edit from "../../../components/ActionIcons/Edit";
import { useState } from "react";
import { useUpdateJobTypeMutation } from "../../../Redux/Service/job.type.service";
import { toaster } from "../../../components/ui/toaster";
function EditJobeModel({ id, localData, refetch }: { id: number, localData: any, refetch: VoidFunction }) {
const [jobtype, setJobType] = useState("");
const [updateJobType] = useUpdateJobTypeMutation()
const [isOpen, setIsOpen] = useState(false);
const handleOpenModal = () => {
const template = localData?.find((item: any) => item.id === id);
if (template) {
setJobType(template.en_name);
setIsOpen(true);
}
};
function EditJobeModel() { const handleSubmit = async () => {
if (!jobtype.trim()) {
toaster.create({
title: "Error",
description: "Title and Subtitle cannot be empty.",
type: "error",
});
return;
}
const payload = {
id: id,
en_name: jobtype,
};
try {
return ( await updateJobType(payload);
refetch()
setIsOpen(false);
} catch (error) {
console.error("Error updating template:", error);
alert("Failed to update template");
}
};
<DialogRoot placement="center"> return (
<DialogTrigger asChild> <DialogRoot placement="center" open={isOpen} onOpenChange={({ open }) => setIsOpen(open)}>
{/* <Button bg={"transparent"} size="sm"> <DialogTrigger asChild>
<MdOutlineRemoveRedEye style={{ cursor: "pointer", fontSize: "16px" }} /> <Box bg={"transparent"} onClick={handleOpenModal}>
</Button> */} <Edit />
<Button bg={"transparent"} size="sm"> </Box>
<FaRegEdit style={{ cursor: "pointer", fontSize: "14px" }} color="#000"/> </DialogTrigger>
</Button>
</DialogTrigger> <DialogContent
bg={"#fff"}
// w={{ lg: "60%", md: "230px" }}
w={{ base: "90%", md: "400px" }}
height={"auto"}
overflowX="hidden"
p={3} // Reduced padding
bgSize={"md"}
>
<DialogHeader bg="white">
<DialogTitle alignSelf="center" color="black" fontSize="14px">
Edit
</DialogTitle>
</DialogHeader>
<DialogContent <DialogBody bg="white">
bg={"#fff"} <Stack py={3}>
// w={{ lg: "60%", md: "230px" }} <Field.Root>
w={{ base: '90%', md: '400px' }} <Field.Label color="black" pt={1} fontSize="12px">
height={'auto'} Job Type
</Field.Label>
overflowX="hidden" <Input
p={3} // Reduced padding value={jobtype}
bgSize={'md'} bgColor="#EEEEEE"
> color="black"
<DialogHeader bg="white" > border="none"
<DialogTitle alignSelf="center" color="black" fontSize="14px">Edit</DialogTitle> pl={1}
</DialogHeader> fontSize="12px"
height="30px"
onChange={(e) => setJobType(e.target.value)}
/>
</Field.Root>
</Stack>
</DialogBody>
<DialogFooter display="flex" justifyContent="center" pt={"2"}>
<Button w="100%" bg="#02A0A0" color={"#fff"} onClick={handleSubmit}>
Save
</Button>
</DialogFooter>
<DialogBody bg="white"> <DialogCloseTrigger color="black" onClick={() => setIsOpen(false)} />
<Stack py={3}> </DialogContent>
</DialogRoot>
<Field.Root> );
<Field.Label color="black" pt={1} fontSize="12px">Job Type</Field.Label>
<Input value="Lorem Ipsum" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" />
</Field.Root>
</Stack>
</DialogBody>
<DialogFooter display="flex" justifyContent="center" pt={"2"}>
<Button w="100%" bg="#02A0A0" color={"#fff"}>
Save
</Button>
</DialogFooter>
<DialogCloseTrigger color="black" />
</DialogContent>
</DialogRoot >
)
} }
export default EditJobeModel export default EditJobeModel;

View File

@@ -1,32 +1,66 @@
import { DialogBody, DialogCloseTrigger, DialogContent, DialogFooter, DialogHeader, DialogRoot, DialogTitle, DialogTrigger } from "../../../components/ui/dialog" import { DialogBody, DialogCloseTrigger, DialogContent, DialogFooter, DialogHeader, DialogRoot, DialogTitle, DialogTrigger } from "../../../components/ui/dialog"
import { Box, Field, IconButton, Input, Stack, Text, Textarea } from "@chakra-ui/react" import { Field, Input, Stack, Text } from "@chakra-ui/react"
import { IoMdAdd } from "react-icons/io" import { IoMdAdd } from "react-icons/io"
import { Button } from "../../../components/ui/button" import { Button } from "../../../components/ui/button"
import { useState } from "react";
import { useCreateJobTypePostMutation } from "../../../Redux/Service/job.type.service";
import { toaster } from "../../../components/ui/toaster";
function JobAddModel({ refetch }: { refetch: VoidFunction }) {
const [jobType, setJobType] = useState("");
const [isOpen, setIsOpen] = useState(false);
const [createJobTypePost] = useCreateJobTypePostMutation()
const handleOpenModal = () => {
setIsOpen(true); // Open modal when clicking "Add"
};
const handleSubmit = async () => {
if (!jobType.trim()) {
toaster.create({
title: "Error",
description: "Title and Subtitle cannot be empty.",
type: "error",
});
return;
}
const payload = {
en_name: jobType,
};
try {
await createJobTypePost(payload);
refetch()
setIsOpen(false);
} catch (error) {
console.error("Error updating template:", error);
alert("Failed to update template");
}
};
function JobAddModel() {
return ( return (
<DialogRoot placement="center"> <DialogRoot placement="center" open={isOpen}>
<DialogTrigger asChild> <DialogTrigger asChild>
{/* <Button bg={"transparent"} size="sm"> {/* <Button bg={"transparent"} size="sm">
<MdOutlineRemoveRedEye style={{ cursor: "pointer", fontSize: "16px" }} /> <MdOutlineRemoveRedEye style={{ cursor: "pointer", fontSize: "16px" }} />
</Button> */} </Button> */}
<Button px={5} size={"xs"} bg={"#02A0A0"}> <Button px={5} size={"xs"} bg={"#02A0A0"} onClick={handleOpenModal}>
<IoMdAdd /> <Text>Add</Text> <IoMdAdd /> <Text>Add</Text>
</Button> </Button>
</DialogTrigger> </DialogTrigger>
<DialogContent <DialogContent
bg={"#fff"} bg={"#fff"}
// w={{ lg: "60%", md: "230px" }} // w={{ lg: "60%", md: "230px" }}
w={{ base: '90%', md: '400px' }} w={{ base: '90%', md: '400px' }}
height={'auto'} height={'auto'}
overflowX="hidden" overflowX="hidden"
p={3} // Reduced padding p={3} // Reduced padding
bgSize={'md'} bgSize={'md'}
> >
<DialogHeader bg="white" > <DialogHeader bg="white" >
<DialogTitle alignSelf="center" color="black" fontSize="14px">Add</DialogTitle> <DialogTitle alignSelf="center" color="black" fontSize="14px">Add</DialogTitle>
@@ -37,18 +71,28 @@ function JobAddModel() {
<Field.Root> <Field.Root>
<Field.Label color="black" pt={1} fontSize="12px">Job Type</Field.Label> <Field.Label color="black" pt={1} fontSize="12px">Job Type</Field.Label>
<Input placeholder="" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" /> <Input
placeholder=""
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
value={jobType}
onChange={(e) => setJobType(e.target.value)}
/>
</Field.Root> </Field.Root>
</Stack> </Stack>
</DialogBody> </DialogBody>
<DialogFooter display="flex" justifyContent="center" pt={"2"}> <DialogFooter display="flex" justifyContent="center" pt={"2"}>
<Button w="100%" bg="#02A0A0" color={"#fff"}> <Button w="100%" bg="#02A0A0" color={"#fff"} onClick={handleSubmit}>
Save Save
</Button> </Button>
</DialogFooter> </DialogFooter>
<DialogCloseTrigger color="black" /> <DialogCloseTrigger color="black" onClick={() => setIsOpen(false)} />
</DialogContent> </DialogContent>
</DialogRoot > </DialogRoot >

View File

@@ -1,11 +1,14 @@
import { Box, HStack, Image, Input, Text } from "@chakra-ui/react"; import { Box, HStack, Text } from "@chakra-ui/react";
import MainFrame from "../../../components/MainFrame" import MainFrame from "../../../components/MainFrame"
import { InputGroup } from "../../../components/ui/input-group"; // import { InputGroup } from "../../../components/ui/input-group";
import { LuSearch } from "react-icons/lu"; // import { LuSearch } from "react-icons/lu";
import DataTable from "../../../components/DataTable"; import DataTable from "../../../components/DataTable";
import { Switch } from "../../../components/ui/switch"; import { Switch } from "../../../components/ui/switch";
import JobAddModel from "./JobAddModel"; import JobAddModel from "./JobAddModel";
import EditJobeModel from "./EditJobModel"; import EditJobeModel from "./EditJobModel";
import { JobTypeData, useGetJobTypeQuery } from "../../../Redux/Service/job.type.service";
import { useEffect, useState } from "react";
import SearchComponent from "../../../components/SearchComponent";
@@ -15,25 +18,91 @@ const tableHeadRow = [
"Sr. No", "Sr. No",
"Title", "Title",
"Action" "Action"
]; ];
const managepost: any[] = [ // const managepost: any[] = [
...Array.from({ length: 12 }, (_, i) => ({ // ...Array.from({ length: 12 }, (_, i) => ({
"Sr. No": i + 1, // "Sr. No": i + 1,
"Title": "Lorem Ipsum", // "Title": "Lorem Ipsum",
// "Action": (
// <HStack justifyContent="center">
// <EditJobeModel />
// <Box>
// <Switch colorPalette={'teal'} size={"xs"} />
// </Box>
// </HStack>
// ),
// })),
// ];
const JobType = () => {
const [currentPage, setCurrentPage] = useState(1);
const { data, refetch } = useGetJobTypeQuery(currentPage)
const [localData, setLocalData] = useState<any[]>([]);
const [searchTerm, setSearchTerm] = useState("");
// const [templateMasterToggle] = useTemplateMasterToggleMutation()
console.log('DATA', data?.data.data);
useEffect(() => {
if (data?.data?.data) {
setLocalData(data?.data.data);
}
}, [data]);
const handlePageChange = (page: number) => {
setCurrentPage(page);
};
const filteredData = localData?.filter((agency) => {
const searchLower = searchTerm.toLowerCase();
const title = agency.en_name?.toLowerCase().includes(searchLower);
return title;
});
// const handleToggle = async (agencyId: string, currentStatus: number) => {
// const newStatus = currentStatus ? 0 : 1;
// setLocalData((prevData) =>
// prevData.map((agency) =>
// agency.id === agencyId ? { ...agency, is_active: newStatus } : agency
// )
// );
// try {
// await templateMasterToggle({ id: agencyId, is_active: newStatus }).unwrap();
// refetch()
// } catch (error) {
// console.error("Error updating privacy policy:", error);
// setLocalData((prevData) =>
// prevData.map((agency) =>
// agency.id === agencyId ? { ...agency, is_active: currentStatus } : agency
// )
// );
// }
// };
const managepost = filteredData?.map((agency: JobTypeData, index: number) => ({
'id': (currentPage - 1) * (data?.data.per_page ?? 0) + index + 1,
"Sr. No": index + 1,
"Title": agency.en_name,
"Action": ( "Action": (
<HStack justifyContent="center"> <HStack justifyContent="center">
<EditJobeModel /> <EditJobeModel id={agency.id} localData={localData} refetch={refetch} />
<Box> <Box>
<Switch colorPalette={'teal'} size={"xs"}/> <Switch
colorPalette={'teal'}
size={"xs"}
// onChange={() => handleToggle(agency.id, Number(agency.is_active))}
checked={Boolean(Number(agency.is_active))}
/>
</Box> </Box>
</HStack> </HStack>
), ),
})), }));
];
const JobType = () => {
return ( return (
<MainFrame> <MainFrame>
@@ -46,40 +115,35 @@ const JobType = () => {
px={3} px={3}
> >
<Text as={"span"} fontSize={"sm"} fontWeight={500} color={"#000"}> <Text as={"span"} fontSize={"sm"} fontWeight={500} color={"#000"}>
Job Type Job Type
</Text> </Text>
<HStack mr={5}> <HStack >
<InputGroup marginRight={"1rem"} <SearchComponent
startElement={ value={searchTerm}
<LuSearch fontSize={"xs"} style={{ position: 'relative', left: '10px' }} /> onChange={(value) => {
} setSearchTerm(value);
color={"#000"} // setCurrentPage(1);
> refetch()
<Input }}
p={3} />
w={300}
bg={"#fff"}
colorPalette={"blue"}
_focus={{ border: "1px solid #02A0A0" }}
rounded={"md"}
size={"2xs"}
fontSize={"2sm"}
placeholder="Search..."
bgColor={'#EEEEEE'}
ps={8}
/>
</InputGroup>
{/* <Button bgColor={'#EEEEEE'} pl={3} pr={3}><IoMdAdd /> <Text>Add</Text></Button> */} {/* <Button bgColor={'#EEEEEE'} pl={3} pr={3}><IoMdAdd /> <Text>Add</Text></Button> */}
<JobAddModel /> <JobAddModel refetch={refetch} />
</HStack> </HStack>
</HStack> </HStack>
<DataTable <DataTable
sortableColumns={["Name", "Registration Date "]} sortableColumns={["Name", "Registration Date "]}
tableHeadRow={tableHeadRow} tableHeadRow={tableHeadRow}
data={managepost} data={managepost}
paginationData={{
current_page: data?.data.current_page || 1,
last_page: data?.data.last_page || 1,
per_page: data?.data.per_page || 10,
total: data?.data.total || 0
}}
onPageChange={handlePageChange}
/> />
</Box> </Box>
</MainFrame> </MainFrame>
) )
} }

View File

@@ -1,100 +1,309 @@
import { DialogBody, DialogCloseTrigger, DialogContent, DialogFooter, DialogHeader, DialogRoot, DialogTitle, DialogTrigger } from "../../../components/ui/dialog" import {
import { Box, Field, IconButton, Input, Stack, Text, Textarea } from "@chakra-ui/react" DialogBody,
import { Button } from "../../../components/ui/button" DialogCloseTrigger,
DialogContent,
DialogFooter,
DialogHeader,
DialogRoot,
DialogTitle,
} from "../../../components/ui/dialog";
import {
Box,
Field,
Input,
Stack,
} from "@chakra-ui/react";
import { Button } from "../../../components/ui/button";
import { FiUpload } from "react-icons/fi"; import { FiUpload } from "react-icons/fi";
import { useState } from "react"; import { useState } from "react";
import { FaRegEdit } from "react-icons/fa"; // import { FaRegEdit } from "react-icons/fa";
import Edit from "../../../components/ActionIcons/Edit";
import { Toaster, toaster } from "../../../components/ui/toaster";
import { Template } from "../../../Redux/Service/template.master.service";
import axios from "axios";
const IMGURL = import.meta.env.VITE_IMG_TEMPLATES
const APIURL = import.meta.env.VITE_API_URL
function EditTemplateModel() { function EditTemplateModel({ id, localData, refetch }: { id: number, localData: any, refetch: VoidFunction }) {
const [title, setTitle] = useState("");
const [subTitle, setSubTitle] = useState("");
const [userType, setUserType] = useState<number | "">("");
const [images, setImages] = useState<(File | string)[]>([]);
// const [objectURLs, setObjectURLs] = useState<string[]>([]); // Store object URLs separately
// const [updateTemplateMaster] = useUpdateTemplateMasterMutation()
const [isOpen, setIsOpen] = useState(false);
const [selectedTemplate, setSelectedTemplate] = useState<Template | null>(null);
const token = localStorage.getItem("token");
const [images, setImages] = useState<string[]>([]); console.log(selectedTemplate);
const handleImageChange = (event: React.ChangeEvent<HTMLInputElement>) => { const handleImageChange = async (event: React.ChangeEvent<HTMLInputElement>) => {
if (event.target.files) { if (event.target.files) {
const selectedFiles = Array.from(event.target.files); const file = event.target.files[0];
if (!["image/jpeg", "image/jpg", "image/png"].includes(file.type)) {
const newImages = selectedFiles.map((file) => { toaster.create({
return URL.createObjectURL(file); // Convert to preview URL title: "Error",
description: "Only JPEG, JPG, and PNG files are allowed.",
type: "error",
}); });
return;
setImages((prevImages) => [...prevImages, ...newImages]); // Append new images
} }
};
setImages((prevImages) => [...prevImages, file]);
return ( }
};
<DialogRoot placement="center"> const handleOpenModal = () => {
<DialogTrigger asChild> const template = localData?.find((item: any) => item.id === id);
{/* <Button bg={"transparent"} size="sm"> if (template) {
<MdOutlineRemoveRedEye style={{ cursor: "pointer", fontSize: "16px" }} /> setSelectedTemplate(template);
</Button> */} setTitle(template.post_template_translate.length > 0 ? template.post_template_translate[0].title : "");
<Button bg={"transparent"} size="sm"> setSubTitle(template.post_template_translate.length > 0 ? template.post_template_translate[0].sub_title : "");
<FaRegEdit style={{ cursor: "pointer", fontSize: "14px" }} color="#000"/> setUserType(template.principle_type_xid?.toString() || "");
</Button>
</DialogTrigger> // Convert image URLs to File objects if needed
const templateImages = template.post_template_image.map((img: any) => `${IMGURL}${img.image_name}`);
setImages(templateImages);
<DialogContent setIsOpen(true);
bg={"#fff"} }
// w={{ lg: "60%", md: "230px" }} };
w={{ base: '90%', md: '400px' }}
height={'auto'}
overflowX="hidden"
p={3} // Reduced padding
bgSize={'md'}
>
<DialogHeader bg="white" >
<DialogTitle alignSelf="center" color="black" fontSize="14px">Add</DialogTitle>
</DialogHeader>
<DialogBody bg="white">
<Stack py={3}>
<Field.Root> const handleSubmit = async () => {
<Field.Label color="black" pt={1} fontSize="12px">Template Name</Field.Label> if (!title.trim() || !subTitle.trim()) {
<Input placeholder="" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" /> toaster.create({
title: "Error",
description: "Title and Subtitle cannot be empty.",
type: "error",
});
return;
}
if (userType === "" || isNaN(Number(userType))) {
<Field.Label color="black" pt={1} fontSize="12px">Images</Field.Label> toaster.create({
<Box display="flex" alignItems="center" justifyContent="space-between" px={3} bgColor="#EEEEEE" border="none" width="100%" height="50px" cursor="pointer" position="relative"> title: "Error",
<Input type="file" accept="image/*" opacity={0} position="absolute" bgColor="#EEEEEE" border="none" pl={1} width="100%" height="100%" cursor="pointer" onChange={handleImageChange}/> description: "Please select a valid user type.",
<Box display="flex" gap={2} overflow="hidden"> type: "error",
{images.length > 0 ? ( });
images.map((img, index) => ( return;
<img }
key={index}
src={img}
alt={`Uploaded ${index}`}
style={{ maxHeight: "40px", maxWidth: "70px", objectFit: "contain" }}
/>
))
) : (
<Box width="70px" height="40px" /> // Placeholder to maintain layout
)}
</Box>
<FiUpload color="#000" />
</Box>
{/* <Input placeholder="" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" /> */}
</Field.Root> const newImages = images.filter((image) => image instanceof File);
</Stack>
</DialogBody> if (newImages.length === 0) {
<DialogFooter display="flex" justifyContent="center" pt={"2"}> toaster.create({
<Button w="100%" bg="#02A0A0" color={"#fff"}> title: "Error",
Save description: "Please upload at least one image.",
</Button> type: "error",
</DialogFooter> });
return;
}
<DialogCloseTrigger color="black" /> const formData = new FormData();
</DialogContent> formData.append("id", `${id}`);
</DialogRoot > formData.append("principle_type_xid", `${userType}`);
formData.append("title", title);
formData.append("sub_title", subTitle);
) newImages.forEach((image, index) => {
formData.append(`image_name[${index}]`, image, image.name);
});
try {
// await updateTemplateMaster(formData);
if (token) {
await axios.post(`${APIURL}/template-update`, formData, {
headers: {
'Content-Type': 'multipart/form-data',
'access-token': `${token}`,
},
// withCredentials: true,
});
}
setIsOpen(false);
refetch()
} catch (error) {
console.error("Error updating template:", error);
toaster.create({
title: "Error",
description: "Failed to update template. Please try again.",
type: "error",
});
}
};
// const handleSubmit = async () => {
// if (!title.trim() || !subTitle.trim()) {
// toaster.create({
// title: "Error",
// description: "Title and Subtitle cannot be empty.",
// type: "error",
// });
// return;
// }
// if (userType === "" || isNaN(Number(userType))) {
// toaster.create({
// title: "Error",
// description: "Please select a valid user type.",
// type: "error",
// });
// return;
// }
// if (images.length === 0) {
// toaster.create({
// title: "Error",
// description: "Please upload at least one image.",
// type: "error",
// });
// return;
// }
// const existingImageUrls = images.filter((img) => typeof img === "string") as string[];
// const newBase64Images = images.filter((img) => typeof img === "string" && img.startsWith("data:image")) as string[];
// const payload = {
// id: id,
// principle_type_xid: userType,
// title,
// sub_title: subTitle,
// image_name: [...existingImageUrls, ...newBase64Images], // Send only Base64 strings
// };
// try {
// await updateTemplateMaster(payload)
// setIsOpen(false)
// } catch (error) {
// console.error("Error creating template:", error);
// alert("Failed to create template");
// }
// };
return (
<DialogRoot placement="center" open={isOpen} onOpenChange={({ open }) => setIsOpen(open)}>
{/* <Button bg={"transparent"} size="sm">
<MdOutlineRemoveRedEye style={{ cursor: "pointer", fontSize: "16px" }} />
</Button> */}
<Box bg={"transparent"} onClick={handleOpenModal}>
<Edit />
</Box>
<DialogContent
bg={"#fff"}
// w={{ lg: "60%", md: "230px" }}
w={{ base: '90%', md: '400px' }}
height={'auto'}
overflowX="hidden"
p={3} // Reduced padding
bgSize={'md'}
>
<DialogHeader bg="white" >
<DialogTitle alignSelf="center" color="black" fontSize="14px">Edit</DialogTitle>
</DialogHeader>
<DialogBody bg="white">
<Stack py={3}>
<Field.Root>
<Field.Label color="black" pt={1} fontSize="12px">Title</Field.Label>
<Input
placeholder="Enter Title"
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
value={title}
onChange={(e) => setTitle(e.target.value)}
/>
</Field.Root>
<Field.Root>
<Field.Label color="black" pt={1} fontSize="12px">Subtitle</Field.Label>
<Input
placeholder="Enter subtitle"
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
value={subTitle}
onChange={(e) => setSubTitle(e.target.value)}
/>
</Field.Root>
<Field.Root>
<Field.Label color="black" pt={1} fontSize="12px">Select User Type</Field.Label>
<Box bgColor="#EEEEEE" borderRadius="md" p={1}>
<select
style={{
width: "100%",
background: "transparent",
color: "black",
border: "none",
fontSize: "12px",
height: "30px",
outline: "none",
}}
value={userType}
onChange={(e) => setUserType(Number(e.target.value))}
>
<option value="">Select User Type</option>
<option value="2">Recruiter</option>
<option value="3">Jobseeker</option>
</select>
</Box>
</Field.Root>
<Field.Root>
<Field.Label color="black" pt={1} fontSize="12px">Images</Field.Label>
<Box display="flex" alignItems="center" justifyContent="space-between" px={3} bgColor="#EEEEEE" border="none" width="100%" height="50px" cursor="pointer" position="relative">
<Input type="file" accept="image/*" opacity={0} position="absolute" bgColor="#EEEEEE" border="none" pl={1} width="100%" height="100%" cursor="pointer" onChange={handleImageChange} />
<Box display="flex" gap={2} overflow="hidden">
{images.length > 0 ? (
images.map((img, index) => (
<img
key={index}
src={img instanceof File ? URL.createObjectURL(img) : img}
alt={`Uploaded ${index}`}
style={{ maxHeight: "40px", maxWidth: "70px", objectFit: "contain" }}
/>
))
) : (
<Box width="70px" height="40px" /> // Placeholder to maintain layout
)}
</Box>
<FiUpload color="#000" />
</Box>
<Box>
</Box>
{/* <Input placeholder="" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" /> */}
</Field.Root>
</Stack>
</DialogBody>
<DialogFooter display="flex" justifyContent="center" pt={"2"}>
<Button w="100%" bg="#02A0A0" color={"#fff"} onClick={handleSubmit}>
Save
</Button>
</DialogFooter>
<DialogCloseTrigger color="black" onClick={() => setIsOpen(false)} />
</DialogContent>
<Toaster />
</DialogRoot >
);
} }
export default EditTemplateModel export default EditTemplateModel;

View File

@@ -1,50 +1,142 @@
import { DialogBody, DialogCloseTrigger, DialogContent, DialogFooter, DialogHeader, DialogRoot, DialogTitle, DialogTrigger } from "../../../components/ui/dialog" import { DialogBody, DialogCloseTrigger, DialogContent, DialogFooter, DialogHeader, DialogRoot, DialogTitle, DialogTrigger } from "../../../components/ui/dialog"
import { Box, Field, IconButton, Input, Stack, Text, Textarea } from "@chakra-ui/react" import { Box, Field, Input, Stack, Text } from "@chakra-ui/react"
import { IoMdAdd } from "react-icons/io" import { IoMdAdd } from "react-icons/io"
import { Button } from "../../../components/ui/button" import { Button } from "../../../components/ui/button"
import { FiUpload } from "react-icons/fi"; import { FiUpload } from "react-icons/fi";
import { useState } from "react"; import { useState } from "react";
// import { useCreateTemplatePostMutation } from "../../../Redux/Service/template.master.service";
import { Toaster, toaster } from "../../../components/ui/toaster"
import axios from "axios";
const APIURL = import.meta.env.VITE_API_URL
function TemplateAddModel() { function TemplateAddModel({ refetch }: { refetch: VoidFunction }) {
const [title, setTitle] = useState("");
const [subTitle, setSubTitle] = useState("");
const [userType, setUserType] = useState<number | "">("");
const [images, setImages] = useState<(File | string)[]>([]);
// const [createTemplatePost] = useCreateTemplatePostMutation()
const [isOpen, setIsOpen] = useState(false);
const token = localStorage.getItem("token");
if (!token) {
console.error("No token found in localStorage!");
return;
}
const [images, setImages] = useState<string[]>([]); const handleOpenModal = () => {
setIsOpen(true); // Open modal when clicking "Add"
const handleImageChange = (event: React.ChangeEvent<HTMLInputElement>) => {
if (event.target.files) {
const selectedFiles = Array.from(event.target.files);
const newImages = selectedFiles.map((file) => {
return URL.createObjectURL(file); // Convert to preview URL
});
setImages((prevImages) => [...prevImages, ...newImages]); // Append new images
}
}; };
const handleImageChange = async (event: React.ChangeEvent<HTMLInputElement>) => {
if (event.target.files) {
const file = event.target.files[0];
if (!["image/jpeg", "image/jpg", "image/png"].includes(file.type)) {
toaster.create({
title: "Error",
description: "Only JPEG, JPG, and PNG files are allowed.",
type: "error",
});
return;
}
setImages((prevImages) => [...prevImages, file]);
}
};
const handleSubmit = async () => {
if (!title || !subTitle || images.length === 0) {
toaster.create({
title: "Error",
description: "Please fill in all required fields and upload at least one image.",
type: "error",
});
return;
}
if (userType === "" || isNaN(Number(userType))) {
toaster.create({
title: "Error",
description: "Please select a valid user type.",
type: "error",
});
return;
}
// const payload = {
// id: id,
// principle_type_xid: userType,
// title,
// sub_title: subTitle,
// image_name: images.filter((img) => typeof img === "string"), // Send only Base64 strings
// };
const formData = new FormData();
formData.append("principle_type_xid", `${userType}`);
formData.append("title", title);
formData.append("sub_title", subTitle);
images.forEach((image, index) => {
if (image instanceof File) {
formData.append(`image_name[${index}]`, image, image.name); // Ensure indexed naming
}
});
if (token) {
const payload = JSON.parse(atob(token.split(".")[1]));
console.log("Token Payload:", payload);
}
try {
// await createTemplatePost(formData)
if (token) {
await axios.post(`${APIURL}/template-store`, formData, {
headers: {
'Content-Type': 'multipart/form-data',
'access-token': `${token}`,
},
// withCredentials: true,
});
}
refetch();
setTitle("");
setSubTitle("");
setUserType("");
setImages([]);
setIsOpen(false)
} catch (error) {
console.error("Error creating template:", error);
// alert("Failed to create template");
}
};
// console.log("Token stored:", window.localStorage.getItem("token"));
return ( return (
<DialogRoot placement="center"> <DialogRoot placement="center" open={isOpen}>
<DialogTrigger asChild> <DialogTrigger asChild>
{/* <Button bg={"transparent"} size="sm"> {/* <Button bg={"transparent"} size="sm">
<MdOutlineRemoveRedEye style={{ cursor: "pointer", fontSize: "16px" }} /> <MdOutlineRemoveRedEye style={{ cursor: "pointer", fontSize: "16px" }} />
</Button> */} </Button> */}
<Button px={5} size={"xs"} bg={"#02A0A0"}> <Button px={5} size={"xs"} bg={"#02A0A0"} onClick={handleOpenModal}>
<IoMdAdd /> <Text>Add</Text> <IoMdAdd /> <Text>Add</Text>
</Button> </Button>
</DialogTrigger> </DialogTrigger>
<DialogContent <DialogContent
bg={"#fff"} bg={"#fff"}
// w={{ lg: "60%", md: "230px" }} // w={{ lg: "60%", md: "230px" }}
w={{ base: '90%', md: '400px' }} w={{ base: '90%', md: '400px' }}
height={'auto'} height={'auto'}
overflowX="hidden" overflowX="hidden"
p={3} // Reduced padding p={3} // Reduced padding
bgSize={'md'} bgSize={'md'}
> >
<DialogHeader bg="white" > <DialogHeader bg="white" >
<DialogTitle alignSelf="center" color="black" fontSize="14px">Add</DialogTitle> <DialogTitle alignSelf="center" color="black" fontSize="14px">Add</DialogTitle>
@@ -54,30 +146,79 @@ function TemplateAddModel() {
<Stack py={3}> <Stack py={3}>
<Field.Root> <Field.Root>
<Field.Label color="black" pt={1} fontSize="12px">Template Name</Field.Label> <Field.Label color="black" pt={1} fontSize="12px">Title</Field.Label>
<Input placeholder="" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" /> <Input
placeholder="Enter Title"
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
value={title}
onChange={(e) => setTitle(e.target.value)}
/>
</Field.Root>
<Field.Root>
<Field.Label color="black" pt={1} fontSize="12px">Subtitle</Field.Label>
<Input
placeholder="Enter subtitle"
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
value={subTitle}
onChange={(e) => setSubTitle(e.target.value)}
/>
</Field.Root>
<Field.Root>
<Field.Label color="black" pt={1} fontSize="12px">Select User Type</Field.Label>
<Box bgColor="#EEEEEE" borderRadius="md" p={1}>
<select
style={{
width: "100%",
background: "transparent",
color: "black",
border: "none",
fontSize: "12px",
height: "30px",
outline: "none",
}}
value={userType}
onChange={(e) => setUserType(Number(e.target.value))}
>
<option value="">Select User Type</option>
<option value="2">Recruiter</option>
<option value="3">Jobseeker</option>
</select>
</Box>
</Field.Root>
<Field.Root>
<Field.Label color="black" pt={1} fontSize="12px">Images</Field.Label> <Field.Label color="black" pt={1} fontSize="12px">Images</Field.Label>
<Box display="flex" alignItems="center" justifyContent="space-between" px={3} bgColor="#EEEEEE" border="none" width="100%" height="50px" cursor="pointer" position="relative"> <Box display="flex" alignItems="center" justifyContent="space-between" px={3} bgColor="#EEEEEE" border="none" width="100%" height="50px" cursor="pointer" position="relative">
<Input type="file" accept="image/*" opacity={0} position="absolute" bgColor="#EEEEEE" border="none" pl={1} width="100%" height="100%" cursor="pointer" onChange={handleImageChange}/> <Input type="file" accept="image/*" opacity={0} position="absolute" bgColor="#EEEEEE" border="none" pl={1} width="100%" height="100%" cursor="pointer" onChange={handleImageChange} />
<Box display="flex" gap={2} overflow="hidden"> <Box display="flex" gap={2} overflow="hidden">
{images.length > 0 ? ( {images.length > 0 ? (
images.map((img, index) => ( images.map((img, index) => (
<img <img
key={index} key={index}
src={img} src={img instanceof File ? URL.createObjectURL(img) : img}
alt={`Uploaded ${index}`} alt={`Uploaded ${index}`}
style={{ maxHeight: "40px", maxWidth: "70px", objectFit: "contain" }} style={{ maxHeight: "40px", maxWidth: "70px", objectFit: "contain" }}
/> />
)) ))
) : ( ) : (
<Box width="70px" height="40px" /> // Placeholder to maintain layout <Box width="70px" height="40px" /> // Placeholder to maintain layout
)} )}
</Box>
<FiUpload color="#000" />
</Box> </Box>
<FiUpload color="#000" />
</Box>
{/* <Input placeholder="" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" /> */} {/* <Input placeholder="" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" /> */}
</Field.Root> </Field.Root>
@@ -85,13 +226,14 @@ function TemplateAddModel() {
</DialogBody> </DialogBody>
<DialogFooter display="flex" justifyContent="center" pt={"2"}> <DialogFooter display="flex" justifyContent="center" pt={"2"}>
<Button w="100%" bg="#02A0A0" color={"#fff"}> <Button w="100%" bg="#02A0A0" color={"#fff"} onClick={handleSubmit}>
Save Save
</Button> </Button>
</DialogFooter> </DialogFooter>
<DialogCloseTrigger color="black" /> <DialogCloseTrigger color="black" onClick={() => setIsOpen(false)} />
</DialogContent> </DialogContent>
<Toaster />
</DialogRoot > </DialogRoot >
) )

View File

@@ -1,15 +1,16 @@
import { Box, HStack, Image, Input, Text } from "@chakra-ui/react"; import { Box, HStack, Image, Text } from "@chakra-ui/react";
import MainFrame from "../../../components/MainFrame" import MainFrame from "../../../components/MainFrame"
import { InputGroup } from "../../../components/ui/input-group";
import { LuSearch } from "react-icons/lu";
import DataTable from "../../../components/DataTable"; import DataTable from "../../../components/DataTable";
import { Switch } from "../../../components/ui/switch"; import { Switch } from "../../../components/ui/switch";
import img from "../../../assets/waterfall.jpg" // import img from "../../../assets/waterfall.jpg"
import Templateimg from "../../../assets/Template_img.png" // import Templateimg from "../../../assets/Template_img.png"
import TemplateAddModel from "./TemplateAddModel"; import TemplateAddModel from "./TemplateAddModel";
import EditTemplateModel from "./EditTemplateModel"; import EditTemplateModel from "./EditTemplateModel";
import { Template, useGetTemplateMasterQuery, useTemplateMasterToggleMutation } from "../../../Redux/Service/template.master.service";
import { useEffect, useState } from "react";
import SearchComponent from "../../../components/SearchComponent";
const APIURL = import.meta.env.VITE_IMG_TEMPLATES
// table data // table data
@@ -18,35 +19,105 @@ const tableHeadRow = [
"Title", "Title",
"Images", "Images",
"Action" "Action"
]; ];
const managepost: any[] = [ // const managepost: any[] = [
...Array.from({ length: 12 }, (_, i) => ({ // ...Array.from({ length: 12 }, (_, i) => ({
"Sr. No": i + 1, // "Sr. No": i + 1,
"Title": "Lorem Ipsum", // "Title": "Lorem Ipsum",
// "Images": (
// // <Image w={50} src={img} />
// <HStack >
// <Image rounded={'lg'} w={100} h={50} src={img} />
// <Image rounded={'lg'} w={100} h={50} src={Templateimg} />
// </HStack>
// ),
// "Action": (
// <HStack justifyContent="center">
// <EditTemplateModel />
// <Box>
// <Switch colorPalette={'teal'} size={"xs"} />
// </Box>
// </HStack>
// ),
// })),
// ];
const TemplateMaster = () => {
const [currentPage, setCurrentPage] = useState(1);
const { data, refetch } = useGetTemplateMasterQuery(currentPage)
const [localData, setLocalData] = useState<any[]>([]);
const [templateMasterToggle] = useTemplateMasterToggleMutation();
const [searchTerm, setSearchTerm] = useState("");
console.log('DATA', data?.data.data);
useEffect(() => {
if (data?.data?.data) {
setLocalData(data?.data.data);
}
}, [data]);
const handlePageChange = (page: number) => {
setCurrentPage(page);
};
const handleToggle = async (agencyId: string, currentStatus: number) => {
const newStatus = currentStatus ? 0 : 1;
setLocalData((prevData) =>
prevData.map((agency) =>
agency.id === agencyId ? { ...agency, is_active: newStatus } : agency
)
);
try {
await templateMasterToggle({ id: agencyId, is_active: newStatus }).unwrap();
refetch()
} catch (error) {
console.error("Error updating privacy policy:", error);
setLocalData((prevData) =>
prevData.map((agency) =>
agency.id === agencyId ? { ...agency, is_active: currentStatus } : agency
)
);
}
};
const filteredData = localData?.filter((agency) =>
agency.post_template_translate[0].title.toLowerCase().includes(searchTerm.toLowerCase())
);
const managepost = filteredData?.map((agency: Template, index: number) => ({
'id': agency.id,
"Sr. No": (currentPage - 1) * (data?.data.per_page ?? 0) + index + 1,
"Title": agency.post_template_translate.length > 0
? agency.post_template_translate[0].title
: "N/A",
"Images": ( "Images": (
// <Image w={50} src={img} /> // <Image w={50} src={img} />
<HStack > <HStack key={agency.id}>
<Image w={100} h={50} src={img} /> {agency.post_template_image.map((img) => (
<Image w={100} h={50} src={Templateimg} /> <Image rounded={'lg'} w={100} h={50} src={`${APIURL}${img.image_name}`} />
))}
{/* <Image rounded={'lg'} w={100} h={50} src={Templateimg} /> */}
</HStack> </HStack>
), ),
"Action": ( "Action": (
<HStack justifyContent="center"> <HStack justifyContent="center">
<EditTemplateModel /> <EditTemplateModel id={agency.id} localData={localData} refetch={refetch} />
<Box> <Box>
<Switch colorPalette={'teal'} size={"xs"}/> <Switch
colorPalette={'teal'}
size={"xs"}
onChange={() => handleToggle(agency.id.toString(), Number(agency.is_active ?? 0))}
checked={Boolean(Number(agency.is_active))}
/>
</Box> </Box>
</HStack> </HStack>
), ),
})), }));
];
const TemplateMaster = () => {
return ( return (
<MainFrame> <MainFrame>
@@ -59,11 +130,11 @@ const TemplateMaster = () => {
px={3} px={3}
> >
<Text as={"span"} fontSize={"sm"} fontWeight={500} color={"#000"}> <Text as={"span"} fontSize={"sm"} fontWeight={500} color={"#000"}>
Template Master Template Master
</Text> </Text>
<HStack mr={5}> <HStack >
<InputGroup marginRight={"1rem"} {/* <InputGroup
startElement={ startElement={
<LuSearch fontSize={"xs"} style={{ position: 'relative', left: '10px' }} /> <LuSearch fontSize={"xs"} style={{ position: 'relative', left: '10px' }} />
} }
@@ -76,23 +147,33 @@ const TemplateMaster = () => {
colorPalette={"blue"} colorPalette={"blue"}
_focus={{ border: "1px solid #02A0A0" }} _focus={{ border: "1px solid #02A0A0" }}
rounded={"md"} rounded={"md"}
size={"2xs"} size={"xs"}
fontSize={"2sm"} fontSize={"sm"}
placeholder="Search..." placeholder="Search..."
bgColor={'#EEEEEE'} bgColor={'#EEEEEE'}
ps={8} ps={8}
/> />
</InputGroup> </InputGroup> */}
{/* <Button bgColor={'#EEEEEE'} pl={3} pr={3}><IoMdAdd /> <Text>Add</Text></Button> */} <SearchComponent
<TemplateAddModel /> value={searchTerm}
onChange={setSearchTerm}
/>
<TemplateAddModel refetch={refetch} />
</HStack> </HStack>
</HStack> </HStack>
<DataTable <DataTable
sortableColumns={["Name", "Registration Date "]} sortableColumns={["Name", "Registration Date "]}
tableHeadRow={tableHeadRow} tableHeadRow={tableHeadRow}
data={managepost} data={managepost}
paginationData={{
current_page: data?.data.current_page || 1,
last_page: data?.data.last_page || 1,
per_page: data?.data.per_page || 10,
total: data?.data.total || 0
}}
onPageChange={handlePageChange}
/> />
</Box> </Box>
</MainFrame> </MainFrame>
) )
} }

View File

@@ -1,61 +1,118 @@
import { DialogBody, DialogCloseTrigger, DialogContent, DialogFooter, DialogHeader, DialogRoot, DialogTitle, DialogTrigger } from "../../../components/ui/dialog" import {
import { Box, Field, IconButton, Input, Stack, Text, Textarea } from "@chakra-ui/react" DialogBody,
import { Button } from "../../../components/ui/button" DialogCloseTrigger,
import { FaRegEdit } from "react-icons/fa"; DialogContent,
DialogFooter,
DialogHeader,
DialogRoot,
DialogTitle,
DialogTrigger,
} from "../../../components/ui/dialog";
import {
Box,
Field,
Input,
Stack,
} from "@chakra-ui/react";
import { Button } from "../../../components/ui/button";
// import { FaRegEdit } from "react-icons/fa";
import Edit from "../../../components/ActionIcons/Edit";
import { useState } from "react";
import { toaster } from "../../../components/ui/toaster";
import { useUpdateWorkSpaceMutation } from "../../../Redux/Service/workspace.mode";
function EditWorkModel({ localData, refetch }: {localData: any, refetch: VoidFunction}) {
const [title, setTitle] = useState(localData?.en_name);
const [isOpen, setIsOpen] = useState(false);
const [updateWorkSpace] = useUpdateWorkSpaceMutation()
console.log("localData", localData)
const handleOpenModal = () => {
// const template = localData?.find((item: any) => item.id === id);
if (localData) {
setIsOpen(true);
// setTitle(localData?.localData.en_name);
}
};
function EditWorkModel() { const handleSubmit = async () => {
if (!title.trim()) {
toaster.create({
title: "Error",
description: "Title field cannot be empty.",
type: "error",
});
return;
}
const payload = {
id: localData?.id,
en_name: title
};
try {
return ( await updateWorkSpace(payload).unwrap();
refetch()
setIsOpen(false);
} catch (error) {
console.error("Error updating template:", error);
alert("Failed to update template");
}
};
<DialogRoot placement="center"> return (
<DialogTrigger asChild> <DialogRoot placement="center" open={isOpen} onOpenChange={({ open }) => setIsOpen(open)}>
{/* <Button bg={"transparent"} size="sm"> <DialogTrigger asChild>
<MdOutlineRemoveRedEye style={{ cursor: "pointer", fontSize: "16px" }} /> <Box bg={"transparent"} onClick={handleOpenModal}>
</Button> */} <Edit />
<Button bg={"transparent"} size="sm"> </Box>
<FaRegEdit style={{ cursor: "pointer", fontSize: "14px" }} color="#000"/> </DialogTrigger>
</Button>
</DialogTrigger> <DialogContent
bg={"#fff"}
// w={{ lg: "60%", md: "230px" }}
w={{ base: "90%", md: "400px" }}
height={"auto"}
overflowX="hidden"
p={3} // Reduced padding
bgSize={"md"}
>
<DialogHeader bg="white">
<DialogTitle alignSelf="center" color="black" fontSize="14px">
Edit
</DialogTitle>
</DialogHeader>
<DialogContent <DialogBody bg="white">
bg={"#fff"} <Stack py={3}>
// w={{ lg: "60%", md: "230px" }} <Field.Root>
w={{ base: '90%', md: '400px' }} <Field.Label color="black" pt={1} fontSize="12px">
height={'auto'} Workspace Mode
</Field.Label>
overflowX="hidden" <Input
p={3} // Reduced padding value={title}
bgSize={'md'} bgColor="#EEEEEE"
> color="black"
<DialogHeader bg="white" > border="none"
<DialogTitle alignSelf="center" color="black" fontSize="14px">Edit</DialogTitle> pl={1}
</DialogHeader> fontSize="12px"
height="30px"
onChange={(e) => setTitle(e.target.value)}
/>
</Field.Root>
</Stack>
</DialogBody>
<DialogFooter display="flex" justifyContent="center" pt={"2"}>
<Button w="100%" bg="#02A0A0" color={"#fff"} onClick={handleSubmit}>
Save
</Button>
</DialogFooter>
<DialogBody bg="white"> <DialogCloseTrigger color="black" />
<Stack py={3}> </DialogContent>
</DialogRoot>
<Field.Root> );
<Field.Label color="black" pt={1} fontSize="12px">Workspace Mode</Field.Label>
<Input value="Lorem Ipsum" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" />
</Field.Root>
</Stack>
</DialogBody>
<DialogFooter display="flex" justifyContent="center" pt={"2"}>
<Button w="100%" bg="#02A0A0" color={"#fff"}>
Save
</Button>
</DialogFooter>
<DialogCloseTrigger color="black" />
</DialogContent>
</DialogRoot >
)
} }
export default EditWorkModel export default EditWorkModel;

View File

@@ -1,32 +1,67 @@
import { DialogBody, DialogCloseTrigger, DialogContent, DialogFooter, DialogHeader, DialogRoot, DialogTitle, DialogTrigger } from "../../../components/ui/dialog" import { DialogBody, DialogCloseTrigger, DialogContent, DialogFooter, DialogHeader, DialogRoot, DialogTitle, DialogTrigger } from "../../../components/ui/dialog"
import { Box, Field, IconButton, Input, Stack, Text, Textarea } from "@chakra-ui/react" import { Field, Input, Stack, Text } from "@chakra-ui/react"
import { IoMdAdd } from "react-icons/io" import { IoMdAdd } from "react-icons/io"
import { Button } from "../../../components/ui/button" import { Button } from "../../../components/ui/button"
import { useState } from "react";
import { useCreateWorkspacePostMutation } from "../../../Redux/Service/workspace.mode";
import { Toaster, toaster } from "../../../components/ui/toaster";
function WorkAddModel({ refetch }: { refetch: VoidFunction }) {
const [title, setTitle] = useState('')
const [isOpen, setIsOpen] = useState(false);
const [createWorkspacePost] = useCreateWorkspacePostMutation()
const handleOpenModal = () => {
setIsOpen(true);
};
const handleSubmit = async () => {
if (!title.trim()) {
toaster.create({
title: "Error",
description: "Title field cannot be empty.",
type: "error",
});
return;
}
const payload = {
en_name: title,
};
try {
await createWorkspacePost(payload);
refetch()
setIsOpen(false);
setTitle('')
} catch (error) {
console.error("Error updating template:", error);
alert("Failed to update template");
}
};
function WorkAddModel() {
return ( return (
<DialogRoot placement="center"> <DialogRoot placement="center" open={isOpen}>
<DialogTrigger asChild> <DialogTrigger asChild>
{/* <Button bg={"transparent"} size="sm"> {/* <Button bg={"transparent"} size="sm">
<MdOutlineRemoveRedEye style={{ cursor: "pointer", fontSize: "16px" }} /> <MdOutlineRemoveRedEye style={{ cursor: "pointer", fontSize: "16px" }} />
</Button> */} </Button> */}
<Button px={5} size={"xs"} bg={"#02A0A0"}> <Button px={5} size={"xs"} bg={"#02A0A0"} onClick={handleOpenModal}>
<IoMdAdd /> <Text>Add</Text> <IoMdAdd /> <Text>Add</Text>
</Button> </Button>
</DialogTrigger> </DialogTrigger>
<DialogContent <DialogContent
bg={"#fff"} bg={"#fff"}
// w={{ lg: "60%", md: "230px" }} // w={{ lg: "60%", md: "230px" }}
w={{ base: '90%', md: '400px' }} w={{ base: '90%', md: '400px' }}
height={'auto'} height={'auto'}
overflowX="hidden" overflowX="hidden"
p={3} // Reduced padding p={3} // Reduced padding
bgSize={'md'} bgSize={'md'}
> >
<DialogHeader bg="white" > <DialogHeader bg="white" >
<DialogTitle alignSelf="center" color="black" fontSize="14px">Add</DialogTitle> <DialogTitle alignSelf="center" color="black" fontSize="14px">Add</DialogTitle>
@@ -37,19 +72,30 @@ function WorkAddModel() {
<Field.Root> <Field.Root>
<Field.Label color="black" pt={1} fontSize="12px">Workspace Mode</Field.Label> <Field.Label color="black" pt={1} fontSize="12px">Workspace Mode</Field.Label>
<Input placeholder="" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" /> <Input
placeholder=""
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
value={title}
onChange={(e) => setTitle(e.target.value)}
/>
</Field.Root> </Field.Root>
</Stack> </Stack>
</DialogBody> </DialogBody>
<DialogFooter display="flex" justifyContent="center" pt={"2"}> <DialogFooter display="flex" justifyContent="center" pt={"2"}>
<Button w="100%" bg="#02A0A0" color={"#fff"}> <Button w="100%" bg="#02A0A0" color={"#fff"} onClick={handleSubmit}>
Save Save
</Button> </Button>
</DialogFooter> </DialogFooter>
<DialogCloseTrigger color="black" /> <DialogCloseTrigger color="black" onClick={() => setIsOpen(false)} />
</DialogContent> </DialogContent>
<Toaster />
</DialogRoot > </DialogRoot >
) )

View File

@@ -1,11 +1,13 @@
import { Box, HStack, Image, Input, Text } from "@chakra-ui/react"; import { Box, HStack, Text } from "@chakra-ui/react";
import MainFrame from "../../../components/MainFrame" import MainFrame from "../../../components/MainFrame"
import { InputGroup } from "../../../components/ui/input-group";
import { LuSearch } from "react-icons/lu";
import DataTable from "../../../components/DataTable"; import DataTable from "../../../components/DataTable";
import { Switch } from "../../../components/ui/switch"; import { Switch } from "../../../components/ui/switch";
import WorkAddModel from "./WorkAddModel"; import WorkAddModel from "./WorkAddModel";
import EditWorkModel from "./EditWorkModel"; import EditWorkModel from "./EditWorkModel";
import { useEffect, useState } from "react";
import { useGetWorkSpaceModeQuery, useWorkspaceToggleMutation } from "../../../Redux/Service/workspace.mode";
import SearchComponent from "../../../components/SearchComponent";
import { Toaster, toaster } from "../../../components/ui/toaster";
@@ -15,25 +17,95 @@ const tableHeadRow = [
"Sr. No", "Sr. No",
"Title", "Title",
"Action" "Action"
]; ];
const managepost: any[] = [ // const managepost: any[] = [
...Array.from({ length: 12 }, (_, i) => ({ // ...Array.from({ length: 12 }, (_, i) => ({
"Sr. No": i + 1, // "Sr. No": i + 1,
"Title": "Lorem Ipsum", // "Title": "Lorem Ipsum",
// "Action": (
// <HStack justifyContent="center">
// <EditWorkModel />
// <Box>
// <Switch colorPalette={'teal'} size={"xs"} />
// </Box>
// </HStack>
// ),
// })),
// ];
const WorkspaceMode = () => {
const [currentPage, setCurrentPage] = useState(1);
const { data, refetch } = useGetWorkSpaceModeQuery(currentPage)
const [localData, setLocalData] = useState<any[]>([]);
const [searchTerm, setSearchTerm] = useState("");
const [workspaceToggle] = useWorkspaceToggleMutation()
console.log("Workspace Data", data?.data.data)
useEffect(() => {
if (data?.data?.data) {
setLocalData(data?.data.data);
}
}, [data]);
const handlePageChange = (page: number) => {
setCurrentPage(page);
};
const handleToggle = async (agencyId: string, currentStatus: number) => {
const newStatus = currentStatus ? 0 : 1;
setLocalData((prevData) =>
prevData.map((agency) =>
agency.id === agencyId ? { ...agency, is_active: newStatus } : agency
)
);
try {
await workspaceToggle({ id: agencyId, is_active: newStatus }).unwrap();
refetch()
} catch (error) {
console.error("Error updating privacy policy:", error);
toaster.create({
title: "Error",
description: "Someting went wrong.",
type: "error",
});
setLocalData((prevData) =>
prevData.map((agency) =>
agency.id === agencyId ? { ...agency, is_active: currentStatus } : agency
)
);
}
};
const filteredData = localData?.filter((agency) => {
const searchLower = searchTerm.toLowerCase();
const title = agency.en_name?.toLowerCase().includes(searchLower);
return title;
});
const managepost = filteredData?.map((agency: any, index: number) => ({
'id': agency.id,
"Sr. No": (currentPage - 1) * (data?.data.per_page ?? 0) + index + 1,
"Title": agency.en_name,
"is_active": agency.is_active,
"Action": ( "Action": (
<HStack justifyContent="center"> <HStack justifyContent="center">
<EditWorkModel /> {/* <ViewAgencyMaster agency={localData} id={agency.id} /> */}
<EditWorkModel localData={agency} refetch={refetch} />
<Box> <Box>
<Switch colorPalette={'teal'} size={"xs"}/> <Switch
colorPalette={"teal"}
size={"xs"}
onChange={() => handleToggle(agency.id, Number(agency.is_active))}
checked={Boolean(Number(agency.is_active))}
/>
</Box> </Box>
</HStack> </HStack>
), ),
})), }));
];
const WorkspaceMode = () => {
return ( return (
<MainFrame> <MainFrame>
@@ -46,40 +118,36 @@ const WorkspaceMode = () => {
px={3} px={3}
> >
<Text as={"span"} fontSize={"sm"} fontWeight={500} color={"#000"}> <Text as={"span"} fontSize={"sm"} fontWeight={500} color={"#000"}>
Workspace Mode Workspace Mode
</Text> </Text>
<HStack mr={5}> <HStack >
<InputGroup marginRight={"1rem"} <SearchComponent
startElement={ value={searchTerm}
<LuSearch fontSize={"xs"} style={{ position: 'relative', left: '10px' }} /> onChange={(value) => {
} setSearchTerm(value);
color={"#000"} // setCurrentPage(1);
> refetch()
<Input }}
p={3} />
w={300}
bg={"#fff"}
colorPalette={"blue"}
_focus={{ border: "1px solid #02A0A0" }}
rounded={"md"}
size={"2xs"}
fontSize={"2sm"}
placeholder="Search..."
bgColor={'#EEEEEE'}
ps={8}
/>
</InputGroup>
{/* <Button bgColor={'#EEEEEE'} pl={3} pr={3}><IoMdAdd /> <Text>Add</Text></Button> */} {/* <Button bgColor={'#EEEEEE'} pl={3} pr={3}><IoMdAdd /> <Text>Add</Text></Button> */}
<WorkAddModel /> <WorkAddModel refetch={refetch}/>
</HStack> </HStack>
</HStack> </HStack>
<DataTable <DataTable
sortableColumns={["Name", "Registration Date "]} sortableColumns={["Name", "Registration Date "]}
tableHeadRow={tableHeadRow} tableHeadRow={tableHeadRow}
data={managepost} data={managepost}
paginationData={{
current_page: data?.data.current_page || 1,
last_page: data?.data.last_page || 1,
per_page: data?.data.per_page || 10,
total: data?.data.total || 0
}}
onPageChange={handlePageChange}
/> />
</Box> </Box>
<Toaster />
</MainFrame> </MainFrame>
) )
} }

View File

@@ -1,149 +0,0 @@
import { Center, HStack, Image, Input, Text, VStack } from "@chakra-ui/react";
import { useContext, useState } from "react";
import { useForm } from "react-hook-form";
import GlobalStateContext from "../../Contexts/GlobalStateContext";
import logo from "../../assets/logo.svg";
import { Button } from "../../components/ui/button";
import { Field } from "../../components/ui/field";
import { Toaster, toaster } from "../../components/ui/toaster";
interface FormValues {
password: string;
confirmPassword: string;
}
const CreatePass = () => {
const [isLoading, setIsLoading] = useState<boolean>(false);
const context = useContext(GlobalStateContext);
if (!context) {
throw new Error("App must be used within a GlobalStateProvider");
}
const { setIsAuthenticate } = context;
const {
register,
handleSubmit,
formState: { errors },
} = useForm<FormValues>();
const onSubmit = handleSubmit((data) => {
setIsLoading(true);
if (data?.password === "password123") {
setTimeout(() => {
setIsAuthenticate(true);
setIsLoading(false);
}, 3000);
} else {
toaster.create({
title: `Invalid Credentials`,
type: "error",
});
setIsLoading(false);
}
});
return (
<VStack w={"100%"} h={"100vh"} bg={"#ffffff"}>
<HStack
boxShadow={"rgba(99, 99, 99, 0.2) 0px 2px 8px 0px"}
w={"100%"}
ps={8}
h={"7%"}
justifyContent={"flex-start"}
>
<Image w={50} src={logo} />
</HStack>
<HStack w={"100%"} h={"93%"} p={8} gap={8}>
<Center
display={{ base: "none", md: "flex" }}
bg={"#02A0A033"}
w={"50%"}
h={"100%"}
rounded={"3xl"}
>
<Image w={250} src={logo} />
</Center>
<Center
as={"form"}
onSubmit={onSubmit}
p={{ base: 4, md: 16 }}
w={{ base: "100%", md: "50%" }}
h={"100%"}
>
<VStack gap={2} w={"100%"} alignItems={"flex-start"}>
<Text
w={"100%"}
textAlign={"center"}
fontSize={"24px"}
fontWeight={"normal"}
color={"#313039"}
textTransform={"uppercase"}
>
create a password
</Text>
<VStack mt={6} gap={4} w={"full"}>
<Field
color={"#313039"}
label={"Enter password"}
w={"100%"}
invalid={!!errors.password}
errorText={errors.password?.message}
>
<Input
ps={3}
type="password"
{...register("password", {
required: "Password is required",
minLength: {
value: 6,
message: "Password must be at least 6 characters long",
},
})}
placeholder="Enter your password"
/>
</Field>
<Field
color={"#313039"}
label={"Confirm password"}
w={"100%"}
invalid={!!errors.confirmPassword}
errorText={errors.confirmPassword?.message}
>
<Input
ps={3}
type="password"
{...register("confirmPassword", {
required: "Please confirm your password",
validate: (value) =>
value === getValues("password") || "Passwords do not match",
})}
placeholder="Confirm your password"
/>
</Field>
<Button
loading={isLoading}
mt={4}
size={"sm"}
bg={"#02A0A0"}
rounded={"md"}
w={"100%"}
color={"#ffffff"}
type="submit"
textTransform="capitalize"
>
Confirm Password
</Button>
<Text>Forgot password</Text>
</VStack>
</VStack>
</Center>
<Toaster />
</HStack>
</VStack>
);
};
export default CreatePass;

View File

@@ -1,142 +0,0 @@
import { Center, HStack, Image, Input, Text, VStack } from "@chakra-ui/react";
import { useContext, useState } from "react";
import { useForm } from "react-hook-form";
import GlobalStateContext from "../../Contexts/GlobalStateContext";
import logo from "../../assets/logo.svg";
import uiEdit from "../../assets/icons/edit.png";
import { Button } from "../../components/ui/button";
import { Field } from "../../components/ui/field";
import { Toaster, toaster } from "../../components/ui/toaster";
import { PinInput } from "../../components/ui/pin-input";
interface FormValues {
mobileNumber: number;
}
const LoginOtp = () => {
const [isLoading, setIsLoading] = useState<boolean>(false);
const context = useContext(GlobalStateContext);
if (!context) {
throw new Error("App must be used within a GlobalStateProvider");
}
const { setIsAuthenticate } = context;
const {
register,
handleSubmit,
formState: { errors },
} = useForm<FormValues>();
const onSubmit = handleSubmit((data) => {
setIsLoading(true);
if (data?.mobileNumber === 1234567890) {
setTimeout(() => {
setIsAuthenticate(true);
setIsLoading(false);
}, 3000); // 3-second delay
} else {
toaster.create({
title: `Invalid Credentials`,
type: "error",
});
setIsLoading(false);
}
});
return (
<VStack w={"100%"} h={"100vh"} bg={"#ffffff"}>
<HStack
boxShadow={"rgba(99, 99, 99, 0.2) 0px 2px 8px 0px"}
w={"100%"}
ps={8}
h={"7%"}
justifyContent={"flex-start"}
>
<Image w={50} src={logo} />
</HStack>
<HStack w={"100%"} h={"93%"} p={8} gap={8}>
<Center
display={{ base: "none", md: "flex" }}
bg={"#02A0A033"}
w={"50%"}
h={"100%"}
rounded={"3xl"}
>
<Image w={250} src={logo} />
</Center>
<Center
as={"form"}
onSubmit={onSubmit}
p={{ base: 4, md: 16 }}
w={{ base: "100%", md: "50%" }}
h={"100%"}
>
<VStack gap={2} w={"100%"} alignItems={"center"}>
<Text
w={"100%"}
textAlign={"center"}
fontSize={"24px"}
fontWeight={"normal"}
color={"#313039"}
>
Enter otp
</Text>
<Text
w={"100%"}
textAlign={"center"}
fontSize={"sm"}
fontWeight={"normal"}
color={"#49475A"}
>
OTP has been send to your E-mail Address
</Text>
<HStack>
<Image src={uiEdit} h="24px" w="24px" />
<Text
w={"100%"}
textAlign={"center"}
fontSize={"sm"}
fontWeight={"normal"}
color={"#49475A"}
>
9619565889
</Text>
</HStack>
<VStack mt={6} gap={4} w={"full"}>
<PinInput />
<Text
w={"100%"}
textAlign={"center"}
fontSize={"sm"}
fontWeight={"600"}
color={"#4746F4"}
textDecoration="underline"
>
Resend OTP
</Text>
<Button
loading={isLoading}
mt={4}
size={"sm"}
bg={"#02A0A0"}
rounded={"md"}
w={"100%"}
color={"#ffffff"}
type="submit"
>
Send OTP
</Button>
<Text>Forgot password</Text>
</VStack>
</VStack>
</Center>
<Toaster />
</HStack>
</VStack>
);
};
export default LoginOtp;

View File

@@ -1,57 +1,246 @@
import { DialogBody, DialogCloseTrigger, DialogContent, DialogFooter, DialogHeader, DialogRoot, DialogTitle, DialogTrigger } from "../../components/ui/dialog" import { DialogCloseTrigger, Field, IconButton, Input, Stack, Text } from "@chakra-ui/react";
import { Field, Grid, Heading, Input, Stack, Text } from "@chakra-ui/react"
import { FaRegEdit } from "react-icons/fa";
import { Button } from "../../components/ui/button"; import { Button } from "../../components/ui/button";
import EnterPassword from "./EnterPassword"; import { DialogBody, DialogContent, DialogFooter, DialogHeader, DialogRoot, DialogTitle, DialogTrigger } from "../../components/ui/dialog";
function Changepassword() { // import EnterPassword from "./EnterPassword";
import { useForm } from "react-hook-form";
import { useEffect, useState } from "react";
import { toaster } from "../../components/ui/toaster";
import { useNewPasswordSetMutation } from "../../Redux/Service/profile.password";
import { LuEye, LuEyeOff } from "react-icons/lu";
import { InputGroup } from "../../components/ui/input-group";
type EnterPasswordProps = {
onClose: () => void;
isOpen: boolean;
};
type FormData = {
new_password: string;
confirm_password: string;
};
function Changepassword({ onClose, isOpen }: EnterPasswordProps) {
const [showOldPassword, setShowOldPassword] = useState(false);
const [showNewPassword, setShowNewPassword] = useState(false);
const [newPasswordSet] = useNewPasswordSetMutation()
const [isLoading, setIsLoading] = useState(false);
const {
register,
handleSubmit,
formState: { errors },
setError,
clearErrors,
watch,
reset,
} = useForm<FormData>({
defaultValues: {
new_password: '',
confirm_password: ''
}
});
const newPassword = watch("new_password");
const confirmPassword = watch("confirm_password");
useEffect(() => {
if (newPassword && confirmPassword && newPassword !== confirmPassword) {
setError("confirm_password", {
type: "manual",
message: "Passwords do not match"
});
} else if (confirmPassword) {
clearErrors("confirm_password");
}
}, [newPassword, confirmPassword, setError, clearErrors]);
const onSubmit = async (data: FormData) => {
if (data.new_password === '' || data.confirm_password === '') {
return
}
if (data.new_password !== data.confirm_password) {
setError("confirm_password", {
type: "manual",
message: "Passwords do not match"
});
return;
}
console.log('ERROR', errors)
console.log('Change submitted:', data);
clearErrors("confirm_password");
setIsLoading(true);
const payload = {
new_password: data.new_password,
confirm_password: data.confirm_password
}
try {
const res = await newPasswordSet(payload).unwrap()
if (res.status === 'success') {
toaster.create({
title: "Password changed Successfully",
type: "success",
});
onClose()
} else {
toaster.create({
title: res.data.message || "Invalid password",
type: "error",
});
}
reset()
} catch (error: any) {
toaster.create({
title: error.data.message || "Something went wrong",
type: "error",
});
} finally {
setIsLoading(false);
}
};
return ( return (
<>
<DialogRoot placement="center"> <DialogRoot
<DialogTrigger asChild> placement="center"
<Button bg="#02A0A0" color={"#fff"} p={4} fontSize={"12px"} mt={2}> open={isOpen}
Change Password onOpenChange={(open) => !open && onClose()}
</Button>
</DialogTrigger>
<DialogContent
bg={"#fff"}
// w={{ lg: "60%", md: "230px" }}
w={{ base: '90%', md: '400px' }}
// height={'80vh'}
// overflow={'scroll'}
p={2} // Reduced padding
bgSize={'md'}
> >
<DialogHeader bg="white" pt={3} pb={2} >
<DialogTitle alignSelf="center" color="black" fontSize="18px" textAlign={"center"}>CHANGE PASSWORD</DialogTitle>
</DialogHeader>
<DialogBody bg="white" pt={5}> <DialogTrigger asChild>
<Stack p={2} > <Button bg="#02A0A0" size={'2xs'} color={"#fff"} px={2} >
<Field.Root> Change Password
<Field.Label color="black" pt={1} fontSize="12px">New password</Field.Label> </Button>
<Input color="black" pl={1} fontSize="12px" height="30px" type="password" border="1px solid grey" /></Field.Root> </DialogTrigger>
<Field.Root>
<Field.Label color="black" pt={1} fontSize="12px">Confirm password</Field.Label>
<Input color="black" pl={1} fontSize="12px" height="30px" type="password" border="1px solid grey" /></Field.Root>
</Stack> <DialogContent
</DialogBody> bg={"#fff"}
<DialogFooter display="flex" justifyContent="center" mt={2} p={2} w={{ base: '90%', md: '400px' }}
p={2}
bgSize={'md'}
> >
{/* <Button w="100%" bg="#02A0A0" color={"#fff"}> <DialogHeader bg="white" pt={3} pb={2} >
Save <DialogTitle alignSelf="center" color="black" fontSize="18px" textAlign={"center"}>CHANGE PASSWORD</DialogTitle>
</Button> */} </DialogHeader>
<EnterPassword /> <form onSubmit={handleSubmit(onSubmit)}>
</DialogFooter> <DialogBody bg="white" pt={5}>
<Stack p={2} >
<Field.Root>
<Field.Label color="black" pt={1} fontSize="12px">New password</Field.Label>
<InputGroup
width={'100%'}
endElement={
<IconButton
aria-label={showOldPassword ? "Hide password" : "Show password"}
size="sm"
// variant="outline"
onClick={() => setShowOldPassword(!showOldPassword)}
_hover={{ bg: "transparent" }}
height={'fit-content'}
mr={2}
>
{showOldPassword ? <LuEye /> : <LuEyeOff />}
</IconButton>
}>
<Input
color="black"
pl={1}
fontSize="12px"
height="30px"
type={showOldPassword ? "text" : "password"}
border={errors.new_password ? "1px solid red" : "1px solid grey"}
{...register("new_password", {
required: "Password is required",
minLength: {
value: 8,
message: "Password must be at least 8 characters",
},
})}
/>
</InputGroup>
{/* <IconButton
aria-label={showPassword ? "Hide password" : "Show password"}
size="sm"
variant="ghost"
onClick={() => setShowPassword(!showPassword)}
>
{showPassword ? <LuEye /> : <LuEyeOff />}
</IconButton> */}
{/* <DialogCloseTrigger color="black" /> */} {errors.new_password && (
</DialogContent> <Text color="red.500" fontSize="xs" mt={1}>
</DialogRoot > {errors.new_password.message}
</Text>
)}
</Field.Root>
<Field.Root>
<Field.Label color="black" pt={1} fontSize="12px">Confirm password</Field.Label>
<InputGroup
width={'100%'}
endElement={
<IconButton
aria-label={showNewPassword ? "Hide password" : "Show password"}
size="sm"
// variant="outline"
onClick={() => setShowNewPassword(!showNewPassword)}
_hover={{ bg: "transparent" }}
height={'fit-content'}
mr={2}
>
{showNewPassword ? <LuEye /> : <LuEyeOff />}
</IconButton>
}>
<Input
color="black"
pl={1}
fontSize="12px"
height="30px"
type= {showNewPassword ? "password" : "Text"}
border={errors.confirm_password ? "1px solid red" : "1px solid grey"}
{...register("confirm_password", {
required: "Please confirm your password",
validate: (value) =>
value === newPassword || "Passwords do not match",
})}
/>
</InputGroup>
{errors.confirm_password && (
<Text color="red.500" fontSize="xs" mt={1}>
{errors.confirm_password.message}
</Text>
)}
</Field.Root>
</Stack>
</DialogBody>
<DialogFooter display="flex" justifyContent="center" mt={2} p={2}
>
{/* <EnterPassword /> */}
<Button
loading={isLoading}
mt={6}
w="100%"
bg="#02A0A0"
color="white"
type="submit"
>
Submit
</Button>
</DialogFooter>
</form>
<DialogCloseTrigger color="black" />
</DialogContent>
</DialogRoot >
</>
) )
} }

View File

@@ -1,11 +1,87 @@
import { DialogBody, DialogContent, DialogFooter, DialogHeader, DialogRoot, DialogTitle, DialogTrigger } from "../../components/ui/dialog" import { DialogBody, DialogCloseTrigger, DialogContent, DialogFooter, DialogHeader, DialogRoot, DialogTitle } from "../../components/ui/dialog"
import { Box, Input, Stack, Text } from "@chakra-ui/react" import { Box, Input, Stack, Text } from "@chakra-ui/react"
import { Button } from "../../components/ui/button"; import { Button } from "../../components/ui/button";
import { useState } from "react"; import { useEffect, useState } from "react";
import { BiSolidEdit } from "react-icons/bi"; // import { BiSolidEdit } from "react-icons/bi";
import { Toaster, toaster } from "../../components/ui/toaster";
import { useGetProfileQuery, useResendOtpMutation, useVerifyOTPMutation } from "../../Redux/Service/profile.password";
import { useForm } from "react-hook-form";
import Changepassword from "./ChangePassword";
function EnterOTP() { type EnterOTPProps = {
const [otp, setOtp] = useState<string[]>(["", "", "", ""]); onClose: () => void;
isOpen: boolean;
};
type FormData = {
otp: string[];
};
function EnterOTP({ onClose, isOpen }: EnterOTPProps) {
const [isLoading, setIsLoading] = useState(false);
const [timer, setTimer] = useState(60);
const [isResendDisabled, setIsResendDisabled] = useState(true);
const [verifyOTP] = useVerifyOTPMutation()
const [otpSuccess, setOtpSuccess] = useState(false);
const [resendOtp] = useResendOtpMutation()
const { data } = useGetProfileQuery()
const id = data?.data.id
const {
register,
handleSubmit,
formState: { errors },
reset,
} = useForm<FormData>({
defaultValues: {
otp: ["", "", "", ""] // Initialize with empty strings for each digit
}
});
useEffect(() => {
let interval: NodeJS.Timeout;
if (timer > 0 && isResendDisabled) {
interval = setInterval(() => {
setTimer((prevTimer) => prevTimer - 1);
}, 1000);
} else if (timer === 0) {
setIsResendDisabled(false);
}
return () => clearInterval(interval);
}, [timer, isResendDisabled]);
const handleResendOTP = async () => {
setIsResendDisabled(true);
setTimer(60); // Reset timer to 1 minute
try {
const res = await resendOtp({ mobile_number: Number(id) }).unwrap()
if (res.status === 200) {
toaster.create({
title: "OTP resent successfully",
type: "success",
});
} else {
toaster.create({
title: res.data.message || "Failed to resend OTP",
type: "error",
});
setIsResendDisabled(false); // Enable button if failed
}
} catch (error: any) {
toaster.create({
title: error.response?.data?.message || "Failed to resend OTP",
type: "error",
});
setIsResendDisabled(false); // Enable button if error
}
};
// Handle change for OTP inputs // Handle change for OTP inputs
const handleChange = (e: React.ChangeEvent<HTMLInputElement>, index: number): void => { const handleChange = (e: React.ChangeEvent<HTMLInputElement>, index: number): void => {
@@ -15,94 +91,174 @@ function EnterOTP() {
if (/[^0-9]/.test(value)) return; if (/[^0-9]/.test(value)) return;
// Update the OTP state with the new value // Update the OTP state with the new value
const newOtp = [...otp]; // const newOtp = [...otp];
newOtp[index] = value; // newOtp[index] = value;
setOtp(newOtp); // setOtp(newOtp);
// Move focus to the next input automatically if (value && index < 3) {
if (value && index < otp.length - 1) {
const nextInput = document.getElementById(`otp-input-${index + 1}`) as HTMLInputElement; const nextInput = document.getElementById(`otp-input-${index + 1}`) as HTMLInputElement;
if (nextInput) nextInput.focus(); if (nextInput) nextInput.focus();
} }
// Move focus to the next input automatically
// if (value && index < otp.length - 1) {
// const nextInput = document.getElementById(`otp-input-${index + 1}`) as HTMLInputElement;
// if (nextInput) nextInput.focus();
// }
if (value === "" && index > 0) {
const prevInput = document.getElementById(`otp-input-${index - 1}`) as HTMLInputElement;
if (prevInput) prevInput.focus();
}
};
const onSubmit = async (data: FormData) => {
console.log('ERROR', errors)
if (data.otp.length !== 4) {
toaster.create({
title: "OTP must be 4 digits",
type: "error",
});
return;
}
const fullOtp = data.otp.join('');
console.log('OTP submitted:', fullOtp);
setIsLoading(true);
try {
const res = await verifyOTP({ otp: fullOtp }).unwrap()
if (res.status === 'success') {
toaster.create({
title: "OTP Verified Successfully",
type: "success",
});
setOtpSuccess(true);
reset();
} else {
toaster.create({
title: res.data.message || "Invalid OTP",
type: "error",
});
}
reset()
} catch (error: any) {
toaster.create({
title: error.data?.message || "Something went wrong",
type: "error",
});
setOtpSuccess(false);
} finally {
setIsLoading(false);
}
}; };
return ( return (
<>
<DialogRoot placement="center"> <DialogRoot placement="center"
<DialogTrigger asChild> open={isOpen}
<Button w="100%" bg="#02A0A0" color={"#fff"}> onOpenChange={(open) => !open && onClose()}>
Save {/* <DialogTrigger asChild>
</Button>
</DialogTrigger>
<DialogContent
bg={"#fff"}
// w={{ lg: "60%", md: "230px" }}
w={{ base: '90%', md: '400px' }}
// height={'80vh'}
// overflow={'scroll'}
p={2} // Reduced padding
bgSize={'md'}
>
<DialogHeader bg="white" pt={3}>
<DialogTitle alignSelf="center" color="black" fontSize="18px" textAlign={"center"}>ENTER OTP</DialogTitle>
</DialogHeader>
<DialogBody bg="white" pt={2}>
<Text color={"black"} textAlign={"center"}>OTP has been send to your E-mail Address</Text>
<Box display="flex" flexDirection="row" alignItems="center" justifyContent="center" p={3}>
<BiSolidEdit color="black" />
<Text color="black" textAlign="center" ml={2}>9619565889</Text>
</Box>
<Stack direction="row" justify="center" pt={2}>
{/* 4 OTP Inputs */}
{otp.map((digit, index) => (
<Input
key={index}
id={`otp-input-${index}`}
value={digit}
maxW="50px"
color={"black"}
textAlign="center"
fontSize="20px"
placeholder="0"
border="1px solid grey"
onChange={(e) => handleChange(e, index)}
maxLength={1} // Only allows 1 character per input
/>
))}
</Stack>
<Box textAlign="center">
<Text
color="#4746F4"
textDecoration="underline"
fontWeight="bold"
mt={3}
cursor="pointer"
display="inline-block"
px={2} // Adds padding for better appearance
>
Resend OTP
</Text>
</Box>
</DialogBody>
<DialogFooter display="flex" justifyContent="center" mt={2} p={2}
>
<Button w="100%" bg="#02A0A0" color={"#fff"}> <Button w="100%" bg="#02A0A0" color={"#fff"}>
Save Submit
</Button> </Button>
</DialogFooter>
{/* <DialogCloseTrigger color="black" /> */} </DialogTrigger> */}
</DialogContent>
</DialogRoot >
<DialogContent
bg={"#fff"}
// w={{ lg: "60%", md: "230px" }}
w={{ base: '90%', md: '400px' }}
// height={'80vh'}
// overflow={'scroll'}
p={2} // Reduced padding
bgSize={'md'}
>
<DialogHeader bg="white" pt={3} alignSelf="center">
<DialogTitle alignSelf="center" color="black" fontSize="18px" textAlign={"center"}>ENTER OTP</DialogTitle>
</DialogHeader>
<form onSubmit={handleSubmit(onSubmit)}>
<DialogBody bg="white" pt={2}>
<Text color={"black"} textAlign={"center"}>OTP has been sent successfully</Text>
{/* <Box display="flex" flexDirection="row" alignItems="center" justifyContent="center" p={3}>
<BiSolidEdit color="black" />
<Text color="black" textAlign="center" ml={2}>9619565889</Text>
</Box> */}
<Stack direction="row" justify="center" pt={2}>
{/* 4 OTP Inputs */}
{Array.from({ length: 4 }).map((_, index) => (
<Input
key={index}
id={`otp-input-${index}`}
maxW="50px"
color="black"
textAlign="center"
fontSize="20px"
placeholder="0"
border={errors.otp?.[index] ? "1px solid red" : "1px solid grey"}
maxLength={1}
{...register(`otp.${index}`, {
required: "Digit required",
pattern: {
value: /^[0-9]$/,
message: "Must be a single digit"
},
onChange: (e) => handleChange(e, index)
})}
/>
))}
</Stack>
<Box textAlign="center" mt={4}>
{isResendDisabled ? (
<Text color="gray.500">
Resend OTP in {timer} seconds
</Text>
) : (
<Text
color="#4746F4"
textDecoration="underline"
fontWeight="bold"
cursor="pointer"
onClick={handleResendOTP}
>
Resend OTP
</Text>
)}
</Box>
</DialogBody>
<DialogFooter display="flex" justifyContent="center" mt={2} p={2}
>
<Button
loading={isLoading}
mt={6}
w="100%"
bg="#02A0A0"
color="white"
type="submit"
>
Verify OTP
</Button>
</DialogFooter>
</form>
<DialogCloseTrigger color="black" />
</DialogContent>
</DialogRoot >
{otpSuccess && (<Changepassword
onClose={() => {
setOtpSuccess(false);
onClose()
}}
isOpen={otpSuccess}
/>)}
<Toaster />
</>
) )
} }

View File

@@ -1,53 +1,127 @@
import { DialogBody, DialogContent, DialogFooter, DialogHeader, DialogRoot, DialogTitle, DialogTrigger } from "../../components/ui/dialog" import { DialogBody, DialogCloseTrigger, DialogContent, DialogFooter, DialogHeader, DialogRoot, DialogTitle, DialogTrigger } from "../../components/ui/dialog"
import { Field, Input, Stack } from "@chakra-ui/react" import { Field, Input, Stack, Text } from "@chakra-ui/react"
import { useForm } from "react-hook-form";
import { Button } from "../../components/ui/button"; import { Button } from "../../components/ui/button";
import EnterOTP from "./EnterOTP"; import EnterOTP from "./EnterOTP";
import { useProfilePasswordMutation } from "../../Redux/Service/profile.password";
import { useState } from "react";
import { Toaster, toaster } from "../../components/ui/toaster";
type FormData = {
password: string;
};
function EnterPassword() { function EnterPassword() {
const [profilePassword] = useProfilePasswordMutation();
const [isSuccess, setIsSuccess] = useState(false);
const [isDialogOpen, setIsDialogOpen] = useState(false);
const {
register,
handleSubmit,
formState: { errors },
reset,
} = useForm<FormData>();
const onSubmit = async (data: FormData) => {
if (!data.password) {
return
}
try {
await profilePassword({ password: data.password }).unwrap();
setIsSuccess(true);
reset();
setIsDialogOpen(false);
// Handle success (e.g., show a success message or redirect)
} catch (error: any) {
// Handle error (e.g., show an error message)
toaster.create({
title: error?.data.message || "Invalid password",
type: "error",
});
console.error("Password change failed:", error.data.message);
setIsSuccess(false);
}
};
return ( return (
<>
<DialogRoot placement="center"> <DialogRoot placement="center"
<DialogTrigger asChild> open={isDialogOpen}
<Button w="100%" bg="#02A0A0" color={"#fff"}> onOpenChange={(details) => setIsDialogOpen(details.open)}
Save
</Button>
</DialogTrigger>
<DialogContent
bg={"#fff"}
// w={{ lg: "60%", md: "230px" }}
w={{ base: '90%', md: '400px' }}
// height={'80vh'}
// overflow={'scroll'}
p={2} // Reduced padding
bgSize={'md'}
> >
<DialogHeader bg="white" pt={3} pb={2} > <DialogTrigger asChild>
<DialogTitle alignSelf="center" color="black" fontSize="18px" textAlign={"center"}>ENTER PASSWORD</DialogTitle> <Button bg="#02A0A0" size={'2xs'} color={"#fff"} px={2} >
</DialogHeader> Change Password
</Button>
<DialogBody bg="white" pt={5}> </DialogTrigger>
<Stack p={2} > <DialogContent
<Field.Root> bg={"#fff"}
<Field.Label color="black" pt={1} fontSize="12px">Password</Field.Label> // w={{ lg: "60%", md: "230px" }}
<Input color="black" pl={1} fontSize="12px" height="30px" type="password" border="1px solid grey" /></Field.Root> w={{ base: '90%', md: '400px' }}
// height={'80vh'}
</Stack> // overflow={'scroll'}
</DialogBody> p={2} // Reduced padding
<DialogFooter display="flex" justifyContent="center" mt={2} p={2} bgSize={'md'}
> >
{/* <Button w="100%" bg="#02A0A0" color={"#fff"}> <DialogHeader bg="white" pt={3} pb={2} >
<DialogTitle alignSelf="center" color="black" fontSize="18px" textAlign={"center"}>ENTER PASSWORD</DialogTitle>
</DialogHeader>
<form onSubmit={handleSubmit(onSubmit)}>
<DialogBody bg="white" pt={5}>
<Stack p={2} >
<Field.Root>
<Field.Label color="black" pt={1} fontSize="12px">Password</Field.Label>
<Input
color="black"
pl={1}
fontSize="12px"
height="30px"
type="password"
border={errors.password ? "1px solid red" : "1px solid grey"}
{...register("password", {
required: "Password is required",
minLength: {
value: 8,
message: "Password must be at least 8 characters",
},
})}
/>
{errors.password && (
<Text color="red.500" fontSize="xs" mt={1}>
{errors.password.message}
</Text>
)}
</Field.Root>
</Stack>
</DialogBody>
<DialogFooter display="flex" justifyContent="center" mt={2} p={2}
>
{/* <Button w="100%" bg="#02A0A0" color={"#fff"}>
Save Save
</Button> */} </Button> */}
<EnterOTP /> <Button type="submit" w="100%" bg="#02A0A0" color={"#fff"}>
</DialogFooter> Submit
</Button>
</DialogFooter>
{/* <DialogCloseTrigger color="black" /> */} <DialogCloseTrigger color="black" />
</DialogContent> </form>
</DialogRoot > </DialogContent>
</DialogRoot >
{isSuccess && (<EnterOTP
onClose={() => {
setIsSuccess(false);
setIsDialogOpen(false);
}}
isOpen={isSuccess}
/>)
}
<Toaster />
</>
) )
} }

View File

@@ -1,10 +1,70 @@
import MainFrame from "../../components/MainFrame" import { Avatar, Box, HStack, Text, VStack } from "@chakra-ui/react";
import { FaCamera } from "react-icons/fa";
import EditableInput from "../../components/EditableInput";
import MainFrame from "../../components/MainFrame";
import { Field } from "../../components/ui/field";
// import Changepassword from "./ChangePassword";
import EnterPassword from "./EnterPassword";
import { useGetProfileQuery } from "../../Redux/Service/profile.password";
const Profile = () => { const Profile = () => {
const { data } = useGetProfileQuery()
console.log('PROFILE DATA:', data?.data);
return ( return (
<MainFrame > <MainFrame >
<HStack alignItems={'flex-start'} justifyContent={'center'} pt={0} h={'89vh'} w={'100%'} >
</MainFrame> <VStack w={'50%'} p={3} rounded={'lg'} mb={3}>
<HStack shadow={'md'} rounded={'lg'} justifyContent={'space-between'} alignItems={'flex-end'} w={'100%'} px={3} py={3} >
<VStack w={'100%'} alignItems={'flex-start'} gap={0}>
<Box mb={2} position="relative" width="fit-content"
cursor="pointer" onClick={() => alert("Avatar clicked!")}>
<Avatar.Root size={"2xl"} style={{ display: "inline-block", width: "auto" }}>
<Avatar.Fallback />
<Avatar.Image src="https://i.pinimg.com/736x/d6/cd/0f/d6cd0ffd4634b0763d3958a7325ce26e.jpg" />
</Avatar.Root>
<Box
position="absolute"
bottom="-2px"
left={"39px"}
p="2px"
>
<FaCamera color="#ccc" size={16} />
</Box>
</Box>
<Text color={"black"} as={'span'} fontSize={'sm'} fontWeight={"bold"}>{`${data?.data?.first_name.charAt(0).toUpperCase()}${data?.data.first_name.slice(1)}`}
</Text>
{/* <Text color="black" as={'span'} fontSize={'xs'}>
Employee ID: <span>#1245679</span>
</Text> */}
</VStack>
<EnterPassword />
{/* <Changepassword /> */}
</HStack>
<VStack w={"100%"} >
<Field mt={4} label="First Name" fontSize="xs" required>
<EditableInput value={`${data?.data.first_name}`} placeholder="Enter first name" isDisabled />
</Field>
<Field mt={4} label="Last Name" fontSize="xs" required>
<EditableInput value={`${data?.data.last_name}`} placeholder="Enter last name" isDisabled />
</Field>
<Field mt={4} label="Mobile Number" fontSize="xs" required>
<EditableInput value={`${data?.data.phone_number}`} placeholder="Mobile Number" type='number' isDisabled />
</Field>
</VStack>
</VStack>
</HStack>
</MainFrame >
) )
} }

View File

@@ -0,0 +1,197 @@
import {
Box,
Center,
HStack,
IconButton,
Image,
Input,
Stack,
Text,
VStack,
} from "@chakra-ui/react";
import axios from "axios";
import { useState } from "react";
import { useNavigate } from "react-router-dom";
import logo from "../assets/logo.svg";
import { Button } from "../components/ui/button";
import { toaster, Toaster } from "../components/ui/toaster";
import { InputGroup } from "../components/ui/input-group";
import { LuEye, LuEyeOff } from "react-icons/lu";
const SetNewPassword = () => {
const [password, setPassword] = useState("");
const [confirmPassword, setConfirmPassword] = useState("");
const [isLoading, setIsLoading] = useState(false);
const navigate = useNavigate();
const queryParams = new URLSearchParams(window.location.search);
const id = queryParams.get("id");
const [showOldPassword, setShowOldPassword] = useState(false);
const [showNewPassword, setShowNewPassword] = useState(false);
const handlePasswordSubmit = async () => {
// Validation
if (password.length < 8) {
toaster.create({
title: "Password must be at least 8 characters long",
type: "error",
});
return;
}
if (password !== confirmPassword) {
toaster.create({
title: "Passwords do not match",
type: "error",
});
return;
}
setIsLoading(true);
try {
const res = await axios.post(
`${import.meta.env.VITE_API_URL}/update-password`,
{
password: password,
confirm_password: confirmPassword,
id: Number(id),
}
);
if (res.data.status === "success") {
toaster.create({
title: "Password updated successfully",
type: "success",
});
navigate("/login"); // Redirect to login page
} else {
toaster.create({
title: res.data.message || "Failed to update password",
type: "error",
});
}
} catch (error: any) {
toaster.create({
title: error.response?.data?.message || "Something went wrong",
type: "error",
});
} finally {
setIsLoading(false);
}
};
return (
<VStack w="100%" h="100vh" bg="#ffffff">
<HStack
boxShadow="rgba(99, 99, 99, 0.2) 0px 2px 8px 0px"
w="100%"
ps={8}
h="7%"
justifyContent="flex-start"
>
<Image w={50} src={logo} />
</HStack>
<Center w="100%" h="93%" p={8}>
<Box p={8} borderWidth={1} borderRadius="lg" boxShadow="lg" w={"400px"}>
<Text
fontSize="20px"
fontWeight="bold"
color="#313039"
marginBottom={"20px"}
>
Create a Password
</Text>
<Stack>
<Box mb={3}>
<Text color="black" fontSize="12px" mb={2}>
New password
</Text>
<InputGroup
width={"100%"}
endElement={
<IconButton
aria-label={
showOldPassword ? "Hide password" : "Show password"
}
size="sm"
onClick={() => setShowOldPassword(!showOldPassword)}
// _hover={{ bg: "transparent" }}
bg={"transparent"}
color={"#000"}
height={"fit-content"}
mr={2}
>
{showOldPassword ? <LuEye /> : <LuEyeOff />}
</IconButton>
}
>
<Input
color="black"
pl={1}
fontSize="12px"
type={showOldPassword ? "password" : "text"}
border="1px solid grey"
value={password}
onChange={(e) => setPassword(e.target.value)}
size={"sm"}
/>
</InputGroup>
</Box>
<Box>
<Text color="black" mb={2} fontSize="12px">
Confirm password
</Text>
<InputGroup
width={"100%"}
endElement={
<IconButton
aria-label={
showNewPassword ? "Hide password" : "Show password"
}
size="sm"
// variant="outline"
onClick={() => setShowNewPassword(!showNewPassword)}
bg={"transparent"}
color={"#000"}
mr={2}
>
{showNewPassword ? <LuEye /> : <LuEyeOff />}
</IconButton>
}
>
<Input
color="black"
pl={1}
fontSize="12px"
type={showNewPassword ? "password" : "text"}
border="1px solid grey"
value={confirmPassword}
onChange={(e) => setConfirmPassword(e.target.value)}
size={"sm"}
/>
</InputGroup>
</Box>
</Stack>
<Button
loading={isLoading}
mt={6}
w="100%"
bg="#02A0A0"
color="white"
onClick={handlePasswordSubmit}
>
Confirm Password
</Button>
</Box>
</Center>
<Toaster />
</VStack>
);
};
export default SetNewPassword;

View File

@@ -1,80 +1,233 @@
import { Button } from "../../components/ui/button" import { Button } from "../../components/ui/button";
import { DialogBody, DialogCloseTrigger, DialogContent, DialogFooter, DialogHeader, DialogRoot, DialogTitle, DialogTrigger } from "../../components/ui/dialog" import {
import { Field, Grid, Heading, Input, Stack, Text } from "@chakra-ui/react" DialogBody,
import { IoMdAdd } from "react-icons/io" DialogCloseTrigger,
import { Checkbox } from "../../components/ui/checkbox" DialogContent,
DialogFooter,
DialogHeader,
DialogRoot,
DialogTitle,
DialogTrigger,
} from "../../components/ui/dialog";
import { Field, Grid, Heading, Input, Stack, Text } from "@chakra-ui/react";
import { IoMdAdd } from "react-icons/io";
import { Checkbox } from "../../components/ui/checkbox";
import { useCreateSubAdminPostMutation } from "../../Redux/Service/manage.subadmin.service";
import { toaster } from "../../components/ui/toaster";
import { useState } from "react";
function AddModel() { function AddModel({ refetch }: { refetch: VoidFunction }) {
return ( const [createSubAdminPost] = useCreateSubAdminPostMutation();
<DialogRoot placement="center"> // State fields
<DialogTrigger asChild> const [firstName, setFirstName] = useState("");
{/* <Button bg={"transparent"} size="sm"> const [lastName, setLastName] = useState("");
<MdOutlineRemoveRedEye style={{ cursor: "pointer", fontSize: "16px" }} /> const [userName, setUserName] = useState("");
</Button> */} const [dateOfBirth, setDateOfBirth] = useState("");
<Button px={4} size={"xs"} bg={"#02A0A0"}><IoMdAdd /> <Text>Add</Text></Button> const [gender, setGender] = useState("");
const [ setIsOpen] = useState(false);
</DialogTrigger> const handleSubmit = async () => {
if (
!firstName.trim() ||
!lastName.trim() ||
!userName.trim() ||
!dateOfBirth.trim() ||
!gender.trim()
) {
toaster.create({
title: "Error",
description: "Please fill in all required fields",
type: "error",
});
return;
}
<DialogContent const payload = {
bg={"#fff"} principal_type_xid: 4,
// w={{ lg: "60%", md: "230px" }} principal_source_xid: 1,
w={{ base: '90%', md: '400px' }} user_name: userName,
height={'80vh'} first_name: firstName,
overflow={'scroll'} last_name: lastName,
overflowX="hidden" date_of_birth: dateOfBirth,
p={3} // Reduced padding gender: gender,
bgSize={'md'} email_address: "example@yopmail.com", // Hardcoded
> phone_number: "9876543210", // Hardcoded
<DialogHeader bg="white" > created_by: 1,
<DialogTitle alignSelf="center" color="black" fontSize="14px" };
>Add Sub Admin Account</DialogTitle>
</DialogHeader>
<DialogBody bg="white"> try {
<Stack py={3} > const response = await createSubAdminPost(payload).unwrap();
if (response) {
toaster.create({
title: "Success",
description: "Sub-admin created successfully",
type: "success",
});
refetch();
setIsOpen(false);
setFirstName("");
setLastName("");
setUserName("");
setDateOfBirth("");
setGender("");
}
} catch (error) {
console.error("Error creating sub-admin:", error);
toaster.create({
title: "Error",
description: "Failed to create sub-admin",
type: "error",
});
}
};
<Field.Root> return (
<Field.Label color="black" pt={1} fontSize="12px">First Name</Field.Label> <DialogRoot placement="center">
<Input placeholder="Enter the First Name" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" /> <DialogTrigger asChild>
<Button rounded={"md"} px={4} py={2} size={"xs"} bg={"#02A0A0"}>
<IoMdAdd /> Add
</Button>
</DialogTrigger>
<Field.Label color="black" pt={1} fontSize="12px">Last Name</Field.Label> <DialogContent
<Input placeholder="Enter the Last Name" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" /> bg={"#fff"}
w={{ base: "90%", md: "400px" }}
height={"80vh"}
overflow={"scroll"}
overflowX="hidden"
p={3}
bgSize={"md"}
>
<DialogHeader bg="white">
<DialogTitle alignSelf="center" color="black" fontSize="14px">
Add Sub Admin Account
</DialogTitle>
</DialogHeader>
<Field.Label color="black" pt={1} fontSize="12px">DOB</Field.Label> <DialogBody bg="white">
<Input placeholder="Enter the DOB" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" /> <Stack py={3}>
<Field.Root>
<Field.Label color="black" pt={1} fontSize="12px">
First Name
</Field.Label>
<Input
placeholder="Enter the First Name"
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
value={firstName}
onChange={(e) => setFirstName(e.target.value)}
/>
<Field.Label color="black" pt={1} fontSize="12px">Gender</Field.Label> <Field.Label color="black" pt={1} fontSize="12px">
<Input placeholder="Enter the Gender" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" /> Last Name
<Heading mt={5} color={'#000'} fontSize={'sm'}>Permissions</Heading> </Field.Label>
</Field.Root> <Input
<Grid templateColumns="repeat(2, 1fr)" gap={4}> placeholder="Enter the Last Name"
<Checkbox size={'sm'} color={"black"} ><Text fontSize={12}>Dashboard</Text></Checkbox> bgColor="#EEEEEE"
<Checkbox size={'sm'} color={"black"} ><Text fontSize={12}>Manage contact us</Text></Checkbox> color="black"
<Checkbox size={'sm'} color={"black"} ><Text fontSize={12}>manage User</Text></Checkbox> border="none"
<Checkbox size={'sm'} color={"black"} ><Text fontSize={12}>Manage CMS</Text></Checkbox> pl={1}
<Checkbox size={'sm'} color={"black"} ><Text fontSize={12}>Manage Post</Text></Checkbox> fontSize="12px"
<Checkbox size={'sm'} color={"black"} ><Text fontSize={12}>Manage Reports</Text></Checkbox> height="30px"
<Checkbox size={'sm'} color={"black"} ><Text fontSize={12}>manage Sub-Admin</Text></Checkbox> value={lastName}
<Checkbox size={'sm'} color={"black"} ><Text fontSize={12}>My profile</Text></Checkbox> onChange={(e) => setLastName(e.target.value)}
<Checkbox size={'sm'} color={"black"} ><Text fontSize={12}>Manage Jobs</Text> </Checkbox> />
<Checkbox size={'sm'} color={"black"} ><Text fontSize={12}> manage feedbacks</Text></Checkbox>
<Checkbox size={'sm'} color={"black"} ><Text fontSize={12}>Manage community</Text> </Checkbox>
<Checkbox size={'sm'} color={"black"} ><Text fontSize={12}> Notification</Text></Checkbox>
</Grid>
</Stack>
</DialogBody>
<DialogFooter display="flex" justifyContent="center" pt={"2"}>
<Button w="100%" bg="#02A0A0" color={"#fff"}>
Save
</Button>
</DialogFooter>
<DialogCloseTrigger color="black" /> <Field.Label color="black" pt={1} fontSize="12px">
</DialogContent> Username
</DialogRoot > </Field.Label>
<Input
placeholder="Enter the Username"
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
value={userName}
onChange={(e) => setUserName(e.target.value)}
/>
) <Field.Label color="black" pt={1} fontSize="12px">
DOB
</Field.Label>
<Input
placeholder="Enter the DOB"
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
type="date"
value={dateOfBirth}
onChange={(e) => setDateOfBirth(e.target.value)}
/>
<Field.Label color="black" pt={1} fontSize="12px">
Gender
</Field.Label>
<Input
placeholder="Enter the Gender"
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
value={gender}
onChange={(e) => setGender(e.target.value)}
/>
<Heading mt={5} color={"#000"} fontSize={"sm"}>
Permissions
</Heading>
</Field.Root>
<Grid templateColumns="repeat(2, 1fr)" gap={4}>
{[
"Dashboard",
"Manage contact us",
"manage User",
"Manage CMS",
"Manage Post",
"Manage Reports",
"manage Sub-Admin",
"My profile",
"Manage Jobs",
"manage feedbacks",
"Manage community",
"Notification",
].map((permission) => (
<Checkbox size="sm" color="black" key={permission}>
<Text fontSize={12}>{permission}</Text>
</Checkbox>
))}
</Grid>
</Stack>
</DialogBody>
<DialogFooter display="flex" justifyContent="center" pt={"2"}>
<Button
size={"xs"}
w="100%"
bg="#02A0A0"
color={"#fff"}
onClick={handleSubmit}
>
Save
</Button>
</DialogFooter>
<DialogCloseTrigger color="black" />
</DialogContent>
</DialogRoot>
);
} }
export default AddModel export default AddModel;

View File

@@ -3,11 +3,15 @@ import MainFrame from "../../components/MainFrame"
import { InputGroup } from "../../components/ui/input-group" import { InputGroup } from "../../components/ui/input-group"
import { LuSearch } from "react-icons/lu" import { LuSearch } from "react-icons/lu"
import DataTable from "../../components/DataTable" import DataTable from "../../components/DataTable"
import AlertDailog from "../../components/AlertDailog" import AlertDailog from "../../components/AlertDailog";
import { RiDeleteBin5Line } from "react-icons/ri"; // import { RiDeleteBin5Line } from "react-icons/ri";
import AddModel from "./AddModel" import AddModel from "./AddModel"
import EditSubAdmin from "../../components/EditSubAdmin" import EditSubAdmin from "../../components/EditSubAdmin"
import ViewSubAdmin from "./ViewSubAdmin" import ViewSubAdmin from "./ViewSubAdmin"
import Delete from "../../components/ActionIcons/Delete"
import { useDeleteSubAdminPostMutation, useGetSubAdminQuery } from "../../Redux/Service/manage.subadmin.service"
import { useEffect, useState } from "react"
import { toaster } from "../../components/ui/toaster"
// table data // table data
@@ -22,39 +26,114 @@ const tableHeadRow = [
"Action", "Action",
]; ];
const managepost: any[] = [ // const managepost: any[] = [
...Array.from({ length: 12 }, (_, i) => ({ // ...Array.from({ length: 12 }, (_, i) => ({
"Sr. No": i + 1, // "Sr. No": i + 1,
"Id": 12565, // "Id": 12565,
"First Name": "Kamlesh", // "First Name": "Kamlesh",
"last Name": "Pandey", // "last Name": "Pandey",
"DOB": "12/01/1987", // "DOB": "12/01/1987",
"Gender": "Male", // "Gender": "Male",
// "Action": (
// <HStack justifyContent="center">
// <ViewSubAdmin />
// <EditSubAdmin />
// <AlertDailog
// AltertTiggerIcon={() => <Delete />}
// alertText="Delete Users"
// alertIcon={<Image src={"DeleteIcon"} h={"39px"} />}
// alertCaption="are you sure you want to delete ?"
// onConfirm={() => {
// console.log("User deleted:", i + 1);
// }}
// />
// </HStack>
// ),
// })),
// ];
const SubAdmin = () => {
const { data, refetch } = useGetSubAdminQuery()
const [localData, setLocalData] = useState<any[]>([]);
const [deleteModal, setDeleteModal] = useState(false)
const [deleteSubAdminPost] = useDeleteSubAdminPostMutation()
console.log("============================",data);
useEffect(() => {
if (data?.data.data) {
setLocalData(data?.data.data);
}
}, [data]);
console.log('localData', localData);
const handleDeleteFaq = async (faqId: number) => {
try {
const response = await deleteSubAdminPost(faqId).unwrap();
if (response.success) {
toaster.create({
title: "Success",
description: "FAQ deleted successfully",
type: "success",
});
refetch()
console.log("FAQ deleted successfully:", response);
}
// Optionally, refetch data or update state after deletion
} catch (error) {
console.error("Error deleting FAQ:", error);
toaster.create({
title: "Error",
description: "Something went wrong",
type: "error",
});
}
};
const formatDateOfBirth = (dob: string): string => {
return new Date(dob).toLocaleDateString("en-GB", {
day: "2-digit",
month: "2-digit",
year: "numeric",
});
};
const managepost = localData?.map((agency: any, index: number) => ({
'id': agency.id,
"Sr. No": index + 1,
"Id": agency.unique_id,
"First Name": agency.first_name,
"last Name": agency.last_name,
"DOB": formatDateOfBirth(agency.date_of_birth),
"Gender": agency.gender,
"Action": ( "Action": (
<HStack justifyContent="center"> <HStack justifyContent="center">
{/* <EditDetails rowData={{ id: agency.id, question: agency.question, answer: agency.answer }} refetch={refetch} /> */}
<ViewSubAdmin id={agency.id}/>
<EditSubAdmin id={agency.id} refetch={refetch} />
{/* <MdOutlineRemoveRedEye
style={{ cursor: "pointer", fontSize: "16px" }}
/> */}
{/* <ViewDailog /> */}
<ViewSubAdmin />
<EditSubAdmin />
{/* <RiDeleteBin5Line style={{ cursor: "pointer" }} /> */}
<AlertDailog <AlertDailog
AltertTiggerIcon={RiDeleteBin5Line} isOpen={deleteModal}
alertText="Delete Users" AltertTiggerIcon={() => <Delete onClick={() => setDeleteModal(prev => !prev)} />}
alertText="Delete FAQ"
alertIcon={<Image src={"DeleteIcon"} h={"39px"} />} alertIcon={<Image src={"DeleteIcon"} h={"39px"} />}
alertCaption="are you sure you want to delete ?" alertCaption="are you sure you want to delete ?"
onClose={() => setDeleteModal(false)}
onConfirm={() => { onConfirm={() => {
console.log("User deleted:", i + 1); // console.log("User deleted:", index + 1);
setDeleteModal(false);
handleDeleteFaq(agency.id)
}} }}
/> />
</HStack> </HStack>
), ),
})), }));
];
const SubAdmin = () => {
return ( return (
<MainFrame > <MainFrame >
@@ -71,7 +150,7 @@ const SubAdmin = () => {
</Text> </Text>
<HStack> <HStack>
<InputGroup <InputGroup
startElement={ startElement={
<LuSearch fontSize={"xs"} style={{ position: 'relative', left: '10px' }} /> <LuSearch fontSize={"xs"} style={{ position: 'relative', left: '10px' }} />
} }
@@ -81,11 +160,11 @@ const SubAdmin = () => {
p={3} p={3}
w={300} w={300}
bg={"#fff"} bg={"#fff"}
colorPalette={"blue"} colorPalette={"cyan"}
_focus={{ border: "1px solid #02A0A0" }} _focus={{ border: "1px solid #02A0A0" }}
rounded={"md"} rounded={"md"}
size={"2xs"} size={"xs"}
fontSize={"2sm"} fontSize={"sm"}
placeholder="Search..." placeholder="Search..."
bgColor={'#EEEEEE'} bgColor={'#EEEEEE'}
ps={8} ps={8}
@@ -99,6 +178,8 @@ const SubAdmin = () => {
sortableColumns={["Name", "Registration Date "]} sortableColumns={["Name", "Registration Date "]}
tableHeadRow={tableHeadRow} tableHeadRow={tableHeadRow}
data={managepost} data={managepost}
// paginationData={data?.data}
// refetch={refetch}
/> />
</Box> </MainFrame> </Box> </MainFrame>
) )

View File

@@ -1,82 +1,217 @@
import { Button } from "../../components/ui/button" // import { Button } from "../../components/ui/button";
import { DialogBody, DialogCloseTrigger, DialogContent, DialogFooter, DialogHeader, DialogRoot, DialogTitle, DialogTrigger } from "../../components/ui/dialog" import {
import { Field, Grid, Heading, Input, Stack, Text } from "@chakra-ui/react" DialogBody,
import { Checkbox } from "../../components/ui/checkbox" DialogCloseTrigger,
import { MdOutlineRemoveRedEye } from "react-icons/md"; DialogContent,
function ViewSubAdmin() { DialogFooter,
return ( DialogHeader,
DialogRoot,
DialogTitle,
DialogTrigger,
} from "../../components/ui/dialog";
import {
Field,
Grid,
Heading,
Input,
Stack,
Text,
} from "@chakra-ui/react";
import { Checkbox } from "../../components/ui/checkbox";
// import { MdOutlineRemoveRedEye } from "react-icons/md";
// import { FaRegEdit } from "react-icons/fa";
import View from "../../components/ActionIcons/View";
import { Button } from "../../components/ui/button";
import { useLazyViewSubAdminQuery } from "../../Redux/Service/manage.subadmin.service";
<DialogRoot placement="center" > function ViewSubAdmin({ id }: { id: number }) {
<DialogTrigger asChild> const [trigger, { data }] = useLazyViewSubAdminQuery();
<Button bg={"transparent"} size="sm">
<MdOutlineRemoveRedEye style={{ cursor: "pointer", }} color="#000"/>
</Button>
{/* <Button><FaRegEdit /></Button> */}
</DialogTrigger> const handleView = () => {
trigger(id)
}
const viewSubAdmin = data?.data
<DialogContent const formatDateOfBirth = (dob: string): string => {
bg={"#fff"} return new Date(dob).toLocaleDateString("en-GB", {
// w={{ lg: "60%", md: "230px" }} day: "2-digit",
w={{ base: '90%', md: '400px' }} month: "2-digit",
height={'80vh'} year: "numeric",
overflow={'scroll'} });
overflowX="hidden" };
p={3} // Reduced padding
bgSize={'md'}
>
<DialogHeader bg="white">
<DialogTitle alignSelf="center" color="black" fontSize="14px">View Sub Admin Account</DialogTitle>
</DialogHeader>
<DialogBody bg="white"> console.log('data', data?.data);
<Stack py={3} > return (
<DialogRoot placement="center">
<DialogTrigger asChild>
<Button
onClick={handleView}
bg={'transparent'}
color={"black"}
>
<View />
</Button>
</DialogTrigger>
<Field.Root> {viewSubAdmin?.map((data: any) => (
<Field.Label color="black" pt={1} fontSize="12px">First Name</Field.Label> <DialogContent
<Input value="Priyanka" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" readOnly /> bg={"#fff"}
// w={{ lg: "60%", md: "230px" }}
w={{ base: "90%", md: "400px" }}
height={"80vh"}
overflow={"scroll"}
overflowX="hidden"
p={3} // Reduced padding
bgSize={"md"}
>
<DialogHeader bg="white">
<DialogTitle alignSelf="center" color="black" fontSize="14px">
View Sub Admin Account
</DialogTitle>
</DialogHeader>
<Field.Label color="black" pt={1} fontSize="12px">Last Name</Field.Label> <DialogBody bg="white">
<Input value="Joshi" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" readOnly /> <Stack py={3}>
<Field.Root>
<Field.Label color="black" pt={1} fontSize="12px">
First Name
</Field.Label>
<Input
value={data.first_name}
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
readOnly
/>
<Field.Label color="black" pt={1} fontSize="12px">ID</Field.Label> <Field.Label color="black" pt={1} fontSize="12px">
<Input value="ID" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" readOnly /> Last Name
</Field.Label>
<Input
value={data.last_name}
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
readOnly
/>
<Field.Label color="black" pt={1} fontSize="12px">DOB</Field.Label> <Field.Label color="black" pt={1} fontSize="12px">
<Input value="11/02/1989" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" readOnly /> ID
</Field.Label>
<Input
value={data.unique_id}
bgColor="#EEEEEE"
color="black"
border="none"
pl={1}
fontSize="12px"
height="30px"
readOnly
/>
<Field.Label color="black" pt={1} fontSize="12px">Gender</Field.Label> <Field.Label color="black" pt={1} fontSize="12px">
<Input value="Male" bgColor="#EEEEEE" color="black" border="none" pl={1} fontSize="12px" height="30px" readOnly DOB
/> </Field.Label>
<Heading mt={5} color={'#000'} fontSize={'sm'}>Permissions</Heading> <Input
</Field.Root> value={formatDateOfBirth(data.date_of_birth)}
<Grid templateColumns="repeat(2, 1fr)" gap={4}> bgColor="#EEEEEE"
<Checkbox size={'sm'} color={"black"} ><Text fontSize={12}>Dashboard</Text></Checkbox> color="black"
<Checkbox size={'sm'} color={"black"}> <Text fontSize={12}>Manage contact us</Text></Checkbox> border="none"
<Checkbox size={'sm'} color={"black"}> <Text fontSize={12}>manage User</Text></Checkbox> pl={1}
<Checkbox size={'sm'} color={"black"}> <Text fontSize={12}>Manage CMS</Text></Checkbox> fontSize="12px"
<Checkbox size={'sm'} color={"black"}> <Text fontSize={12}>Manage Post</Text></Checkbox> height="30px"
<Checkbox size={'sm'} color={"black"}> <Text fontSize={12}>Manage Reports</Text></Checkbox> readOnly
<Checkbox size={'sm'} color={"black"}> <Text fontSize={12}>manage Sub-Admin</Text></Checkbox> />
<Checkbox size={'sm'} color={"black"}> <Text fontSize={12}>My profile</Text></Checkbox>
<Checkbox size={'sm'} color={"black"}><Text fontSize={12}>Manage Jobs</Text> </Checkbox> <Field.Label color="black" pt={1} fontSize="12px">
<Checkbox size={'sm'} color={"black"}><Text fontSize={12}> manage feedbacks</Text></Checkbox> Gender
<Checkbox size={'sm'} color={"black"}><Text fontSize={12}>Manage community</Text> </Checkbox> </Field.Label>
<Checkbox size={'sm'} color={"black"}><Text fontSize={12}> Notification</Text></Checkbox> <Input
</Grid> value={data.gender}
</Stack> bgColor="#EEEEEE"
</DialogBody> color="black"
<DialogFooter display="flex" justifyContent="center" pt={"2"} > border="none"
<Button w="100%" bg="#02A0A0" color={"#fff"}> pl={1}
fontSize="12px"
height="30px"
readOnly
/>
<Heading mt={5} color={"#000"} fontSize={"sm"}>
Permissions
</Heading>
</Field.Root>
<Grid templateColumns="repeat(2, 1fr)" gap={4}>
{data.get_resource_action_link.map((check: any) => (
<Checkbox size={"sm"} color={"black"} checked={check.is_active}>
<Text fontSize={12}>{check.app_resource_xid}</Text>
</Checkbox>
// <>
// <Checkbox size={"sm"} color={"black"}>
// <Text fontSize={12}>Dashboard</Text>
// </Checkbox>
// <Checkbox size={"sm"} color={"black"}>
// {" "}
// <Text fontSize={12}>Manage contact us</Text>
// </Checkbox>
// <Checkbox size={"sm"} color={"black"}>
// {" "}
// <Text fontSize={12}>manage User</Text>
// </Checkbox>
// <Checkbox size={"sm"} color={"black"}>
// {" "}
// <Text fontSize={12}>Manage CMS</Text>
// </Checkbox>
// <Checkbox size={"sm"} color={"black"}>
// {" "}
// <Text fontSize={12}>Manage Post</Text>
// </Checkbox>
// <Checkbox size={"sm"} color={"black"}>
// {" "}
// <Text fontSize={12}>Manage Reports</Text>
// </Checkbox>
// <Checkbox size={"sm"} color={"black"}>
// {" "}
// <Text fontSize={12}>manage Sub-Admin</Text>
// </Checkbox>
// <Checkbox size={"sm"} color={"black"}>
// {" "}
// <Text fontSize={12}>My profile</Text>
// </Checkbox>
// <Checkbox size={"sm"} color={"black"}>
// <Text fontSize={12}>Manage Jobs</Text>{" "}
// </Checkbox>
// <Checkbox size={"sm"} color={"black"}>
// <Text fontSize={12}> manage feedbacks</Text>
// </Checkbox>
// <Checkbox size={"sm"} color={"black"}>
// <Text fontSize={12}>Manage community</Text>{" "}
// </Checkbox>
// <Checkbox size={"sm"} color={"black"}>
// <Text fontSize={12}> Notification</Text>
// </Checkbox>
// </>
))}
</Grid>
</Stack>
</DialogBody>
<DialogFooter display="flex" justifyContent="center" pt={"2"}>
{/* <Button w="100%" bg="#02A0A0" color={"#fff"}>
Save Save
</Button> </Button> */}
</DialogFooter> </DialogFooter>
<DialogCloseTrigger color="black" /> <DialogCloseTrigger color="black" />
</DialogContent> </DialogContent>
</DialogRoot > ))}
</DialogRoot>
) );
} }
export default ViewSubAdmin export default ViewSubAdmin;

View File

@@ -0,0 +1,219 @@
import {
Box,
Center,
HStack,
Image,
Input,
Text,
VStack,
} from "@chakra-ui/react";
import axios from "axios";
import { useEffect, useState } from "react";
import { useNavigate, useLocation } from "react-router-dom";
import logo from "../assets/logo.svg";
import { Button } from "../components/ui/button";
import { toaster, Toaster } from "../components/ui/toaster";
const VerifyOTP = () => {
const [otp, setOtp] = useState<string[]>(["", "", "", ""]);
const [isLoading, setIsLoading] = useState(false);
const [timer, setTimer] = useState(60);
const [isResendDisabled, setIsResendDisabled] = useState(true);
const navigate = useNavigate();
const location = useLocation();
const queryParams = new URLSearchParams(location.search);
const phoneNumber = queryParams.get("phone");
useEffect(() => {
let interval: NodeJS.Timeout;
if (timer > 0 && isResendDisabled) {
interval = setInterval(() => {
setTimer((prevTimer) => prevTimer - 1);
}, 1000);
} else if (timer === 0) {
setIsResendDisabled(false);
}
return () => clearInterval(interval);
}, [timer, isResendDisabled]);
const handleResendOTP = async () => {
setIsResendDisabled(true);
setTimer(60); // Reset timer to 1 minute
try {
const res = await axios.post(`${import.meta.env.VITE_API_URL}/send-otp`, {
mobile_number: phoneNumber,
});
if (res.status === 200) {
toaster.create({
title: "OTP resent successfully",
type: "success",
});
} else {
toaster.create({
title: res.data.message || "Failed to resend OTP",
type: "error",
});
setIsResendDisabled(false); // Enable button if failed
}
} catch (error: any) {
toaster.create({
title: error.response?.data?.message || "Failed to resend OTP",
type: "error",
});
setIsResendDisabled(false); // Enable button if error
}
};
const handleChange = (e: React.ChangeEvent<HTMLInputElement>, index: number): void => {
const value = e.target.value;
// Prevent non-numeric input
if (/[^0-9]/.test(value)) return;
// Update the OTP state with the new value
const newOtp = [...otp];
newOtp[index] = value;
setOtp(newOtp);
// Move focus to the next input automatically
if (value && index < otp.length - 1) {
const nextInput = document.getElementById(`otp-input-${index + 1}`) as HTMLInputElement;
if (nextInput) nextInput.focus();
}
};
const handleOtpSubmit = async () => {
if (otp.length !== 4) {
toaster.create({
title: "OTP must be 4 digits",
type: "error",
});
return;
}
const fullOtp = otp.join('');
setIsLoading(true);
try {
const res = await axios.post(`${import.meta.env.VITE_API_URL}/verify-otp`, {
mobile_number: phoneNumber,
otp: fullOtp,
});
if (res.status === 200) {
toaster.create({
title: "OTP Verified Successfully",
type: "success",
});
const userid = res.data.data.id;
navigate(`/forgot-password/reset-password?id=${userid}`);
} else {
toaster.create({
title: res.data.message || "Invalid OTP",
type: "error",
});
}
} catch (error: any) {
toaster.create({
title: error.response?.data?.message || "Something went wrong",
type: "error",
});
} finally {
setIsLoading(false);
}
};
return (
<VStack w="100%" h="100vh" bg="#ffffff">
<HStack
boxShadow="rgba(99, 99, 99, 0.2) 0px 2px 8px 0px"
w="100%"
ps={8}
h="7%"
justifyContent="flex-start"
>
<Image w={50} src={logo} />
</HStack>
<Center w="100%" h="93%" p={8}>
<Box p={8} borderWidth={1} borderRadius="lg" boxShadow="lg">
<Text fontSize="24px" fontWeight="bold" color="#313039" textAlign="center">
Enter OTP
</Text>
<Text fontSize="14px" color="gray.600" textAlign="center" mt={2}>
OTP sent to {phoneNumber}
</Text>
<HStack gap={4} mt={6} justify="center">
{otp.map((digit, index) => (
<Input
key={index}
id={`otp-input-${index}`}
value={digit}
maxW="50px"
color={"black"}
textAlign="center"
fontSize="20px"
placeholder="0"
border="1px solid grey"
onChange={(e) => handleChange(e, index)}
maxLength={1} // Only allows 1 character per input
/>
))}
</HStack>
{/* <Box textAlign="center">
<Text
color="#4746F4"
textDecoration="underline"
fontWeight="bold"
mt={3}
cursor="pointer"
display="inline-block"
px={2}
>
Resend OTP
</Text>
</Box> */}
<Box textAlign="center" mt={4}>
{isResendDisabled ? (
<Text color="gray.500">
Resend OTP in {timer} seconds
</Text>
) : (
<Text
color="#4746F4"
textDecoration="underline"
fontWeight="bold"
cursor="pointer"
onClick={handleResendOTP}
>
Resend OTP
</Text>
)}
</Box>
<Button
loading={isLoading}
mt={6}
w="100%"
bg="#02A0A0"
color="white"
onClick={handleOtpSubmit}
>
Verify OTP
</Button>
</Box>
</Center>
<Toaster />
</VStack>
);
};
export default VerifyOTP;

View File

@@ -0,0 +1,102 @@
import { createApi } from "@reduxjs/toolkit/query/react";
import { baseQueryWithReauth } from "./apiSlice";
export interface Agency {
id: number;
name: string;
state: string;
rc_status: string;
rc_number: string;
domain_name: string;
gst_number: string;
is_active: boolean,
registered_office: string,
}
export interface AgencyData {
current_page: number;
data: Agency[];
first_page_url: string;
from: number;
last_page: number;
last_page_url: string;
per_page: number;
total: number;
}
export interface AgencyResponse {
status: "success" | "error";
status_code: number;
message: string;
data: AgencyData;
}
export interface UpdatePrivacyPolicyPayload {
id: number,
is_active: boolean,
}
export interface AgencyPost {
raid?: string;
name: string;
auth_signatory?: string;
state: string;
district?: string;
rc_number: string;
contact_details?: string;
registered_office: string;
branch_office?: string;
registered_email?: string;
other_email?: string;
registered_contact?: string;
website?: string;
domain_name: string;
staff_domain_name?: string;
gst_number: string;
rc_status?: "Active" | "Inactive"; // Assuming it's a status with limited values
}
export const agencyMasterModule = createApi({
reducerPath: "agencyMasterModule",
baseQuery: baseQueryWithReauth, // Use enhanced baseQuery with error handling
endpoints: (builder) => ({
createAgencyMasterPost: builder.mutation<AgencyPost, Partial<AgencyPost>>({
query: (data) => ({
url: "/agency-store",
method: "POST",
body: data,
}),
}),
getAgencyMaster: builder.query<AgencyResponse, number>({
query: (page = 1) => `/agency-master?page=${page}`
}),
agencyMasterToggle: builder.mutation({
query: ({ id, is_active }) => ({
url: `/agency-status`,
method: "POST",
body: { id, is_active },
}),
}),
updateAgencyMaster: builder.mutation({
query: (updatedData) => ({
url: "/agency-update",
method: "POST",
body: updatedData,
}),
}),
}),
});
export const {
useCreateAgencyMasterPostMutation,
useGetAgencyMasterQuery,
useAgencyMasterToggleMutation,
useUpdateAgencyMasterMutation,
} = agencyMasterModule;

View File

@@ -0,0 +1,75 @@
import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";
import { BaseQueryFn, FetchArgs, FetchBaseQueryError } from "@reduxjs/toolkit/query";
import { logout } from "./authSlice"; // Import logout action from authSlice
import { RootState } from "../Store";
const baseQuery = fetchBaseQuery({
baseUrl: `${import.meta.env.VITE_API_URL}`,
prepareHeaders: (headers, { getState }) => {
const token = (getState() as RootState).auth.token; // Get token from Redux store
// Encode Basic Auth Credentials
const username = import.meta.env.VITE_USER_NAME||''; // Replace with actual username
const password = import.meta.env.VITE_PASSWORD||''; // Replace with actual password
const basicAuth = `${username} : ${password}`; // Encode to Base64
if (token) {
headers.set("Authorization", `Basic ${basicAuth}`);
headers.set("access-token", `${token}`);
}
headers.set("Content-Type", "application/json");
return headers;
},
});
// ✅ Handle 401 Errors (Auto Logout)
export const baseQueryWithReauth: BaseQueryFn<
string | FetchArgs,
unknown,
FetchBaseQueryError
> = async (args, api, extraOptions) => {
const result = await baseQuery(args, api, extraOptions);
if (result.error && result.error.status === 401) {
api.dispatch(logout()); // Logout user on 401 error
}
return result;
};
export const dashboard = createApi({
reducerPath: "api",
baseQuery: baseQueryWithReauth, // Use enhanced baseQuery with error handling
endpoints: (builder) => ({
getPosts: builder.query<Post[], void>({ query: () => "/posts" }),
// 🔹 POST: Create a new post
logOut: builder.mutation<void, void>({
query: () => ({
url: "/logout",
method: "POST",
}),
}),
}),
});
export const { useGetPostsQuery, useLogOutMutation } = dashboard;
export type Post = {
id: number;
title: string;
body: string;
};

View File

@@ -0,0 +1,27 @@
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
type AuthState = {
token: string | null;
};
const initialState: AuthState = {
token: localStorage.getItem("token"), // Load token from localStorage
};
const authSlice = createSlice({
name: "auth",
initialState,
reducers: {
setToken: (state, action: PayloadAction<string>) => {
state.token = action.payload;
localStorage.setItem("token", action.payload); // ✅ Store token in localStorage
},
logout: (state) => {
state.token = null;
localStorage.removeItem("token"); // ✅ Remove token from localStorage on logout
},
},
});
export const { setToken, logout } = authSlice.actions;
export default authSlice.reducer;

View File

@@ -0,0 +1,110 @@
import { createApi } from "@reduxjs/toolkit/query/react";
import { baseQueryWithReauth } from "./apiSlice";
export interface CountryData {
id: number;
en_name: string;
hi_name: string;
mr_name: string;
te_name: string;
ta_name: string;
bn_name: string;
or_name: string;
country_code: string;
phonecode: string;
capital: string;
currency: string;
currency_name: string;
currency_symbol: string;
is_active: string;
}
interface ApiResponse {
status: string;
status_code: number;
message: string;
data: {
current_page: number,
last_page: number,
total: number,
from: number,
per_page: number,
to: number,
data: CountryData[];
};
}
export interface CountryEdit {
status: string;
status_code: number;
message: string;
data: CountryData[];
}
export type PostCountry = {
en_name: string;
country_code: string;
phonecode: string;
capital: string;
currency: string;
currency_name: string;
currency_symbol: string;
};
export const countryMaster = createApi({
reducerPath: "countryMaster",
baseQuery: baseQueryWithReauth, // Use enhanced baseQuery with error handling
endpoints: (builder) => ({
createCountryPost: builder.mutation<PostCountry, Partial<PostCountry>>({
query: (data) => ({
url: "/country-add",
method: "POST",
body: data,
}),
}),
// 🔹 GET: Fetch all posts
getCountryMaster: builder.query<ApiResponse, number>({
query: (page = 1) => `/country-list?page=${page}`,
}),
getCountryMasterEdit: builder.query<CountryEdit, number>({
query: (id) => `/country-edit/${id}`,
}),
updateCountry: builder.mutation({
query: (updatedData) => ({
url: "/country-update",
method: "POST",
body: updatedData,
}),
}),
countryToggle: builder.mutation({
query: ({ id, is_active }) => ({
url: `/country-status`,
method: "POST",
body: { id, is_active },
}),
}),
// deleteFaqPost: builder.mutation<{ status: string; message: string }, { id: number }>({
// query: ({ id }) => ({
// url: `/faq-delete`,
// method: "POST",
// body: { id },
// }),
// }),
}),
});
export const {
useGetCountryMasterQuery,
useGetCountryMasterEditQuery,
useCreateCountryPostMutation,
useUpdateCountryMutation,
useCountryToggleMutation,
// useDeleteFaqPostMutation
} = countryMaster;

View File

@@ -0,0 +1,30 @@
import { createApi } from "@reduxjs/toolkit/query/react"; // add /react for auto-generated hooks
import { baseQueryWithReauth } from "./apiSlice";
interface DeactivatedData {
id: number;
email: string;
first_name: string;
created_at: string;
}
interface ApiResponse {
data: {
data: DeactivatedData[];
};
}
export const deactivatedAccounts = createApi({
reducerPath: "deactivatedAccounts",
baseQuery: baseQueryWithReauth,
tagTypes: ["Deactivated"],
endpoints: (builder) => ({
getContact: builder.query<ApiResponse, void>({
query: () => "/manage-user-deactivate-list",
providesTags: ["Deactivated"],
}),
}),
});
// ✅ Export the auto-generated hook
export const { useGetContactQuery } = deactivatedAccounts;

View File

@@ -0,0 +1,109 @@
import { createApi } from "@reduxjs/toolkit/query/react";
import { baseQueryWithReauth } from "./apiSlice";
export interface DepartmentData {
id: number;
industry_masters_xid: number;
en_name: string;
hi_name: string;
mr_name: string;
te_name: string;
ta_name: string;
bn_name: string;
or_name: string;
is_active: string;
}
interface ApiResponse {
status: string;
status_code: number;
message: string;
data: {
current_page: number,
last_page: number,
total: number,
from: number,
per_page: number,
to: number,
data: DepartmentData[];
};
}
export interface CountryEdit {
status: string;
status_code: number;
message: string;
data: DepartmentData[];
}
export interface DropDown{
status: string;
status_code: number;
message: string;
data: {
id: number;
en_name: string;
}[]
}
export type PostDepartment = {
en_name: string;
industry_masters_xid: number;
};
export const departmentMaster = createApi({
reducerPath: "departmentMaster",
baseQuery: baseQueryWithReauth, // Use enhanced baseQuery with error handling
endpoints: (builder) => ({
createDepartmentPost: builder.mutation<PostDepartment, Partial<PostDepartment>>({
query: (data) => ({
url: "/department-master-store",
method: "POST",
body: data,
}),
}),
// 🔹 GET: Fetch all posts
getDepartmentMaster: builder.query<ApiResponse, number>({
query: (page = 1) => `/department-master-list?page=${page}`,
}),
getDepartmentMasterDropDown: builder.query<DropDown, void>({
query: () => `/industry-master-get-category`,
}),
updateDepartment: builder.mutation({
query: (updatedData) => ({
url: "/department-master-update",
method: "POST",
body: updatedData,
}),
}),
departmentToggle: builder.mutation({
query: ({ id, is_active }) => ({
url: `/department-master-status`,
method: "POST",
body: { id, is_active },
}),
}),
// deleteFaqPost: builder.mutation<{ status: string; message: string }, { id: number }>({
// query: ({ id }) => ({
// url: `/faq-delete`,
// method: "POST",
// body: { id },
// }),
// }),
}),
});
export const {
useGetDepartmentMasterQuery,
useGetDepartmentMasterDropDownQuery,
useCreateDepartmentPostMutation,
useUpdateDepartmentMutation,
useDepartmentToggleMutation,
// useDeleteFaqPostMutation
} = departmentMaster;

View File

@@ -0,0 +1,91 @@
import { createApi } from "@reduxjs/toolkit/query/react";
import { baseQueryWithReauth } from "./apiSlice";
export interface FaqData {
id: number;
principal_type_xid: number;
is_active: number;
translations:{
id: string,
faqs_xid: number,
language_master_xid: number,
question: string,
answer: string,
}[]
}
interface ApiResponse {
status: string;
status_code: number;
message: string;
data: {
current_page: number,
last_page: number,
total: number,
from: number,
per_page: number,
to: number,
data: FaqData[];
};
}
export type Post = {
principal_type_xid: number;
language_code: string;
question: string;
answer: string;
};
export const faqs = createApi({
reducerPath: "faqs",
baseQuery: baseQueryWithReauth, // Use enhanced baseQuery with error handling
endpoints: (builder) => ({
createFaqPost: builder.mutation<Post, Partial<Post>>({
query: (data) => ({
url: "/faq-store",
method: "POST",
body: data,
}),
}),
// 🔹 GET: Fetch all posts
getFaq: builder.query<ApiResponse, number>({
query: (page = 1) => `/faq-list?page=${page}`,
}),
updateFaq: builder.mutation({
query: (updatedData) => ({
url: "/faq-update",
method: "POST",
body: updatedData,
}),
}),
faqToggle: builder.mutation({
query: ({ id, is_active }) => ({
url: `/faq-status`,
method: "POST",
body: { id, is_active },
}),
}),
deleteFaqPost: builder.mutation<{ status: string; message: string }, { id: number }>({
query: ({ id }) => ({
url: `/faq-delete`,
method: "POST",
body: { id },
}),
}),
}),
});
export const {
useGetFaqQuery,
useCreateFaqPostMutation,
useUpdateFaqMutation,
useFaqToggleMutation,
useDeleteFaqPostMutation
} = faqs;

View File

@@ -0,0 +1,92 @@
import { createApi } from "@reduxjs/toolkit/query/react";
import { baseQueryWithReauth } from "./apiSlice";
interface IndustryMasterResponse {
status: string;
status_code: number;
message: string;
data: PaginationData;
}
interface PaginationData {
current_page: number;
data: IndustryMaster[];
first_page_url: string;
from: number;
last_page: number;
last_page_url: string;
links: PaginationLink[];
next_page_url: string | null;
path: string;
per_page: number;
prev_page_url: string | null;
to: number;
total: number;
}
export interface IndustryMaster {
id: number;
categories_masters_xid: number,
is_active: boolean;
en_name: string;
hi_name: string;
mr_name: string,
te_name: string,
ta_name: string,
bn_name: string,
or_name: string,
}
interface PaginationLink {
url: string | null;
label: string;
active: boolean;
}
export interface Post {
en_name: string,
categories_masters_xid: number
}
export const industryMaster = createApi({
reducerPath: "industryMaster",
baseQuery: baseQueryWithReauth, // Use enhanced baseQuery with error handling
endpoints: (builder) => ({
createIndustryMasterPost: builder.mutation<Post, Partial<Post>>({
query: (data) => ({
url: "/industry-master-store",
method: "POST",
body: data,
}),
}),
// 🔹 GET: Fetch all posts
getIndustryMaster: builder.query<IndustryMasterResponse, number>({
query: (page = 1) => `/industry-master-list?page=${page}`,
}),
updateIndustryMaster: builder.mutation({
query: (updatedData) => ({
url: "industry-master-update",
method: "POST",
body: updatedData,
}),
}),
industryMasterToggle: builder.mutation({
query: ({ id, is_active }) => ({
url: `/industry-master-status`,
method: "POST",
body: { id, is_active },
}),
}),
}),
});
export const {
useGetIndustryMasterQuery,
useCreateIndustryMasterPostMutation,
useUpdateIndustryMasterMutation,
useIndustryMasterToggleMutation,
} = industryMaster;

View File

@@ -0,0 +1,91 @@
import { createApi } from "@reduxjs/toolkit/query/react";
import { baseQueryWithReauth } from "./apiSlice";
export interface JobStatusData {
id: number;
is_active: string;
job_status_translation:{
job_status_xid: number,
title:string,
language_xid:number
}[],
}
interface ApiResponse {
status: string;
status_code: number;
message: string;
data: {
current_page: number,
last_page: number,
total: number,
from: number,
per_page: number,
to: number,
data: JobStatusData[];
};
}
export interface CountryEdit {
status: string;
status_code: number;
message: string;
data: JobStatusData[];
}
export type PostJobStatus = {
title: string
};
export const jobStatus = createApi({
reducerPath: "jobStatus",
baseQuery: baseQueryWithReauth, // Use enhanced baseQuery with error handling
endpoints: (builder) => ({
createJobStatusPost: builder.mutation<PostJobStatus, Partial<PostJobStatus>>({
query: (data) => ({
url: "/job-status-store",
method: "POST",
body: data,
}),
}),
// 🔹 GET: Fetch all posts
getJobStatus: builder.query<ApiResponse, number>({
query: (page = 1) => `/job-status-list?page=${page}`,
}),
updateJobStatus: builder.mutation({
query: (updatedData) => ({
url: "/job-status-update",
method: "POST",
body: updatedData,
}),
}),
jobStatusToggle: builder.mutation({
query: ({ id, is_active }) => ({
url: `/job-status-status`,
method: "POST",
body: { id, is_active },
}),
}),
// deleteFaqPost: builder.mutation<{ status: string; message: string }, { id: number }>({
// query: ({ id }) => ({
// url: `/faq-delete`,
// method: "POST",
// body: { id },
// }),
// }),
}),
});
export const {
useGetJobStatusQuery,
useCreateJobStatusPostMutation,
useUpdateJobStatusMutation,
useJobStatusToggleMutation,
// useDeleteFaqPostMutation
} = jobStatus;

View File

@@ -0,0 +1,90 @@
import { createApi } from "@reduxjs/toolkit/query/react";
import { baseQueryWithReauth } from "./apiSlice";
interface JobTypeResponse {
status: string;
status_code: number;
message: string;
data: PaginationData;
}
interface PaginationData {
current_page: number;
data: JobTypeData[];
first_page_url: string;
from: number;
last_page: number;
last_page_url: string;
links: PaginationLink[];
next_page_url: string | null;
path: string;
per_page: number;
prev_page_url: string | null;
to: number;
total: number;
}
export interface JobTypeData {
id: number;
is_active: boolean;
en_name: string;
hi_name: string;
mr_name:string,
te_name:string,
ta_name:string,
bn_name:string,
or_name:string,
}
interface PaginationLink {
url: string | null;
label: string;
active: boolean;
}
export interface Post {
en_name: string
}
export const jobType = createApi({
reducerPath: "jobType",
baseQuery: baseQueryWithReauth, // Use enhanced baseQuery with error handling
endpoints: (builder) => ({
createJobTypePost: builder.mutation<Post, Partial<Post>>({
query: (data) => ({
url: "/job-type-add",
method: "POST",
body: data,
}),
}),
// 🔹 GET: Fetch all posts
getJobType: builder.query<JobTypeResponse, number>({
query: (page = 1) => `/job-type?page=${page}`,
}),
updateJobType: builder.mutation({
query: (updatedData) => ({
url: "job-type-update",
method: "POST",
body: updatedData,
}),
}),
templateMasterToggle: builder.mutation({
query: ({ id, is_active }) => ({
url: `/template-status`,
method: "POST",
body: { id, is_active },
}),
}),
}),
});
export const {
useGetJobTypeQuery,
useCreateJobTypePostMutation,
useUpdateJobTypeMutation,
useTemplateMasterToggleMutation,
} = jobType;

View File

@@ -0,0 +1,88 @@
import { createApi } from "@reduxjs/toolkit/query/react";
import { baseQueryWithReauth } from "./apiSlice";
import { AboutUsResponse } from "../../Types/aboutUsType";
export const aboutUs = createApi({
reducerPath: "aboutUs",
baseQuery: baseQueryWithReauth, // Use enhanced baseQuery with error handling
endpoints: (builder) => ({
// 🔹 GET: Fetch all posts
getAboutUs: builder.query<AboutUsResponse, void>({
query: () => "/about-us",
}),
// 🔹 GET: Fetch a single post by ID
getPostById: builder.query<Post, number>({
query: (id) => `/posts/${id}`,
}),
// 🔹 POST: Create a new post
createPost: builder.mutation<Post, Partial<Post>>({
query: (data) => ({
url: "/posts",
method: "POST",
body: data,
}),
}),
// 🔹 PUT: Update an existing post
// updateAboutUs: builder.mutation<UpdateAboutUsResponse, UpdateAboutUsRequest>({
// query: ({ id, updatedData }) => ({
// url: `/posts/${id}`,
// method: "POST",
// body: updatedData,
// }),
// }),
// 🔹 PUT: Update an About Us entry
updateAboutUs: builder.mutation({
query: (updatedData) => ({
url: "/about-us/update", // ✅ Updated URL
method: "POST",
body: updatedData,
}),
}),
// 🔹 DELETE: Remove a post by ID
deletePost: builder.mutation<{ success: boolean }, number>({
query: (id) => ({
url: `/posts/${id}`,
method: "DELETE",
}),
}),
}),
});
export const {
useGetAboutUsQuery,
useUpdateAboutUsMutation,
useGetPostByIdQuery,
useCreatePostMutation,
useDeletePostMutation
} = aboutUs;
// Define Post type
export type Post = {
id: number;
title: string;
body: string;
};
export type UpdateAboutUsRequest={
id: number; updatedData: string,language_code:string
}
export type UpdateAboutUsResponse={
id: number; updatedData: string,language_code:string
}
export type AboutUs = {
id: number;
language_master_xid: number;
content: string;
is_active: boolean;
};

View File

@@ -0,0 +1,33 @@
import { createApi } from "@reduxjs/toolkit/query/react";
import { baseQueryWithReauth } from "./apiSlice";
interface ContactData {
id: number;
email: string;
first_name: string;
created_at: string;
}
interface ApiResponse {
data: {
data: ContactData[];
};
}
export const manageContactUs = createApi({
reducerPath: "manageContactUs",
baseQuery: baseQueryWithReauth, // Use enhanced baseQuery with error handling
tagTypes: ["Contact"],
endpoints: (builder) => ({
getContact: builder.query<ApiResponse, void>({
query: () => "/contact-us",
providesTags: ["Contact"],
}),
}),
});
export const { useGetContactQuery } = manageContactUs;

View File

@@ -0,0 +1,26 @@
import { createApi } from "@reduxjs/toolkit/query";
import { baseQueryWithReauth } from "./apiSlice";
export const manageGroups = createApi({
reducerPath: "manageGroups",
baseQuery: baseQueryWithReauth, // Use enhanced baseQuery with error handling
endpoints: (builder) => ({
getPosts: builder.query<Post[], void>({ query: () => "/posts" }),
}),
});
export const { } = manageGroups;
export type Post = {
id: number;
title: string;
body: string;
};

View File

@@ -0,0 +1,96 @@
import { createApi } from "@reduxjs/toolkit/query/react";
import { baseQueryWithReauth } from "./apiSlice";
export interface JobStatusData {
id: number;
job_title: string;
workspace_mode_xid: number;
industry_xid: number;
department_xid: number;
company_name: string;
ctc_currency_symbol: string;
ctc_amount: string;
experience: string;
job_location: string;
country_xid: number;
job_type_xid: number;
skill_description: string;
job_description: string;
job_image: string | null;
industry: {
id: number;
en_name: string;
};
department: {
id: number;
en_name: string;
};
workspace: {
id: number;
en_name: string;
};
country: {
id: number;
en_name: string;
};
job_type: {
id: number;
en_name: string;
};
}
interface ApiResponse {
status: string;
status_code: number;
message: string;
data: {
current_page: number,
last_page: number,
total: number,
from: number,
per_page: number,
to: number,
data: JobStatusData[];
};
}
export interface CountryEdit {
status: string;
status_code: number;
message: string;
data: JobStatusData[];
}
export type PostJobStatus = {
title: string
};
export const manageJobs = createApi({
reducerPath: "manageJobs",
baseQuery: baseQueryWithReauth, // Use enhanced baseQuery with error handling
endpoints: (builder) => ({
getManageJobs: builder.query<ApiResponse, number>({
query: (page = 1) => `/manage-jobs-list?page=${page}`,
}),
viewJobs: builder.query<ApiResponse, number>({
query: (id) => `/manage-jobs-list/${id}`,
}),
deleteJobsPost: builder.mutation<{ status: string; message: string }, { id: number }>({
query: ({ id }) => ({
url: `/manage-jobs-delete`,
method: "POST",
body: { id },
}),
}),
}),
});
export const { useGetManageJobsQuery,useLazyViewJobsQuery,useDeleteJobsPostMutation } = manageJobs;

View File

@@ -0,0 +1,82 @@
import { createApi } from "@reduxjs/toolkit/query/react";
import { baseQueryWithReauth } from "./apiSlice";
export interface JobStatusData {
id: number;
is_active: string;
created_at:string,
job_status_translation:{
job_status_xid: number,
title:string,
language_xid:number
}[],
}
interface ApiResponse {
status: string;
status_code: number;
message: string;
data: {
current_page: number,
last_page: number,
total: number,
from: number,
per_page: number,
to: number,
data: JobStatusData[];
};
}
export interface CountryEdit {
status: string;
status_code: number;
message: string;
data: JobStatusData[];
}
export type PostJobStatus = {
title: string
};
export const managePosts = createApi({
reducerPath: "managePosts",
baseQuery: baseQueryWithReauth, // Use enhanced baseQuery with error handling
endpoints: (builder) => ({
// createJobStatusPost: builder.mutation<PostJobStatus, Partial<PostJobStatus>>({
// query: (data) => ({
// url: "/job-status-store",
// method: "POST",
// body: data,
// }),
// }),
// 🔹 GET: Fetch all posts
getManagePosts: builder.query<ApiResponse, number>({
query: (page = 1) => `/manage-post-list?page=${page}`,
}),
postStatusToggle: builder.mutation({
query: ({ id, is_active }) => ({
url: `/manage-post-status`,
method: "POST",
body: { id, is_active },
}),
}),
// deleteFaqPost: builder.mutation<{ status: string; message: string }, { id: number }>({
// query: ({ id }) => ({
// url: `/faq-delete`,
// method: "POST",
// body: { id },
// }),
// }),
}),
});
export const {
useGetManagePostsQuery,
usePostStatusToggleMutation,
// useDeleteFaqPostMutation
} = managePosts;

View File

@@ -0,0 +1,173 @@
import { createApi } from "@reduxjs/toolkit/query/react";
import { baseQueryWithReauth } from "./apiSlice";
interface PaginationLink {
url: string | null;
label: string;
active: boolean;
}
interface UserData {
id: number;
unique_id: string;
user_name: string;
first_name: string;
last_name: string;
date_of_birth: string;
gender: string;
}
interface PaginatedData {
current_page: number;
data: UserData[];
first_page_url: string;
from: number;
last_page: number;
last_page_url: string;
links: PaginationLink[];
next_page_url: string | null;
path: string;
per_page: number;
prev_page_url: string | null;
to: number;
total: number;
}
interface ApiResponse {
status: string;
status_code: number;
message: string;
data: PaginatedData;
}
// export type SubAdminPost = {
// id: number;
// first_name: string,
// last_name: string,
// unique_id: string,
// date_of_birth: string,
// gender: string,
// }
interface ResourceActionLink {
id: number;
principal_xid: number;
role_xid: number;
app_resource_xid: number;
is_active: boolean;
created_by: number | null;
modified_by: number | null;
deleted_at: string | null;
created_at: string;
updated_at: string;
}
interface SubAdmin {
id: number;
first_name: string;
last_name: string;
unique_id: string;
date_of_birth: string;
gender: string;
get_resource_action_link: ResourceActionLink[];
}
interface SubAdminView {
status: string;
status_code: number;
message: string;
data: SubAdmin[];
}
interface CreateSubAdminPayload {
principal_type_xid: number;
principal_source_xid: number;
user_name: string;
first_name: string;
last_name: string;
date_of_birth: string;
gender: string;
email_address: string;
phone_number: string;
created_by: number;
}
interface CreateSubAdminResponse {
status: string;
status_code: number;
message: string;
data: UserData;
}
export const manageSubAdmin = createApi({
reducerPath: "manageSubAdmin",
baseQuery: baseQueryWithReauth, // Use enhanced baseQuery with error handling
tagTypes: ["SubAdmin"],
endpoints: (builder) => ({
createFaqPost: builder.mutation<Post, Partial<Post>>({
query: (data) => ({
url: "/faq-store",
method: "POST",
body: data,
}),
}),
getSubAdmin: builder.query<ApiResponse, void>({
query: () => `/sub-admin`,
}),
viewSubAdmin: builder.query<SubAdminView, number>({
query: (id) => `/sub-admin-view/${id}`,
}),
updateSubAdmin: builder.mutation({
query: (updatedData) => ({
url: "/sub-admin-update",
method: "POST",
body: updatedData,
}),
}),
createSubAdminPost: builder.mutation<
CreateSubAdminResponse,
CreateSubAdminPayload
>({
query: (data) => ({
url: "/sub-admin-create",
method: "POST",
body: data,
}),
invalidatesTags: ["SubAdmin"], // Add this to invalidate cache
}),
faqToggle: builder.mutation({
query: ({ id, is_active }) => ({
url: `/faq-status`,
method: "POST",
body: { id, is_active },
}),
}),
deleteSubAdminPost: builder.mutation<{ success: boolean }, number>({
query: (id) => ({
url: `/faq-delete/${id}`,
method: "DELETE",
}),
}),
}),
});
export const {
useGetSubAdminQuery,
useLazyViewSubAdminQuery,
useUpdateSubAdminMutation,
useDeleteSubAdminPostMutation,
useCreateSubAdminPostMutation,
} = manageSubAdmin;
export type Post = {
id: number;
title: string;
body: string;
};

Some files were not shown because too many files have changed in this diff Show More