Compare commits

...

87 Commits

Author SHA1 Message Date
victorAnumudu bce00b5c0e request message changed 2023-08-01 16:10:56 +01:00
ameye 312cd54f87 Merge branch 'pending-wrong-assign' of WrenchBoard/Users-Wrench into master 2023-08-01 14:47:44 +00:00
victorAnumudu a0c3437eae pending assign value changed 2023-08-01 15:42:28 +01:00
ameye 711226f913 Merge branch 'tx_ref-change' of WrenchBoard/Users-Wrench into master 2023-08-01 11:07:16 +00:00
Ebube f46c6232b0 updated error scenario for the modal header 2023-08-01 12:05:27 +01:00
Ebube 172f0ccbce cleanup 2 2023-08-01 11:46:33 +01:00
Ebube a2047cc2de clean up 2023-08-01 11:41:57 +01:00
Ebube 6ea52e6481 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into tx_ref-change 2023-08-01 11:38:26 +01:00
Ebube a7bbcfdc1b complete popup fixed 2023-08-01 11:37:56 +01:00
ameye ff28be3e70 Merge branch 'tx_ref-change' of WrenchBoard/Users-Wrench into master 2023-08-01 09:24:46 +00:00
Ebube e91b4a4424 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into tx_ref-change 2023-07-31 23:58:36 +01:00
Ebube 9960033b72 debounced success payment and and fixed credit refresh 2023-07-31 23:55:23 +01:00
ameye ef135f1a9b Merge branch 'tx_ref-change' of WrenchBoard/Users-Wrench into master 2023-07-31 17:56:15 +00:00
Ebube 1df6380c4a Correct Drop Down Style for naira withdrawal 2023-07-31 15:09:12 +01:00
Ebube fc8cf551e5 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into tx_ref-change 2023-07-31 14:47:15 +01:00
Ebube b1feb0438a still testing 2023-07-31 14:46:29 +01:00
ameye a89649f774 Merge branch 'amount-alignment' of WrenchBoard/Users-Wrench into master 2023-07-31 13:36:56 +00:00
victorAnumudu b96e8a3ed5 Merged master into amount-alignment 2023-07-31 14:23:57 +01:00
victorAnumudu f3226a6cfc amount alignment changed 2023-07-31 14:22:55 +01:00
ameye ff4c503100 Merge branch 'tx_ref-change' of WrenchBoard/Users-Wrench into master 2023-07-31 12:04:22 +00:00
Ebube f543a2d893 testing topupResult 2023-07-31 13:02:31 +01:00
ameye 41badd52be Merge branch 'list-alignment-fix' of WrenchBoard/Users-Wrench into master 2023-07-30 16:29:28 +00:00
victorAnumudu eeddd4e0a5 list alignment fixed 2023-07-30 06:10:44 +01:00
tokslaw ee4d136834 wrenchboard-logo-text + image added 2023-07-29 19:04:08 -04:00
tokslaw 283efa42b3 social comment added 2023-07-29 12:16:57 -04:00
tokslaw 5cbab4933c Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench 2023-07-29 12:13:14 -04:00
ameye 4de2181c18 Merge branch 'family-login-no-captcha' of WrenchBoard/Users-Wrench into master 2023-07-29 15:45:31 +00:00
ameye c8f0161a29 Merge branch 'tx_ref-change' of WrenchBoard/Users-Wrench into master 2023-07-29 15:45:26 +00:00
tokslaw 60222b6d88 text error correction 2023-07-29 11:11:23 -04:00
victorAnumudu 9ea3963239 family login captcha removed 2023-07-29 12:25:25 +01:00
Ebube a87592623b Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into tx_ref-change 2023-07-29 07:01:22 +01:00
Ebube bfcf53f763 Not selected should appear not selected 2023-07-29 07:00:50 +01:00
CHIEFSOFT\ameye df4489c6f2 removed start top up 2023-07-29 00:09:59 -04:00
CHIEFSOFT\ameye 37185812b4 Result added 2023-07-28 16:55:45 -04:00
ameye eb3e78244d Merge branch 'tx_ref-change' of WrenchBoard/Users-Wrench into master 2023-07-28 13:25:00 +00:00
Ebube b302d7ba57 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into tx_ref-change 2023-07-28 14:22:18 +01:00
ameye d6c16169d9 Merge branch 'Family-Tabs-Size-Fix' of WrenchBoard/Users-Wrench into master 2023-07-28 13:18:31 +00:00
Ebube 57129da0bd changed tx_ref number 2023-07-28 13:58:10 +01:00
Ebube 9eaf7123d4 reverse 2023-07-28 13:56:23 +01:00
Ebube 096da29149 Changed tx_ref no 2023-07-28 13:51:48 +01:00
CHIEFSOFT\ameye c8331c51cf removed debugger 2023-07-28 08:20:04 -04:00
tokslaw 3b7618702b env text-spell error 2023-07-27 17:04:57 -04:00
Ebube 84968b4435 balance refresh bug for withdraw 2023-07-27 16:28:21 +01:00
Ebube 98f11a3d80 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into Family-Tabs-Size-Fix 2023-07-27 16:18:29 +01:00
CHIEFSOFT\ameye 98d734e869 Post data 2023-07-27 11:17:15 -04:00
Ebube 47004fec8c Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into Family-Tabs-Size-Fix 2023-07-27 16:05:17 +01:00
CHIEFSOFT\ameye 48ce89489e console log 2023-07-27 11:04:01 -04:00
CHIEFSOFT\ameye 1ce05a3be3 add fund page 2023-07-27 11:01:22 -04:00
Ebube 28ab1116e9 Added Credit Limit & Pending Jobs Bug & removed reload for credit 2023-07-27 11:34:27 +01:00
ameye 994060d929 Merge branch 'Family-Tabs-Size-Fix' of WrenchBoard/Users-Wrench into master 2023-07-26 15:57:24 +00:00
Ebube a5c62564b7 Fixed tasks banner breaking 2023-07-26 16:54:31 +01:00
Ebube 22e61d2b41 Enforced send limit 2023-07-26 15:49:04 +01:00
ameye 6ab5eae0c0 Merge branch 'email-input-size' of WrenchBoard/Users-Wrench into master 2023-07-26 14:26:05 +00:00
victorAnumudu 3fbb47ee82 email input character size increased 2023-07-26 14:39:16 +01:00
ameye 3327b2b0df Merge branch 'Family-Tabs-Size-Fix' of WrenchBoard/Users-Wrench into master 2023-07-25 20:13:46 +00:00
Ebube ec204d0389 . 2023-07-25 20:50:56 +01:00
Ebube cb1259d2c8 Added loading height 2023-07-25 20:46:46 +01:00
Ebube 706cf141e7 Add Result Page 2023-07-25 20:26:33 +01:00
ameye 2229ebb9a0 Merge branch 'Family-Tabs-Size-Fix' of WrenchBoard/Users-Wrench into master 2023-07-25 11:17:32 +00:00
Ebube 05022c29b2 Remove the cause for the login error 2023-07-25 12:12:49 +01:00
ameye 9718cfc574 Merge branch 'job-listing-bug' of WrenchBoard/Users-Wrench into master 2023-07-25 10:39:59 +00:00
ameye aef082ac60 Merge branch 'Family-Tabs-Size-Fix' of WrenchBoard/Users-Wrench into master 2023-07-25 10:39:45 +00:00
victorAnumudu 754340fcba Merged master into job-listing-bug 2023-07-25 10:14:29 +01:00
Ebube 16afd4f90c Family Tab Sizes Fixed 2023-07-25 08:53:04 +01:00
ameye b69e2ff53b Merge branch 'blog-page' of WrenchBoard/Users-Wrench into master 2023-07-24 19:29:08 +00:00
victorAnumudu 4ac799f8c9 links to blog page added 2023-07-24 20:06:25 +01:00
ameye c93d3b61a6 Merge branch 'resource-ask-question' of WrenchBoard/Users-Wrench into master 2023-07-24 16:31:16 +00:00
ameye 4fb6dbf30f Merge branch 'my_wallet_layout' of WrenchBoard/Users-Wrench into master 2023-07-24 16:31:10 +00:00
victorAnumudu 11dc8fc659 resource ask question implemented 2023-07-24 15:34:29 +01:00
Ebube 4876ba80c1 Changed name to back 2023-07-24 15:07:22 +01:00
Ebube 71f799d157 Checked Errors in Wallet Page and made some tiny fixes 2023-07-24 15:01:03 +01:00
ameye 77c538ca79 Merge branch 'balance-refresh' of WrenchBoard/Users-Wrench into master 2023-07-24 11:07:41 +00:00
victorAnumudu 6b473b5dc6 wallet refresh 2023-07-24 11:58:09 +01:00
ameye 6aa11793a5 Merge branch 'my_wallet_layout' of WrenchBoard/Users-Wrench into master 2023-07-24 10:14:18 +00:00
victorAnumudu e098eb4626 job listing pagination bug fixed 2023-07-24 07:46:41 +01:00
Ebube 4f8edc3998 Improved solution for the credit refresh bug 2023-07-24 06:28:48 +01:00
Ebube 7dd805b804 Merge branch 'master' of https://gitlab.chiefsoft.net/WrenchBoard/Users-Wrench into my_wallet_layout 2023-07-24 06:15:43 +01:00
Ebube 2aa1219ea9 updated payload for new account 2023-07-24 06:15:22 +01:00
ameye c1a17949f7 Merge branch 'my_wallet_layout' of WrenchBoard/Users-Wrench into master 2023-07-23 23:40:59 +00:00
Ebube 24302c7435 Added New Login 2023-07-23 23:59:20 +01:00
CHIEFSOFT\ameye 27f4fda129 Added images 2023-07-23 07:47:54 -04:00
ameye 7ddef6d52d Merge branch 'notification-menu-close' of WrenchBoard/Users-Wrench into master 2023-07-23 10:20:40 +00:00
victorAnumudu 187ac61396 logged information removed 2023-07-23 07:18:56 +01:00
victorAnumudu 31297efb5b closes notification menu when see all notifications is clicked 2023-07-23 07:15:25 +01:00
ameye f8d6475ff8 Merge branch 'my_wallet_layout' of WrenchBoard/Users-Wrench into master 2023-07-22 23:21:04 +00:00
Ebube 22a45ac15e Added some fixes 2023-07-23 00:12:26 +01:00
ameye 0489be5e69 Merge branch 'notifications' of WrenchBoard/Users-Wrench into master 2023-07-22 22:44:03 +00:00
76 changed files with 1056 additions and 429 deletions
+1 -1
View File
@@ -46,7 +46,7 @@ REACT_APP_GOOGLE_REDIRECT_URL=http://localhost:9082/login/auth/
REACT_APP_FACEBOOK_CLIENT_ID2=390204307987009 REACT_APP_FACEBOOK_CLIENT_ID2=390204307987009
REACT_APP_FACEBOOK_CLIENT_SECRET2=19f778e312f2ab96d147bacb612910c2 REACT_APP_FACEBOOK_CLIENT_SECRET2=19f778e312f2ab96d147bacb612910c2
#developenet Account #development Account Social
REACT_APP_FACEBOOK_CLIENT_ID=677857427521030 REACT_APP_FACEBOOK_CLIENT_ID=677857427521030
REACT_APP_FACEBOOK_CLIENT_SECRET=4801375f22072d8a75f64483fdd89829 REACT_APP_FACEBOOK_CLIENT_SECRET=4801375f22072d8a75f64483fdd89829
Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 713 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

+1
View File
@@ -0,0 +1 @@
{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

+2
View File
@@ -56,6 +56,8 @@ export default function Routers() {
<Routes> <Routes>
{/* guest routes */} {/* guest routes */}
<Route exact path="/login" element={<LoginPage />} /> <Route exact path="/login" element={<LoginPage />} />
<Route exact path="/eoffer" element={<LoginPage />} />
<Route exact path="/signup" element={<SignupPage />} /> <Route exact path="/signup" element={<SignupPage />} />
<Route exact path="/login/auth" element={<AuthRedirect />} /> <Route exact path="/login/auth" element={<AuthRedirect />} />
<Route exact path="/login/auth/flogin" element={<FacebookRedirect />} /> <Route exact path="/login/auth/flogin" element={<FacebookRedirect />} />
Binary file not shown.

After

Width:  |  Height:  |  Size: 172 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

@@ -1,6 +1,6 @@
import React, { useState } from "react"; import React, { useState } from "react";
import { Link, useNavigate } from "react-router-dom"; import { Link, useNavigate } from "react-router-dom";
import WrenchBoard from "../../../assets/images/wrenchboard.png"; import WrenchBoard from "../../../assets/images/wrenchboard-logo-text.png";
import usersService from "../../../services/UsersService"; import usersService from "../../../services/UsersService";
import InputCom from "../../Helpers/Inputs/InputCom"; import InputCom from "../../Helpers/Inputs/InputCom";
import AuthLayout from "../AuthLayout"; import AuthLayout from "../AuthLayout";
+4 -2
View File
@@ -4,7 +4,7 @@ import linkedInLogo from "../../../assets/images/Linkedin.png";
import appleLogo from "../../../assets/images/apple-black.svg"; import appleLogo from "../../../assets/images/apple-black.svg";
import facebookLogo from "../../../assets/images/facebook-4.svg"; import facebookLogo from "../../../assets/images/facebook-4.svg";
import googleLogo from "../../../assets/images/google-logo.svg"; import googleLogo from "../../../assets/images/google-logo.svg";
import WrenchBoard from "../../../assets/images/wrenchboard.png"; import WrenchBoard from "../../../assets/images/wrenchboard-logo-text.png";
import usersService from "../../../services/UsersService"; import usersService from "../../../services/UsersService";
import InputCom from "../../Helpers/Inputs/InputCom"; import InputCom from "../../Helpers/Inputs/InputCom";
import AuthLayout from "../AuthLayout"; import AuthLayout from "../AuthLayout";
@@ -285,7 +285,7 @@ export default function Login() {
<InputCom <InputCom
labelClass="tracking-wider" labelClass="tracking-wider"
fieldClass="sm:px-6 px-2 tracking-[0.25em] text-2xl" fieldClass="sm:px-6 px-2 tracking-[0.25em] text-2xl"
value={password.replace(/./g, "●")} value={password}
inputHandler={handlePassword} inputHandler={handlePassword}
placeholder="● ● ● ● ● ●" placeholder="● ● ● ● ● ●"
label="Password" label="Password"
@@ -432,10 +432,12 @@ export default function Login() {
} }
{/* END of login component */} {/* END of login component */}
{loginType == "full" &&
<div className="pt-5 text-[#181c32] text-center font-semibold text-[13.975px] leading-[20.9625px]"> <div className="pt-5 text-[#181c32] text-center font-semibold text-[13.975px] leading-[20.9625px]">
This site is protected by hCaptcha and the our Privacy Policy This site is protected by hCaptcha and the our Privacy Policy
and Terms of Service apply. and Terms of Service apply.
</div> </div>
}
</div> </div>
</div> </div>
</div> </div>
+54 -10
View File
@@ -1,7 +1,6 @@
import React, { useCallback, useEffect, useState } from "react"; import React, { useCallback, useEffect, useState } from "react";
import { Link, useNavigate } from "react-router-dom"; import { Link, useNavigate } from "react-router-dom";
import facebookLogo from "../../../assets/images/facebook-4.svg"; import WrenchBoard from "../../../assets/images/wrenchboard-logo-text.png";
import WrenchBoard from "../../../assets/images/wrenchboard.png";
import usersService from "../../../services/UsersService"; import usersService from "../../../services/UsersService";
import InputCom from "../../Helpers/Inputs/InputCom"; import InputCom from "../../Helpers/Inputs/InputCom";
import AuthLayout from "../AuthLayout"; import AuthLayout from "../AuthLayout";
@@ -69,13 +68,17 @@ export default function SignUp() {
let regEx = /^[^0-9][a-zA-Z0-9._%+-]+@[a-zA-Z]+(\.[a-zA-Z]+)+$/; let regEx = /^[^0-9][a-zA-Z0-9._%+-]+@[a-zA-Z]+(\.[a-zA-Z]+)+$/;
if (regEx.test(email) == false) { if (regEx.test(email) == false) {
setMsgError("Invalid Email"); setMsgError("Invalid Email");
return setTimeout(()=>{setMsgError("");},3000) return setTimeout(() => {
setMsgError("");
}, 3000);
} }
//checks if terms and condition is checked //checks if terms and condition is checked
if (!checked) { if (!checked) {
setMsgError("Terms and condition required"); setMsgError("Terms and condition required");
return setTimeout(()=>{setMsgError("");},3000) return setTimeout(() => {
setMsgError("");
}, 3000);
} }
setSignUpLoading(true); setSignUpLoading(true);
@@ -95,7 +98,9 @@ export default function SignUp() {
if (res.status === 200) { if (res.status === 200) {
const { data } = res; const { data } = res;
if (data && data.acc === "DULPICATE") { if (data && data.acc === "DULPICATE") {
setMsgError("Unable to use this username. Please try another username."); setMsgError(
"Unable to use this username. Please try another username."
);
setSignUpLoading(false); setSignUpLoading(false);
} }
if (data && data.status === "1") { if (data && data.status === "1") {
@@ -211,10 +216,8 @@ export default function SignUp() {
name="password" name="password"
type={showPassword ? "text" : "password"} type={showPassword ? "text" : "password"}
onClick={togglePasswordVisibility} onClick={togglePasswordVisibility}
passIcon={ passIcon={showPassword ? "show-password" : "hide-password"}
showPassword ? "show-password" : "hide-password" value={formData.password}
}
value={formData.password.replace(/./g, "●")}
inputHandler={handleInputChange} inputHandler={handleInputChange}
/> />
</div> </div>
@@ -223,7 +226,48 @@ export default function SignUp() {
{msgError} {msgError}
</div> </div>
)} )}
<div className="forgot-password-area flex justify-between items-center mb-6"> <div className="forgot-password-area flex justify-between items-center mb-6">
<div className="remember-checkbox flex items-center space-x-2.5 group cursor-pointer">
<button
onClick={rememberMe}
type="button"
className={`w-6 h-6 border-[#4687ba] text-white flex justify-center items-center border rounded-[.45em] group-checked:text-white transition-all duration-200 group-checked:cursor-default ${
checked && "text-white bg-[#4687ba]"
}`}
>
{checked && (
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-5 w-5"
viewBox="0 0 20 20"
fill="currentColor"
>
<path
fillRule="evenodd"
d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z"
clipRule="evenodd"
/>
</svg>
)}
</button>
<span
onClick={rememberMe}
className="cursor-default text-dark-gray dark:text-white text-[15px] group-checked:text-white transition-all duration-200 group-checked:cursor-default"
>
I agree with all
<Link
href="#"
className="text-base text-[#4687ba] hover:text-[#009ef7] mx-1 inline-block"
>
terms and condition
</Link>
</span>
</div>
</div>
{/* Forgot Password */}
{/* <div className="forgot-password-area flex justify-between items-center mb-6">
<div className="remember-checkbox flex items-center space-x-2.5"> <div className="remember-checkbox flex items-center space-x-2.5">
<button <button
onClick={rememberMe} onClick={rememberMe}
@@ -258,7 +302,7 @@ export default function SignUp() {
</Link> </Link>
</span> </span>
</div> </div>
</div> </div> */}
<div className="signin-area mb-1"> <div className="signin-area mb-1">
<div className="flex justify-center"> <div className="flex justify-center">
<button <button
@@ -1,6 +1,6 @@
import { useCallback, useEffect, useState } from "react"; import { useCallback, useEffect, useState } from "react";
import { Link, useLocation, useNavigate } from "react-router-dom"; import { Link, useLocation, useNavigate } from "react-router-dom";
import WrenchBoard from "../../../assets/images/wrenchboard.png"; import WrenchBoard from "../../../assets/images/wrenchboard-logo-text.png";
import debounce from "../../../hooks/debounce"; import debounce from "../../../hooks/debounce";
import usersService from "../../../services/UsersService"; import usersService from "../../../services/UsersService";
import InputCom from "../../Helpers/Inputs/InputCom"; import InputCom from "../../Helpers/Inputs/InputCom";
@@ -1,6 +1,6 @@
import { useState } from "react"; import { useState } from "react";
import { Link, useLocation, useNavigate } from "react-router-dom"; import { Link, useLocation, useNavigate } from "react-router-dom";
import WrenchBoard from "../../../assets/images/wrenchboard.png"; import WrenchBoard from "../../../assets/images/wrenchboard-logo-text.png";
import usersService from "../../../services/UsersService"; import usersService from "../../../services/UsersService";
import InputCom from "../../Helpers/Inputs/InputCom"; import InputCom from "../../Helpers/Inputs/InputCom";
import AuthLayout from "../AuthLayout"; import AuthLayout from "../AuthLayout";
+1 -1
View File
@@ -1,6 +1,6 @@
import { useNavigate, Link } from "react-router-dom"; import { useNavigate, Link } from "react-router-dom";
import AuthLayout from "../AuthLayout"; import AuthLayout from "../AuthLayout";
import WrenchBoard from "../../../assets/images/wrenchboard.png"; import WrenchBoard from "../../../assets/images/wrenchboard-logo-text.png";
export default function VerifyYou() { export default function VerifyYou() {
const navigate = useNavigate(); const navigate = useNavigate();
+58 -20
View File
@@ -1,38 +1,76 @@
import React, { useState } from "react"; import React, { useEffect, useState } from "react";
import { Link } from "react-router-dom"; import { Link, useNavigate } from "react-router-dom";
import Layout from "../Partials/Layout"; import Layout from "../Partials/Layout";
import CommonHead from "../UserHeader/CommonHead"; import CommonHead from "../UserHeader/CommonHead";
import usersService from "../../services/UsersService";
import LoadingSpinner from "../Spinners/LoadingSpinner";
export default function BlogItem(props) { export default function BlogItem(props) {
const apiCall = new usersService()
const navigate = useNavigate()
const [blogdata, setBlogdata] = useState({loading: true, data:{}})
const [selectTab, setValue] = useState("today"); const [selectTab, setValue] = useState("today");
const filterHandler = (value) => { const filterHandler = (value) => {
setValue(value); setValue(value);
}; };
const queryParams = new URLSearchParams(location?.search);
const blog_id = queryParams.get("blog_id");
useEffect(()=>{
if(!blog_id){
navigate('/',{replace:true})
}
apiCall.getSingleBlogData({blog_id}).then(res => {
setBlogdata({loading: false, data:res.data})
}).catch(error => {
setBlogdata({loading: false, data:{}})
console.log('ERROR', error)
})
},[blog_id])
return ( return (
<Layout> <Layout>
<CommonHead <CommonHead
commonHeadData={props.commonHeadData} commonHeadData={props.commonHeadData}
/> />
<div className="notification-page w-full mb-10"> <div className="notification-page w-full mb-10">
<div className="notification-wrapper w-full"> <div className="mb-5">
{/* heading */} <h1 className="text-26 font-bold text-dark-gray dark:text-white">
<div className="sm:flex justify-between items-center mb-6"> <span
<div className="mb-5 sm:mb-0"> className={`${selectTab === "today" ? "block" : "hidden"}`}
<h1 className="text-26 font-bold text-dark-gray dark:text-white"> >
<span {blogdata.data?.blogdata?.[0]?.post_title}
className={`${selectTab === "today" ? "block" : "hidden"}`} </span>
> </h1>
Title of this Blog Items </div>
</span> <div className="notification-wrapper w-full bg-white p-8 rounded-2xl">
</h1> {blogdata.loading ?
</div> <LoadingSpinner size='8' color='sky-blue' height='h-[100px]' />
<div className="slider-btns flex space-x-4"> :
blogdata?.data?.blogdata && blogdata.data?.blogdata.length ?
</div> <div className="w-full">
{/* heading */}
<div className="sm:flex justify-between items-center mb-6">
{/* <div className="mb-5">
<h1 className="text-26 font-bold text-dark-gray dark:text-white">
<span
className={`${selectTab === "today" ? "block" : "hidden"}`}
>
{blogdata.data?.blogdata?.[0]?.post_title}
</span>
</h1>
</div> */}
{/* <div className="slider-btns flex space-x-4">
</div> */}
</div>
<div dangerouslySetInnerHTML={{__html: blogdata.data?.blogdata?.[0]?.post_content}}>
</div>
</div> </div>
<div> :
Blog Items Details need implenet <h1 className="text-26 font-bold text-dark-gray dark:text-white">No Blog Found!</h1>
</div> }
</div> </div>
</div> </div>
</Layout> </Layout>
@@ -16,7 +16,8 @@ export default function HomeBannerOffersCard(props) {
return ( return (
<Link <Link
to={link_result} // to={link_result}
to={link_result == '/blog-page' ? `${link_result}?blog_id=${props.itemData.blog_id}` : `${link_result}`}
className="item p-2 w-full flex items-center min-h-[340px] bg-alice-blue bg-cover bg-center" className="item p-2 w-full flex items-center min-h-[340px] bg-alice-blue bg-cover bg-center"
style={{ style={{
backgroundImage: `url('${imageUrl}')`, backgroundImage: `url('${imageUrl}')`,
+1 -1
View File
@@ -19,7 +19,7 @@ export default function OfferCard({ datas, hidden = false, setOfferPopout }) {
className="thumbnail w-full h-full rounded-xl overflow-hidden px-4 pt-4" className="thumbnail w-full h-full rounded-xl overflow-hidden px-4 pt-4"
style={{ style={{
background: `url(${localImgLoad( background: `url(${localImgLoad(
`images/taskbanners/${datas.banner}` `images/taskbanners/${datas?.banner || "default.jpg"}`
)}) center / contain no-repeat`, )}) center / contain no-repeat`,
}} }}
> >
+7 -6
View File
@@ -50,22 +50,23 @@ export default function ProductCardStyleTwo({
</div> </div>
<div className="details-area"> <div className="details-area">
{/* title */} {/* title */}
<a href={datas.guid} target="_blank" className="mb-2.5" rel="noreferrer"> <Link to={`/blog-page?blog_id=${datas.ID}`} className="mb-2.5" rel="noreferrer">
<h1 className="font-bold text-xl tracking-wide line-clamp-1 text-dark-gray dark:text-white capitalize"> <h1 className="font-bold text-xl tracking-wide line-clamp-1 text-dark-gray dark:text-white capitalize">
{datas.post_title || "dummy title..."} {datas.post_title || "dummy title..."}
</h1> </h1>
</a> </Link>
<div className="flex justify-between"> <div className="flex justify-between">
<div className="flex items-center space-x-2"></div> <div className="flex items-center space-x-2"></div>
<div className="my-1"> <div className="my-1">
<a <Link
href={datas.guid} // href={datas.guid}
target="_blank" // target="_blank"
to={`/blog-page?blog_id=${datas.ID}`}
className="px-4 py-2.5 text-white text-sm bg-pink rounded-full tracking-wide" className="px-4 py-2.5 text-white text-sm bg-pink rounded-full tracking-wide"
rel="noreferrer" rel="noreferrer"
> >
View View
</a> </Link>
</div> </div>
</div> </div>
</div> </div>
+11 -10
View File
@@ -10,10 +10,10 @@ import React, {
} from "react"; } from "react";
import { useReactToPrint } from "react-to-print"; import { useReactToPrint } from "react-to-print";
import profile from "../../assets/images/profile-info-profile.png"; import profile from "../../assets/images/profile-info-profile.png";
import localImgLoad from "../../lib/localImgLoad";
import usersService from "../../services/UsersService"; import usersService from "../../services/UsersService";
import LoadingSpinner from "../Spinners/LoadingSpinner"; import LoadingSpinner from "../Spinners/LoadingSpinner";
import AssignTaskPopout from "./FamilyPopout/AssignTaskPopout"; import AssignTaskPopout from "./FamilyPopout/AssignTaskPopout";
import localImgLoad from "../../lib/localImgLoad";
// Lazy Imports for components // Lazy Imports for components
const FamilyWaitlist = lazy(() => import("./Tabs/FamilyWaitlist")); const FamilyWaitlist = lazy(() => import("./Tabs/FamilyWaitlist"));
@@ -193,19 +193,19 @@ export default function FamilyManageTabs({
return ( return (
<div <div
className={`w-full bg-white dark:bg-dark-white overflow-y-auto rounded-2xl section-shadow min-h-[520px] max-h-[600px] ${ className={`w-full bg-white dark:bg-dark-white overflow-y-auto rounded-2xl section-shadow h-full ${
className || "" className || ""
}`} }`}
> >
<div className="relative w-full overflow-x-auto sm:rounded-lg"> <div className="relative w-full sm:rounded-lg overflow-x-auto">
<Suspense <Suspense
fallback={ fallback={
<div className="h-full min-h-[500px] w-full overflow-hidden flex justify-center items-center"> <div className="h-full min-h-[609px] w-full overflow-hidden flex justify-center items-center">
<LoadingSpinner size="16" color="sky-blue" /> <LoadingSpinner size="16" color="sky-blue" />
</div> </div>
} }
> >
<div className="w-full h-full text-sm text-left text-gray-500 dark:text-gray-400 relative grid grid-cols-4 min-h-[520px]"> <div className="w-full h-full text-sm text-left text-gray-500 dark:text-gray-400 relative grid grid-cols-4 min-h-[575px]">
<div className="border-r border-[#E3E4FE] dark:border-[#a7a9b533] p-6 h-full flex flex-col justify-between"> <div className="border-r border-[#E3E4FE] dark:border-[#a7a9b533] p-6 h-full flex flex-col justify-between">
<ProfileInfo <ProfileInfo
profileImg={profileImg} profileImg={profileImg}
@@ -239,10 +239,10 @@ export default function FamilyManageTabs({
</button> </button>
</div> </div>
</div> </div>
<div className="col-span-3 justify-self-end h-full w-full"> <div className="col-span-3 h-full w-full">
<div className="flex flex-col w-full"> <div className="flex flex-col w-full">
<div className="w-full pr-8 flex items-center gap-1"> <div className="w-full pr-8 flex items-center gap-1 border-b border-b-[#FAFAF]">
<ul className="flex gap-2 items-center border-b border-b-[#FAFAF] w-full"> <ul className="flex gap-2 items-center w-full">
{tabs.map(({ name, id }) => ( {tabs.map(({ name, id }) => (
<li <li
onClick={() => tabHandler(name)} onClick={() => tabHandler(name)}
@@ -265,8 +265,9 @@ export default function FamilyManageTabs({
Add task Add task
</button> </button>
</div> </div>
<div className="flex-[0.9] lg:min-h-[450px] h-full">
<div className="h-full p-4 border border-[#dbd9d9] relative overflow-y-auto"> <div className="flex-[0.9] h-full">
<div className="h-full relative overflow-y-auto">
<Suspense <Suspense
fallback={<LoadingSpinner size="16" color="sky-blue" />} fallback={<LoadingSpinner size="16" color="sky-blue" />}
> >
+1 -1
View File
@@ -23,7 +23,7 @@ export default function FamilyTable({ className, familyList, loader, popUpHandle
return ( return (
<div <div
className={`update-table w-full h-full p-8 bg-white dark:bg-dark-white overflow-y-auto rounded-2xl section-shadow min-h-[520px] ${ className={`update-table w-full h-full p-4 bg-white dark:bg-dark-white overflow-y-auto rounded-2xl section-shadow min-h-[520px] ${
className || "" className || ""
}`} }`}
> >
@@ -4,7 +4,7 @@ import QRCode from "react-qr-code";
const FamilyAccount = forwardRef(({ familyData, myRef, handlePrint }, ref) => { const FamilyAccount = forwardRef(({ familyData, myRef, handlePrint }, ref) => {
return ( return (
<div <div
className="w-full lg:min-h-[500px] h-full flex flex-col items-center justify-center" className="w-full lg:min-h-[538px] p-3 h-full flex flex-col items-center justify-center"
ref={myRef} ref={myRef}
> >
<div className="update-table w-full lg:min-h-[450px] h-full p-8 bg-white dark:bg-dark-white overflow-hidden rounded-2xl section-shadow "> <div className="update-table w-full lg:min-h-[450px] h-full p-8 bg-white dark:bg-dark-white overflow-hidden rounded-2xl section-shadow ">
@@ -53,4 +53,4 @@ const FamilyAccount = forwardRef(({ familyData, myRef, handlePrint }, ref) => {
); );
}); });
export default FamilyAccount; export default FamilyAccount;
@@ -1,9 +1,8 @@
import { useMemo, useState } from "react"; import { useMemo, useState } from "react";
import { PaginatedList, handlePagingFunc } from "../../Pagination";
import { PriceFormatter } from "../../Helpers/PriceFormatter";
import dataImage2 from "../../../assets/images/data-table-user-2.png";
import PendingJobsPopout from "../../jobPopout/PendingJobsPopout";
import localImgLoad from "../../../lib/localImgLoad"; import localImgLoad from "../../../lib/localImgLoad";
import { PriceFormatter } from "../../Helpers/PriceFormatter";
import { PaginatedList, handlePagingFunc } from "../../Pagination";
import PendingJobsPopout from "../../jobPopout/PendingJobsPopout";
export default function FamilyPending({ export default function FamilyPending({
familyData, familyData,
@@ -37,7 +36,7 @@ export default function FamilyPending({
return ( return (
<div <div
className={`update-table w-full p-8 bg-white dark:bg-dark-white overflow-hidden rounded-2xl section-shadow min-h-[520px] ${ className={`update-table w-full p-3 bg-white dark:bg-dark-white overflow-hidden rounded-2xl section-shadow lg:min-h-[538px] ${
className || "" className || ""
}`} }`}
> >
@@ -125,8 +124,10 @@ export default function FamilyPending({
); );
}) })
) : ( ) : (
<tr className="font-bold text-xl text-dark-gray dark:text-white whitespace-nowrap"> <tr>
<td className="p-2">No Pending Task!</td> <td className="font-bold text-xl text-dark-gray dark:text-white whitespace-nowrap text-center py-4 px-2">
No Pending Task!
</td>
</tr> </tr>
)} )}
</> </>
@@ -1,3 +1,11 @@
export default function FamilyProfile() { export default function FamilyProfile({ className }) {
return <>Profile</>; return (
} <div
className={`update-table w-full bg-white dark:bg-dark-white overflow-hidden rounded-2xl section-shadow lg:min-h-[538px] p-3 ${
className || ""
}`}
>
<h1>Profile</h1>
</div>
);
}
+40 -18
View File
@@ -1,20 +1,30 @@
import React, { useState } from "react"; import React, { useMemo, useState } from "react";
import dataImage2 from "../../../assets/images/data-table-user-2.png"; import { useLocation, useNavigate } from "react-router-dom";
import { useNavigate, useLocation } from "react-router-dom"; import localImgLoad from "../../../lib/localImgLoad";
import Icons from "../../Helpers/Icons";
import { PriceFormatter } from "../../Helpers/PriceFormatter";
import { handlePagingFunc } from "../../Pagination/HandlePagination"; import { handlePagingFunc } from "../../Pagination/HandlePagination";
import PaginatedList from "../../Pagination/PaginatedList"; import PaginatedList from "../../Pagination/PaginatedList";
import LoadingSpinner from "../../Spinners/LoadingSpinner"; import LoadingSpinner from "../../Spinners/LoadingSpinner";
import Icons from "../../Helpers/Icons";
import { PriceFormatter } from "../../Helpers/PriceFormatter";
import ModalCom from "../../Helpers/ModalCom";
import Detail from "../../jobPopout/popoutcomponent/Detail";
import localImgLoad from "../../../lib/localImgLoad";
export default function FamilyTasks({
export default function FamilyTasks({ familyData, className, loader, accountDetails }) { familyData,
className,
loader,
accountDetails,
}) {
let navigate = useNavigate(); let navigate = useNavigate();
let { pathname } = useLocation(); let { pathname } = useLocation();
// ...
const filteredFamilyData = useMemo(
() =>
familyData?.result_list?.filter(
(data) => data?.family_uid === accountDetails?.family_uid
),
[familyData, accountDetails]
);
const [currentPage, setCurrentPage] = useState(0); const [currentPage, setCurrentPage] = useState(0);
const indexOfFirstItem = Number(currentPage); const indexOfFirstItem = Number(currentPage);
const indexOfLastItem = const indexOfLastItem =
@@ -26,9 +36,10 @@ export default function FamilyTasks({ familyData, className, loader, accountDeta
const handlePagination = (e) => handlePagingFunc(e, setCurrentPage); const handlePagination = (e) => handlePagingFunc(e, setCurrentPage);
return ( return (
<div <div
className={`update-table w-full bg-white dark:bg-dark-white h-full lg:min-h-[450px] overflow-hidden rounded-2xl section-shadow ${ className={`update-table w-full bg-white dark:bg-dark-white h-full lg:min-h-[538px] overflow-hidden rounded-2xl section-shadow p-3 ${
className || "" className || ""
}`} }`}
> >
@@ -45,8 +56,8 @@ export default function FamilyTasks({ familyData, className, loader, accountDeta
{ {
<> <>
{familyData && {familyData &&
familyData?.result_list && familyData?.result_list &&
familyData.result_list.length > 0 && familyData.result_list.length > 0 ? (
currentTask.map((value, index) => { currentTask.map((value, index) => {
// find due date // find due date
const dueDate = value?.delivery_date.split(" ")[0]; const dueDate = value?.delivery_date.split(" ")[0];
@@ -56,7 +67,9 @@ export default function FamilyTasks({ familyData, className, loader, accountDeta
value?.currency_code, value?.currency_code,
value?.currency value?.currency
); );
let image = value.banner ? value.banner : 'default.jpg' let image = value.banner
? value.banner
: "default.jpg";
return ( return (
<tr <tr
key={index} key={index}
@@ -66,7 +79,9 @@ export default function FamilyTasks({ familyData, className, loader, accountDeta
<div className="flex space-x-2 items-center w-full"> <div className="flex space-x-2 items-center w-full">
<div className="w-[60px] h-[60px] p-2 bg-alice-blue rounded-full overflow-hidden flex justify-center items-center"> <div className="w-[60px] h-[60px] p-2 bg-alice-blue rounded-full overflow-hidden flex justify-center items-center">
<img <img
src={localImgLoad(`images/taskbanners/${image}`)} src={localImgLoad(
`images/taskbanners/${image}`
)}
alt="data" alt="data"
className="w-full h-full rounded-full" className="w-full h-full rounded-full"
/> />
@@ -109,8 +124,8 @@ export default function FamilyTasks({ familyData, className, loader, accountDeta
state: { state: {
...value, ...value,
pathname, pathname,
accountDetails accountDetails,
} },
}); });
}} }}
className="w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white" className="w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
@@ -120,7 +135,14 @@ export default function FamilyTasks({ familyData, className, loader, accountDeta
</td> </td>
</tr> </tr>
); );
})} })
) : (
<tr>
<td colSpan="2" className="text-center py-4 font-bold text-xl text-dark-gray dark:text-white whitespace-nowrap">
No Family Task
</td>
</tr>
)}
</> </>
} }
</tbody> </tbody>
@@ -48,7 +48,7 @@ const FamilyWaitlist = memo(
return ( return (
<div <div
className={`update-table w-full bg-white dark:bg-dark-white h-full lg:min-h-[450px] overflow-hidden rounded-2xl section-shadow ${ className={`update-table w-full bg-white dark:bg-dark-white h-full lg:min-h-[538px] p-3 overflow-hidden rounded-2xl section-shadow ${
className || "" className || ""
}`} }`}
> >
@@ -22,7 +22,7 @@ export default function InputCom({
spanTag, spanTag,
inputBg, inputBg,
onInput, onInput,
maxLength = 30, maxLength = 45,
minLength = 0, minLength = 0,
direction, direction,
error, error,
@@ -91,8 +91,8 @@ export default function InputCom({
placeholder={placeholder} placeholder={placeholder}
value={value} value={value}
onChange={inputHandler} onChange={inputHandler}
className={`input-field placeholder:text-base text-dark-gray w-full h-full tracking-wide ${ className={`input-field placeholder:text-base text-dark-gray w-full h-full ${
inputBg ? inputBg : "bg-[#FAFAFA]" inputBg ? inputBg : "bg-[#FAFAFA] tracking-wide"
} dark:bg-[#11131F] focus:ring-0 focus:outline-none ${fieldClass}`} } dark:bg-[#11131F] focus:ring-0 focus:outline-none ${fieldClass}`}
type={type} type={type}
id={name} id={name}
@@ -124,7 +124,7 @@ export default function InputCom({
} }
const inputConfigs = { const inputConfigs = {
email: { minLength: 7, maxLength: 35 }, email: { minLength: 7, maxLength: 45 },
first_name: { minLength: 3, maxLength: 25, pattern: "[a-zA-Z]+" }, first_name: { minLength: 3, maxLength: 25, pattern: "[a-zA-Z]+" },
last_name: { minLength: 3, maxLength: 25, pattern: "[a-zA-Z]+" }, last_name: { minLength: 3, maxLength: 25, pattern: "[a-zA-Z]+" },
address: { minLength: 5, maxLength: 49, pattern: "[a-zA-Z0-9]+" }, address: { minLength: 5, maxLength: 49, pattern: "[a-zA-Z0-9]+" },
+2
View File
@@ -7,6 +7,7 @@ export default function SearchCom({
placeholder, placeholder,
handleSearch, handleSearch,
value, value,
name,
}) { }) {
return ( return (
<div <div
@@ -22,6 +23,7 @@ export default function SearchCom({
className={`w-full h-full focus:outline-0 focus:ring-0 dark:bg-dark-white dark:text-white ${ className={`w-full h-full focus:outline-0 focus:ring-0 dark:bg-dark-white dark:text-white ${
inputClasses || "" inputClasses || ""
}`} }`}
name={name}
type="text" type="text"
onInput={handleSearch} onInput={handleSearch}
value={value} value={value}
+4 -4
View File
@@ -110,13 +110,13 @@ export default function MyJobTable({ MyJobList, reloadJobList, className }) {
return ( return (
<tr <tr
key={index} key={index}
className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] hover:bg-gray-50" className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] hover:bg-gray-50"
> >
<td className="py-9"> <td className="py-9">
<div className="sm:flex sm:space-x-2 sm:justify-between sm:items-center job-items"> <div className="sm:flex sm:space-x-2 sm:justify-between sm:items-center job-items">
<div className="flex space-x-2 items-center job-items w-full"> <div className="flex space-x-2 items-center job-items w-full">
<div className="w-[60px] h-[60px] p-2 bg-alice-blue rounded-full overflow-hidden flex justify-center items-center"> <div className="w-[60px] h-[60px] p-2 bg-alice-blue rounded-full overflow-hidden flex justify-center items-center">
<img src={localImgLoad(`images/taskbanners/${value.banner}`)} alt="data" className="w-full h-full rounded-full" /> <img src={localImgLoad(`images/taskbanners/${value.banner ? value.banner : 'default.jpg'}`)} alt="data" className="w-full h-full rounded-full" />
</div> </div>
<div className="flex flex-col flex-[0.9]"> <div className="flex flex-col flex-[0.9]">
<h1 className="font-bold text-xl text-dark-gray dark:text-white"> <h1 className="font-bold text-xl text-dark-gray dark:text-white">
@@ -175,7 +175,7 @@ export default function MyJobTable({ MyJobList, reloadJobList, className }) {
}} }}
className="w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white" className="w-20 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
> >
Manage Assign
</button> </button>
</td> </td>
</tr> </tr>
@@ -204,7 +204,7 @@ export default function MyJobTable({ MyJobList, reloadJobList, className }) {
{MyJobList.loading ? ( {MyJobList.loading ? (
<LoadingSpinner size="16" color="sky-blue" /> <LoadingSpinner size="16" color="sky-blue" />
) : ( ) : (
<div className="relative w-full overflow-x-auto sm:rounded-lg flex flex-col justify-between h-full"> <div className="relative w-full overflow-x-auto sm:rounded-lg flex flex-col justify-between min-h-[520px]">
<table className="table-auto min-w-full text-sm text-left text-gray-500 dark:text-gray-400"> <table className="table-auto min-w-full text-sm text-left text-gray-500 dark:text-gray-400">
<tbody> <tbody>
<> <>
@@ -6,6 +6,7 @@ import PendingJobsPopout from "../jobPopout/PendingJobsPopout";
import { PriceFormatter } from "../Helpers/PriceFormatter"; import { PriceFormatter } from "../Helpers/PriceFormatter";
import localImgLoad from "../../lib/localImgLoad"; import localImgLoad from "../../lib/localImgLoad";
export default function MyPendingJobTable({ MyJobList, className }) { export default function MyPendingJobTable({ MyJobList, className }) {
let [jobPopout, setJobPopout] = useState({ show: false, data: {} }); // STATE TO HOLD THE VALUE OF THE ALERT DETAILS AND DETERMINE WHEN TO SHOW let [jobPopout, setJobPopout] = useState({ show: false, data: {} }); // STATE TO HOLD THE VALUE OF THE ALERT DETAILS AND DETERMINE WHEN TO SHOW
@@ -58,7 +59,7 @@ export default function MyPendingJobTable({ MyJobList, className }) {
<div className="flex space-x-2 items-center w-full"> <div className="flex space-x-2 items-center w-full">
<div className="w-[60px] h-[60px] p-2 bg-alice-blue rounded-full overflow-hidden flex justify-center items-center"> <div className="w-[60px] h-[60px] p-2 bg-alice-blue rounded-full overflow-hidden flex justify-center items-center">
<img <img
src={localImgLoad(`images/taskbanners/${value.banner}`)} src={localImgLoad(`images/taskbanners/${value.banner || "default.jpg"}`)}
alt="data" alt="data"
className="w-full h-full rounded-full" className="w-full h-full rounded-full"
/> />
+9 -2
View File
@@ -3,13 +3,14 @@ import { Link } from "react-router-dom";
import Layout from "../Partials/Layout"; import Layout from "../Partials/Layout";
import CommonHead from "../UserHeader/CommonHead"; import CommonHead from "../UserHeader/CommonHead";
import MyPendingJobTable from "./MyPendingJobTable"; import MyPendingJobTable from "./MyPendingJobTable";
import LoadingSpinner from "../Spinners/LoadingSpinner";
export default function MyPendingJobs(props) { export default function MyPendingJobs(props) {
const [selectTab, setValue] = useState("today"); const [selectTab, setValue] = useState("today");
const filterHandler = (value) => { const filterHandler = (value) => {
setValue(value); setValue(value);
}; };
console.log("AMEYE LOC1", props.MyJobList); // console.log("AMEYE LOC1", props.MyJobList);
return ( return (
<Layout> <Layout>
<CommonHead <CommonHead
@@ -35,7 +36,13 @@ export default function MyPendingJobs(props) {
></div> ></div>
</div> </div>
</div> </div>
<MyPendingJobTable MyJobList={props.MyJobList} /> {props.MyJobList.loading ?
<div className="bg-white">
<LoadingSpinner size='16' color='sky-blue' height='min-h-[300px]' />
</div>
:
<MyPendingJobTable MyJobList={props.MyJobList.data} />
}
</div> </div>
</div> </div>
</Layout> </Layout>
@@ -136,6 +136,12 @@ function AddFundDollars(props) {
return; return;
} }
if (Number(props.input) * 100 > Number(props.walletItem?.transfer_limit)) {
props.setInputError("Credit limit has been exceeded");
setTimeout(() => props.setInputError(""), 5000);
return;
}
if (tab === "previous") { if (tab === "previous") {
// To check if card is empty // To check if card is empty
if (Object.keys(prevCardDetails).length === 0) { if (Object.keys(prevCardDetails).length === 0) {
@@ -487,7 +493,7 @@ function AddFundDollars(props) {
{/* Postal Code and State */} {/* Postal Code and State */}
<div className="sm:grid gap-5 grid-cols-3 my-2"> <div className="sm:grid gap-5 grid-cols-3 my-2">
<div className="field w-full mb-6 xl:mb-0 col-span-1"> <div className="field w-full xl:mb-0 col-span-1">
<InputCom <InputCom
fieldClass="px-6" fieldClass="px-6"
spanTag="*" spanTag="*"
@@ -521,7 +527,7 @@ function AddFundDollars(props) {
</div> </div>
</div> </div>
<div className="md:px-8 md:pt-4 px-4 pt-2 add-fund-btn flex justify-end items-center gap-3"> <div className="md:px-8 add-fund-btn flex justify-end items-center gap-3">
<button <button
className="px-4 py-1 h-11 max-w-[100px] w-full flex justify-center items-center border-gradient text-base rounded-full" className="px-4 py-1 h-11 max-w-[100px] w-full flex justify-center items-center border-gradient text-base rounded-full"
onClick={handleClose} onClick={handleClose}
+9 -5
View File
@@ -1,5 +1,4 @@
import React, { useState } from "react"; import React, { useState } from "react";
import { useNavigate } from "react-router-dom";
import usersService from "../../../services/UsersService"; import usersService from "../../../services/UsersService";
import Icons from "../../Helpers/Icons"; import Icons from "../../Helpers/Icons";
import InputCom from "../../Helpers/Inputs/InputCom"; import InputCom from "../../Helpers/Inputs/InputCom";
@@ -15,10 +14,9 @@ function AddFundPop({
setConfirmCredit, setConfirmCredit,
walletItem, walletItem,
}) { }) {
const navigate = useNavigate();
const apiCall = new usersService(); const apiCall = new usersService();
let countryWallet = walletItem?.country; let countryWallet = walletItem?.country;
const { payment, currency } = _payment; const { currency } = _payment;
const [inputError, setInputError] = useState(""); const [inputError, setInputError] = useState("");
let __awaitComponent = confirmCredit.show.awaitConfirm; let __awaitComponent = confirmCredit.show.awaitConfirm;
@@ -44,6 +42,12 @@ function AddFundPop({
return; return;
} }
if (Number(input) * 100 > Number(walletItem?.transfer_limit)) {
setInputError("Credit limit has been exceeded");
setTimeout(() => setInputError(""), 5000);
return;
}
if (isNaN(input)) { if (isNaN(input)) {
setConfirmCredit((prev) => ({ setConfirmCredit((prev) => ({
...prev, ...prev,
@@ -106,14 +110,14 @@ function AddFundPop({
</h1> </h1>
<div className="field w-full max-w-[250px]"> <div className="field w-full max-w-[250px]">
<InputCom <InputCom
fieldClass="px-6" fieldClass="px-6 text-right"
type="text" type="text"
name="amount" name="amount"
placeholder="0" placeholder="0"
value={input} value={input}
inputHandler={handleChange} inputHandler={handleChange}
/> />
<p className="text-base text-red-500 h-5"> <p className="text-base text-red-500 italic h-5">
{inputError && inputError} {inputError && inputError}
</p> </p>
</div> </div>
@@ -17,7 +17,8 @@ function CompleteConfirmCredit({ onClose, confirmCredit }) {
> >
{/* Success Icon for now */} {/* Success Icon for now */}
<div className="flex items-center w-full justify-center"> <div className="flex items-center w-full justify-center">
{data?.result == "Charge success" ? ( {data?.result == "Charge success" ||
data?.status == "successful" ? (
<svg <svg
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
width="100" width="100"
@@ -55,7 +56,8 @@ function CompleteConfirmCredit({ onClose, confirmCredit }) {
<div className={`flex items-center`}> <div className={`flex items-center`}>
<h1 className="text-xl font-semibold text-dark-gray dark:text-white tracking-tighter my-1"> <h1 className="text-xl font-semibold text-dark-gray dark:text-white tracking-tighter my-1">
{data?.result == "Charge success" {data?.result == "Charge success" ||
data?.status == "successful"
? "Credit was Successful!" ? "Credit was Successful!"
: "Credit was Unsuccessful"} : "Credit was Unsuccessful"}
</h1> </h1>
@@ -1,8 +1,8 @@
import { FlutterWaveButton, closePaymentModal } from "flutterwave-react-v3"; import { FlutterWaveButton, closePaymentModal } from "flutterwave-react-v3";
import React, { useState } from "react"; import React, { useState } from "react";
import { useDispatch } from "react-redux"; import { useDispatch, useSelector } from "react-redux";
import { useNavigate } from "react-router-dom";
import { toast } from "react-toastify"; import { toast } from "react-toastify";
import debounce from "../../../hooks/debounce";
import usersService from "../../../services/UsersService"; import usersService from "../../../services/UsersService";
import { tableReload } from "../../../store/TableReloads"; import { tableReload } from "../../../store/TableReloads";
import LoadingSpinner from "../../Spinners/LoadingSpinner"; import LoadingSpinner from "../../Spinners/LoadingSpinner";
@@ -99,7 +99,9 @@ function ConfirmAddFund({
: __confirmData.card; : __confirmData.card;
const apiURL = new usersService(); const apiURL = new usersService();
const navigate = useNavigate();
const { userDetails } = useSelector((state) => state?.userDetails);
const dispatch = useDispatch(); const dispatch = useDispatch();
const [requestStatus, setRequestStatus] = useState({ const [requestStatus, setRequestStatus] = useState({
@@ -110,32 +112,48 @@ function ConfirmAddFund({
const config = { const config = {
public_key: process.env.REACT_APP_FLUTTERWAVE_APIKEY, public_key: process.env.REACT_APP_FLUTTERWAVE_APIKEY,
tx_ref: Date.now(), tx_ref: __confirmData?.credit_reference,
currency: "NGN", currency: "NGN",
amount: Number(__confirmData.amount),
payment_options: "card,mobilemoney,ussd", payment_options: "card,mobilemoney,ussd",
customer: {
email: userDetails.email,
phone_number: userDetails.phone,
name: `${userDetails.lastname} ${userDetails.firstname}`,
},
customizations: { customizations: {
title: "WrenchBoard", title: "WrenchBoard",
description: "Topup Payment", description: "Add Credit Payment",
logo: "https://st2.depositphotos.com/4403291/7418/v/450/depositphotos_74189661-stock-illustration-online-shop-log.jpg", logo: "https://www.wrenchboard.com/assets/images/wrench-500-500-icon.png",
}, },
}; };
//debugger;
const fwConfig = { const fwConfig = {
...config, ...config,
text: "Proceed", text: "Proceed",
callback: (response) => { callback: (response) => {
onSuccessPayment(); debouncedSuccessPayment(); //delays the call for 5 secs
closePaymentModal();
setTimeout(() => {
closePaymentModal();
setConfirmCredit((prev) => ({
...prev,
show: {
awaitConfirm: { loader: false, state: false },
acceptConfirm: { loader: false, state: true },
},
data: response,
}));
}, 1500);
}, },
onClose: () => {},
}; };
const onSuccessPayment = () => { const onSuccessPayment = () => {
setRequestStatus({ message: "", loading: true, status: false }); setRequestStatus({ message: "", loading: true, status: false });
const reqData = { amount: __confirmData?.account, currency: "NGN" }; const reqData = { tx_ref: __confirmData?.credit_reference };
console.log("**** onSuccessPayment **** THIS WAS REACHED");
apiURL apiURL
.startTopUp(reqData) .resultTopUp(reqData)
.then((res) => { .then((res) => {
if (res.data.internal_return < 0) { if (res.data.internal_return < 0) {
setRequestStatus({ setRequestStatus({
@@ -143,18 +161,9 @@ function ConfirmAddFund({
loading: false, loading: false,
status: false, status: false,
}); });
toast.success("Opps! something went wrong");
} else {
setRequestStatus({
message: "Topup successful",
loading: false,
status: true,
});
toast.success("Account Topup was successful");
setTimeout(() => {
navigate("/my-wallet", { replace: true });
}, 1000);
} }
return dispatch(tableReload({ type: "WALLETTABLE" }));
}) })
.catch((err) => { .catch((err) => {
setRequestStatus({ setRequestStatus({
@@ -162,10 +171,23 @@ function ConfirmAddFund({
loading: false, loading: false,
status: false, status: false,
}); });
setTimeout(() => {
setConfirmCredit((prev) => ({
...prev,
show: {
awaitConfirm: { loader: false, state: false },
acceptConfirm: { loader: false, state: true },
},
data: err,
}));
}, 1500);
toast.success("Opps! something went wrong"); toast.success("Opps! something went wrong");
}); });
}; };
const debouncedSuccessPayment = debounce(onSuccessPayment, 5000);
const handlePrevCard = async () => { const handlePrevCard = async () => {
const { amount, credit_reference, currency } = __confirmData; const { amount, credit_reference, currency } = __confirmData;
const { card_uid } = __confirmCardDetails; const { card_uid } = __confirmCardDetails;
@@ -205,6 +227,7 @@ function ConfirmAddFund({
}, },
data: _response, data: _response,
})); }));
dispatch(tableReload({ type: "WALLETTABLE" }));
}, 1500); }, 1500);
} catch (error) { } catch (error) {
setConfirmCredit((prev) => ({ setConfirmCredit((prev) => ({
@@ -254,9 +277,8 @@ function ConfirmAddFund({
})); }));
return; return;
} }
setTimeout(() => { setTimeout(() => {
dispatch(tableReload({ type: "WALLETTABLE" }));
setConfirmCredit((prev) => ({ setConfirmCredit((prev) => ({
...prev, ...prev,
show: { show: {
@@ -265,6 +287,7 @@ function ConfirmAddFund({
}, },
data: _response, data: _response,
})); }));
dispatch(tableReload({ type: "WALLETTABLE" }));
}, 1500); }, 1500);
} catch (error) { } catch (error) {
setConfirmCredit((prev) => ({ setConfirmCredit((prev) => ({
@@ -278,7 +301,16 @@ function ConfirmAddFund({
} }
}; };
// console.log(confirmCredit?.data); const getBack = () => {
setConfirmCredit((prev) => ({
...prev,
show: {
awaitConfirm: { loader: false, state: false },
acceptConfirm: { loader: false, state: false },
},
data: {},
}));
};
return ( return (
<div className="content-wrapper w-full h-[32rem]"> <div className="content-wrapper w-full h-[32rem]">
@@ -348,9 +380,9 @@ function ConfirmAddFund({
<div className="md:p-8 p-4 add-fund-btn flex justify-end items-center py-4 gap-4"> <div className="md:p-8 p-4 add-fund-btn flex justify-end items-center py-4 gap-4">
<button <button
className="px-4 h-11 flex justify-center items-center border-gradient text-base rounded-full" className="px-4 h-11 flex justify-center items-center border-gradient text-base rounded-full"
onClick={onClose} onClick={getBack}
> >
Cancel Back
</button> </button>
{__confirmCountry === "US" && ( {__confirmCountry === "US" && (
<button <button
@@ -1,54 +1,98 @@
import React, { useState } from "react"; import { useState } from "react";
import { useNavigate } from "react-router-dom"; import usersService from "../../../services/UsersService";
import { toast } from "react-toastify";
import InputCom from "../../Helpers/Inputs/InputCom"; import InputCom from "../../Helpers/Inputs/InputCom";
import ModalCom from "../../Helpers/ModalCom"; import ModalCom from "../../Helpers/ModalCom";
import LoadingSpinner from "../../Spinners/LoadingSpinner"; import LoadingSpinner from "../../Spinners/LoadingSpinner";
import { useDispatch } from "react-redux";
import { tableReload } from "../../../store/TableReloads";
import usersService from "../../../services/UsersService"; function ConfirmNairaWithdraw({
payment,
function ConfirmNairaWithdraw({ payment, wallet, action, situation, state }) { wallet,
action,
situation,
state,
setShowNairaWithdraw,
}) {
const apiURL = new usersService(); const apiURL = new usersService();
const dispatch = useDispatch();
const navigate = useNavigate();
let [requestStatus, setRequestStatus] = useState({ let [requestStatus, setRequestStatus] = useState({
message: "", message: "",
loading: false, loading: false,
status: false, status: false,
}); });
let [pageLoading, setPageLoading] = useState(true);
const [completeNairaWithdraw, setShowCompleteNairaWithdraw] = useState({
show: false,
load: false,
state: {},
}); // DETERMINES WHEN CONFIRM NAIRA WITHDRAWAL POPS UP
//FUNCTION TO HANDLE SUBMIT //FUNCTION TO HANDLE SUBMIT
const handleSubmit = () => { const handleSubmit = () => {
setRequestStatus({ message: "", loading: true, status: false }); setRequestStatus({ message: "", loading: true, status: false });
setShowCompleteNairaWithdraw({ load: true });
let reqData = { let reqData = {
amount: Number(state.amount * 100), amount: Number(state.amount * 100),
Fee: Number(state.fee), Fee: Number(state.fee),
recipient_uid: Number(state.details?.recipient_uid),
wallet_uid: wallet.wallet_uid, wallet_uid: wallet.wallet_uid,
}; };
if (state?.choice === "prev") {
reqData.recipient_uid = state.details?.recipient_uid;
reqData.mode = 100;
}
if (state?.choice === "new") {
reqData.account_no = state?.details?.accountNumber;
reqData.account_type = Number(state?.details?.accountType);
reqData.bank_uid = state?.details?.bank_uid;
reqData.country = state?.details?.country;
reqData.state = state?.details?.state;
reqData.city = state?.details?.city;
reqData.mode = 500;
}
apiURL apiURL
.sendMoney(reqData) .sendMoney(reqData)
.then((res) => { .then((res) => {
if (res.data.internal_return < 0) { if (res.data.internal_return < 0) {
// if (res.data?.status_message?.toLowerCase().includes("limit")) {
// setRequestStatus({
// message: ,
// loading: false,
// status: false,
// });
// }
return setTimeout(() => {
setRequestStatus({
message: "",
loading: false,
status: false,
});
setShowCompleteNairaWithdraw({
show: true,
load: false,
state: res.data,
});
}, 5000);
}
setTimeout(() => {
setRequestStatus({ setRequestStatus({
message: "Could not perform transaction", message: "",
loading: false, loading: false,
status: false, status: false,
}); });
return; setShowCompleteNairaWithdraw({
} show: true,
setRequestStatus({ load: false,
message: "transfer successful", state: res.data,
loading: false, });
status: true, }, 5000);
}); dispatch(tableReload({ type: "WALLETTABLE" }));
toast.success("Transfer sucessful"); return;
setTimeout(() => {
navigate("/my-wallet", { replace: true });
window.location.reload(true);
}, 1000);
}) })
.catch((error) => { .catch((error) => {
setRequestStatus({ setRequestStatus({
@@ -59,17 +103,26 @@ function ConfirmNairaWithdraw({ payment, wallet, action, situation, state }) {
}); });
}; };
console.log(state)
return ( return (
<ModalCom action={action} situation={situation} className="edit-popup"> <ModalCom action={action} situation={situation} className="edit-popup">
<div className="logout-modal-wrapper lw-[90%] md:w-[768px] h-full lg:h-auto bg-white dark:bg-dark-white lg:rounded-2xl"> <div className="logout-modal-wrapper lw-[90%] md:w-[768px] h-full lg:h-auto bg-white dark:bg-dark-white lg:rounded-2xl">
<div className="w-full"> <div className="w-full">
<div className="logout-modal-header w-full flex items-center justify-between lg:p-6 px-[30px] py-[23px] border-b dark:border-[#5356fb29] border-light-purple"> <div className="logout-modal-header w-full flex items-center justify-between lg:p-6 px-[30px] py-[23px] border-b dark:border-[#5356fb29] border-light-purple">
<h2 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide"> <h2 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide">
{`Withdraw from ${wallet.description} Wallet : ${wallet.symbol}${( {completeNairaWithdraw.load ? (
wallet.amount * 0.01 "Confirming..."
).toFixed(2)}`} ) : (
<>
{" "}
{completeNairaWithdraw.show
? completeNairaWithdraw?.state?.internal_return >= 0
? "Transfer Success"
: "Transfer Error"
: `Withdraw from ${wallet.description} Wallet : ${
wallet.symbol
}${(wallet.amount * 0.01).toFixed(2)}`}
</>
)}
</h2> </h2>
<button <button
type="button" type="button"
@@ -99,100 +152,276 @@ function ConfirmNairaWithdraw({ payment, wallet, action, situation, state }) {
</div> </div>
<hr /> <hr />
<div className="add-fund w-full bg-white dark:bg-dark-white rounded-2xl shadow"> <div className="add-fund w-full bg-white dark:bg-dark-white rounded-2xl shadow">
<div className="px-4 md:px-8 py-4 add-fund-info"> {completeNairaWithdraw.load ? (
<h2 className="my-2 text-slate-900 dark:text-white text-sm xl:text-xl font-medium"> <div className="h-[35rem] flex items-center justify-center">
{/* Confirm Withdraw to Account */} <LoadingSpinner size="12" color="sky-blue" />
</h2>
{/* AMOUNT */}
<div className="field w-full mb-3">
<InputCom
fieldClass="px-6"
label="Amount:"
type="text"
name="amount"
value={state?.amount || ""}
disable={true}
/>
</div> </div>
) : completeNairaWithdraw.show ? (
<div className="px-4 md:p-8 py-4 add-fund-info">
<div className="field w-full mb-3 min-h-[23rem]">
<div className="flex items-center w-full justify-center mb-3">
{completeNairaWithdraw.state?.sendmoney_message
?.toLowerCase()
?.includes("completed") ? (
<svg
xmlns="http://www.w3.org/2000/svg"
width="100"
height="100"
viewBox="0 0 24 24"
fill="none"
stroke="green"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
className="feather feather-check-circle"
>
<path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"></path>
<polyline points="22 4 12 14.01 9 11.01"></polyline>
</svg>
) : (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="none"
width="100"
height="100"
stroke="red"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
className="feather feather-x-circle"
>
<circle cx="12" cy="12" r="10"></circle>
<line x1="15" y1="9" x2="9" y2="15"></line>
<line x1="9" y1="9" x2="15" y2="15"></line>
</svg>
)}
</div>
{/* RECIPIENT ACC: */} {completeNairaWithdraw.state?.internal_return >= 0 ? (
<div className="field w-full mb-3"> <>
<InputCom <div className={`flex items-center`}>
fieldClass="px-6" <h1 className="text-xl font-semibold text-dark-gray dark:text-white tracking-tighter my-1">
label="Recipient Acc:" {completeNairaWithdraw.state?.sendmoney_message || ""}
type="text" </h1>
name="recipient" </div>
value={state?.details.recipient || ""} <div className="flex items-center gap-8">
disable={true} <h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
/> Amount(
{completeNairaWithdraw.state
?.terminatingcountrycode || ""}
)
</h1>
<span className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
{Number(
completeNairaWithdraw.state?.TerminatingAmount *
0.01
).toLocaleString() || ""}
</span>
</div>
<div className="flex items-center gap-8">
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
Recipient
</h1>
<span className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
{completeNairaWithdraw.state?.recitient}
</span>
</div>
<div className="flex items-center gap-8">
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
Confirmation Number
</h1>
<span className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
{completeNairaWithdraw.state?.confirmation}
</span>
</div>{" "}
</>
) : (
<>
<div className={`flex items-center`}>
<h1 className="text-xl font-semibold text-dark-gray dark:text-white tracking-tighter my-1">
{completeNairaWithdraw.state?.status_message
?.toLowerCase()
.includes("not_found")
? "Wallet Error Occurred"
: completeNairaWithdraw.state?.status_message
?.toLowerCase()
.includes("recipient_add_error")
? "Recipient Error Occurred"
: completeNairaWithdraw.state?.status_message
?.toLowerCase()
.includes("limit")
? "Transfer limit Error"
: completeNairaWithdraw.state?.bad_param
?.toLowerCase()
.includes("balance")
? "Insufficient Balance"
: "An Error Occurred"}{" "}
</h1>
</div>
<div className="flex items-center gap-8">
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
Message:
</h1>
<span className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
{completeNairaWithdraw.state?.status_message
?.toLowerCase()
.includes("not_found")
? "This Wallet is not Found"
: completeNairaWithdraw.state?.status_message
?.toLowerCase()
.includes("recipient_add_error")
? "No Recipient Found"
: completeNairaWithdraw.state?.status_message
?.toLowerCase()
.includes("limit")
? "The transfer limit has been exceeded"
: completeNairaWithdraw.state?.bad_param
?.toLowerCase()
.includes("balance")
? "Insufficient Balance for Transaction"
: "Could not perform transaction"}
</span>
</div>
</>
)}
</div>
</div> </div>
) : (
<div className="px-4 md:px-8 py-4 add-fund-info">
<h2 className="my-2 text-slate-900 dark:text-white text-sm xl:text-xl font-medium">
{/* Confirm Withdraw to Account */}
</h2>
{/* AMOUNT */}
<div className="field w-full mb-3">
<InputCom
fieldClass="px-6"
label="Amount:"
type="text"
name="amount"
value={state?.amount || ""}
disable={true}
/>
</div>
{/* PROCESSING FEE: */} {state?.choice === "prev" && (
<div className="field w-full mb-3"> <>
<InputCom {/* RECIPIENT ACC: */}
fieldClass="px-6" <div className="field w-full mb-3">
label="Processing Fee:" <InputCom
type="text" fieldClass="px-6"
name="processingFee" label="Recipient Acc:"
value={(state?.fee * 0.01).toFixed(2) || ""} type="text"
disable={true} name="recipient"
/> value={state?.details?.recipient || ""}
disable={true}
/>
</div>
</>
)}
{state?.choice === "new" && (
<>
{/* RECIPIENT ACC: */}
<div className="field w-full mb-3">
<InputCom
fieldClass="px-6"
label="Bank Acc:"
type="text"
name="bank"
value={
`${state?.details?.name} ${state?.details?.country}` ||
""
}
disable={true}
/>
</div>
</>
)}
{/* PROCESSING FEE: */}
<div className="field w-full mb-3">
<InputCom
fieldClass="px-6"
label="Processing Fee:"
type="text"
name="processingFee"
value={(state?.fee * 0.01).toFixed(2) || ""}
disable={true}
/>
</div>
{/* TOTAL */}
<div className="field w-full mb-3">
<InputCom
fieldClass="px-6"
label="Total"
type="text"
name="total"
value={(state?.total * 0.01).toFixed(2) || ""}
disable={true}
/>
</div>
{/* COMMENT/NOTE */}
<div className="field w-full mb-3">
<InputCom
fieldClass="px-6"
label="Comment/Note:"
type="text"
name="comment"
value={state?.comment || ""}
disable={true}
/>
</div>
</div> </div>
{/* TOTAL */}
<div className="field w-full mb-3">
<InputCom
fieldClass="px-6"
label="Total"
type="text"
name="total"
value={(state?.total * 0.01).toFixed(2) || ""}
disable={true}
/>
</div>
{/* COMMENT/NOTE */}
<div className="field w-full mb-3">
<InputCom
fieldClass="px-6"
label="Comment/Note:"
type="text"
name="comment"
value={state?.comment || ""}
disable={true}
/>
</div>
</div>
<hr />
{requestStatus.message && (
<p
className={`text-base ${
requestStatus.status ? "text-green-500" : "text-red-500"
} px-4 md:px-8 py-4`}
>
{requestStatus.message}
</p>
)} )}
<div className="px-4 md:px-8 py-4 add-fund-btn flex justify-end items-center gap-2">
<button {!completeNairaWithdraw.load && (
type="button" <>
onClick={action} {" "}
className="border-gradient text-base tracking-wide px-4 py-2 rounded-full" <hr />
> <p
<span className="text-gradient">Cancel</span> className={`text-base ${
</button> requestStatus.status ? "text-green-500" : "text-red-500"
{requestStatus.loading ? ( } px-4 md:px-8 py-4 h-5`}
<LoadingSpinner size="8" color="sky-blue" />
) : (
<button
onClick={handleSubmit}
className="btn-gradient text-base tracking-wide px-4 py-2 rounded-full text-white cursor-pointer"
> >
Transfer {requestStatus.message && requestStatus.message}
</button> </p>
)} <div className="px-4 md:px-8 py-4 add-fund-btn flex justify-end items-center gap-2">
</div> {!completeNairaWithdraw.show && (
<button
type="button"
onClick={action}
className="border-gradient text-base tracking-wide px-4 py-2 rounded-full"
>
<span className="text-gradient">Cancel</span>
</button>
)}
<button
onClick={
completeNairaWithdraw.show
? action
: completeNairaWithdraw?.state?.internal_return < 0
? action
: handleSubmit
}
className="btn-gradient text-base tracking-wide px-4 py-2 rounded-full text-white cursor-pointer min-w-[100px]"
>
{requestStatus.loading ? (
<LoadingSpinner size="6" color="sky-blue" />
) : completeNairaWithdraw.show ? (
"Okay"
) : completeNairaWithdraw?.state?.internal_return < 0 ? (
"Cancel"
) : (
"Transfer"
)}
</button>
</div>
</>
)}
</div> </div>
</div> </div>
</div> </div>
@@ -60,14 +60,6 @@ function ConfirmTransfer({ payment, wallet }) {
}); });
}; };
useEffect(() => {
// what happens if not state redirect user
if (!state) {
navigate("/my-wallet/transfer-fund", { replace: true });
} else {
setPageLoading(false);
}
}, []);
return ( return (
<div className="content-wrapper w-full lg:flex xl:space-x-8 lg:space-x-4 bottomMargin"> <div className="content-wrapper w-full lg:flex xl:space-x-8 lg:space-x-4 bottomMargin">
{pageLoading ? ( {pageLoading ? (
@@ -25,7 +25,8 @@ const CreditPopup = ({ details, onClose, situation, walletItem }) => {
<div className="logout-modal-header w-full flex items-center justify-between lg:p-6 px-[30px] py-[23px] border-b dark:border-[#5356fb29] border-light-purple"> <div className="logout-modal-header w-full flex items-center justify-between lg:p-6 px-[30px] py-[23px] border-b dark:border-[#5356fb29] border-light-purple">
<h1 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide"> <h1 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide">
{confirmCredit?.show?.acceptConfirm?.state && {confirmCredit?.show?.acceptConfirm?.state &&
confirmCredit?.data?.internal_return < 0 ? ( (confirmCredit?.data?.internal_return < 0 ||
confirmCredit?.data?.status !== "successful") ? (
"Credit Unsuccessful" "Credit Unsuccessful"
) : ( ) : (
<> <>
+93 -57
View File
@@ -1,37 +1,37 @@
import { Form, Formik } from "formik"; import { Form, Formik } from "formik";
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import { useNavigate } from "react-router-dom";
import usersService from "../../../services/UsersService"; import usersService from "../../../services/UsersService";
import InputCom from "../../Helpers/Inputs/InputCom"; import InputCom from "../../Helpers/Inputs/InputCom";
import ModalCom from "../../Helpers/ModalCom"; import ModalCom from "../../Helpers/ModalCom";
import LoadingSpinner from "../../Spinners/LoadingSpinner"; import LoadingSpinner from "../../Spinners/LoadingSpinner";
const initialValues = {
amount: "",
comment: "",
previousAccount: {
recipientID: "",
},
newAccount: {
country: "",
bank: "",
accountNumber: "",
accountType: "",
state: "",
city: "",
},
};
function NairaWithdraw({ function NairaWithdraw({
wallet, wallet,
action, action,
situation, situation,
state,
setShowConfirmNairaWithdraw, setShowConfirmNairaWithdraw,
}) { }) {
const apiCall = new usersService(); // API CLASS CALL const apiCall = new usersService();
const navigate = useNavigate();
const [tab, setTab] = useState("previous"); const [tab, setTab] = useState("previous");
let [requestStatus, setRequestStatus] = useState(false); let [requestStatus, setRequestStatus] = useState(false);
const initialValues = {
amount: state?.amount || "",
comment: state?.comment || "",
previousAccount: {
recipientID: state?.previousAccount?.recipientID || "",
},
newAccount: {
country: state?.newAccount?.amount || "",
bank: state?.newAccount?.amount || "",
accountNumber: state?.newAccount?.amount || "",
accountType: state?.newAccount?.amount || "",
state: state?.newAccount?.amount || "",
city: state?.newAccount?.amount || "",
},
};
const [errorMsgs, setErrorMsgs] = useState(initialValues); const [errorMsgs, setErrorMsgs] = useState(initialValues);
let [sendMoneyFee, setSendMoneyFee] = useState({ let [sendMoneyFee, setSendMoneyFee] = useState({
@@ -65,7 +65,7 @@ function NairaWithdraw({
// Handling card change // Handling card change
const handleBankOptions = (event) => { const handleBankOptions = (event) => {
const { name, value } = event.target; const { value } = event.target;
setBankName((prev) => ({ loading: true, data: [] })); setBankName((prev) => ({ loading: true, data: [] }));
apiCall apiCall
.getCountryBank({ country: value }) .getCountryBank({ country: value })
@@ -167,15 +167,16 @@ function NairaWithdraw({
//FUNCTION TO HANDLE SUBMIT //FUNCTION TO HANDLE SUBMIT
const handleSubmit = async (values, helpers) => { const handleSubmit = async (values, helpers) => {
try { try {
// Validate the form using Yup validation schema
// await validationSchema.validate(values, { abortEarly: false });
// If validation passes, proceed with form submission
console.log("Form data is valid!", values);
if (!values?.amount) { if (!values?.amount) {
setErrorMsgs({ amount: "Please enter an amount" }); setErrorMsgs({ amount: "amount required" });
setTimeout(() => setErrorMsgs({ amount: "" }), 1000); setTimeout(() => setErrorMsgs({ amount: "" }), 3000);
return;
}else if (Number(values.amount * 100) > Number(wallet?.transfer_limit)) {
setErrorMsgs({ amount: "Withdraw limit has been exceeded" });
setTimeout(() => setErrorMsgs({ amount: "" }), 3000);
return; return;
} }
if (values?.comment?.length >= 50) { if (values?.comment?.length >= 50) {
setErrorMsgs({ comment: "50 chars max" }); setErrorMsgs({ comment: "50 chars max" });
setTimeout(() => setErrorMsgs({ comment: "" }), 1000); setTimeout(() => setErrorMsgs({ comment: "" }), 1000);
@@ -210,12 +211,13 @@ function NairaWithdraw({
const stateData = { const stateData = {
amount: values.amount, amount: values.amount,
comment: values.comment, comment: values.comment,
wallet_uid: wallet.wallet_uid, choice: "prev",
wallet_uid: wallet.wallet_uid,
...sendMoneyFee, ...sendMoneyFee,
details: { ...recipientDetails[0] }, details: { ...recipientDetails[0] },
}; };
setTimeout(() => { return setTimeout(() => {
setRequestStatus(false); setRequestStatus(false);
// navigate("confirm-withdraw-naira", { state: stateData }); // navigate("confirm-withdraw-naira", { state: stateData });
action(); action();
@@ -226,11 +228,50 @@ function NairaWithdraw({
if (tab === "new") { if (tab === "new") {
const { accountNumber, accountType, bank, city, country, state } = const { accountNumber, accountType, bank, city, country, state } =
values?.newAccount; values?.newAccount;
if (
!accountNumber ||
!accountType ||
!bank ||
!city ||
!country ||
!state
) {
return;
}
setRequestStatus(true);
// Ensure bankDetails is an array and not undefined
const bankDetails = bankName.data?.filter(
(item) => item.bank_uid === bank
);
// Ensure bankDetails is not empty
if (!bankDetails || bankDetails.length === 0) {
// Handle the case when bankDetails is empty or undefined
setRequestStatus(false);
return;
}
const stateData = {
amount: values.amount,
comment: values.comment,
choice: "new",
wallet_uid: wallet.wallet_uid,
...sendMoneyFee,
details: { ...bankDetails[0], ...values?.newAccount },
};
return setTimeout(() => {
setRequestStatus(false);
action();
setShowConfirmNairaWithdraw({ show: true, state: stateData });
}, 1000);
} }
} catch (errors) { } catch (errors) {
// If validation fails, handle the validation errors // If validation fails, handle the validation errors
throw new Error("Validation errors:", errors); throw new Error("Validation errors:", errors);
//
} }
}; };
@@ -275,11 +316,7 @@ function NairaWithdraw({
</button> </button>
</div> </div>
<div className="add-fund w-full md:p-8 p-4 bg-white dark:bg-dark-white h-full rounded-2xl"> <div className="add-fund w-full md:p-8 p-4 bg-white dark:bg-dark-white h-full rounded-2xl">
<Formik <Formik initialValues={initialValues} onSubmit={handleSubmit}>
initialValues={initialValues}
// validationSchema={validationSchema}
onSubmit={handleSubmit}
>
{(props) => { {(props) => {
return ( return (
<Form className="transfer-fund-info"> <Form className="transfer-fund-info">
@@ -287,26 +324,21 @@ function NairaWithdraw({
<div className="flex flex-col"> <div className="flex flex-col">
<div className="field w-full"> <div className="field w-full">
<InputCom <InputCom
fieldClass="px-4" fieldClass="px-4 text-end"
parentClass="flex items-center gap-1 justify-between" parentClass="flex items-center gap-1 justify-between"
labelClass="flex-[0.2] mb-0" labelClass="flex-[0.4] mb-0"
inputClass="flex-[0.8] max-w-[12rem]" inputClass="flex-[0.6] max-w-[12rem]"
label="Amount:" label="Amount:"
type="number" type="number"
name="amount" name="amount"
placeholder="0" placeholder="0"
direction="rtl"
value={props.values.amount} value={props.values.amount}
inputHandler={props.handleChange} inputHandler={props.handleChange}
blurHandler={(e) => { blurHandler={(e) => {
getSendMoneyFee(e); getSendMoneyFee(e);
}} }}
error={errorMsgs.amount && errorMsgs.amount}
/> />
{errorMsgs?.amount && (
<p className="sm:text-sm text-[12px] text-red-500 sm:text-left text-right sm:translate-y-0 translate-y-1">
{errorMsgs.amount}
</p>
)}
</div> </div>
<div className="field w-full"> <div className="field w-full">
@@ -416,7 +448,7 @@ function NairaWithdraw({
{/* <label className="text-[#181c32] dark:text-white text-base font-semibold block flex-[0.2] mb-0 mt-3"></label> */} {/* <label className="text-[#181c32] dark:text-white text-base font-semibold block flex-[0.2] mb-0 mt-3"></label> */}
<div className="flex flex-col gap-3 flex-[0.8] items-center"> <div className="flex flex-col gap-3 flex-[0.8] items-center">
<select <select
className="sm:w-full w-48 text-base p-2 text-dark-gray dark:text-white rounded-md border border-slate-300 outline-0 flex-[0.8]" className="sm:w-full w-48 text-dark-gray border-slate-300 outline-0 flex-[0.8] my-3 rounded-full p-2 outline-none text-base dark:text-gray-100 bg-[#FAFAFA] dark:bg-[#11131F] border appearance-none"
value={ value={
props.values.previousAccount?.recipientID props.values.previousAccount?.recipientID
} }
@@ -441,7 +473,7 @@ function NairaWithdraw({
?.recipientID ?.recipientID
? errorMsgs.previousAccount ? errorMsgs.previousAccount
.recipientID .recipientID
: "Select..."} : "Select an account"}
</option> </option>
{recipients.data.map((item, index) => ( {recipients.data.map((item, index) => (
<option <option
@@ -485,7 +517,7 @@ function NairaWithdraw({
</div> </div>
</div> </div>
</div> </div>
<div className="h-[7.6rem]"></div> <div className="h-[7.8rem]"></div>
</> </>
)} )}
@@ -503,12 +535,13 @@ function NairaWithdraw({
<span className="text-red-500">*</span> <span className="text-red-500">*</span>
</label> </label>
<select <select
className="w-full text-base p-2 text-dark-gray dark:text-white border border-slate-300 outline-0 flex-[0.6] rounded-full h-[42px] overflow-hidden relative font-medium leading-6 bg-clip-padding" className="w-full text-base p-2 text-dark-gray dark:text-white border border-slate-300 outline-0 flex-[0.6] rounded-full h-[42px] overflow-hidden relative font-medium leading-6 bg-clip-padding tracking-[1.5px]"
name="newAccount.country" name="newAccount.country"
value={props.values.newAccount?.country} value={props.values.newAccount?.country}
onChange={ onChange={(e) => {
props.handleChange || handleBankOptions props.handleChange(e);
} handleBankOptions(e);
}}
> >
{allCountries.loading ? ( {allCountries.loading ? (
<option <option
@@ -558,7 +591,7 @@ function NairaWithdraw({
<div className="add-recipient w-full flex items-center flex-1"> <div className="add-recipient w-full flex items-center flex-1">
<label <label
htmlFor="newAccount.bank" htmlFor="newAccount.bank"
className="input-label text-[#181c32] dark:text-white text-base font-semibold inline-flex flex-[0.4]" className="input-label text-[#181c32] dark:text-white text-base font-semibold inline-flex flex-[0.4] tracking-[1.5px]"
> >
Bank Name{" "} Bank Name{" "}
<span className="text-red-500">*</span> <span className="text-red-500">*</span>
@@ -589,7 +622,7 @@ function NairaWithdraw({
<option <option
key={index} key={index}
className="text-slate-500 text-lg" className="text-slate-500 text-lg"
value={item.code} value={item.bank_uid}
> >
{item.name} {item.name}
</option> </option>
@@ -600,7 +633,9 @@ function NairaWithdraw({
className="text-slate-500 text-lg" className="text-slate-500 text-lg"
value="" value=""
> >
No Options Found! {allCountries.data?.length
? "Select..."
: "No Options Found!"}
</option> </option>
)} )}
</select> </select>
@@ -623,11 +658,12 @@ function NairaWithdraw({
<span className="text-red-500">*</span> <span className="text-red-500">*</span>
</label> </label>
<InputCom <InputCom
fieldClass="px-6" fieldClass="px-6 tracking-[1.5px]"
inputClass="flex items-center max-w-[15rem]" inputClass="flex items-center max-w-[15rem]"
type="text" type="text"
name="newAccount.accountNumber" name="newAccount.accountNumber"
placeholder="Account No" placeholder="Account No"
maxLength={10}
value={props.values.newAccount?.accountNumber} value={props.values.newAccount?.accountNumber}
inputHandler={props.handleChange} inputHandler={props.handleChange}
blurHandler={props.handleBlur} blurHandler={props.handleBlur}
@@ -649,7 +685,7 @@ function NairaWithdraw({
Type <span className="text-red-500">*</span> Type <span className="text-red-500">*</span>
</label> </label>
<select <select
className="w-full text-base p-2 text-dark-gray dark:text-white border border-slate-300 outline-0 flex-[0.6] rounded-full h-[42px] overflow-hidden relative font-medium leading-6 bg-clip-padding flex-grow" className="w-full text-base p-2 text-dark-gray dark:text-white border border-slate-300 outline-0 flex-[0.6] rounded-full h-[42px] overflow-hidden relative font-medium leading-6 bg-clip-padding flex-grow tracking-[1.5px]"
name="newAccount.accountType" name="newAccount.accountType"
value={props.values.newAccount?.accountType} value={props.values.newAccount?.accountType}
onChange={props.handleChange} onChange={props.handleChange}
@@ -708,7 +744,7 @@ function NairaWithdraw({
State <span className="text-red-500">*</span> State <span className="text-red-500">*</span>
</label> </label>
<InputCom <InputCom
fieldClass="px-6" fieldClass="px-6 tracking-[1.5px]"
inputClass="max-w-[10rem]" inputClass="max-w-[10rem]"
type="text" type="text"
name="newAccount.state" name="newAccount.state"
@@ -733,7 +769,7 @@ function NairaWithdraw({
City <span className="text-red-500">*</span> City <span className="text-red-500">*</span>
</label> </label>
<InputCom <InputCom
fieldClass="px-6" fieldClass="px-6 tracking-[1.5px]"
type="text" type="text"
inputClass="max-w-[10rem]" inputClass="max-w-[10rem]"
name="newAccount.city" name="newAccount.city"
+17 -22
View File
@@ -13,7 +13,7 @@ import LoadingSpinner from "../Spinners/LoadingSpinner";
const WalletBox = lazy(() => import("./WalletBox")); const WalletBox = lazy(() => import("./WalletBox"));
const WalletRoutes = () => { const WalletRoutes = () => {
const apiCall = useMemo(() => new usersService(), []); const apiCall = new usersService();
const { walletTable } = useSelector((state) => state.tableReload); const { walletTable } = useSelector((state) => state.tableReload);
const [walletList, setWalletList] = useState({ const [walletList, setWalletList] = useState({
loading: true, loading: true,
@@ -25,29 +25,23 @@ const WalletRoutes = () => {
data: [], data: [],
}); });
const getWalletList = useCallback(() => { const getWalletList = () => {
return apiCall apiCall
.getUserWallets() .getUserWallets()
.then((res) => { .then((res) => {
if (res.data.internal_return < 0) { if (res.data.internal_return < 0) {
setWalletList({ loading: false, data: [] }); setWalletList({ loading: false, data: [] });
} else { } else {
setWalletList({ loading: true, data: [] }); setWalletList({ loading: false, data: res.data?.result_list });
setTimeout(
() =>
setWalletList({ loading: false, data: res.data?.result_list }),
500
);
} }
}) })
.catch(() => { .catch(() => {
setWalletList({ loading: false, data: [] }); setWalletList({ loading: false, data: [] });
}); });
}, [apiCall]); }
const getPaymentHistory = useCallback(() => { const getPaymentHistory = () => {
return apiCall apiCall
.getPaymentHx() .getPaymentHx()
.then((res) => { .then((res) => {
if (res.data.internal_return < 0) { if (res.data.internal_return < 0) {
@@ -59,19 +53,20 @@ const WalletRoutes = () => {
.catch(() => { .catch(() => {
setPaymentHistory({ loading: false, data: [] }); setPaymentHistory({ loading: false, data: [] });
}); });
}, [apiCall]); }
useEffect(() => { useEffect(() => {
const fetchData = async () => { // const fetchData = async () => {
await Promise.all([getWalletList(), getPaymentHistory()]); // await Promise.all([getWalletList(), getPaymentHistory()]);
}; // };
if (walletList.loading) { // if (walletList.loading) {
fetchData(); // fetchData();
} // }
}, [walletTable, walletList.loading]); getWalletList()
getPaymentHistory()
}, [walletTable]);
console.log(walletTable);
return ( return (
<Layout> <Layout>
<Suspense fallback={<LoadingSpinner size="16" color="sky-blue" />}> <Suspense fallback={<LoadingSpinner size="16" color="sky-blue" />}>
+15 -25
View File
@@ -1,40 +1,25 @@
import React, { useCallback, useState } from "react"; import React, { useCallback, useState } from "react";
import usersService from "../../services/UsersService";
import ConfirmNairaWithdraw from "./Popup/ConfirmNairaWithdraw"; import ConfirmNairaWithdraw from "./Popup/ConfirmNairaWithdraw";
import NairaWithdraw from "./Popup/NairaWithdraw"; import NairaWithdraw from "./Popup/NairaWithdraw";
import usersService from "../../services/UsersService";
function WalletAction({ walletItem, payment, openPopUp }) { function WalletAction({ walletItem, payment, openPopUp }) {
const [showNairaWithdraw, setShowNairaWithdraw] = useState(false); // DETERMINES WHEN NAIRA WITHDRAWAL POPS UP const [showNairaWithdraw, setShowNairaWithdraw] = useState({
const [countries, setCountries] = useState([]); show: false,
state: {},
}); // DETERMINES WHEN NAIRA WITHDRAWAL POPS UP
const [showConfirmNairaWithdraw, setShowConfirmNairaWithdraw] = useState({ const [showConfirmNairaWithdraw, setShowConfirmNairaWithdraw] = useState({
show: false, show: false,
state: {}, state: {},
}); // DETERMINES WHEN CONFIRM NAIRA WITHDRAWAL POPS UP }); // DETERMINES WHEN CONFIRM NAIRA WITHDRAWAL POPS UP
const userApi = new usersService();
// Get Country Api
const getCountryList = useCallback(async () => {
const res = await userApi.getSignupCountryData();
try {
if (res.status === 200) {
const { signup_country } = await res.data;
setCountries(signup_country);
} else if (res.data.result !== 100) {
setCountries("Nothing see here!");
}
} catch (error) {
throw new Error(error);
}
}, []);
return ( return (
<div className="counters w-full flex justify-between gap-2"> <div className="counters w-full flex justify-between gap-2">
<div className="w-1/2 flex justify-center items-center"> <div className="w-1/2 flex justify-center items-center">
<button <button
onClick={() => { onClick={() => {
setShowNairaWithdraw(true); setShowNairaWithdraw((prev) => ({ ...prev, show: true }));
}} }}
className={`${ className={`${
walletItem.code != "NAIRA" && "invisible" walletItem.code != "NAIRA" && "invisible"
@@ -57,13 +42,17 @@ function WalletAction({ walletItem, payment, openPopUp }) {
</button> </button>
</div> </div>
{showNairaWithdraw && ( {showNairaWithdraw.show && (
<NairaWithdraw <NairaWithdraw
wallet={walletItem} wallet={walletItem}
action={() => { action={() => {
setShowNairaWithdraw((prev) => !prev); setShowNairaWithdraw((prev) => ({
...prev,
show: !prev.show,
}));
}} }}
situation={showNairaWithdraw} situation={showNairaWithdraw.show}
state={showNairaWithdraw.state}
setShowConfirmNairaWithdraw={setShowConfirmNairaWithdraw} setShowConfirmNairaWithdraw={setShowConfirmNairaWithdraw}
/> />
)} )}
@@ -78,6 +67,7 @@ function WalletAction({ walletItem, payment, openPopUp }) {
show: !prev.show, show: !prev.show,
})); }));
}} }}
setShowNairaWithdraw={setShowNairaWithdraw}
situation={showConfirmNairaWithdraw.show} situation={showConfirmNairaWithdraw.show}
/> />
)} )}
-1
View File
@@ -35,7 +35,6 @@ export default function Notification() {
const indexOfLastItem = Number(indexOfFirstItem) + Number(process.env.REACT_APP_ITEM_PER_PAGE); const indexOfLastItem = Number(indexOfFirstItem) + Number(process.env.REACT_APP_ITEM_PER_PAGE);
const currentNotifications = notificationData?.slice(indexOfFirstItem, indexOfLastItem); const currentNotifications = notificationData?.slice(indexOfFirstItem, indexOfLastItem);
console.log('TESTING', currentNotifications)
const filterHandler = (value) => { const filterHandler = (value) => {
setValue(value); setValue(value);
switch(value){ switch(value){
+10 -3
View File
@@ -1,5 +1,5 @@
import React, { useContext, useEffect, useMemo, useState } from "react"; import React, { useContext, useEffect, useMemo, useState } from "react";
import { Link, useLocation } from "react-router-dom"; import { Link, useLocation, useNavigate } from "react-router-dom";
import bank1 from "../../assets/images/bank-1.png"; import bank1 from "../../assets/images/bank-1.png";
import bank2 from "../../assets/images/bank-2.png"; import bank2 from "../../assets/images/bank-2.png";
import bank3 from "../../assets/images/bank-3.png"; import bank3 from "../../assets/images/bank-3.png";
@@ -14,7 +14,7 @@ import WalletHeader from "../MyWallet/WalletHeader";
import { useDispatch, useSelector } from "react-redux"; import { useDispatch, useSelector } from "react-redux";
import Flag from "../../assets/images/united-states.svg"; import Flag from "../../assets/images/united-states.svg";
import siteLogo from "../../assets/images/wrenchboard.png"; import siteLogo from "../../assets/images/wrenchboard-logo-text.png";
import formattedDate from "../../lib/fomattedDate"; import formattedDate from "../../lib/fomattedDate";
import { updateNotifications } from "../../store/notifications"; import { updateNotifications } from "../../store/notifications";
import TimeDifference from "../Helpers/TimeDifference"; import TimeDifference from "../Helpers/TimeDifference";
@@ -26,9 +26,11 @@ export default function Header({ logoutModalHandler, sidebarHandler }) {
const [moneyPopup, setPopup] = useToggle(false); const [moneyPopup, setPopup] = useToggle(false);
const darkMode = useContext(DarkModeContext); const darkMode = useContext(DarkModeContext);
const { userDetails } = useSelector((state) => state?.userDetails); const { userDetails } = useSelector((state) => state?.userDetails);
const { walletTable } = useSelector((state) => state.tableReload); // DETERMINES WHEN WALLET RELOADS
const [myWalletList, setMyWalletList] = useState([]); const [myWalletList, setMyWalletList] = useState([]);
const api = useMemo(() => new usersService(), []); const api = useMemo(() => new usersService(), []);
const dispatch = useDispatch(); const dispatch = useDispatch();
const navigate = useNavigate()
const { notifications } = useSelector((state) => state?.notifications); // NOTIFICATION STORE const { notifications } = useSelector((state) => state?.notifications); // NOTIFICATION STORE
@@ -43,7 +45,7 @@ export default function Header({ logoutModalHandler, sidebarHandler }) {
}; };
useEffect(() => { useEffect(() => {
getMyWalletList(); getMyWalletList();
}, []); }, [walletTable]);
const handlerBalance = () => { const handlerBalance = () => {
setbalanceValue.toggle(); setbalanceValue.toggle();
@@ -317,9 +319,14 @@ export default function Header({ logoutModalHandler, sidebarHandler }) {
<Link <Link
to="/notification" to="/notification"
className="text-purple text-sm font-medium" className="text-purple text-sm font-medium"
onClick={handlerNotification}
> >
See all Notification See all Notification
</Link> </Link>
{/* <button className="text-purple text-sm font-medium" onClick={()=>{
handlerNotification()
navigate('/notification', {replace: true})
}}>See all Notification</button> */}
</div> </div>
</div> </div>
</div> </div>
+1 -1
View File
@@ -4,7 +4,7 @@ import { NavLink } from "react-router-dom";
import { import {
default as logo, default as logo,
default as logo3, default as logo3,
} from "../../assets/images/wrenchboard.png"; //logo-2.svg"; } from "../../assets/images/wrenchboard-logo-text.png"; //logo-2.svg";
import DarkModeContext from "../Contexts/DarkModeContext"; import DarkModeContext from "../Contexts/DarkModeContext";
import Icons from "../Helpers/Icons"; import Icons from "../Helpers/Icons";
+1 -1
View File
@@ -4,7 +4,7 @@ import { NavLink } from "react-router-dom";
import { import {
default as logo, default as logo,
default as logo3, default as logo3,
} from "../../assets/images/wrenchboard.png"; } from "../../assets/images/wrenchboard-logo-text.png";
import DarkModeContext from "../Contexts/DarkModeContext"; import DarkModeContext from "../Contexts/DarkModeContext";
import Icons from "../Helpers/Icons"; import Icons from "../Helpers/Icons";
+84 -8
View File
@@ -1,9 +1,65 @@
import { useEffect, useState } from "react";
import ProductCardStyleTwo from "../../Cards/ProductCardStyleTwo"; import ProductCardStyleTwo from "../../Cards/ProductCardStyleTwo";
import DataIteration from "../../Helpers/DataIteration"; import DataIteration from "../../Helpers/DataIteration";
import SearchCom from "../../Helpers/SearchCom"; import SearchCom from "../../Helpers/SearchCom";
import localImgLoad from "../../../lib/localImgLoad"; import localImgLoad from "../../../lib/localImgLoad";
import usersService from "../../../services/UsersService";
import LoadingSpinner from "../../Spinners/LoadingSpinner";
export default function QuestionsTab({ className, products }) { export default function QuestionsTab({ className, products }) {
const apiCall = new usersService()
const [requestStatus, setRequestStatus] = useState({loading: false, status: false, message: ''})
const [error, setError] = useState({question: '', searchPhrase: ''})
const [questions, setQuestions] = useState({loading: true, data: []})
const [askQuestion, setAskQuestion] = useState({question: '', searchPhrase: ''})
const changeAskQuestion = ({target: {name, value}}) => {
setAskQuestion(prev => ({...prev, [name]: value}))
setRequestStatus({loading: false, status: false, message: ''})
}
const onSearch = () => {
setError({question: '', searchPhrase: ''}) // sets error to false
if(!askQuestion.question){
return setError(prev => ({...prev, question: 'Select a question'}))
}
if(!askQuestion.searchPhrase){
return setError(prev => ({...prev, searchPhrase: 'Enter search parameter'}))
}
if(askQuestion.searchPhrase.length > 60){
return setError(prev => ({...prev, searchPhrase: 'Max of 60 characters'}))
}
setRequestStatus({loading: true, status: false, message: ''})
let reqData = {
question_key: '',
question: ''
}
apiCall.askResourcesResult().then(res => {
console.log(res.data.choices[0].text)
if(!res.data || res.data?.choices?.length < 1){
setRequestStatus({loading: false, status: false, message: 'No result found!'})
}
setRequestStatus({loading: false, status: false, message: res.data?.choices[0].text})
}).catch(error => {
setRequestStatus({loading: false, status: false, message: 'No result found!'})
})
}
useEffect(()=>{
apiCall.getResourceList().then(res => {
setQuestions({loading: false, data: res.data?.ask_categories?.data})
}).catch(error => {
setQuestions({loading: false, data: []})
console.log('ERROR', error)
})
}, [])
return ( return (
<> <>
<div className={`onsale-tab-wrapper w-full ${className || ""}`}> <div className={`onsale-tab-wrapper w-full ${className || ""}`}>
@@ -16,29 +72,49 @@ export default function QuestionsTab({ className, products }) {
</div> </div>
<div className="p-8 bg-white rounded-2xl h-full"> <div className="p-8 bg-white rounded-2xl h-full">
<div className="input-wrapper border border-[#f5f8fa] dark:border-[#5e6278] w-full rounded-full h-[42px] overflow-hidden relative font-medium leading-6 bg-clip-padding text-[#5e6278] dark:text-gray-100 bg-[#f5f8fa] dark:bg-[#5e6278] text-base"> <div className="input-wrapper border border-[#f5f8fa] dark:border-[#5e6278] w-full rounded-full h-[42px] overflow-hidden relative font-medium leading-6 bg-clip-padding text-[#5e6278] dark:text-gray-100 bg-[#f5f8fa] dark:bg-[#5e6278] text-base">
<select className="input-field px-2 placeholder:text-base text-dark-gray w-full h-full tracking-wide dark:bg-[#11131F] bg-[#fafafa] focus:ring-0 focus:outline-none"> <select value={askQuestion.question} name='question' onChange={changeAskQuestion} className="input-field px-2 placeholder:text-base text-dark-gray w-full h-full tracking-wide dark:bg-[#11131F] bg-[#fafafa] focus:ring-0 focus:outline-none">
<option className="rounded-full">Find answer on:</option> {questions.loading ?
<option value='' className="">Loading...</option>
:
<>
<option value='' className="">Find answer on:</option>
{questions.data.length > 0 && questions.data.map((item, index)=>(
<option key={index} value={item.question_key} className="">{item.name}</option>
))}
</>
}
</select> </select>
</div> </div>
{error.question && <p className="text-red-500 text-[12px]">{error.question}</p>}
{/* filter-search */} {/* filter-search */}
<div className="w-full my-5 border-2 rounded-full"> <div className="w-full my-5 border-2 rounded-full">
<SearchCom /> <SearchCom
name={'searchPhrase'}
value={askQuestion.searchPhrase}
handleSearch={changeAskQuestion}
/>
</div> </div>
{error.searchPhrase && <p className="text-red-500 text-[12px]">{error.searchPhrase}</p>}
<div className="w-full flex justify-end items-center border-b-2 pb-4"> <div className="w-full flex justify-end items-center border-b-2 pb-4">
<button <button
onClick={onSearch}
disabled={requestStatus.loading}
className="btn-gradient text-base tracking-wide px-4 py-2 rounded-full text-white cursor-pointer" className="btn-gradient text-base tracking-wide px-4 py-2 rounded-full text-white cursor-pointer"
> >
Search Search
</button> </button>
</div> </div>
<div className="search_result my-2 max-h-[400px] overflow-auto">
{requestStatus.loading ?
<LoadingSpinner size='8' color='sky-blue' height='h-[100px]' />
:
<p className="py-2 text-sm font-bold text-dark-gray dark:text-white tracking-wide">{requestStatus.message}</p>
}
</div>
</div> </div>
</div> </div>
</div> </div>
{/* <div className="content-section w-full-width">
<div className="grid lg:grid-cols-3 sm:grid-cols-2 grid-cols-1 gap-[30px]">
</div>
</div> */}
</div> </div>
</div> </div>
</> </>
@@ -100,7 +100,7 @@ export default function RecomendedSliders({ className, bannerData }) {
<div className="slider-content"> <div className="slider-content">
<SliderCom settings={settings} selector={sellSlider}> <SliderCom settings={settings} selector={sellSlider}>
{bannerData.map((item, index) => ( {bannerData.map((item, index) => (
<Link key={index} to={`/${item.link_path}`}> <Link key={index} to={item.link_path == 'blog-page' ? `/${item.link_path}?blog_id=${item.blog_id}` : `/${item.link_path}`}>
<div className="item"> <div className="item">
<div <div
className={`commonHeaderSliderItem flex gap-1 flex-col justify-between items-center ${item.short_style}`} className={`commonHeaderSliderItem flex gap-1 flex-col justify-between items-center ${item.short_style}`}
+94 -41
View File
@@ -1,10 +1,14 @@
import React, { useCallback, useMemo, useState } from "react"; import React, { useMemo, useState } from "react";
import Detail from "./popoutcomponent/Detail";
import ModalCom from "../Helpers/ModalCom";
import usersService from "../../services/UsersService";
import { toast } from "react-toastify"; import { toast } from "react-toastify";
import LoadingSpinner from "../Spinners/LoadingSpinner"; import usersService from "../../services/UsersService";
import ModalCom from "../Helpers/ModalCom";
import { PriceFormatter } from "../Helpers/PriceFormatter"; import { PriceFormatter } from "../Helpers/PriceFormatter";
import LoadingSpinner from "../Spinners/LoadingSpinner";
import Detail from "./popoutcomponent/Detail";
import { useNavigate } from "react-router-dom";
import { useDispatch } from "react-redux";
import { tableReload } from "../../store/TableReloads";
const showSuccessToast = (message) => { const showSuccessToast = (message) => {
toast.success(message, { toast.success(message, {
@@ -14,48 +18,85 @@ const showSuccessToast = (message) => {
}; };
function PendingJobsPopout({ details, onClose, situation }) { function PendingJobsPopout({ details, onClose, situation }) {
const dispatch = useDispatch()
const navigate = useNavigate()
const [pendingJobLoader, setPendingJobLoader] = useState({ const [pendingJobLoader, setPendingJobLoader] = useState({
extend: false, extend: false,
offer: false, offer: false,
}); });
const apiCall = useMemo(() => new usersService(), []);
const handlePendingJobsBtn = useCallback( let [requestMessage, setRequestMessage] = useState({status: false, message: ''})
async ({ target: { name } }) => {
const apiCall = new usersService();
const handlePendingJobsBtn = ({ target: { name } }) => {
let { job_uid, offer_code } = details; let { job_uid, offer_code } = details;
let reqData; let reqData;
let pendingData = { job_uid, offer_code }; let pendingData = { job_uid, offer_code };
if(name=='extend'){ // RUNS THIS TO EXTEND JOB EXPIRY BY ONE WEEK
reqData = { ...pendingData };
setPendingJobLoader({ extend: true });
apiCall.pendingJobExtend(reqData).then(res => {
setRequestMessage({status: true, message: res.data.status})
dispatch(tableReload({ type: "PENDINGTABLE" }));
setTimeout(() => {
setPendingJobLoader({ extend: false, offer: false });
setRequestMessage({status: false, message: ''})
onClose();
}, 2700);
}).catch(error => {
setRequestMessage({status: false, message:'Try Again'})
setTimeout(() => {
setPendingJobLoader({ extend: false, offer: false });
setRequestMessage({status: false, message: ''})
}, 2700);
})
}else if(name=='offer'){ // RUNS THIS IF JOB IS SENT TO USER
reqData = { ...pendingData };
setPendingJobLoader({ offer: true });
apiCall.pendingJobSendTome(reqData).then(res => {
setRequestMessage({status: true, message: res.data.status})
setTimeout(() => {
setPendingJobLoader({ extend: false, offer: false });
setRequestMessage({status: false, message: ''})
}, 2700);
}).catch(error => {
setRequestMessage('Try Again')
setTimeout(() => {
setPendingJobLoader({ extend: false, offer: false });
setRequestMessage({status: false, message: ''})
}, 2700);
})
} else return
// try {
// if (name === "extend") {
// setPendingJobLoader({ extend: true });
// reqData = { ...pendingData };
// // let { data } =
// await apiCall.pendingJobExtend(reqData);
// showSuccessToast("Job has been extended by a week!");
// dispatch(tableReload({ type: "PENDINGTABLE" }));
// } else if (name === "offer") {
// setPendingJobLoader({ offer: true });
// reqData = { ...pendingData };
// // let { data } =
// await apiCall.pendingJobSendTome(reqData);
// showSuccessToast("Offer sent, check your email");
// } else return;
try { // setTimeout(() => {
if (name === "extend") { // setPendingJobLoader({ extend: false, offer: false });
setPendingJobLoader({ extend: true }); // onClose();
reqData = { ...pendingData }; // }, 2700);
// let { data } = // } catch (error) {
await apiCall.pendingJobExtend(reqData); // setPendingJobLoader({ extend: false, offer: false });
// console.log("This is for extend", data); // throw new Error(error);
showSuccessToast("Job has been extended by a week!"); // }
} else if (name === "offer") { }
setPendingJobLoader({ offer: true });
reqData = { ...pendingData };
// let { data } =
await apiCall.pendingJobSendTome(reqData);
// console.log("This is for offer", data);
showSuccessToast("Offer sent, check your email");
} else return;
setTimeout(() => {
setPendingJobLoader({ extend: false, offer: false });
onClose();
}, 2700);
} catch (error) {
setPendingJobLoader({ extend: false, offer: false });
throw new Error(error);
}
},
[onClose, apiCall, details]
);
return ( return (
<ModalCom action={onClose} situation={situation} className="edit-popup"> <ModalCom action={onClose} situation={situation} className="edit-popup">
@@ -101,7 +142,8 @@ function PendingJobsPopout({ details, onClose, situation }) {
</span> </span>
<div className=""> <div className="">
<p className="text-sm"> <p className="text-sm">
This Job have been sent to public view {/* This Job have been sent to public view */}
This Job have been sent to {details.job_to}
</p> </p>
<p className="text-sm text-slate-600">This Job will expire</p> <p className="text-sm text-slate-600">This Job will expire</p>
</div> </div>
@@ -153,13 +195,13 @@ function PendingJobsPopout({ details, onClose, situation }) {
/> />
</div> </div>
<div className="my-2 md:flex"> {/* <div className="my-2 md:flex">
<Detail <Detail
label="Public Link" label="Public Link"
value="https://work.wrenchboard.com/plb/viewjob/218B4BWB83" value="https://work.wrenchboard.com/plb/viewjob/218B4BWB83"
bg="bg-slate-200" bg="bg-slate-200"
/> />
</div> </div> */}
</div> </div>
{/* ACTION SECTION */} {/* ACTION SECTION */}
@@ -168,11 +210,11 @@ function PendingJobsPopout({ details, onClose, situation }) {
<div className="mb-3"> <div className="mb-3">
<p className="px-2 py-1 text-sm bg-slate-100"> <p className="px-2 py-1 text-sm bg-slate-100">
Job sent to public view Job sent to {details.job_to}
</p> </p>
</div> </div>
<div className="my-3"> <div className="mt-3 mb-8">
<button <button
className="px-2 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white" className="px-2 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
onClick={handlePendingJobsBtn} onClick={handlePendingJobsBtn}
@@ -187,6 +229,11 @@ function PendingJobsPopout({ details, onClose, situation }) {
)} )}
</button> </button>
</div> </div>
{pendingJobLoader.extend && requestMessage.message &&
<div className={`p-1 ${requestMessage.status ? 'bg-green-500':'bg-red-500'} text-white rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}>
<p>{requestMessage.message}</p>
</div>
}
<div className="my-3"> <div className="my-3">
<button <button
@@ -204,6 +251,12 @@ function PendingJobsPopout({ details, onClose, situation }) {
</button> </button>
</div> </div>
{pendingJobLoader.offer && requestMessage.message &&
<div className={`p-1 ${requestMessage.status ? 'bg-green-500':'bg-red-500'} text-white rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}>
<p>{requestMessage.message}</p>
</div>
}
<div className="mt-10 md:mt-32 md:flex md:justify-center"> <div className="mt-10 md:mt-32 md:flex md:justify-center">
<button <button
className="px-2 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white" className="px-2 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
+21
View File
@@ -0,0 +1,21 @@
const checkAndSetError = (field, value, setErrorFunc, errorMessage) => {
const isNotEmpty = () => {
if (!value) {
setErrorFunc({ [field]: errorMessage });
setTimeout(() => setErrorFunc({ [field]: "" }), 1000);
return false;
}
};
const textCount = () => {
if (!value) {
setErrorFunc({ [field]: errorMessage });
setTimeout(() => setErrorFunc({ [field]: "" }), 1000);
return false;
}
};
return { isNotEmpty, textCount };
};
export default checkAndSetError;
+9 -1
View File
@@ -1,5 +1,13 @@
import ClearCookies from "./ClearCookies"; import ClearCookies from "./ClearCookies";
import checkAndSetError from "./checkAndSetError";
import formattedDate from "./fomattedDate";
import getTimeAgo from "./getTimeAgo"; import getTimeAgo from "./getTimeAgo";
import localImgLoad from "./localImgLoad"; import localImgLoad from "./localImgLoad";
export {ClearCookies, getTimeAgo, localImgLoad} export {
ClearCookies,
checkAndSetError,
formattedDate,
getTimeAgo,
localImgLoad,
};
+44 -5
View File
@@ -411,6 +411,19 @@ class usersService {
}; };
return this.postAuxEnd("/resources", postData); return this.postAuxEnd("/resources", postData);
} }
// ASK QUESTION RESOURCES
askResourcesResult(reqData) {
var postData = {
uuid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
action: 22010,
...reqData,
};
return this.postAuxEnd("/askresources", postData);
}
getMyWiatingJobList() { getMyWiatingJobList() {
// jobs you have shown inteterest in // jobs you have shown inteterest in
var postData = { var postData = {
@@ -480,7 +493,6 @@ class usersService {
member_id: localStorage.getItem("member_id"), member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"), sessionid: localStorage.getItem("session_token"),
action: 33020, action: 33020,
mode: 100,
...reqData, ...reqData,
}; };
return this.postAuxEnd("/sendmoney", postData); return this.postAuxEnd("/sendmoney", postData);
@@ -565,16 +577,31 @@ class usersService {
return this.postAuxEnd("/familymanage", postData); return this.postAuxEnd("/familymanage", postData);
} }
//END POINT CALL FOR ACCOUNT TOP // END POINT CALL FOR ACCOUNT TOP
startTopUp(post) { startTopUp(post) {
alert("WHY ARE WE CALLING THIS ?");
// var postData = {
// uid: localStorage.getItem("uid"),
// member_id: localStorage.getItem("member_id"),
// sessionid: localStorage.getItem("session_token"),
// action: 11062,
// ...post,
// };
// console.log("starttopup",postData);
// return this.postAuxEnd("/starttopup", postData);
}
resultTopUp(post) {
var postData = { var postData = {
uid: localStorage.getItem("uid"), uid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"), member_id: Number(localStorage.getItem("member_id")),
sessionid: localStorage.getItem("session_token"), sessionid: localStorage.getItem("session_token"),
action: 11062, action: 11061,
...post, ...post,
}; };
return this.postAuxEnd("/starttopup", postData); console.log("topupresult",postData);
return this.postAuxEnd("/topupresult", postData);
} }
//END POINT CALL FOR SENDING REFERRAL MESSAGE //END POINT CALL FOR SENDING REFERRAL MESSAGE
@@ -992,6 +1019,18 @@ class usersService {
return this.postAuxEnd("/payremcard", postData); return this.postAuxEnd("/payremcard", postData);
} }
// FUNCTION TO GET SINGLE BLOG ITEM
getSingleBlogData(reqData) {
var postData = {
uid: localStorage.getItem("uid"),
member_id: localStorage.getItem("member_id"),
sessionid: localStorage.getItem("session_token"),
limit: 4,
...reqData,
};
return this.postAuxEnd("/blogdata", postData);
}
/* /*
- 20:27:30.118 FLOG_MAX [757411]: REQ_STRING(username) - 20:27:30.118 FLOG_MAX [757411]: REQ_STRING(username)
- 20:27:30.118 FLOG_MAX [757411]: REQ_STRING(password) - 20:27:30.118 FLOG_MAX [757411]: REQ_STRING(password)
+9 -3
View File
@@ -5,20 +5,26 @@ import { useSelector } from "react-redux";
export default function MyPendingJobsPage() { export default function MyPendingJobsPage() {
let { commonHeadBanner } = useSelector((state) => state.commonHeadBanner); let { commonHeadBanner } = useSelector((state) => state.commonHeadBanner);
const [MyJobList, setMyJobList] = useState([]); let { pendingListTable } = useSelector((state) => state.tableReload);
console.log('TESTING', pendingListTable)
const [MyJobList, setMyJobList] = useState({loading: true, data: []});
const api = new usersService(); const api = new usersService();
const getMyJobList = async () => { const getMyJobList = async () => {
try { try {
const res = await api.getMyPendingJobList(); const res = await api.getMyPendingJobList();
setMyJobList(res.data); setMyJobList({loading: false, data: res.data});
} catch (error) { } catch (error) {
setMyJobList({loading: false, data: []});
console.log("Error getting mode"); console.log("Error getting mode");
} }
}; };
useEffect(() => { useEffect(() => {
getMyJobList(); getMyJobList();
}, []); }, [pendingListTable]);
// debugger; // debugger;
return ( return (