Compare commits

..

51 Commits

Author SHA1 Message Date
victorAnumudu 81707c7bd8 payment count down timer added 2024-04-04 20:41:57 +01:00
victorAnumudu e5b36e3f45 added count down timer 2024-04-04 20:33:49 +01:00
ameye 6f2fc17090 Merge branch 'wallet-page-btn' of WrenchBoard/Users-Wrench into master 2024-04-04 15:19:31 +00:00
victorAnumudu e6392bc433 adjusted wallet btn size 2024-04-04 15:25:50 +01:00
victorAnumudu f8e14fe6a0 initial commit 2024-04-04 14:09:53 +01:00
ameye 91a42cfe9d Merge branch 'interest-btn' of WrenchBoard/Users-Wrench into master 2024-04-04 10:51:33 +00:00
victorAnumudu 3128a77b46 interest button style changed 2024-04-04 11:36:06 +01:00
ameye d7d67e4763 Merge branch 'offer-code-removal' of WrenchBoard/Users-Wrench into master 2024-04-03 21:49:54 +00:00
victorAnumudu 388e49467e removed contract code display 2024-04-03 20:08:27 +01:00
ameye 043718837d Merge branch 'button-style-change' of WrenchBoard/Users-Wrench into master 2024-04-03 10:22:29 +00:00
ameye d0e2ba0aa3 Merge branch 'modal-footer-class' of WrenchBoard/Users-Wrench into master 2024-04-03 10:22:23 +00:00
victorAnumudu a1dc72e5b0 added modal footer class to edit job modal 2024-04-03 10:35:59 +01:00
victorAnumudu 2ab1c960c7 accept btn style changed 2024-04-03 10:06:49 +01:00
ameye 25734882cb Merge branch 'dummy-game-layout' of WrenchBoard/Users-Wrench into master 2024-04-02 19:20:42 +00:00
victorAnumudu ae31962cd7 added game layout 2024-04-02 19:04:42 +01:00
victorAnumudu 96d775d0ba added dummy coming soon text 2024-04-02 17:31:54 +01:00
victorAnumudu bcd45edb2f added game link to env file 2024-04-02 17:23:54 +01:00
victorAnumudu a5631b6291 initial commit 2024-04-02 16:42:54 +01:00
CHIEFSOFT\ameye 2fff427346 CORS iSSUES 2024-04-02 10:53:10 -04:00
CHIEFSOFT\ameye 6ef445958c removed ket temp 2024-04-02 10:45:57 -04:00
ameye 66660d98f9 Merge branch 'popout-btn-adjustment' of WrenchBoard/Users-Wrench into master 2024-04-02 14:22:01 +00:00
victorAnumudu 359344772e added space between buttons 2024-04-02 14:56:07 +01:00
ameye 1533465f8d Merge branch 'media-detail-style' of WrenchBoard/Users-Wrench into master 2024-04-02 12:03:37 +00:00
victorAnumudu 66b1ff5f92 updated style 2024-04-02 11:24:45 +01:00
ameye c141ab1ef2 Merge branch 'media-layout' of WrenchBoard/Users-Wrench into master 2024-04-01 20:53:44 +00:00
victorAnumudu 8a7b56068d added media layout 2024-04-01 21:47:00 +01:00
victorAnumudu bb5a966249 added media layout 2024-04-01 21:42:29 +01:00
ameye 199dec01fe Merge branch 'wallet-modal-style' of WrenchBoard/Users-Wrench into master 2024-04-01 17:36:20 +00:00
victorAnumudu 3775c520ff added modal style to wallet modal 2024-04-01 18:23:34 +01:00
ameye bf19dfe86a Merge branch 'currency-auto-select' of WrenchBoard/Users-Wrench into master 2024-04-01 15:59:59 +00:00
victorAnumudu 4b7c3beb53 auto selecting currency if user has only one wallet 2024-04-01 16:20:58 +01:00
ameye f032ed21b5 Merge branch 'assign-popout-style-update' of WrenchBoard/Users-Wrench into master 2024-04-01 12:07:32 +00:00
victorAnumudu cab461bd2e style adjustment 2024-04-01 11:41:29 +01:00
tokslaw a4307310ad Merge branch 'quick-links' of WrenchBoard/Users-Wrench into master 2024-03-30 23:47:37 +00:00
CHIEFSOFT\ameye dda3207573 xl:ml-[110px] 2024-03-30 13:38:45 -04:00
CHIEFSOFT\ameye 0dd7e5cd19 nft-main-container full 2024-03-30 13:25:17 -04:00
CHIEFSOFT\ameye caaff883f1 added new page for media 2024-03-30 13:19:38 -04:00
victorAnumudu f4ea8d9197 removed quick links on family login 2024-03-29 09:22:51 +01:00
ameye df136b3b30 Merge branch 'manage-media-taskpage' of WrenchBoard/Users-Wrench into master 2024-03-28 16:55:39 +00:00
victorAnumudu c04b909489 added style for manage media task page 2024-03-28 17:48:00 +01:00
ameye 4c208e8a58 Merge branch 'manage-media-task' of WrenchBoard/Users-Wrench into master 2024-03-28 12:55:34 +00:00
ameye d5017db2ba Merge branch 'family-pending-start' of WrenchBoard/Users-Wrench into master 2024-03-28 12:55:30 +00:00
ameye 78ebed6e55 Merge branch 'refactoring-component' of WrenchBoard/Users-Wrench into master 2024-03-28 12:55:23 +00:00
victorAnumudu f0c016deb8 manage media task style 2024-03-28 11:26:41 +01:00
victorAnumudu 4a0cfa03a5 Family pending task start popout style changed 2024-03-28 08:22:00 +01:00
victorAnumudu 36d8c70fd9 refactored some components and seperated their API calls 2024-03-27 23:17:58 +01:00
tokslaw 23443a4677 Merge branch 'family-media-task' of WrenchBoard/Users-Wrench into master 2024-03-27 17:42:54 +00:00
victorAnumudu 16e5656422 rendered video component for media task type 2024-03-27 18:39:04 +01:00
ameye 0e42668285 Merge branch 'media-task-api' of WrenchBoard/Users-Wrench into master 2024-03-27 12:42:23 +00:00
victorAnumudu 66bd8cf6ec added api for assign media task 2024-03-27 13:38:17 +01:00
ameye 3d7ad25517 Merge branch 'media-task' of WrenchBoard/Users-Wrench into master 2024-03-27 11:40:30 +00:00
55 changed files with 4201 additions and 1867 deletions
+8 -1
View File
@@ -14,6 +14,7 @@ REACT_APP_APPSITE="https://myfitapp.mermsemr.com"
REACT_APP_AUX_ENDPOINT="https://apigate.lotus.g1.wrenchboard.com/en/wrench/api/v1"
REACT_APP_USERS_ENDPOINT="https://apigate.lotus.g1.wrenchboard.com/en/wrench/api/v1"
REACT_APP_ENDPOINT_KEY="WRENCH-BOARD-2024"
#SOCKETS ENDS
REACT_APP_PRIMARY_SOCKET="https://socket-dev.wrenchboard.com"
@@ -117,4 +118,10 @@ REACT_APP_SHOW_ACCOUNT_DASH=1
REACT_APP_SHOW_SLIDER_BANNERS=0
# FOR MEDIA LINK
REACT_APP_MEDIA_LINK='https://dev-media.wrenchboard.com '
REACT_APP_MEDIA_LINK='https://dev-media.wrenchboard.com'
# FOR FAMILY GAME LINK
REACT_APP_FAM_GAME_LINK='https://games.wrenchboard.com'
# REACT APP CUSTOMTIMER
REACT_APP_CUSTOMTIMER=90
+8 -1
View File
@@ -14,6 +14,7 @@ REACT_APP_APPSITE="https://myfitapp.mermsemr.com"
REACT_APP_AUX_ENDPOINT="https://apigate.lotus.g1.wrenchboard.com/en/wrench/api/v1"
REACT_APP_USERS_ENDPOINT="https://apigate.lotus.g1.wrenchboard.com/en/wrench/api/v1"
REACT_APP_ENDPOINT_KEY="WRENCH-BOARD-2024"
#SOCKETS ENDS
REACT_APP_PRIMARY_SOCKET="https://socket-dev.wrenchboard.com"
@@ -85,4 +86,10 @@ REACT_APP_SHOW_ACCOUNT_DASH=1
REACT_APP_SHOW_SLIDER_BANNERS=0
# FOR MEDIA LINK
REACT_APP_MEDIA_LINK='https://dev-media.wrenchboard.com '
REACT_APP_MEDIA_LINK='https://dev-media.wrenchboard.com'
# FOR FAMILY GAME LINK
REACT_APP_FAM_GAME_LINK='https://games.wrenchboard.com'
# REACT APP CUSTOMTIMER
REACT_APP_CUSTOMTIMER=90
+8 -1
View File
@@ -14,6 +14,7 @@ REACT_APP_APPSITE="https://myfitapp.mermsemr.com"
REACT_APP_AUX_ENDPOINT="https://apigate.orion.g1.wrenchboard.com/en/wrench/api/v1"
REACT_APP_USERS_ENDPOINT="https://apigate.orion.g1.wrenchboard.com/en/wrench/api/v1"
REACT_APP_ENDPOINT_KEY="WRENCH-BOARD-2024"
#SOCKETS ENDS
REACT_APP_PRIMARY_SOCKET="https://socket.wrenchboard.com"
@@ -91,4 +92,10 @@ REACT_APP_SHOW_ACCOUNT_DASH=1
REACT_APP_SHOW_SLIDER_BANNERS=0
# FOR MEDIA LINK
REACT_APP_MEDIA_LINK='https://media.wrenchboard.com '
REACT_APP_MEDIA_LINK='https://media.wrenchboard.com'
# FOR FAMILY GAME LINK
REACT_APP_FAM_GAME_LINK='https://games.wrenchboard.com'
# REACT APP CUSTOMTIMER
REACT_APP_CUSTOMTIMER=90
+2
View File
@@ -66,6 +66,7 @@ import FamWorkInProgressPage from "./views/FamWorkInProgressPage";
import MyPastDueTasksPage from "./views/MyPastDueTasksPage";
import FamilyWalletPage from "./views/FamilyWalletPage";
import FamilyActivitiesPage from "./views/FamilyActivitiesPage";
import FamGamesPage from "./views/FamGamesPage";
export default function Routers() {
return (
@@ -144,6 +145,7 @@ export default function Routers() {
<Route exact path="/ai-question" element={<FamAIQuestionPage />} />
<Route exact path="/myfiles" element={<FamMyFilesPage />} />
<Route exact path="/ai-lab" element={<FamAIQuestionPage />} />
<Route exact path="/fam-games" element={<FamGamesPage />} />
<Route exact path="/work-in-progress" element={<FamWorkInProgressPage />} />
<Route
exact
+243 -243
View File
@@ -73,8 +73,7 @@ function AddJob({ popUpHandler, categories }) {
};
return (
<div className="add-job p-5 w-full bg-white dark:bg-dark-white dark:text-white rounded-md flex flex-col justify-between">
<Formik
<Formik
initialValues={IV}
validationSchema={validationSchema}
onSubmit={handleAddJob}
@@ -82,281 +81,282 @@ function AddJob({ popUpHandler, categories }) {
{(props) => {
return (
<Form>
<div className="flex flex-col-reverse sm:flex-row">
<div className="fields w-full">
{/* inputs starts here */}
<div className="xl:flex xl:space-x-7 mb-[5px]">
<div className="field w-full mb-6 xl:mb-0">
<label
htmlFor="country"
className="job-label job-label-flex"
>
<span>Currency</span>
{props.errors.country && props.touched.country && (
<span className="text-[12px] text-red-500">
{props.errors.country}
</span>
)}
</label>
<select
id="country"
name="country"
value={props.values.country}
className={`input-field p-2 mt-3 rounded-md placeholder:text-base text-dark-gray dark:text-white w-full h-10 bg-slate-100 dark:bg-[#11131F] focus:ring-0 focus:outline-none border`}
onChange={props.handleChange}
onBlur={props.handleBlur}
>
{walletDetails?.loading ? (
<option className="text-slate-500 text-lg" value="">
Loading...
</option>
) : walletDetails.data.length ? (
<>
<div className="add-job p-5 w-full bg-white dark:bg-dark-white dark:text-white rounded-md flex flex-col justify-between">
<div className="flex flex-col-reverse sm:flex-row">
<div className="fields w-full">
{/* inputs starts here */}
<div className="xl:flex xl:space-x-7 mb-[5px]">
<div className="field w-full mb-6 xl:mb-0">
<label
htmlFor="country"
className="job-label job-label-flex"
>
<span>Currency</span>
{props.errors.country && props.touched.country && (
<span className="text-[12px] text-red-500">
{props.errors.country}
</span>
)}
</label>
<select
id="country"
name="country"
value={props.values.country}
className={`input-field p-2 mt-3 rounded-md placeholder:text-base text-dark-gray dark:text-white w-full h-10 bg-slate-100 dark:bg-[#11131F] focus:ring-0 focus:outline-none border`}
onChange={props.handleChange}
onBlur={props.handleBlur}
>
{walletDetails?.loading ? (
<option className="text-slate-500 text-lg" value="">
Select a currency
Loading...
</option>
{walletDetails.data?.map((item, index) => (
<option
key={index}
className="text-slate-500 text-lg"
value={item?.country}
>
{item?.description}
) : walletDetails.data.length ? (
<>
<option className="text-slate-500 text-lg" value="">
Select a currency
</option>
))}
</>
) : (
<option className="text-slate-500 text-lg" value="">
No Options Found! Try Again
</option>
)}
</select>
{walletDetails.data?.map((item, index) => (
<option
key={index}
className="text-slate-500 text-lg"
value={item?.country}
>
{item?.description}
</option>
))}
</>
) : (
<option className="text-slate-500 text-lg" value="">
No Options Found! Try Again
</option>
)}
</select>
</div>
{/* Price */}
<div className="field w-full">
<InputCom
fieldClass="px-6 text-right flex"
label="Price"
labelClass=""
type="number"
name="price"
placeholder="0"
value={props.values.price}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
error={
props.errors.price &&
props.touched.price &&
props.errors.price
}
/>
</div>
</div>
{/* Price */}
<div className="field w-full">
{/* Title */}
<div className="field w-full mb-[5px]">
<InputCom
fieldClass="px-6 text-right flex"
label="Price"
fieldClass="px-6"
label="Title"
labelClass=""
type="number"
name="price"
placeholder="0"
value={props.values.price}
type="text"
name="title"
value={props.values.title}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
error={
props.errors.price &&
props.touched.price &&
props.errors.price
props.errors.title &&
props.touched.title &&
props.errors.title
}
/>
</div>
</div>
{/* Title */}
<div className="field w-full mb-[5px]">
<InputCom
fieldClass="px-6"
label="Title"
labelClass=""
type="text"
name="title"
value={props.values.title}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
error={
props.errors.title &&
props.touched.title &&
props.errors.title
}
/>
</div>
{/* Description */}
<div className="field w-full mb-[5px]">
<InputCom
fieldClass="px-6"
label="Description"
labelClass=""
type="text"
name="description"
value={props.values.description}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
error={
props.errors.description &&
props.touched.description &&
props.errors.description
}
/>
</div>
{/* Details */}
<div className="field flex flex-col sm:flex-row w-full mb-[5px] gap-2">
<div className="sm:w-[60%] w-full">
<label
htmlFor="Job Delivery Details"
className="job-label job-label-flex"
>
Job Delivery Details
{props.errors.job_detail &&
props.touched.job_detail && (
<span className="text-[12px] text-red-500">
{props.errors.job_detail}
</span>
)}
</label>
<textarea
id="Job Delivery Details"
rows="5"
className={`input-field px-3 py-2 placeholder:text-base text-dark-gray dark:text-white w-full h-[100px] bg-slate-100 dark:bg-[#11131F] focus:ring-0 focus:outline-[#dce4e9] rounded-[10px] border`}
style={{ resize: "none" }}
name="job_detail"
value={props.values.job_detail}
onChange={props.handleChange}
onBlur={props.handleBlur}
{/* Description */}
<div className="field w-full mb-[5px]">
<InputCom
fieldClass="px-6"
label="Description"
labelClass=""
type="text"
name="description"
value={props.values.description}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
error={
props.errors.description &&
props.touched.description &&
props.errors.description
}
/>
</div>
<div className="sm:w-[35%] w-full">
<label
htmlFor="Job Categories"
className='job-label'
id="checked-group"
>
Categories
</label>
<div
className="sm:flex-col flex flex-wrap px-3 mt-3"
role="group"
aria-labelledby="checked-group"
>
{categories ? (
<>
{Object?.entries(categories).map(([key, value]) => (
<label
key={key}
className="flex gap-1 w-full items-center"
>
<Field
type="checkbox"
name="category"
value={key}
/>
<span className="text-[13.975px]">{value}</span>
</label>
))}
</>
) : (
<label className="flex gap-1 w-full items-center">
<Field type="checkbox" name="category" />
<span className="text-[13.975px]">null</span>
</label>
)}
<span className="h-5 text-sm italic text-[#cf3917]">
{props.errors.category &&
props.touched.category &&
"please select a category"}
</span>
{/* Details */}
<div className="field flex flex-col sm:flex-row w-full mb-[5px] gap-2">
<div className="sm:w-[60%] w-full">
<label
htmlFor="Job Delivery Details"
className="job-label job-label-flex"
>
Job Delivery Details
{props.errors.job_detail &&
props.touched.job_detail && (
<span className="text-[12px] text-red-500">
{props.errors.job_detail}
</span>
)}
</label>
<textarea
id="Job Delivery Details"
rows="5"
className={`input-field px-3 py-2 placeholder:text-base text-dark-gray dark:text-white w-full h-[100px] bg-slate-100 dark:bg-[#11131F] focus:ring-0 focus:outline-[#dce4e9] rounded-[10px] border`}
style={{ resize: "none" }}
name="job_detail"
value={props.values.job_detail}
onChange={props.handleChange}
onBlur={props.handleBlur}
/>
</div>
<div className="sm:w-[35%] w-full">
<label
htmlFor="Job Categories"
className='job-label'
id="checked-group"
>
Categories
</label>
<div
className="sm:flex-col flex flex-wrap px-3 mt-3"
role="group"
aria-labelledby="checked-group"
>
{categories ? (
<>
{Object?.entries(categories).map(([key, value]) => (
<label
key={key}
className="flex gap-1 w-full items-center"
>
<Field
type="checkbox"
name="category"
value={key}
/>
<span className="text-[13.975px]">{value}</span>
</label>
))}
</>
) : (
<label className="flex gap-1 w-full items-center">
<Field type="checkbox" name="category" />
<span className="text-[13.975px]">null</span>
</label>
)}
<span className="h-5 text-sm italic text-[#cf3917]">
{props.errors.category &&
props.touched.category &&
"please select a category"}
</span>
</div>
</div>
</div>
</div>
<div className="field w-full mb-[5px]">
<div className={`flex items-center justify-between mb-2.5`}>
<label
className="job-label"
htmlFor="timeline_days"
>
Timeline
<span className="text-green-700 text-sm tracking-wide">
- Expected duration of this task
</span>
</label>
</div>
<Field
component="select"
name="timeline_days"
className={`input-field p-2 mt-3 rounded-md placeholder:text-base text-dark-gray dark:text-white w-full h-10 bg-slate-100 dark:bg-[#11131F] focus:ring-0 focus:outline-none border ${
props.errors.timeline_days &&
props.touched.timeline_days
? "border-[#ff0a0a63] shadow-red-500 border-[0.5px] animate-shake"
: "border border-[#f5f8fa] dark:border-[#5e6278]"
}`}
value={props.values.timeline_days}
>
<option value="">Select Duration</option>
{publicArray.map(({ name, duration }, idx) => (
<option
key={idx}
className="text-slate-500 text-lg"
value={duration}
<div className="field w-full mb-[5px]">
<div className={`flex items-center justify-between mb-2.5`}>
<label
className="job-label"
htmlFor="timeline_days"
>
{name}
</option>
))}
</Field>
</div>
{/* inputs ends here */}
</div>
</div>
Timeline
<span className="text-green-700 text-sm tracking-wide">
- Expected duration of this task
</span>
</label>
</div>
{/* ERROR DISPLAY AND SUBMIT BUTTON */}
<div className="content-footer w-full">
{/* error or success display */}
{requestStatus.message != "" &&
(!requestStatus.status ? (
<div
className={`relative p-4 my-4 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}
>
{requestStatus.message}
<Field
component="select"
name="timeline_days"
className={`input-field p-2 mt-3 rounded-md placeholder:text-base text-dark-gray dark:text-white w-full h-10 bg-slate-100 dark:bg-[#11131F] focus:ring-0 focus:outline-none border ${
props.errors.timeline_days &&
props.touched.timeline_days
? "border-[#ff0a0a63] shadow-red-500 border-[0.5px] animate-shake"
: "border border-[#f5f8fa] dark:border-[#5e6278]"
}`}
value={props.values.timeline_days}
>
<option value="">Select Duration</option>
{publicArray.map(({ name, duration }, idx) => (
<option
key={idx}
className="text-slate-500 text-lg"
value={duration}
>
{name}
</option>
))}
</Field>
</div>
) : (
requestStatus.status && (
{/* inputs ends here */}
</div>
</div>
{/* ERROR DISPLAY AND SUBMIT BUTTON */}
<div className="content-footer w-full">
{/* error or success display */}
{requestStatus.message != "" &&
(!requestStatus.status ? (
<div
className={`relative p-4 my-4 text-green-700 bg-slate-200 border-slate-800 mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}
className={`relative p-4 my-4 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}
>
{requestStatus.message}
</div>
)
))}
{/* End of error or success display */}
<div className="w-full h-[70px] border-t border-light-purple dark:border-[#5356fb29] flex justify-end items-center">
<div className="flex items-center space-x-4 mr-9">
<button
type="button"
className="text-18 tracking-wide h-11 flex justify-center items-center border border-light-red text-base rounded-full text-light-red cursor-pointer"
>
<span
className="px-2"
onClick={popUpHandler}
>
{" "}
Cancel
</span>
</button>
{requestStatus?.loading ? (
<LoadingSpinner size="8" color="sky-blue" />
) : (
<button
type="submit"
className="w-[152px] h-[46px] flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
Add Job
</button>
)}
</div>
requestStatus.status && (
<div
className={`relative p-4 my-4 text-green-700 bg-slate-200 border-slate-800 mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}
>
{requestStatus.message}
</div>
)
))}
{/* End of error or success display */}
</div>
</div>
<div className="modal-footer-wrapper grid grid-cols-1 xxs:grid-cols-3">
<div className="w-full col-span-1 xxs:col-span-2 xxs:col-start-2 flex justify-between items-center">
<button
type="button"
className="custom-btn border border-light-red text-light-red"
>
<span
className="px-2"
onClick={popUpHandler}
>
{" "}
Cancel
</span>
</button>
{requestStatus?.loading ? (
<LoadingSpinner size="8" color="sky-blue" />
) : (
<button
type="submit"
className="custom-btn btn-gradient text-white"
>
Add Job
</button>
)}
</div>
</div>
</Form>
);
}}
</Formik>
</div>
);
}
+13 -5
View File
@@ -1,7 +1,10 @@
import { Suspense, lazy } from "react";
import localImgLoad from "../../lib/localImgLoad";
import CountDown from "../Helpers/CountDown";
import { PriceFormatter } from "../Helpers/PriceFormatter";
const VideoElement = lazy(() => import("../VideoCom/VideoElement")); // LAZY IMPORTING VIDEO COMPONENT
export default function OfferCard({
datas,
hidden = false,
@@ -19,9 +22,13 @@ export default function OfferCard({
return (
<div className="card-style-one flex flex-col justify-between w-full h-[387px] bg-white dark:bg-dark-white p-3 pb rounded-2xl">
<div className="content">
{/* thumbnail */}
<div className="w-full h-40">
{/* thumbnail image */}
{/* thumbnail image/video */}
{datas.job_type == "MEDIA" ?
<Suspense fallback={<p>Loading...</p>}>
<VideoElement videoId={datas?.media_uid} />
</Suspense>
:
<div
className="thumbnail w-full h-full rounded-xl overflow-hidden px-4 pt-4"
style={{
@@ -30,6 +37,7 @@ export default function OfferCard({
>
{hidden && <div className="flex justify-center"></div>}
</div>
}
</div>
{/* details */}
<div className="details">
@@ -38,15 +46,15 @@ export default function OfferCard({
</h1>
<div className="w-full p-2 rounded-lg border border-[#E3E4FE] dark:border-[#a7a9b533] ">
<div className="grid grid-cols-2 gap-2">
<div className="flex flex-col justify-between items-center border-r-2">
<div className="grid grid-cols-1 gap-2">
{/* <div className="flex flex-col justify-between items-center border-r-2">
<p className="text-sm text-thin-light-gray dark:text-white tracking-wide">
Task Code
</p>
<p className="text-base font-bold tracking-wide text-dark-gray dark:text-white">
{datas.contract}
</p>
</div>
</div> */}
<div className="flex flex-col justify-between items-center">
<p className="text-sm text-red-500 tracking-wide">Expires</p>
<p className="text-base font-bold tracking-wide text-dark-gray dark:text-white">
+102 -101
View File
@@ -14,6 +14,7 @@ import LoadingSpinner from "../Spinners/LoadingSpinner";
import AssignTaskPopout from "./FamilyPopout/AssignTaskPopout";
import FamilyWallet from "./Tabs/FamilyWallet";
import { apiConst } from "../../lib/apiConst";
import { useSelector } from "react-redux";
// Lazy Imports for components
const FamilyWaitlist = lazy(() => import("./Tabs/FamilyWaitlist"));
@@ -29,43 +30,32 @@ export default function FamilyManageTabs({
listReload,
loader,
}) {
const { jobListTable, pendingListTable, parentFamilyTaskList } = useSelector((state) => state.tableReload); // TABLE RELOAD TRIGGERS
// Initial state for family details
const initialDetailState = {
loading: false,
data: null,
data: [],
};
// console.log('accountDetails',accountDetails)
// State for family details, tasks, waitlist, and pending
const [details, setDetails] = useState({
familyDetails: { ...initialDetailState },
familyTasks: { ...initialDetailState },
familyWaitList: { ...initialDetailState },
familyPending: { ...initialDetailState },
});
// Function to reset family details, tasks, waitlist, and pending
const resetDetails = () => {
setDetails({
familyDetails: { ...initialDetailState },
familyTasks: { ...initialDetailState },
familyWaitList: { ...initialDetailState },
familyPending: { ...initialDetailState },
});
};
// State for family details, tasks, waitlist, and pending
let [familyDetails, setFamilyDetails] = useState({loading: false, data: {}})
let [familyTasks, setFamilyTasks] = useState({...initialDetailState})
let [familyWaitList, setFamilyWaitList] = useState({...initialDetailState})
let [familyPending, setFamilyPending] = useState({...initialDetailState})
const [updatePage, setUpdatePage] = useState(false) // State to determine when to update the page
// State for family task data
const [familyTask, setFamilyTask] = useState({ loading: false, data: [] });
// State for list of created jobs by FULL USER
const [jobList, setJobList] = useState({ loading: false, data: [] });
// State for active task
// State for active/selected job
const [activeTask, setActiveTask] = useState({ id: 0, data: {} });
// State for error messages
const [errMsg, setErrMsg] = useState("");
// State for family task popout
const [familyTaskPopout, setFamilyTaskPopout] = useState(false);
const [assignTaskPopout, setAssignTaskPopout] = useState(false);
let [uploadStatus, setUploadStatus] = useState({loading: false, status: false, message:''}) // HOLDS STATE FOR UPLOAD PROFILE PICTURE STATUS
@@ -79,8 +69,8 @@ export default function FamilyManageTabs({
const apiCall = useMemo(() => new usersService(), []);
// Function to handle toggling the family task popout
const familyPopUpHandler = () => {
setFamilyTaskPopout((prev) => !prev);
const familyAssignPopUpHandler = () => {
setAssignTaskPopout((prev) => !prev);
};
// Function to trigger a click on the hidden profile image input
@@ -177,44 +167,40 @@ export default function FamilyManageTabs({
Tasks: (
<FamilyTasks
className={className}
loader={details.familyTasks.loading}
familyData={details.familyTasks.data}
familyData={familyTasks}
accountDetails={accountDetails}
/>
),
Waiting: (
<FamilyWaitlist
familyData={details.familyWaitList.data}
familyData={familyWaitList}
accountDetails={accountDetails}
loader={details.familyWaitList.loading}
setUpdatePage={setUpdatePage}
/>
),
Pending: (
<FamilyPending
familyData={details.familyPending.data}
familyData={familyPending}
accountDetails={accountDetails}
loader={details.familyPending.loading}
setUpdatePage={setUpdatePage}
/>
),
Account: (
<FamilyAccount
familyData={details.familyDetails.data}
familyData={familyDetails}
myRef={accountRef}
loader={details.familyDetails.loading}
handlePrint={useHandlePrint}
/>
),
Profile: <FamilyProfile familyData={details.familyDetails.data} />,
wallet: <FamilyWallet familyData={details.familyDetails.data} />,
Profile: <FamilyProfile familyData={familyDetails.data} />,
wallet: <FamilyWallet familyData={familyDetails.data} />,
};
// Default tab component
const defaultTabComponent = (
<FamilyTasks
className={className}
loader={details.familyTasks.loading}
familyData={details.familyTasks.data}
familyData={familyTasks}
accountDetails={accountDetails}
/>
);
@@ -222,67 +208,90 @@ export default function FamilyManageTabs({
// Selected tab component based on the current 'tab'
const selectedTabComponent = tabComponents[tab] || defaultTabComponent;
// Effect to manage family details and related data
// Effect to manage family details
useEffect(() => {
const manageFamily = async () => {
setFamilyDetails({loading:true, data: {}})
try {
resetDetails();
setDetails({
familyDetails: { loading: true },
familyTasks: { loading: true },
familyWaitList: { loading: true },
familyPending: { loading: true },
});
const { family_uid } = accountDetails;
const reqData = { family_uid };
const [familyRes, tasksRes, familyWaitRes, familyPending] =
await Promise.all([
apiCall.ManageFamily(reqData),
apiCall.ManageTasks(reqData),
apiCall.ManageFamilyWaitlist(),
apiCall.ManageFamilyPending(),
]);
const familyData = familyRes.data;
const tasksData = tasksRes.data;
const familyWaitData = familyWaitRes.data;
const familyPendingData = familyPending.data;
// Function to check for errors in data
const checkDataError = (data) => data?.internal_return < 0;
if (
checkDataError(familyData) ||
checkDataError(tasksData) ||
checkDataError(familyWaitData) ||
checkDataError(familyPendingData)
) {
return;
const response = await apiCall.ManageFamily(reqData)
if(response.status != 200 || !response?.data){
return setFamilyDetails({loading:false, data: {}})
}
setDetails({
familyDetails: { loading: false, data: familyData },
familyTasks: { loading: false, data: tasksData },
familyWaitList: { loading: false, data: familyWaitData },
familyPending: { loading: false, data: familyPendingData },
});
setFamilyDetails({loading:false, data: response?.data})
} catch (error) {
resetDetails();
setErrMsg("An error occurred");
throw new Error(error);
setFamilyDetails({loading:false, data: {}})
}
};
// Invoke the manageFamily function when the component mounts
manageFamily();
}, []);
// Effect to manage active family task details
useEffect(() => {
const manageTasks = async () => {
setFamilyTasks({loading:true, data: []})
try {
const { family_uid } = accountDetails;
const reqData = { family_uid };
const response = await apiCall.ManageTasks(reqData)
if(response.status != 200 || !response?.data){
return setFamilyTasks({loading:false, data: []})
}
setFamilyTasks({loading:false, data: response?.data})
} catch (error) {
throw new Error(error);
setFamilyTasks({loading:false, data: []})
}
};
// Invoke the manageFamily function when the component mounts
manageTasks();
}, [updatePage, parentFamilyTaskList]);
// Effect to manage family wait task details
useEffect(() => {
const manageFamilyWaitlist = async () => {
setFamilyWaitList({loading:true, data: []})
try {
const response = await apiCall.ManageFamilyWaitlist()
if(response.status != 200 || !response?.data){
return setFamilyWaitList({loading:false, data: []})
}
setFamilyWaitList({loading:false, data: response?.data})
} catch (error) {
throw new Error(error);
setFamilyWaitList({loading:false, data: []})
}
};
// Invoke the manageFamily function when the component mounts
manageFamilyWaitlist();
}, [updatePage]);
// Effect to manage family tasks
// Effect to manage family pending task details
useEffect(() => {
const manageFamilyPending = async () => {
setFamilyPending({loading:true, data: []})
try {
const response = await apiCall.ManageFamilyPending()
if(response.status != 200 || !response?.data){
return setFamilyPending({loading:false, data: []})
}
setFamilyPending({loading:false, data: response?.data})
} catch (error) {
throw new Error(error);
setFamilyPending({loading:false, data: []})
}
};
// Invoke the manageFamily function when the component mounts
manageFamilyPending();
}, [updatePage, pendingListTable]);
// Effect to get all parent job list
useEffect(() => {
let checkFamilyTask = true;
const reqData = {
limit: 30,
offset: 0,
@@ -290,12 +299,11 @@ export default function FamilyManageTabs({
action: apiConst.WRENCHBOARD_PICTURE_FAMMEMBER,
};
if (checkFamilyTask) {
setFamilyTask({ loading: true });
setJobList({ loading: true });
apiCall
.getMyJobList(reqData)
.then((res) => {
setFamilyTask({ loading: false, data: res?.data?.result_list });
setJobList({ loading: false, data: res?.data?.result_list });
if (res?.data?.result_list?.length) {
setActiveTask((prev) => ({
...prev,
@@ -304,15 +312,9 @@ export default function FamilyManageTabs({
}
})
.catch((err) => {
setFamilyTask({ loading: false, data: [] });
setJobList({ loading: false, data: [] });
console.log("Error", err);
});
}
// Cleanup function to prevent memory leaks
return () => {
checkFamilyTask = false;
};
}, []);
return (
@@ -395,7 +397,7 @@ export default function FamilyManageTabs({
</ul>
<button
type="button"
onClick={familyPopUpHandler}
onClick={familyAssignPopUpHandler}
className="p-1 my-1 w-[100px] flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
Add task
@@ -417,15 +419,14 @@ export default function FamilyManageTabs({
</Suspense>
</div>
{familyTaskPopout && (
{assignTaskPopout && (
<AssignTaskPopout
action={familyPopUpHandler}
situation={familyTaskPopout}
familyTask={familyTask}
setFamilyTask={setFamilyTask}
action={familyAssignPopUpHandler}
situation={assignTaskPopout}
jobList={jobList}
setActiveTask={setActiveTask}
activeTask={activeTask}
familyDetailsData={details.familyDetails.data}
familyDetailsData={familyDetails.data}
setUpdatePage={setUpdatePage}
/>
)}
@@ -10,7 +10,7 @@ import { Form, Formik } from "formik";
// To get the validation schema
const validationSchema = Yup.object().shape({
country: Yup.string()
currency: Yup.string()
.min(1, "Minimum 3 characters")
.max(25, "Maximum 25 characters")
.required("required"),
@@ -28,7 +28,7 @@ const validationSchema = Yup.object().shape({
.min(3, "Minimum 3 characters")
.max(499, "Maximum 499 characters")
.required("required"),
timeline: Yup.number()
timeline_days: Yup.number()
.typeError("you must specify a number")
.min(1, "Must be greater than 0")
.required("required"),
@@ -49,25 +49,27 @@ export default function AssignMediaTask({
family_uid
}) {
const {userDetails} = useSelector((state) => state?.userDetails); // CHECKS IF USER Details are avaliable, to determine if user is active
const { walletDetails } = useSelector((state) => state?.walletDetails); // WALLET STORE
// For form initial values
const initialValues = {
// initial values for formik
country: "",
currency: walletDetails.data.length == 1 ? walletDetails.data[0].country : '',
amount: "",
job_description: "",
timeline: "",
media_uid: activeMedia.uid,
timeline_days: "",
media_uid: activeMedia?.uid,
family_uid: family_uid,
media_type: "COMMON"
};
const {userDetails} = useSelector((state) => state?.userDetails); // CHECKS IF USER Details are avaliable, to determine if user is active
const { walletDetails } = useSelector((state) => state?.walletDetails); // WALLET STORE
let imageSrc = (localStorage.getItem("session_token")
? `${userDetails?.session_image_server}${localStorage.getItem("session_token")}/job/${activeMedia.uid}` : ""); // FOR GETTING JOB IMAGE
// let imageSrc = (localStorage.getItem("session_token")
// ? `${userDetails?.session_image_server}${localStorage.getItem("session_token")}/job/${activeMedia.uid}` : ""); // FOR GETTING JOB IMAGE
return (
<>
@@ -89,7 +91,7 @@ export default function AssignMediaTask({
className={`job-action-modal-body w-full min-h-[450px] max-h-[450px] overflow-y-auto md:grid md:grid-cols-2`}
>
<div className="p-4 pt-0">
<div className="p-4 w-full min-h-[400px] max-h-[400px] overflow-y-auto bg-slate-100 rounded-md dark:bg-[#11131f] dark:text-white">
<div className="p-4 w-full min-h-[410px] max-h-[410px] overflow-y-auto bg-slate-100 rounded-md dark:bg-[#11131f] dark:text-white">
{commonMedia?.data?.length ? (
commonMedia?.data?.map((item, index) => (
<div
@@ -140,12 +142,12 @@ export default function AssignMediaTask({
</Suspense>
</div>
</div>
<div className="grid grid-cols-2 gap-3">
<div className="grid grid-cols-3 gap-3">
{/* Price */}
<div className="field w-full">
<div className="field w-full flex flex-col justify-between">
<label htmlFor="price" className="job-label flex gap-1">
Price
<span className='text-red-500 text-[10px]'>{props.errors.amount && props.touched.amount && props.errors.amount}</span>
Reward
<span className='text-red-500 text-base'>{props.errors.amount && props.touched.amount && '*'}</span>
</label>
<InputCom
fieldClass="px-6 text-right"
@@ -162,20 +164,21 @@ export default function AssignMediaTask({
</div>
{/* Currency */}
<div className="field w-full">
<div className="field w-full flex flex-col justify-between">
<label
htmlFor="country"
className="job-label flex gap-1"
htmlFor="currency"
className="job-label flex gap-1 invisible"
>
Currency
{props.errors.country && props.touched.country && <span className="text-[10px] text-red-500">{props.errors.country}</span>}
{props.errors.currency && props.touched.currency && <span className="text-base text-red-500">*</span>}
</label>
<select
id="country"
name="country"
value={props.values.country}
className={`input-field w-full h-[42px] flex items-center px-2 mt-2 rounded-full placeholder:text-base text-dark-gray dark:text-white bg-slate-100 dark:bg-[#11131F] focus:ring-0 focus:outline-none`}
id="currency"
name="currency"
value={props.values.currency}
className={`input-field w-full h-[42px] flex items-center px-2 mt-2 rounded-full placeholder:text-base text-dark-gray dark:text-white bg-slate-100 dark:bg-[#11131F] focus:ring-0 focus:outline-none ${props.errors.currency && props.touched.currency && 'border border-red-500'}`}
onChange={props.handleChange}
disabled={walletDetails.data.length == 1}
>
{walletDetails?.loading ? (
<option className="text-slate-500 text-[13.975px]" value="">
@@ -183,68 +186,84 @@ export default function AssignMediaTask({
</option>
) : walletDetails.data.length ? (
<>
<option className="text-slate-500 text-[13.975px]" value="">
Currency
</option>
{walletDetails.data?.map((item, index) => (
<option
key={index}
className="text-slate-500 text-lg"
value={item?.country}
>
{item?.code}
</option>
))}
{walletDetails.data.length == 1 ?
<>
{walletDetails.data?.map((item, index) => (
<option
key={index}
className="text-slate-500 text-lg"
value={item?.country}
>
{item?.code}
</option>
))}
</>
:
<>
<option className="text-slate-500 text-[13.975px]" value="">
Select
</option>
{walletDetails.data?.map((item, index) => (
<option
key={index}
className="text-slate-500 text-lg"
value={item?.country}
>
{item?.code}
</option>
))}
</>
}
</>
) : (
<option className="text-slate-500 text-lg" value="">
No Options Found! Try Again
No Options Found!
</option>
)}
</select>
</div>
</div>
{/* Duration */}
<div className="field w-full">
<label
htmlFor="timeline_days"
className="job-label flex gap-1"
>
Timeline
{props.errors.timeline && props.touched.timeline && <span className="text-[12px] text-red-500">{props.errors.timeline}</span>}
</label>
<select
id="timeline_days"
name="timeline"
value={props.values.timeline}
className={`input-field w-full h-[42px] flex items-center px-2 mt-2 rounded-full placeholder:text-base text-dark-gray dark:text-white bg-slate-100 dark:bg-[#11131F] focus:ring-0 focus:outline-none`}
onChange={props.handleChange}
>
{publicArray.length && (
<>
<option className="text-slate-500 text-[13.975px]" value="">
Duration
</option>
{publicArray.map(({ name, duration }, idx) => (
<option
key={idx}
className="text-slate-500 text-[13.975px]"
value={duration}
>
{name}
{/* Duration */}
<div className="field w-full flex flex-col justify-between">
<label
htmlFor="timeline_days"
className="job-label flex gap-1"
>
Timeline
{props.errors.timeline_days && props.touched.timeline_days && <span className="text-base text-red-500">*</span>}
</label>
<select
id="timeline_days"
name="timeline_days"
value={props.values.timeline_days}
className={`input-field w-full h-[42px] flex items-center px-2 mt-2 rounded-full placeholder:text-base text-dark-gray dark:text-white bg-slate-100 dark:bg-[#11131F] focus:ring-0 focus:outline-none`}
onChange={props.handleChange}
>
{publicArray.length && (
<>
<option className="text-slate-500 text-[13.975px]" value="">
Select
</option>
))}
</>
)}
</select>
{publicArray.map(({ name, duration }, idx) => (
<option
key={idx}
className="text-slate-500 text-[13.975px]"
value={duration}
>
{name}
</option>
))}
</>
)}
</select>
</div>
</div>
{/* Delivery Detail */}
<div className="my-3">
<label className="w-full job-label flex gap-1">
Delivery Detail
{props.errors.job_description && props.touched.job_description && <span className="text-[12px] text-red-500">{props.errors.job_description}</span>}
{props.errors.job_description && props.touched.job_description && <span className="text-base text-red-500">*</span>}
</label>
<textarea
className={`p-1 w-full text-sm text-slate-900 dark:text-white bg-transparent outline-none border border-slate-300 rounded-md`}
@@ -5,7 +5,7 @@ import { PriceFormatter } from '../../Helpers/PriceFormatter'
import { useSelector } from 'react-redux';
export default function AssignPrevNewTask({
familyTask,
jobList,
requestStatus,
assignFamilyTask,
taskType,
@@ -25,7 +25,7 @@ export default function AssignPrevNewTask({
return (
<>
{familyTask?.loading ? (
{jobList?.loading ? (
<div className="h-[30rem] w-full flex justify-center items-center">
<LoadingSpinner color="sky-blue" size="16" />
</div>
@@ -36,7 +36,7 @@ export default function AssignPrevNewTask({
taskType !== "new" ? "md:grid-cols-2" : "md:grid-cols-1"
}`}
>
<div className="p-4 pt-0">
<div className="px-4">
<div className="mb-2 w-full flex items-center gap-4">
<div className="flex items-center gap-2 text-sky-blue text-base">
<input
@@ -64,8 +64,8 @@ export default function AssignPrevNewTask({
{/* Task Type === select */}
{taskType == "select" && (
<div className="p-4 w-full h-[400px] overflow-y-auto bg-slate-100 rounded-md dark:bg-[#11131f] dark:text-white">
{familyTask?.data?.length ? (
familyTask?.data?.map((item, index) => (
{jobList?.data?.length ? (
jobList?.data?.map((item, index) => (
<div
key={item.job_uid}
className="mb-2 flex justify-start items-center gap-2 text-sky-blue text-base cursor-pointer"
@@ -96,7 +96,7 @@ export default function AssignPrevNewTask({
</div>
)}
{taskType == "new" && (
<div className="p-4 w-full h-full">
<div className="px-4 w-full">
<NewTasks
formState={formState}
setFormState={setFormState}
@@ -108,10 +108,10 @@ export default function AssignPrevNewTask({
{/*Right Hand Side for details && Task Type === select */}
{taskType == "select" && (
<>
{familyTask?.data?.length > 0 ? (
<div className="p-4 pt-0 h-full">
{jobList?.data?.length > 0 ? (
<div className="px-4">
<div className="w-full">
<p className="text-lg font-bold text-dark-gray dark:text-white tracking-wide border-b-2">
<p className="text-lg font-bold text-dark-gray dark:text-white tracking-wide border-b-2 max-h-[50px] overflow-y-auto">
{activeTask?.data?.title}
</p>
{/* <div className="my-3">
@@ -124,7 +124,7 @@ export default function AssignPrevNewTask({
<label className="job-label">
Description
</label>
<p className="p-1 text-sm text-slate-900 dark:text-white">
<p className="p-1 text-sm text-slate-900 dark:text-white max-h-[100px] overflow-y-auto">
{activeTask?.data?.description}
</p>
</div>
@@ -19,15 +19,16 @@ const AssignTaskPopout = ({
details,
situation,
familyDetailsData,
familyTask,
jobList,
activeTask,
setActiveTask,
setUpdatePage,
// assignTaskChecker,
setUpdatePage,
}) => {
const {parentAssignJobToKid} = SocketValues()
const { walletDetails } = useSelector((state) => state?.walletDetails); // WALLET STORE
const apiCall = new usersService();
let { pathname, state } = useLocation();
@@ -88,7 +89,7 @@ const AssignTaskPopout = ({
const [formState, setFormState] = useState({
// Initialize form state with desired fields
banner: details?.banner || "default.jpg",
country: details?.country || "",
country: details?.country ? details?.country : walletDetails.data.length == 1 ? walletDetails.data[0].country : '',
price: details?.price || "",
title: details?.title || "",
description: details?.description || "",
@@ -258,14 +259,33 @@ const AssignTaskPopout = ({
setRequestStatus({ loading: false, status: false, message: "" });
}, 3000);
}
// values.family_uid = selectedFamilyUid
// values.media_uid = activeMedia.uid
// values.amount = values.amount * 100
let reqData = {...values, assign_mode:'110012', family_uid:selectedFamilyUid, media_uid:activeMedia.uid, amount:values.amount * 100}
console.log(reqData)
return setTimeout(()=>{
setRequestStatus({ loading: false, status: false, message: "" });
},2000)
apiCall.parentAssignMediaTask(reqData).then(res => { // API CALL TO ASSIGN MEDIA TASK
if(res.status != 200 || res.data.internal_return < 0){
let error = errorMsg[res?.data?.error_msg] || ''
setRequestStatus({
loading: false,
status: false,
message: error? error : "failed to assign task",
});
return setTimeout(()=>{
setRequestStatus({ loading: false, status: false, message: "" });
}, 3000)
}
setRequestStatus({ loading: false, status: true, message: "Task Assigned Successfully" });
return setTimeout(()=>{
setRequestStatus({ loading: false, status: false, message: "" });
closeModal() // FOR CLOSING ASSIGN MODAL
}, 3000)
}).catch(err => {
setRequestStatus({ loading: false, status: false, message: "Failed, something went wrong. Try Again" });
return setTimeout(()=>{
setRequestStatus({ loading: false, status: false, message: "" });
}, 3000)
})
}
useEffect(()=>{ // effect to update family UID when components mounts
@@ -280,7 +300,7 @@ const AssignTaskPopout = ({
useEffect(()=>{
apiCall.getParentCommonMedia().then((res)=>{
console.log('RESPONSE', res)
// console.log('RESPONSE', res)
setCommonMedia({loading: false, data: res?.data?.result, image: ''})
setActiveMedia(res?.data?.result[0])
}).catch(err => {
@@ -366,7 +386,7 @@ const AssignTaskPopout = ({
<div className="">
{assignType == 'task' ?
<AssignPrevNewTask
familyTask={familyTask}
jobList={jobList}
requestStatus={requestStatus}
assignFamilyTask={assignFamilyTask}
taskType={taskType}
@@ -74,21 +74,6 @@ export default function NewTasks({ formState, setFormState }) {
</div>
{/* Description */}
{/* <div className="field w-full mb-[5px]">
<label htmlFor="description" className="job-label">Description</label>
<InputCom
fieldClass="px-6"
// label="Description"
// labelClass="tracking-wide"
inputBg="bg-slate-100"
type="text"
name="description"
value={formState.description}
inputHandler={handleInputChange}
// blurHandler={props.handleBlur}
// error={props.errors.description && props.touched.description && props.errors.description}
/>
</div> */}
<div className="field flex flex-col sm:flex-row w-full gap-2">
<div className="w-full">
<label
@@ -100,7 +85,7 @@ export default function NewTasks({ formState, setFormState }) {
<textarea
id="description"
rows="5"
className={`input-field px-3 py-2 placeholder:text-base text-dark-gray dark:text-white w-full h-[100px] bg-slate-100 dark:bg-[#11131F] focus:ring-0 focus:outline-[#dce4e9] rounded-[10px]`}
className={`input-field px-3 py-2 placeholder:text-base text-dark-gray dark:text-white w-full h-[80px] bg-slate-100 dark:bg-[#11131F] focus:ring-0 focus:outline-[#dce4e9] rounded-[10px]`}
style={{ resize: "none" }}
name="description"
value={formState.description}
@@ -117,7 +102,7 @@ export default function NewTasks({ formState, setFormState }) {
htmlFor="Job Delivery Details"
className='job-label'
>
Job Delivery Details
Delivery Detail
{/* {props.errors.job_detail && props.touched.job_detail && <span className="text-[12px] text-red-500">{props.errors.job_detail}</span>} */}
</label>
<textarea
@@ -136,66 +121,85 @@ export default function NewTasks({ formState, setFormState }) {
{/* inputs starts here */}
<div className="w-full flex flex-col gap-2">
{/* Currency */}
<div className="field w-full">
<label
htmlFor="country"
className="job-label"
>
Currency
{/* {props.errors.country && props.touched.country && <span className="text-[12px] text-red-500">{props.errors.country}</span>} */}
</label>
<select
id="country"
name="country"
value={formState.country}
className={`input-field w-full h-[42px] flex items-center px-2 mt-2 rounded-full placeholder:text-base text-dark-gray dark:text-white bg-slate-100 dark:bg-[#11131F] focus:ring-0 focus:outline-none`}
onChange={handleInputChange}
// onBlur={props.handleBlur}
>
{walletDetails?.loading ? (
<option className="text-slate-500 text-[13.975px]" value="">
Loading...
</option>
) : walletDetails.data.length ? (
<>
<option className="text-slate-500 text-[13.975px]" value="">
Currency
</option>
{walletDetails.data?.map((item, index) => (
<option
key={index}
className="text-slate-500 text-lg"
value={item?.country}
>
{item?.code}
</option>
))}
</>
) : (
<option className="text-slate-500 text-lg" value="">
No Options Found! Try Again
</option>
)}
</select>
</div>
<div className="grid grid-cols-2 gap-3">
{/* Price */}
<div className="field w-full">
<label htmlFor="price" className="job-label">Reward</label>
<InputCom
fieldClass="px-6 text-right"
// label="Price"
// labelClass="tracking-wide"
inputBg="bg-slate-100"
type="number"
name="price"
placeholder="0"
value={formState.price}
inputHandler={handleInputChange}
// blurHandler={props.handleBlur}
// error={props.errors.price && props.touched.price && props.errors.price}
/>
</div>
{/* Price */}
<div className="field w-full">
<label htmlFor="price" className="job-label">Price</label>
<InputCom
fieldClass="px-6 text-right"
// label="Price"
// labelClass="tracking-wide"
inputBg="bg-slate-100"
type="number"
name="price"
placeholder="0"
value={formState.price}
inputHandler={handleInputChange}
// blurHandler={props.handleBlur}
// error={props.errors.price && props.touched.price && props.errors.price}
/>
{/* Currency */}
<div className="field w-full">
<label
htmlFor="country"
className="job-label invisible"
>
Currency
{/* {props.errors.country && props.touched.country && <span className="text-[12px] text-red-500">{props.errors.country}</span>} */}
</label>
<select
id="country"
name="country"
value={formState.country}
className={`input-field w-full h-[42px] flex items-center px-2 mt-2 rounded-full placeholder:text-base text-dark-gray dark:text-white bg-slate-100 dark:bg-[#11131F] focus:ring-0 focus:outline-none`}
onChange={handleInputChange}
disabled={walletDetails.data.length == 1}
// onBlur={props.handleBlur}
>
{walletDetails?.loading ? (
<option className="text-slate-500 text-[13.975px]" value="">
Loading...
</option>
) : walletDetails.data.length ? (
<>
{walletDetails.data.length == 1 ?
<>
{walletDetails.data?.map((item, index) => (
<option
key={index}
className="text-slate-500 text-lg"
value={item?.country}
>
{item?.code}
</option>
))}
</>
:
<>
<option className="text-slate-500 text-[13.975px]" value="">
Select
</option>
{walletDetails.data?.map((item, index) => (
<option
key={index}
className="text-slate-500 text-lg"
value={item?.country}
>
{item?.code}
</option>
))}
</>
}
</>
) : (
<option className="text-slate-500 text-lg" value="">
No Options Found! Try Again
</option>
)}
</select>
</div>
</div>
{/* Duration */}
@@ -218,7 +222,7 @@ export default function NewTasks({ formState, setFormState }) {
{publicArray.length && (
<>
<option className="text-slate-500 text-[13.975px]" value="">
Duration
Select
</option>
{publicArray.map(({ name, duration }, idx) => (
<option
+78 -128
View File
@@ -13,59 +13,42 @@ const FamilyPending = lazy(() => import("./Tabs/FamilyNewPending"));
export default function FamilyTableNew() {
const { parentFamilyTaskList } = useSelector((state) => state.tableReload);
console.log('parentFamilyTaskList', parentFamilyTaskList)
const { jobListTable, pendingListTable, parentFamilyTaskList } = useSelector((state) => state.tableReload); // TABLE RELOAD TRIGGERS
let { pathname } = useLocation();
// Initial state for family details
const initialDetailState = {
loading: true,
data: null,
link: "",
loading: false,
data: [],
};
const [assignTaskChecker, setAssignTaskChecker] = useState(false);
// console.log('accountDetails',accountDetails)
// State for family details, tasks, waitlist, and pending
const [details, setDetails] = useState({
familyDetails: { ...initialDetailState },
familyTasks: { ...initialDetailState },
familyWaitList: { ...initialDetailState },
familyPending: { ...initialDetailState },
});
let [familyTasks, setFamilyTasks] = useState({...initialDetailState})
// Function to reset family details, tasks, waitlist, and pending
const resetDetails = () => {
setDetails({
familyDetails: { ...initialDetailState },
familyTasks: { ...initialDetailState },
familyWaitList: { ...initialDetailState },
familyPending: { ...initialDetailState },
});
};
let [familyPending, setFamilyPending] = useState({...initialDetailState})
let [familyWaitList, setFamilyWaitList] = useState({...initialDetailState})
const [updatePage, setUpdatePage] = useState(false); // State to determine when to update the page
// State for family task data
const [familyTask, setFamilyTask] = useState({ loading: false, data: [] });
// State for list of created jobs by FULL USER
const [jobList, setJobList] = useState({ loading: false, data: [] });
// State for active task
// State for active/selected job
const [activeTask, setActiveTask] = useState({ id: 0, data: {} });
// State for error messages
const [errMsg, setErrMsg] = useState("");
// State for family task popout
const [familyTaskPopout, setFamilyTaskPopout] = useState(false);
const [assignTaskPopout, setAssignTaskPopout] = useState(false);
// Create an instance of the usersService class
const apiCall = useMemo(() => new usersService(), []);
// Function to handle toggling the family task popout
const familyPopUpHandler = () => {
setFamilyTaskPopout((prev) => !prev);
const familyAssignPopUpHandler = () => {
setAssignTaskPopout((prev) => !prev);
};
// Array of tab names
@@ -87,26 +70,19 @@ export default function FamilyTableNew() {
const tabComponents = {
Tasks: (
<FamilyTasks
image_link={details.familyTasks.link}
loader={details.familyTasks.loading}
familyData={details.familyTasks.data}
action={familyPopUpHandler}
setAssignTaskChecker={setAssignTaskChecker}
familyData={familyTasks}
action={familyAssignPopUpHandler}
/>
),
Waiting: (
<FamilyWaitlist
image_link={details.familyWaitList.link}
familyData={details.familyWaitList.data}
loader={details.familyWaitList.loading}
familyData={familyWaitList}
setUpdatePage={setUpdatePage}
/>
),
Pending: (
<FamilyPending
image_link={details.familyPending.link}
familyData={details.familyPending.data}
loader={details.familyPending.loading}
familyData={familyPending}
/>
),
};
@@ -116,83 +92,66 @@ export default function FamilyTableNew() {
// Selected tab component based on the current 'tab'
const selectedTabComponent = tabComponents[tab] || defaultTabComponent;
// Effect to manage family details and related data
// Effect to manage active family task details
useEffect(() => {
const manageFamily = async () => {
const manageTasks = async () => {
setFamilyTasks({loading:true, data: []})
try {
// resetDetails();
// setDetails({
// familyTasks: { loading: true },
// familyWaitList: { loading: true },
// familyPending: { loading: true },
// });
// const { family_uid } = accountDetails;
// const reqData = { family_uid };
const [familyTasksData, familyWaitingRes, familyPendingRes] =
await Promise.all([
apiCall.getMyActiveJobList(),
apiCall.ManageFamilyNewWaitlist(),
apiCall.ManageFamilyPending(),
]);
let tasksData = familyTasksData?.data?.result_list;
let _familyWaitData = familyWaitingRes?.data?.result_list;
let familyPendingData = familyPendingRes?.data?.result_list;
// Getting the image server link
let imageServerLink = familyWaitingRes.data?.session_image_server;
// Function to check for errors in data
const checkDataError = (data) => data?.internal_return < 0;
if (
checkDataError(tasksData) ||
checkDataError(_familyWaitData) ||
checkDataError(familyPendingData)
) {
return;
const response = await apiCall.getMyActiveJobList()
if(response.status != 200 || !response?.data){
return setFamilyTasks({loading:false, data: []})
}
setDetails({
familyTasks: {
loading: false,
data: tasksData,
link: imageServerLink,
},
familyWaitList: {
loading: false,
data: _familyWaitData,
link: imageServerLink,
},
familyPending: {
loading: false,
data: familyPendingData,
link: imageServerLink,
},
});
setFamilyTasks({loading:false, data: response?.data})
} catch (error) {
// resetDetails();
setDetails({
familyDetails: { ...initialDetailState, loading: false, },
familyTasks: { ...initialDetailState, loading: false, },
familyWaitList: { ...initialDetailState, loading: false,},
familyPending: { ...initialDetailState, loading: false, },
})
setErrMsg("An error occurred");
throw new Error(error);
setFamilyTasks({loading:false, data: []})
}
};
// Invoke the manageFamily function when the component mounts
manageFamily();
manageTasks();
}, [updatePage, parentFamilyTaskList]);
// Effect to manage family tasks
// Effect to manage family wait task details
useEffect(() => {
const manageFamilyWaitlist = async () => {
setFamilyWaitList({loading:true, data: []})
try {
const response = await apiCall.ManageFamilyWaitlist()
if(response.status != 200 || !response?.data){
return setFamilyWaitList({loading:false, data: []})
}
setFamilyWaitList({loading:false, data: response?.data})
} catch (error) {
throw new Error(error);
setFamilyWaitList({loading:false, data: []})
}
};
// Invoke the manageFamily function when the component mounts
manageFamilyWaitlist();
}, [updatePage]);
// Effect to manage family pending task details
useEffect(() => {
const manageFamilyPending = async () => {
setFamilyPending({loading:true, data: []})
try {
const response = await apiCall.ManageFamilyPending()
if(response.status != 200 || !response?.data){
return setFamilyPending({loading:false, data: []})
}
setFamilyPending({loading:false, data: response?.data})
} catch (error) {
throw new Error(error);
setFamilyPending({loading:false, data: []})
}
};
// Invoke the manageFamily function when the component mounts
manageFamilyPending();
}, [updatePage, pendingListTable]);
// Effect to get all parent job list
useEffect(() => {
let checkFamilyTask = true;
const reqData = {
limit: 30,
offset: 0,
@@ -200,12 +159,11 @@ export default function FamilyTableNew() {
action: apiConst.WRENCHBOARD_PICTURE_FAMMEMBER,
};
if (checkFamilyTask) {
setFamilyTask({ loading: true });
setJobList({ loading: true });
apiCall
.getMyJobList(reqData)
.then((res) => {
setFamilyTask({ loading: false, data: res?.data?.result_list });
setJobList({ loading: false, data: res?.data?.result_list });
if (res?.data?.result_list?.length) {
setActiveTask((prev) => ({
...prev,
@@ -214,15 +172,9 @@ export default function FamilyTableNew() {
}
})
.catch((err) => {
setFamilyTask({ loading: false, data: [] });
setJobList({ loading: false, data: [] });
console.log("Error", err);
});
}
// Cleanup function to prevent memory leaks
return () => {
checkFamilyTask = false;
};
}, []);
// console.log(updatePage);
@@ -260,7 +212,7 @@ export default function FamilyTableNew() {
</ul>
<button
type="button"
onClick={familyPopUpHandler}
onClick={familyAssignPopUpHandler}
className="p-1 my-1 w-[100px] flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
Add task
@@ -282,20 +234,18 @@ export default function FamilyTableNew() {
</Suspense>
</div>
{familyTaskPopout && (
{assignTaskPopout && (
<AssignTaskPopout
action={familyPopUpHandler}
situation={familyTaskPopout}
familyTask={familyTask}
setFamilyTask={setFamilyTask}
action={familyAssignPopUpHandler}
situation={assignTaskPopout}
jobList={jobList}
setActiveTask={setActiveTask}
activeTask={activeTask}
familyDetailsData={''}
setUpdatePage={setUpdatePage}
// updateFamilyPendingTable={updateFamilyPendingTable}
pathname={pathname}
assignTaskChecker={assignTaskChecker}
/>
)}
</div>
);
}
@@ -3,7 +3,7 @@ import QRCode from "react-qr-code";
import { useSelector } from "react-redux";
import LoadingSpinner from "../../Spinners/LoadingSpinner";
const FamilyAccount = forwardRef(({ familyData, myRef, handlePrint, loader }, ref) => {
const FamilyAccount = forwardRef(({ familyData, myRef, handlePrint}, ref) => {
const { userDetails } = useSelector((state) => state.userDetails);
return (
<div
@@ -16,13 +16,13 @@ const FamilyAccount = forwardRef(({ familyData, myRef, handlePrint, loader }, re
<h2 className="font-bold text-lg tracking-wide line-clamp-1 text-dark-gray dark:text-white capitalize">
Username:{" "}
<span className="ml-2 normal-case">
{familyData?.username ? familyData?.username : "please wait..."}
{familyData?.data?.username ? familyData?.data?.username : "please wait..."}
</span>
</h2>
<h2 className="font-bold text-lg tracking-wide line-clamp-1 text-dark-gray dark:text-white capitalize">
Pin:{" "}
<span className="ml-2 normal-case">
{familyData?.pin ? familyData?.pin : "please wait..."}
{familyData?.data?.pin ? familyData?.data?.pin : "please wait..."}
</span>
</h2>
</div>
@@ -35,7 +35,7 @@ const FamilyAccount = forwardRef(({ familyData, myRef, handlePrint, loader }, re
<p className="text-xl tracking-wide mb-[15px] text-center font-bold text-dark-gray dark:text-white">
Scan the code from mobile app
</p>
{loader ?
{familyData.loading ?
<div className="w-full">
<LoadingSpinner size='8' color='sky-blue' />
</div>
@@ -44,7 +44,7 @@ const FamilyAccount = forwardRef(({ familyData, myRef, handlePrint, loader }, re
size={256}
style={{ height: "auto", maxWidth: "100%", width: "100%" }}
// value={`https://www.google.com`}
value={`${userDetails?.uid}@${familyData?.username}@${familyData?.uid}`}
value={`${userDetails?.uid}@${familyData?.data?.username}@${familyData?.data?.uid}`}
viewBox={`0 0 256 256`}
/>
}
@@ -2,13 +2,14 @@ import { useMemo, useState } from "react";
import { PriceFormatter } from "../../Helpers/PriceFormatter";
import { PaginatedList, handlePagingFunc } from "../../Pagination";
import PendingJobsPopout from "../../jobPopout/PendingJobsPopout";
import LoadingSpinner from "../../Spinners/LoadingSpinner";
export default function FamilyPending({ familyData, image_link, loader }) {
export default function FamilyPending({ familyData }) {
let [jobPopout, setJobPopout] = useState({ show: false, data: {} }); // STATE TO HOLD THE VALUE OF THE ALERT DETAILS AND DETERMINE WHEN TO SHOW
let filteredFamilyData = useMemo(
() => familyData?.filter((data) => data.family_uid !== ""),
[familyData]
() => familyData?.data?.result_list?.filter((data) => data.family_uid !== ""),
[familyData?.data?.result_list]
);
const [currentPage, setCurrentPage] = useState(0);
@@ -25,13 +26,18 @@ export default function FamilyPending({ familyData, image_link, loader }) {
handlePagingFunc(e, setCurrentPage);
};
console.log(image_link);
return (
<div
className={`update-table w-full p-3 bg-white dark:bg-dark-white overflow-hidden rounded-2xl section-shadow lg:min-h-[538px]`}
>
{familyData && (
{familyData.loading ?
(<div className="w-full h-full flex justify-center items-center">
<LoadingSpinner size={16} color="sky-blue" height='h-[30rem]' />
</div>
):
<>
{familyData?.data?.result_list && (
<div className="relative w-full overflow-x-auto sm:rounded-lg flex flex-col justify-between h-full">
<table className="w-full text-sm text-left text-gray-500 dark:text-gray-400">
<tbody>
@@ -45,7 +51,7 @@ export default function FamilyPending({ familyData, image_link, loader }) {
value?.currency_code,
value?.currency
);
let image = `${image_link}${localStorage.getItem(
let image = `${familyData?.data?.session_image_server}${localStorage.getItem(
"session_token"
)}/job/${value.job_uid}`;
return (
@@ -137,7 +143,8 @@ export default function FamilyPending({ familyData, image_link, loader }) {
{/* END OF PAGINATION BUTTON */}
</div>
)}
</>
}
{/* Active Job Popout */}
{jobPopout.show && (
<PendingJobsPopout
@@ -9,17 +9,15 @@ import LoadingSpinner from "../../Spinners/LoadingSpinner";
export default function FamilyNewTasks({
familyData,
className,
loader,
action,
image_link,
}) {
let navigate = useNavigate();
let { pathname } = useLocation();
// ...
let filteredFamilyData = useMemo(
() => familyData?.filter((data) => data.family_uid !== ""),
[familyData]
() => familyData?.data?.result_list?.filter((data) => data.family_uid !== ""),
[familyData?.data?.result_list]
);
const [currentPage, setCurrentPage] = useState(0);
@@ -36,22 +34,22 @@ export default function FamilyNewTasks({
return (
<div
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 ${
familyData?.length <= 0 && "flex items-center justify-center"
familyData?.data?.result_list?.length <= 0 && "flex items-center justify-center"
}`}
>
{loader ? (
<div className="w-full h-full flex justify-center items-center lg:min-h-[470px]">
<LoadingSpinner size={16} color="sky-blue" />
{familyData.loading ? (
<div className="w-full h-full flex justify-center items-center">
<LoadingSpinner size={16} color="sky-blue" height='h-[30rem]' />
</div>
) : (
<>
{familyData && (
{familyData?.data?.result_list && (
<div className="relative w-full overflow-x-auto sm:rounded-lg flex flex-col justify-between h-full">
<table className="w-full text-sm text-left text-gray-500 dark:text-gray-400">
<tbody>
{
<>
{familyData?.length <= 0 ? (
{familyData?.data?.result_list?.length <= 0 ? (
<tr>
<td
colSpan="2"
@@ -76,7 +74,7 @@ export default function FamilyNewTasks({
value?.currency_code,
value?.currency
);
let image = `${image_link}${localStorage.getItem(
let image = `${familyData?.data?.result_list}${localStorage.getItem(
"session_token"
)}/job/${value.job_uid}`;
return (
@@ -8,8 +8,6 @@ import Icons from "../../Helpers/Icons";
const FamilyNewWaitlist = ({
familyData,
className,
accountDetails,
loader,
setUpdatePage
}) => {
const [popUp, setPopUp] = useState({ show: false, data: {} });
@@ -22,7 +20,7 @@ const FamilyNewWaitlist = ({
const itemsPerPage = Number(process.env.REACT_APP_ITEM_PER_PAGE);
const indexOfFirstItem = currentPage;
const indexOfLastItem = currentPage + itemsPerPage;
const currentTask = familyData?.slice(
const currentTask = familyData?.data?.result_list?.slice(
indexOfFirstItem,
indexOfLastItem
);
@@ -53,13 +51,13 @@ const FamilyNewWaitlist = ({
className || ""
}`}
>
{loader ? (
<div className="w-full h-full flex justify-center items-center lg:min-h-[470px]">
<LoadingSpinner size={16} color="sky-blue" />
{familyData.loading ? (
<div className="w-full h-full flex justify-center items-center">
<LoadingSpinner size={16} color="sky-blue" height='h-[30rem]' />
</div>
) : (
<>
{familyData && (
{familyData?.data?.result_list && (
<div className="relative w-full overflow-x-auto sm:rounded-lg flex flex-col justify-between h-full">
<table className="w-full text-sm text-left text-gray-500 dark:text-gray-400">
<tbody>
@@ -69,7 +67,7 @@ const FamilyNewWaitlist = ({
value?.banner || "default.jpg"
}`);
// console.log("VALUE", value);
// let image = `${familyData.session_image_server}${localStorage.getItem('session_token')}/job/${value.job_uid}`
// let image = `${familyData?.data?.session_image_server}${localStorage.getItem('session_token')}/job/${value.job_uid}`
return (
<tr
className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] hover:bg-gray-50"
@@ -121,8 +119,8 @@ const FamilyNewWaitlist = ({
<PaginatedList
onClick={handlePagination}
prev={currentPage === 0}
next={currentPage + itemsPerPage >= familyData?.length}
data={familyData}
next={currentPage + itemsPerPage >= familyData?.data?.result_list?.length}
data={familyData?.data?.result_list}
start={indexOfFirstItem}
stop={indexOfLastItem}
/>
@@ -3,21 +3,23 @@ import localImgLoad from "../../../lib/localImgLoad";
import { PriceFormatter } from "../../Helpers/PriceFormatter";
import { PaginatedList, handlePagingFunc } from "../../Pagination";
import PendingJobsPopout from "../../jobPopout/PendingJobsPopout";
import LoadingSpinner from "../../Spinners/LoadingSpinner";
export default function FamilyPending({
familyData,
className,
accountDetails,
loader,
setUpdatePage,
}) {
let [jobPopout, setJobPopout] = useState({ show: false, data: {} }); // STATE TO HOLD THE VALUE OF THE ALERT DETAILS AND DETERMINE WHEN TO SHOW
let filteredFamilyData = useMemo(
() =>
familyData?.result_list?.filter(
familyData?.data?.result_list?.filter(
(data) => data?.family_uid === accountDetails?.family_uid
),
[accountDetails?.family_uid, familyData?.result_list]
[accountDetails?.family_uid, familyData?.data?.result_list]
);
const [currentPage, setCurrentPage] = useState(0);
@@ -40,6 +42,12 @@ export default function FamilyPending({
className || ""
}`}
>
{familyData.loading ?
(<div className="w-full h-full flex justify-center items-center">
<LoadingSpinner size={16} color="sky-blue" height='h-[30rem]' />
</div>
):
<>
{filteredFamilyData && (
<div className="relative w-full overflow-x-auto sm:rounded-lg flex flex-col justify-between h-full">
<table className="w-full text-sm text-left text-gray-500 dark:text-gray-400">
@@ -54,7 +62,7 @@ export default function FamilyPending({
value?.currency_code,
value?.currency
);
let image = `${familyData.session_image_server}${localStorage.getItem('session_token')}/job/${value.job_uid}`
let image = `${familyData.data.session_image_server}${localStorage.getItem('session_token')}/job/${value.job_uid}`
return (
<tr
key={index}
@@ -144,6 +152,8 @@ export default function FamilyPending({
{/* END OF PAGINATION BUTTON */}
</div>
)}
</>
}
{/* Active Job Popout */}
{jobPopout.show && (
@@ -151,6 +161,7 @@ export default function FamilyPending({
details={jobPopout.data}
onClose={() => {
setJobPopout({ show: false, data: {} });
setUpdatePage(prev => !prev);
}}
situation={jobPopout.show}
/>
+13 -14
View File
@@ -10,7 +10,6 @@ import LoadingSpinner from "../../Spinners/LoadingSpinner";
export default function FamilyTasks({
familyData,
className,
loader,
accountDetails,
}) {
let navigate = useNavigate();
@@ -19,17 +18,17 @@ export default function FamilyTasks({
// ...
const filteredFamilyData = useMemo(
() =>
familyData?.result_list?.filter(
familyData?.data?.result_list?.filter(
(data) => data?.family_uid === accountDetails?.family_uid
),
[familyData, accountDetails]
[familyData?.data, accountDetails]
);
const [currentPage, setCurrentPage] = useState(0);
const indexOfFirstItem = Number(currentPage);
const indexOfLastItem =
Number(indexOfFirstItem) + Number(process.env.REACT_APP_ITEM_PER_PAGE);
const currentTask = familyData?.result_list.slice(
const currentTask = familyData?.data?.result_list?.slice(
indexOfFirstItem,
indexOfLastItem
);
@@ -43,21 +42,21 @@ export default function FamilyTasks({
className || ""
}`}
>
{loader ? (
<div className="w-full h-full flex justify-center items-center lg:min-h-[470px]">
<LoadingSpinner size={16} color="sky-blue" />
{familyData.loading ? (
<div className="w-full h-full flex justify-center items-center">
<LoadingSpinner size={16} color="sky-blue" height='h-[30rem]' />
</div>
) : (
<>
{familyData && familyData?.result_list && (
{familyData?.data && familyData?.data?.result_list && (
<div className="relative w-full overflow-x-auto sm:rounded-lg flex flex-col justify-between h-full">
<table className="w-full text-sm text-left text-gray-500 dark:text-gray-400">
<tbody>
{
<>
{familyData &&
familyData?.result_list &&
familyData.result_list.length > 0 ? (
{familyData?.data &&
familyData?.data?.result_list &&
familyData?.data.result_list.length > 0 ? (
currentTask.map((value, index) => {
// find due date
const dueDate = value?.delivery_date.split(" ")[0];
@@ -67,7 +66,7 @@ export default function FamilyTasks({
value?.currency_code,
value?.currency
);
let image = `${familyData.session_image_server}${localStorage.getItem('session_token')}/job/${value.job_uid}`
let image = `${familyData?.data?.session_image_server}${localStorage.getItem('session_token')}/job/${value.job_uid}`
return (
<tr
key={index}
@@ -149,11 +148,11 @@ export default function FamilyTasks({
prev={currentPage == 0 ? true : false}
next={
currentPage + Number(process.env.REACT_APP_ITEM_PER_PAGE) >=
familyData?.result_list.length
familyData?.data?.result_list.length
? true
: false
}
data={familyData?.result_list}
data={familyData?.data?.result_list}
start={indexOfFirstItem}
stop={indexOfLastItem}
/>
@@ -5,7 +5,7 @@ import LoadingSpinner from "../../Spinners/LoadingSpinner";
import AssignTaskPopout from "../FamilyPopout/AssignTaskPopout";
const FamilyWaitlist = memo(
({ familyData, className, accountDetails, loader, setUpdatePage }) => {
({ familyData, className, accountDetails, setUpdatePage }) => {
const [popUp, setPopUp] = useState({ show: false, data: {} });
const [continueTaskPopup, setContinueTaskPopup] = useState({
show: false,
@@ -13,10 +13,10 @@ const FamilyWaitlist = memo(
});
const filteredFamilyData = useMemo(
() =>
familyData?.result_list?.filter(
familyData?.data?.result_list?.filter(
(data) => data?.family_uid === accountDetails?.family_uid
),
[familyData, accountDetails]
[familyData.data, accountDetails]
);
const [currentPage, setCurrentPage] = useState(0);
@@ -52,9 +52,9 @@ const FamilyWaitlist = memo(
className || ""
}`}
>
{loader ? (
<div className="w-full h-full flex justify-center items-center lg:min-h-[470px]">
<LoadingSpinner size={16} color="sky-blue" />
{familyData.loading ? (
<div className="w-full h-full flex justify-center items-center">
<LoadingSpinner size={16} color="sky-blue" height='h-[30rem]' />
</div>
) : (
<>
@@ -67,8 +67,7 @@ const FamilyWaitlist = memo(
const selectedImage = require(`../../../assets/images/family/${
value?.banner || "default.jpg"
}`);
console.log('VALUE', value)
// let image = `${familyData.session_image_server}${localStorage.getItem('session_token')}/job/${value.job_uid}`
// let image = `${familyData.data.session_image_server}${localStorage.getItem('session_token')}/job/${value.job_uid}`
return (
<tr
className="bg-white dark:bg-dark-white border-b dark:border-[#5356fb29] hover:bg-gray-50"
@@ -17,8 +17,6 @@ function FamilyWallet({familyData}) {
setFamilyWallet({loading:true, data: []})
apiUrl.getKidWallets({family_uid:familyData?.uid}).then(res => {
setFamilyWallet({loading:false, data: res?.data?.result_list || []})
console.log('familyData', familyData, res?.data?.result_list)
}).catch(error => {
setFamilyWallet({loading:false, data: []})
})
@@ -80,8 +80,6 @@ const SuggestTask = ({ details, onClose, situation, continuePopupData }) => {
}
};
console.log(details);
return (
<ModalCom action={onClose} situation={situation}>
<div className="logout-modal-wrapper lw-[90%] md:w-[48rem] min-h-[500px] bg-white dark:bg-dark-white lg:rounded-2xl">
+12
View File
@@ -0,0 +1,12 @@
import React from 'react'
export default function Iframe({src, title}) {
return (
<iframe
src={src}
title={title}
className='w-full h-full'
>
</iframe>
)
}
+9
View File
@@ -0,0 +1,9 @@
import React from 'react'
export default function ImageElement({className, src, alt}) {
return (
<div className='w-full h-full flex justify-center items-center'>
<img src={src} alt={alt} className={`object-cover w-auto h-full ${className && className}`} />
</div>
)
}
@@ -256,14 +256,16 @@ const MarketPopUp = ({ details, onClose, situation, marketInt }) => {
</p>
<hr />
<button
className="bg-[#57cd89] text-center text-lg font-semibold text-white py-2 px-4 rounded-md inline-flex sm:flex-col flex-row sm:gap-0 gap-1 items-center justify-center"
className="btn-gradient text-white px-2 py-2 border-4 border-slate-300 text-lg lg:text-xl font-medium rounded-2xl"
name="market-interest"
onClick={ManageInterest}
>
{" "}
<span>Send</span>
<span>Interest</span>
<span>Request</span>
<div className="w-full flex flex-col justify-between gap-2">
<span>Send</span>
<span>Interest</span>
<span>Request</span>
</div>
</button>
<>
{manageInt.loading ? (
@@ -0,0 +1,63 @@
import React, { useState } from "react";
import dataImage1 from "../../assets/images/data-table-user-1.png";
import dataImage2 from "../../assets/images/data-table-user-2.png";
import dataImage3 from "../../assets/images/data-table-user-3.png";
import dataImage4 from "../../assets/images/data-table-user-4.png";
import SelectBox from "../Helpers/SelectBox";
export default function ActiveJobMessageMedia({ activeJobMesList }) {
return (
<div className='flex flex-col justify-between'>
<div className="w-full h-full min-h-[250px] max-h-[250px] overflow-y-auto">
<table className="wallet-activity w-full table-auto border-collapse text-left">
<thead className='border-b-2'>
<tr className='text-slate-600'>
<th className="p-2"></th>
</tr>
</thead>
{activeJobMesList?.data?.length ?
(
<tbody>
{activeJobMesList.data.map((item, index) =>
{
let imageLink = `${activeJobMesList?.image}${localStorage.getItem('session_token')}/contracts/${item.msg_uid}`
return (
<tr key={index} className='text-slate-500'>
<td>
<div className={`msg_box ${item.who}`}>
<div className="msg_header">{item.msg_date} {item.msg_firstname}</div>
{item.msg_type == 'FILE' ?
<a href={imageLink} target="_blank" className="p-2" dangerouslySetInnerHTML={{__html: item.message}}></a>
:
<span className="p-2" dangerouslySetInnerHTML={{__html: item.message}}></span>
}
</div>
</td>
</tr>
)
}
)}
</tbody>
)
:
activeJobMesList.error ?
(
<tbody>
<tr className='text-slate-500'>
<td className="p-2" colSpan={4}>Opps! an error occurred. Please try again!</td>
</tr>
</tbody>
)
:
<tbody>
<tr className='text-slate-500'>
<td className="p-2" colSpan={4}>No Message Found!</td>
</tr>
</tbody>
}
</table>
</div>
</div>
)
}
+1 -1
View File
@@ -546,7 +546,7 @@ function ActiveJobs(props) {
{/* MESSAGE SECTION */}
<div className="w-full lg:w-1/2">
<div className="flex justify-between items-center gap-5 justify-between">
<div className="flex justify-between items-center gap-5">
<p className="w-full text-lg font-bold text-dark-gray dark:text-white tracking-wide flex items-center gap-2 justify-between">
<span>Message</span>
<button
@@ -0,0 +1,744 @@
import React, { lazy, useEffect, useRef, useState } from "react";
import { useSelector } from "react-redux";
import { useNavigate } from "react-router-dom";
import { useReactToPrint } from "react-to-print";
import CountDown from "../Helpers/CountDown";
import ModalCom from "../Helpers/ModalCom";
import Layout from "../Partials/Layout";
import LoadingSpinner from "../Spinners/LoadingSpinner";
import ActiveJobMessageMedia from "./ActiveJobMessageMedia";
import IndexJobActions from "./JobActions/IndexJobActions";
import MediaLayout from "../Partials/MediaLayout";
const VideoElement = lazy(() => import("../VideoCom/VideoElement"));
import usersService from "../../services/UsersService";
import { PriceFormatter } from "../Helpers/PriceFormatter";
import { SocketValues } from "../Contexts/SocketIOContext";
function ActiveJobsMedia(props) {
let {sendMessage, joinRoom} = SocketValues() // destructures 'SEND MESSAGE' and 'JOIN ROOM' FUNCTIONS FROM SOCKET
const ApiCall = new usersService();
const navigate = useNavigate();
const { userDetails } = useSelector((state) => state.userDetails);
const [passDue, setPassDue] = useState(
new Date() > new Date(props.details?.delivery_date)
); // STATE TO KNOW IF TASK IS PASSED DUE TIME
const [messageToSend, setMessageToSend] = useState(""); // State to hold the value of message to be sent
const [filesToSend, setFilesToSend] = useState([]); // State to hold the value of files to be sent
const [tab, setTab] = useState("message");
const [requestStatus, setRequestStatus] = useState({
loading: false,
status: false,
message: "",
});
let [popUp, setPopUp] = useState(false); // STATE FOR POPOUT MODAL
const printRef = useRef();
// to handle printing
const handlePrint = useReactToPrint({
content: () => printRef.current,
});
const popUpHandler = () => {
// FUNCTION TO HANDLE POPOUT
setPopUp((prev) => !prev);
};
// FUNCTION TO HANDLE MESSAGE CHANGE
const handleMessageChange = ({ target: { value } }) => {
setMessageToSend(value);
};
// FUNCTION TO HANDLE FILE UPlOAD CHANGE
const handleFileChange = ({ target: { files } }) => {
setRequestStatus({ loading: false, status: false, message: "" }); // State to determine error state
if (!files[0]) {
// IF NO FILE SELECTED RETURN
return;
}
if (files[0].size > Number(process.env.REACT_APP_MAX_FILE_SIZE)) {
setRequestStatus({
loading: false,
status: false,
message: "File must be <= 1mb",
});
setTimeout(() => {
setRequestStatus({ loading: false, status: false, message: "" });
}, 5000);
return;
}
if (filesToSend.length >= Number(process.env.REACT_APP_TOTAL_NUM_FILE)) {
setRequestStatus({
loading: false,
status: false,
message: `Total number of attachment is ${Number(
process.env.REACT_APP_TOTAL_NUM_FILE
)}`,
});
setTimeout(() => {
setRequestStatus({ loading: false, status: false, message: "" });
}, 5000);
return;
}
// INCLUDE FILE IF NO ERROR
setFilesToSend((prev) => [...prev, files[0]]);
};
// FUNCTION TO CLEAR ALL TYPED MESSAGE OR FILES
const handleClearAll = ({ target: { name } }) => {
if (tab == "message") {
setMessageToSend("");
} else if (tab == "files") {
setFilesToSend([]);
} else {
return;
}
};
// FUNCTION TO REMOVE AND IMAGE
const handleRemoveImage = (imageToDelete) => {
setFilesToSend((prev) =>
prev.filter((item) => item.name != imageToDelete.name)
);
};
// FUNCTION TO SEND TASK MESSAGE
const sendTaskMessage = () => {
let reqData = {
message: messageToSend,
msg_type: "TEXT",
contract: props.details.contract,
};
if (!reqData.message) {
setRequestStatus({
loading: false,
status: false,
message: "Message is empty",
});
return setTimeout(() => {
setRequestStatus({ loading: false, status: false, message: "" });
}, 5000);
}
setRequestStatus({ loading: true, status: false, message: "" });
ApiCall.sendTaskMessage(reqData)
.then((res) => {
if (res.status != 200 || res.data.internal_return < 0) {
setRequestStatus({
loading: false,
status: false,
message: "Message could not be sent, try again later",
});
return;
}
setRequestStatus({
loading: false,
status: true,
message: "Message Sent Successfully",
});
// function to trigger socket to emit 'send_message'
sendMessage(messageToSend, `${props.details.contract}-${props.details.contract_uid}`)
props.reloadActiveJobList((prev) => !prev); // MAKES ACTIVE JOB MESSAGE LIST TO RELOAD
setMessageToSend(""); // SENDS MESSAGE TO SEND BACK TO EMPTY STRINGS
})
.catch((error) => {
setRequestStatus({
loading: false,
status: false,
message: "Opps! something went wrong",
});
})
.finally(() => {
setTimeout(() => {
setRequestStatus({ loading: false, status: false, message: "" });
}, 5000);
});
};
// FUNCTION TO SEND FILES
const sendFile = async () => {
setRequestStatus({ loading: true, status: false, message: "" });
if (!filesToSend.length) {
// checks if file to send is empty
setRequestStatus({
loading: false,
status: false,
message: "No File(s) selected",
});
return setTimeout(() => {
setRequestStatus({ loading: false, status: false, message: "" });
}, 5000);
}
for (let i = 0; i <= filesToSend.length - 1; i++) {
// Loops through files to send array and trigger upload API call
const fileToBase64 = async () => {
// Converts file data to base64 string
try {
const base64String = await convertFileToBase64(filesToSend[i]);
return base64String;
} catch (error) {
return false;
}
};
// if(await !fileToBase64()){
// return
// }
let reqData = {
file_name: filesToSend[i].name,
file_size: filesToSend[i].size,
file_type: "image/png",
file_data: await fileToBase64(),
msg_type: "FILE",
contract: props.details.contract,
};
ApiCall.sendFiles(reqData)
.then((res) => {
// if(res.status != 200 || res.data.internal_return < 0){
// setRequestStatus({loading: false, status: false, message: 'Files(s) could not be sent, try again later'})
// return
// }
// setRequestStatus({loading: false, status: true, message: 'File(s) Uploaded Successfully'})
// props.reloadActiveJobList(prev => !prev) // MAKES ACTIVE JOB MESSAGE LIST TO RELOAD
// setFilesToSend([]) // SETS FILES TO SEND TO SEND BACK TO EMPTY ARRAY
})
.catch((error) => {
// setRequestStatus({loading: false, status: false, message: 'Opps! something went wrong'})
})
.finally(() => {
if (i == filesToSend.length - 1) {
setRequestStatus({
loading: false,
status: true,
message: "File(s) Uploaded Successfully",
});
setFilesToSend([]); // SETS FILES TO SEND TO SEND BACK TO EMPTY ARRAY
props.reloadActiveJobList((prev) => !prev); // MAKES ACTIVE JOB MESSAGE LIST TO RELOAD
setTimeout(() => {
setRequestStatus({ loading: false, status: false, message: "" });
}, 5000);
}
});
}
};
// FUNCTION TO CHECK IF TASK PASS DUE IS REACHED
let isPassedDue = () => {
// console.log('TESTING',new Date() > new Date(props.details?.delivery_date) )
if (new Date() > new Date(props.details?.delivery_date)) {
setPassDue(true);
} else {
setPassDue(false);
}
};
useEffect(() => {
if (!passDue) {
let passDueInterval = setInterval(() => {
isPassedDue();
}, 1000);
return () => {
clearInterval(passDueInterval);
};
}
}, [passDue]);
let thePrice = PriceFormatter(
props.details?.price * 0.01,
props.details?.currency_code,
props.details?.currency
);
useEffect(()=>{
// calls function to add user to a room
joinRoom(`${props.details.contract}-${props.details.contract_uid}`)
},[props.details.contract, props.details.contract_uid])
return (
<MediaLayout
backpath={props.details.pathname}
title={props.details?.title ? props.details.title : ''}
>
{/* job title */}
{/* <div className="py-[20px] bg-white dark:bg-black dark:text-white px-4 rounded-2xl shadow-md md:flex justify-between items-start gap-16">
<div className="w-full">
<div className="w-full flex justify-start space-x-3 items-start">
<button
type="button"
className="min-w-[45px] h-auto text-[#374557] border border-sky-blue p-1 rounded-full"
onClick={() => {
if (props.details.pathname == "/manage-family") {
navigate(
props.details.pathname,
{ state: { ...props.details.accountDetails } },
{ replace: true }
);
} else {
navigate(props.details.pathname, { replace: true });
}
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="35"
height="35"
viewBox="0 0 24 24"
fill="skyblue"
>
<path d="M19 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H19v-2z" />
</svg>
</button>
<h1 className="text-base md:text-[20px] font-bold text-dark-gray dark:text-white tracking-wide">
{props.details?.title && props.details.title}
</h1>
</div>
</div>
</div> */}
{/* end of job title */}
<div className="my-4 lg:flex justify-between items-start space-y-4 lg:space-x-4 lg:space-y-0">
<div className="w-full mb-4 border-b pb-4 lg:pb-0 lg:mb-0 lg:border-b-0">
<div className="mb-4 w-full h-auto">
<VideoElement videoId={props?.details?.media_uid} />
</div>
<div className="w-full p-4 bg-white dark:bg-black rounded-2xl shadow-md md:flex md:justify-between gap-8">
<div className="w-full flex flex-col justify-between">
<div className="w-full">
<p className="w-full text-base text-right text-sky-blue">
{props?.details && props.details.job_to}
</p>
<div className="text-base tracking-wide">
<p className="font-semibold text-black dark:text-white tracking-wider">
Description:{" "}
</p>
<p className="p-2 ml-8 border-b border-sky-blue">
{props?.details && props.details.description}
</p>
</div>
<div className="mt-6 w-full lg:flex gap-8">
<div className="w-full text-base tracking-wide">
<p className="font-semibold text-black dark:text-white tracking-wider">
Delivery Detail:{" "}
</p>
<p className="p-2 ml-8">
{props?.details && props.details.job_description}
</p>
</div>
<div className="my-2 lg:my-0">
<IndexJobActions details={props.details} />
</div>
</div>
</div>
</div>
{/* job details */}
<div className="w-full md:w-[200px] flex flex-col justify-center gap-4">
{/* <p className="text-base text-sky-blue">Delivery Detail</p> */}
{passDue ? (
<div className="my-1">
<p className="text-base text-slate-700">
<span className="font-semibold">Due: </span>
{props?.details && props.details.delivery_date.split(" ")[0]}
</p>
{props?.delivery_date && (
<p className="py-2 text-base text-slate-700">
{props.details.delivery_date.split(" ")[1]}
</p>
)}
</div>
) : (
<div className="my-1 flex items-start gap-3">
<p className="font-semibold">Due: </p>
<div className="flex flex-col justify-between">
<p className="text-base text-slate-700 tracking-wide">
<CountDown
lastDate={props?.details && props.details.delivery_date}
/>
</p>
<div className="text-base text-slate-700 tracking-wide flex gap-[5px]">
<span>Hrs</span>
<span>Min</span>
<span>Sec</span>
</div>
</div>
</div>
)}
<div className="my-1 text-base text-slate-700 tracking-wide flex items-center gap-3">
<span className="font-semibold text-black dark:text-white">
Reward:{" "}
</span>
<span className="">{thePrice}</span>
</div>
<div className="my-1 text-base text-slate-700 tracking-wide flex items-center gap-3">
<span className="font-semibold text-black dark:text-white">
Duration:{" "}
</span>
<span className="">
{props.details?.timeline_days && props.details.timeline_days}{" "}
day(s)
</span>
</div>
{/* <div className="my-1 text-base text-slate-700 tracking-wide flex items-center gap-3">
<span className="font-semibold text-black dark:text-white">
No:{" "}
</span>
<span className="">
{props.details?.contract && props.details.contract}
</span>
</div> */}
</div>
{/* end of job details */}
</div>
</div>
<div className="w-full lg:w-2/5 grid grid-cols-1 md:grid-cols-2 lg:grid-cols-1 gap-4">
{/* TEXTAREA SECTION */}
<div className="w-full mb-3">
<div className="w-full">
<div className="pl-7 flex items-center gap-3">
<button
name="message"
onClick={(e) => setTab(e.target.name)}
className={`px-4 xl:px-1 xxl:px-4 text-sm py-1 rounded-t-2xl ${
tab == "message"
? "bg-[#4687ba] border-[2px] border-[#4687ba] text-white"
: "bg-white text-[#000] border-t-[2px]"
}`}
>
Send Message
</button>
<button
name="files"
onClick={(e) => setTab(e.target.name)}
className={`px-4 xl:px-1 xxl:px-4 text-sm py-1 rounded-t-2xl ${
tab == "files"
? "bg-[#4687ba] border-[2px] border-[#4687ba] text-white"
: "bg-white text-[#000] border-t-[2px]"
}`}
>
Send Files
</button>
</div>
{tab == "message" ? (
<textarea
className="p-4 w-full h-[150px] text-base text-slate-600 dark:text-white bg-white dark:bg-black border-4 border-[#4687ba] outline-none"
// rows="10"
style={{ resize: "none" }}
name="message"
onChange={handleMessageChange}
value={messageToSend}
autoFocus
/>
) : (
<div className="p-4 mb-2 h-[150px] text-base text-slate-600 border-4 border-[#4687ba]">
<div className="files flex">
<label
htmlFor="file"
className="custom-btn btn-gradient text-base text-white"
>
Select Files to Upload
</label>
<input
type="file"
id="file"
accept="image/*"
style={{ display: "none" }}
onChange={handleFileChange}
/>
</div>
<div className="selected_file my-2 overflow-y-auto">
{filesToSend.length > 0 &&
filesToSend.map((item, index) => (
<p key={index} className="flex items-center space-x-2">
<span>{item.name}</span>
<button
name="remove"
onClick={() => handleRemoveImage(item)}
className="px-2 flex justify-center items-center rounded-full border border-red-500 text-red-500"
>
x
</button>
</p>
))}
</div>
</div>
)}
</div>
{/* ERROR DISPLAY AND SUBMIT BUTTON */}
<div className="w-full">
{/* error or success display */}
{requestStatus.message != "" &&
(!requestStatus.status ? (
<div
className={`relative p-4 my-4 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}
>
{requestStatus.message}
</div>
) : (
requestStatus.status && (
<div
className={`relative p-4 my-4 text-green-700 bg-slate-200 border-slate-800 mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}
>
{requestStatus.message}
</div>
)
))}
</div>
{/* End of error or success display */}
{/* Buttons Sections */}
<div className="py-1 grid grid-cols-1 xxs:grid-cols-3">
<div className="w-full col-span-3 col-start-1 xxs:col-span-2 xxs:col-start-2 flex justify-between items-center gap-4">
<button
type="button"
onClick={handleClearAll}
className="custom-btn border-gradient"
>
<span className="text-gradient">Clear</span>
</button>
{tab == "files" ? (
<button
onClick={sendFile}
type="button"
className="custom-btn btn-gradient text-white"
>
{requestStatus.loading ? (
<LoadingSpinner size="6" color="sky-blue" />
) : (
<>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
width="20"
height="20"
fill="white"
>
<path d="M12 2L2 12h3v8h14v-8h3L12 2zm0 16v-6h-2v6H7l5-5 5 5h-3z" />
</svg>
<span className="text-white">Upload Files</span>
</>
)}
</button>
) : (
<button
onClick={sendTaskMessage}
type="button"
className="custom-btn btn-gradient text-white"
>
{requestStatus.loading ? (
<LoadingSpinner size="6" color="sky-blue" />
) : (
<span className="text-white">Send</span>
)}
</button>
)}
</div>
</div>
{/* end of Buttons Sections */}
</div>
{/* END OF TEXTAREA */}
{/* MESSAGE SECTION */}
<div className="w-full p-4 bg-white dark:bg-black rounded-2xl shadow-md">
<div className="flex justify-between items-center gap-5">
<p className="w-full text-lg font-bold text-dark-gray dark:text-white tracking-wide flex items-center gap-2 justify-between">
<span>Message</span>
<button
type="button"
onClick={popUpHandler}
className="text-[12px] tracking-wider text-gray-400 dark:text-slate-400"
>
View all
</button>
</p>
</div>
{props.activeJobMesList.loading ? (
<LoadingSpinner size="16" color="sky-blue" />
) : (
<ActiveJobMessageMedia activeJobMesList={props.activeJobMesList} />
)}
</div>
{/* END OF MESSAGE */}
</div>
</div>
{/* POPOUT SECTION */}
{popUp && (
<PopModal
popUpHandler={popUpHandler}
popUp={popUp}
details={props.details}
activeJobMesList={props.activeJobMesList}
handlePrint={handlePrint}
myRef={printRef}
/>
)}
{/* END OF POPOUT SECTION */}
</MediaLayout>
);
}
export default ActiveJobsMedia;
function convertFileToBase64(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => {
const base64String = reader.result.split(",")[1];
resolve(base64String);
};
reader.onerror = (error) => {
reject(error);
};
reader.readAsDataURL(file);
});
}
//POPOUT COMPONENT FUNCTION
const PopModal = ({
popUpHandler,
popUp,
details,
activeJobMesList,
handlePrint,
myRef,
}) => {
return (
<ModalCom action={popUpHandler} situation={popUp}>
<div
ref={myRef}
className="message-modal-wrapper w-11/12 min-w-[350px] max-w-[700px] bg-white dark:bg-dark-white lg:rounded-2xl overflow-y-auto"
>
<div className="modal-header-con">
<h1 className="modal-title">
{details?.contract}
</h1>
<button
type="button"
className="modal-close-btn"
onClick={popUpHandler}
>
<svg
width="36"
height="36"
viewBox="0 0 36 36"
fill="none"
className="fill-current"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M36 16.16C36 17.4399 36 18.7199 36 20.0001C35.7911 20.0709 35.8636 20.2554 35.8385 20.4001C34.5321 27.9453 30.246 32.9248 22.9603 35.2822C21.9006 35.6251 20.7753 35.7657 19.6802 35.9997C18.4003 35.9997 17.1204 35.9997 15.8401 35.9997C15.5896 35.7086 15.2189 35.7732 14.9034 35.7093C7.77231 34.2621 3.08728 30.0725 0.769671 23.187C0.435002 22.1926 0.445997 21.1199 0 20.1599C0 18.7198 0 17.2798 0 15.8398C0.291376 15.6195 0.214408 15.2656 0.270759 14.9808C1.71321 7.69774 6.02611 2.99691 13.0428 0.700951C14.0118 0.383805 15.0509 0.386897 15.9999 0C17.2265 0 18.4532 0 19.6799 0C19.7156 0.124041 19.8125 0.136067 19.9225 0.146719C27.3 0.868973 33.5322 6.21922 35.3801 13.427C35.6121 14.3313 35.7945 15.2484 36 16.16ZM33.011 18.0787C33.0433 9.77105 26.3423 3.00309 18.077 2.9945C9.78479 2.98626 3.00344 9.658 2.98523 17.8426C2.96667 26.1633 9.58859 32.9601 17.7602 33.0079C26.197 33.0577 32.9787 26.4186 33.011 18.0787Z"
fill=""
fillOpacity="0.6"
/>
<path
d="M15.9309 18.023C13.9329 16.037 12.007 14.1207 10.0787 12.2072C9.60071 11.733 9.26398 11.2162 9.51996 10.506C9.945 9.32677 11.1954 9.0811 12.1437 10.0174C13.9067 11.7585 15.6766 13.494 17.385 15.2879C17.9108 15.8401 18.1633 15.7487 18.6375 15.258C20.3586 13.4761 22.1199 11.7327 23.8822 9.99096C24.8175 9.06632 26.1095 9.33639 26.4967 10.517C26.7286 11.2241 26.3919 11.7413 25.9133 12.2178C24.1757 13.9472 22.4477 15.6855 20.7104 17.4148C20.5228 17.6018 20.2964 17.7495 20.0466 17.9485C22.0831 19.974 24.0372 21.8992 25.9689 23.8468C26.9262 24.8119 26.6489 26.1101 25.4336 26.4987C24.712 26.7292 24.2131 26.3441 23.7455 25.8757C21.9945 24.1227 20.2232 22.3892 18.5045 20.6049C18.0698 20.1534 17.8716 20.2269 17.4802 20.6282C15.732 22.4215 13.9493 24.1807 12.1777 25.951C11.7022 26.4262 11.193 26.7471 10.4738 26.4537C9.31345 25.9798 9.06881 24.8398 9.98589 23.8952C11.285 22.5576 12.6138 21.2484 13.9387 19.9355C14.5792 19.3005 15.2399 18.6852 15.9309 18.023Z"
fill="#"
fillOpacity="0.6"
/>
</svg>
</button>
</div>
<div className="job-action-modal-body w-full px-10 py-8 gap-4">
<div className="w-full flex flex-col items-center">
{activeJobMesList.loading ? (
<LoadingSpinner size="16" color="sky-blue" />
) : (
<div className="message-table h-[500px] overflow-y-auto">
<table className="wallet-activity w-full table-auto border-collapse text-left">
<thead className="border-b-2">
<tr className="text-slate-600">
<th className="p-2"></th>
</tr>
</thead>
{activeJobMesList?.data?.length ? (
<tbody>
{activeJobMesList?.data?.map((item, index) => (
<tr key={index} className="text-slate-500">
<td>
<div className="msg_box">
<div className="msg_header">
{item.msg_date} {item.msg_firstname}
</div>
<span
className="p-2"
dangerouslySetInnerHTML={{
__html: item.message,
}}
></span>
</div>
</td>
</tr>
))}
</tbody>
) : activeJobMesList.error ? (
<tbody>
<tr className="text-slate-500">
<td className="p-2" colSpan={4}>
Opps! an error occurred. Please try again!
</td>
</tr>
</tbody>
) : (
<tbody>
<tr className="text-slate-500">
<td className="p-2" colSpan={4}>
No Message Found!
</td>
</tr>
</tbody>
)}
</table>
</div>
)}
</div>
{/* btn */}
<div className="flex justify-end items-center">
<div className="py-3 w-full lg:w-1/2 flex justify-between items-center">
<button
onClick={handlePrint}
type="button"
className="custom-btn btn-gradient text-white"
>
<span className="text-white">Print</span>
</button>
<button
onClick={popUpHandler}
type="button"
className="custom-btn border-gradient text-white"
>
<span className="text-gradient">Cancel</span>
</button>
</div>
</div>
</div>
</div>
</ModalCom>
);
};
@@ -3,22 +3,20 @@ import React from 'react'
function CurrentJobAction() {
return (
<div className='job-action dark:bg-black'>
<p className="my-3 py-1 text-base active-owner">
<table className="w-full text-sm text-left text-gray-500 ">
<tbody>
<tr>
<td>
<div className="flex space-x-2 items-center w-full task_action_panel">
<table className="w-full my-3 py-1 text-sm text-left text-gray-500">
<tbody>
<tr>
<td>
<div className="flex space-x-2 items-center w-full task_action_panel">
<div>
Waiting for the completion message from the client before you can approve.
</div>
</div>
</td>
</tr>
</tbody>
</table>
</p>
<div>
Waiting for the completion message from the client before you can approve.
</div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
)
}
@@ -60,44 +60,42 @@ function CurrentTaskAction({jobDetails}) {
}
return (
<div className='job-action dark:bg-black'>
<div className='dark:bg-black'>
<table className="w-full text-sm text-left text-gray-500 active-worker ">
<tbody>
<tr>
<td>
<div className="flex space-x-2 items-center w-full task_action_panel">
<div>
I completed this task and ready for review and acceptance.
</div>
{/*<div className="flex flex-col flex-[0.9]">*/}
<div className="w-full text-sm text-left text-gray-500">
{jobDetails.job_type == 'MEDIA' ?
<div className="flex justify-center items-center">
<button onClick={popUpHandler} type="button" className="btn-gradient text-white p-1 lg:p-2 border-4 border-slate-300 text-lg lg:text-xl font-medium rounded-2xl">
I have completed this task
</button>
</div>
:
<div className='job-action active-worker'>
<div className="flex space-x-2 items-center w-full task_action_panel">
<div>
I completed this task and ready for review and acceptance.
</div>
</div>
{/*</div>*/}
</div>
</td>
</tr>
<tr>
<td>
<div className="flex justify-center items-center">
<button onClick={popUpHandler} type="button" className="w-[150px] h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white">
Send of Review
</button>
</div>
</td>
</tr>
</tbody>
</table>
<div className="flex justify-center items-center">
<button onClick={popUpHandler} type="button" className="custom-btn btn-gradient text-white">
Send for Review
</button>
</div>
</div>
}
</div>
{popUp && (
<ModalCom action={popUpHandler} situation={popUp}>
<div className="logout-modal-wrapper lg:w-[460px] h-full lg:h-auto bg-white dark:bg-dark-white lg:rounded-2xl">
<div className="logout-modal-header w-full flex items-center justify-between lg:px-10 lg:py-8 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">
<div className="modal-header-con">
<h1 className="modal-title">
Confirm Completion
</h1>
<button
type="button"
className="text-[#374557] dark:text-red-500"
className="modal-clode-btn"
onClick={popUpHandler}
>
<svg
@@ -145,33 +143,21 @@ function CurrentTaskAction({jobDetails}) {
{/* FOR SUCCESS/ERROR DISPLAY SECTION*/}
<div className="w-full">
{reqStatus.message != "" &&
(!reqStatus.status ? (
<div
className={`relative p-4 my-4 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}
className={`relative p-4 text-center text-md font-light leading-[19.5px] text-[13px] ${reqStatus.status ? 'text-green-700':'text-[#912741]'}`}
>
{reqStatus.message}
</div>
) : (
reqStatus.status && (
<div
className={`relative p-4 my-4 text-green-700 bg-slate-200 border-slate-800 mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}
>
{reqStatus.message}
</div>
)
))}
</div>
{/* END OF FOR SUCCESS/ERROR DISPLAY SECTION*/}
</div>
{/* cancel btn */}
<div className='flex justify-end items-center'>
<button onClick={popUpHandler} type="button" className="w-20 h-11 flex justify-center items-center border-gradient text-base rounded-full text-white">
<span className='text-gradient'>Cancel</span>
</button>
</div>
</div>
</div>
{/* cancel btn */}
<div className='modal-footer-wrapper flex justify-end items-center'>
<button onClick={popUpHandler} type="button" className="w-20 h-11 flex justify-center items-center border-gradient text-base rounded-full text-white">
<span className='text-gradient'>Cancel</span>
</button>
</div>
</div>
</ModalCom>
)}
@@ -121,7 +121,7 @@ function PastDueJobAction({jobDetails}) {
<button
type="button"
onClick={popUpHandler}
className="px-4 h-[48px] flex justify-center items-center btn-gradient text-base rounded-full text-white"
className="custom-btn btn-gradient text-base text-white"
>
Cancel or Extend Timeline
</button>
@@ -133,14 +133,14 @@ function PastDueJobAction({jobDetails}) {
{popUp && (
<ModalCom action={popUpHandler} situation={popUp}>
<div className="logout-modal-wrapper lg:w-[460px] h-full lg:h-auto bg-white dark:bg-dark-white lg:rounded-2xl">
<div className="logout-modal-header w-full flex items-center justify-between lg:px-10 lg:py-8 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">
<div className="logout-modal-wrapper lg:w-[460px] h-auto bg-white dark:bg-dark-white lg:rounded-2xl overflow-y-auto">
<div className="modal-header-con">
<h1 className="modal-title">
Past Due Task
</h1>
<button
type="button"
className="text-[#374557] dark:text-red-500"
className="modal-close-btn"
onClick={popUpHandler}
>
<svg
@@ -164,7 +164,7 @@ function PastDueJobAction({jobDetails}) {
</svg>
</button>
</div>
<div className="job-action-modal-body w-full px-10 py-8 gap-4">
<div className="relative job-action-modal-body w-full px-10 py-8 gap-4">
<div className="w-full flex flex-col items-center">
<div className="mb-5 flex justify-center items-center gap-2">
<input
@@ -173,26 +173,26 @@ function PastDueJobAction({jobDetails}) {
onChange={()=>{setChecked(prev => !prev)}}
className='w-6 h-6 text-sky-blue bg-gray-100 focus:ring-sky-blue'
/>
<p className='font-bold text-base tracking-wide text-dark-gray dark:text-white'>I am ready to cancel this task</p>
<p className='job-label'>I am ready to cancel this task</p>
</div>
<div className="mb-5 flex justify-center items-center">
<div className="mb-5 w-full flex justify-end items-center">
{reqStatus.loading && action=='cancel'?
<LoadingSpinner color='sky-blue' size='10' />
:
<button disabled={reqStatus.loading} onClick={cancelTask} type="button" className="px-2 py-1 h-11 flex justify-center items-center border-gradient text-base rounded-full text-white">
<button disabled={reqStatus.loading} onClick={cancelTask} type="button" className="custom-btn border-gradient text-base text-white">
<span className='text-gradient'>Cancel this task</span>
</button>
}
</div>
{/* EXTEND TIMELINE SECTION */}
<div className='w-full my-3 py-3 border-y flex flex-col items-center'>
<div className='w-full my-3 py-3 border-t flex flex-col items-center'>
<div className='mb-5 flex items-center gap-2'>
<p className='font-bold text-base tracking-wide text-dark-gray dark:text-white'>Extend the timeline by:</p>
<p className='job-label'>Extend the timeline by:</p>
<select
onChange={({target})=>{setExtendedTime(target.value)}}
className='text-base p-2 text-dark-gray dark:text-white rounded-md border border-slate-300 outline-0'
className='text-base p-2 text-dark-gray dark:text-white border border-slate-300 outline-0 rounded-full'
>
<option className='text-slate-500 text-lg' value=''>select</option>
<option className='text-slate-500 text-lg' value='2'>1 days</option>
@@ -204,25 +204,27 @@ function PastDueJobAction({jobDetails}) {
{reqStatus.loading && action=='extend' ?
<LoadingSpinner color='sky-blue' size='10' />
:
<button disabled={reqStatus.loading} type="button" onClick={extendTime} className="px-2 py-1 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white">
Extend Timeline
</button>
<div className='w-full flex justify-end items-center'>
<button disabled={reqStatus.loading} type="button" onClick={extendTime} className="custom-btn btn-gradient text-base text-white">
Extend Timeline
</button>
</div>
}
</div>
{/* FOR SUCCESS/ERROR DISPLAY SECTION*/}
<div className="w-full">
<div className="w-full absolute left-0 bottom-0 text-center">
{reqStatus.message != "" &&
(!reqStatus.status ? (
<div
className={`relative p-4 my-4 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}
className={`relative p-2 mx-2 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}
>
{reqStatus.message}
</div>
) : (
reqStatus.status && (
<div
className={`relative p-4 my-4 text-green-700 bg-slate-200 border-slate-800 mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}
className={`relative p-2 mx-2 text-green-700 bg-slate-200 border-slate-800 mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}
>
{reqStatus.message}
</div>
@@ -232,17 +234,17 @@ function PastDueJobAction({jobDetails}) {
{/* END OF FOR SUCCESS/ERROR DISPLAY SECTION*/}
</div>
{/* cancel btn */}
<div className='flex justify-end items-center'>
<button onClick={popUpHandler} type="button"
// className="w-20 h-11 flex justify-center items-center border-gradient text-base rounded-full text-white"
className='w-[150px] mt-2 h-[48px] rounded-full text-base bg-transparent border border-red-500 text-red-500'
>
Cancel
{/* <span className='text-gradient'>Cancel</span> */}
</button>
</div>
</div>
{/* cancel btn */}
<div className='modal-footer-wrapper flex justify-center items-center'>
<button onClick={popUpHandler} type="button"
// className="w-20 h-11 flex justify-center items-center border-gradient text-base rounded-full text-white"
className='custom-btn text-base bg-transparent border border-red-500 text-red-500'
>
Cancel
{/* <span className='text-gradient'>Cancel</span> */}
</button>
</div>
</div>
</ModalCom>
)}
@@ -119,7 +119,7 @@ export default function MyOffersFamilyTable({ className, familyOffers, image_ser
</div>
</div>
{/* trending products */}
<div className="trending-products slider-left relative w-full rounded-2xl p-[10px] bg-alice-blue">
<div className="trending-products slider-left relative w-full rounded-2xl p-[10px] bg-alice-blue dark:bg-dark-white/50 transition-all duration-300">
<SliderCom selector={trendingSlider} settings={settings}>
{familyOffers &&
familyOffers.length > 0 &&
@@ -259,7 +259,7 @@ function AddFundDollars(props) {
<div className="w-full">
{/* switch button */}
<div className="flex">
<form className="add-fund-info flex items-center gap-3">
<form className="add-fund-info flex items-center gap-3 md:px-8 md:pt-4 px-4 pt-2">
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
{countryWallet == "US" && "Payment Method"}
</h1>
@@ -313,7 +313,7 @@ function AddFundDollars(props) {
{/* previous selectedOption */}
{selectedOption === "previous" && (
<div className="p-4 previous-details w-full min-h-[16.5rem] flex flex-col">
<div className="px-8 py-4 previous-details w-full h-[300px] flex flex-col">
{payListCards.loading ? (
<LoadingSpinner size="10" color="sky-blue" />
) : payListCards?.data?.length ? (
@@ -367,7 +367,7 @@ function AddFundDollars(props) {
)}
{selectedOption === "new" && (
<div className="new-details w-full max-h-[22rem]">
<div className="new-details w-full">
{payListCards.loading ? (
<div className="pt-10 flex w-full h-full justify-center items-center">
<LoadingSpinner size="10" color="sky-blue" />
@@ -381,8 +381,8 @@ function AddFundDollars(props) {
>
{(props) => {
return (
<Form className="md:pl-8">
<div className="flex flex-col-reverse sm:flex-row">
<Form className="w-full">
<div className="flex flex-col-reverse sm:flex-row md:px-8 md:pt-4 px-4 pt-2">
<div className="flex-1 sm:mr-10">
<div className="fields w-full">
{/* Inputs */}
@@ -588,26 +588,28 @@ function AddFundDollars(props) {
</div>
</div>
<div className="add-fund-btn flex justify-end items-center gap-2 mt-4">
<button
className="px-4 py-1 h-11 max-w-[100px] w-full flex justify-center bg-[#f5a430] text-black items-center text-base rounded-full"
onClick={handleClose}
>
Cancel
</button>
<button
type="submit"
className="px-4 py-1 h-11 max-w-[115px] w-full flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
{loadingState ? (
<LoadingSpinner size="6" color="sky-blue" />
) : (
<>
<span className="text-white">Continue</span>{" "}
<Icons name="chevron-right" />
</>
)}
</button>
<div className="modal-footer-wrapper grid grid-cols-1 xxs:grid-cols-3">
<div className="w-full col-span-1 xxs:col-span-2 xxs:col-start-2 flex justify-between items-center">
<button
className="custom-btn bg-[#f5a430] text-black text-base"
onClick={handleClose}
>
Cancel
</button>
<button
type="submit"
className="custom-btn btn-gradient text-base text-white"
>
{loadingState ? (
<LoadingSpinner size="6" color="sky-blue" />
) : (
<>
<span className="text-white">Continue</span>{" "}
<Icons name="chevron-right" />
</>
)}
</button>
</div>
</div>
</Form>
);
@@ -620,25 +622,27 @@ function AddFundDollars(props) {
</div>
{selectedOption == "previous" && (
<div className="md:py-8 add-fund-btn flex justify-end items-center gap-2 py-4">
<button
className="px-4 py-1 h-11 max-w-[100px] w-full flex justify-center bg-[#f5a430] text-black items-center text-base rounded-full"
onClick={props.onClose}
>
Cancel
</button>
<button
onClick={handleSubmit}
name="previous"
type="button"
className="px-4 py-1 h-11 max-w-[115px] w-full flex justify-center items-center btn-gradient text-base rounded-full text-white"
>
{loadingState ? (
<LoadingSpinner size="6" color="sky-blue" />
) : (
<span className="text-white">Continue</span>
)}
</button>
<div className="modal-footer-wrapper grid grid-cols-1 xxs:grid-cols-3">
<div className="w-full col-span-1 xxs:col-span-2 xxs:col-start-2 flex justify-between items-center">
<button
className="custom-btn bg-[#f5a430] text-black text-base"
onClick={props.onClose}
>
Cancel
</button>
<button
onClick={handleSubmit}
name="previous"
type="button"
className="custom-btn btn-gradient text-base text-white"
>
{loadingState ? (
<LoadingSpinner size="6" color="sky-blue" />
) : (
<span className="text-white">Continue</span>
)}
</button>
</div>
</div>
)}
</>
+45 -43
View File
@@ -126,7 +126,7 @@ function AddFundPop({
};
return (
<div className="h-[33rem] w-full">
<div className="w-full">
<div className="content-wrapper w-full lg:flex xl:space-x-8 lg:space-x-4 bottomMargin">
<div className="lg:w-2/2 w-full mb-10 lg:mb-0">
<div className="add-fund w-full bg-white dark:bg-dark-white rounded-2xl">
@@ -149,51 +149,53 @@ function AddFundPop({
</p>
</div>
</form>
{countryWallet === "US" && (
<div className="w-full md:px-8 md:pt-4 px-4 pt-2 bg-white dark:bg-dark-white rounded-2xl">
<AddFundDollars
setInputError={setInputError}
walletItem={walletItem}
input={input}
setInput={setInput}
currency={currency}
onClose={onClose}
confirmCredit={confirmCredit}
setConfirmCredit={setConfirmCredit}
/>
</div>
)}
{countryWallet == "NG" && <div className="h-[19rem]"></div>}
{countryWallet == "NG" && (
<div className="md:p-8 p-4 add-fund-btn flex justify-end items-center py-4 gap-4">
<button
className="px-4 py-1 h-11 max-w-[100px] w-full flex justify-center items-center bg-[#f5a430] text-black text-base rounded-full"
onClick={onClose}
>
Cancel
</button>
<button
onClick={handleSubmit}
type="button"
className="px-4 py-1 h-11 flex justify-center space-x-1 items-center btn-gradient text-base rounded-full text-white max-w-[100px] w-full"
>
{__awaitComponent.loader ? (
<LoadingSpinner size="6" color="sky-blue" />
) : (
<>
<span className="text-white">Continue</span>{" "}
<Icons name="chevron-right" />
</>
)}
</button>
</div>
)}
</div>
</div>
</div>
{countryWallet === "US" && (
<div className="w-full bg-white dark:bg-dark-white rounded-2xl">
<AddFundDollars
setInputError={setInputError}
walletItem={walletItem}
input={input}
setInput={setInput}
currency={currency}
onClose={onClose}
confirmCredit={confirmCredit}
setConfirmCredit={setConfirmCredit}
/>
</div>
)}
{countryWallet == "NG" && <div className="h-[19rem]"></div>}
{countryWallet == "NG" && (
<div className="modal-footer-wrapper grid grid-cols-1 xxs:grid-cols-3">
<div className="w-full col-span-1 xxs:col-span-2 xxs:col-start-2 flex justify-between items-center">
<button
className="custom-btn bg-[#f5a430] text-black text-base"
onClick={onClose}
>
Cancel
</button>
<button
onClick={handleSubmit}
type="button"
className="custom-btn btn-gradient text-base text-white"
>
{__awaitComponent.loader ? (
<LoadingSpinner size="6" color="sky-blue" />
) : (
<>
<span className="text-white">Continue</span>{" "}
<Icons name="chevron-right" />
</>
)}
</button>
</div>
</div>
)}
</div>
);
}
@@ -8,7 +8,7 @@ function CompleteConfirmCredit({ onClose, confirmCredit }) {
data?.result === "Charge success" || data?.status === "successful";
return (
<div className="logout-modal-body w-full flex flex-col items-center">
<div className="logout-modal-body w-full">
<div className="content-wrapper w-full h-[32rem]">
<div className="w-full mb-10">
<div className="add-fund w-full bg-white dark:bg-dark-white rounded-2xl">
@@ -49,7 +49,7 @@ function CompleteConfirmCredit({ onClose, confirmCredit }) {
</svg>
</div>
<div className="flex items-center">
<div className="w-full flex justify-center items-center">
<h1 className="text-xl font-semibold text-dark-gray dark:text-white tracking-tighter my-1">
{isSuccess
? "Credit was Successful!"
@@ -59,55 +59,56 @@ function CompleteConfirmCredit({ onClose, confirmCredit }) {
{data?.internal_return >= 0 &&
data?.result !== "Charge failed" && (
<>
<div className="flex items-center gap-8">
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
<div className="w-full md:w-[60%] mx-auto">
<div className="grid grid-cols-2 gap-8 my-2">
<h1 className="job-label">
Amount({data?.currency || ""})
</h1>
<span className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
<span className="w-full text-base text-dark-gray dark:text-white tracking-tighter flex justify-end items-end">
{`${data?.symbol || ""} ${
Number(data?.amount * 0.01).toLocaleString() || ""
Number(data?.amount * 0.01).toFixed(2) || ""
}`}
</span>
</div>
{data?.curr_balance &&
<div className="flex items-center gap-8">
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
<div className="grid grid-cols-2 gap-8 my-2">
<h1 className="job-label">
Wallet Balance
</h1>
<span className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
{data?.curr_balance * 0.01}
<span className="w-full text-base text-dark-gray dark:text-white tracking-tighter flex justify-end items-end">
{(data?.curr_balance * 0.01).toFixed(2)}
</span>
</div>
}
{isSuccess && (
<div className="flex items-center gap-8">
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
<div className="grid grid-cols-2 gap-8 my-2">
<h1 className="job-label">
Confirmation Number
</h1>
<span className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
<span className="w-full text-base text-dark-gray dark:text-white tracking-tighter flex justify-end items-end">
{data?.confirmation}
</span>
</div>
)}
</>
)}
</div>
)
}
</div>
</div>
</div>
<div className="md:p-8 p-4 add-fund-btn flex justify-end items-center py-4 gap-4">
<button
className="px-4 h-11 flex justify-center items-center btn-gradient text-white text-base rounded-full w-[100px]"
onClick={onClose}
>
Ok
</button>
</div>
</div>
</div>
</div>
<div className="modal-footer-wrapper w-full flex justify-end items-center gap-4">
<button
className="custom-btn btn-gradient text-white text-base"
onClick={onClose}
>
Ok
</button>
</div>
</div>
);
}
+99 -103
View File
@@ -46,14 +46,13 @@ function ThePaymentText({ value, type }) {
*/
function AmountSection({ currency, amount, country }) {
const formattedAmount = (+amount * 0.01)?.toFixed(2);
const gapClassName = country === "US" ? "gap-14" : "gap-4";
return (
<div className={`flex items-center ${gapClassName}`}>
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
<div className={`flex items-center gap-8`}>
<h1 className="min-w-[150px] text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
Amount({currency})
</h1>
<span className="text-xl font-normal text-dark-gray dark:text-white tracking-tighter my-1">
<span className="min-w-[100px] text-xl text-right font-normal text-dark-gray dark:text-white tracking-tighter my-1">
{formattedAmount}
</span>
</div>
@@ -66,14 +65,13 @@ function AmountSection({ currency, amount, country }) {
*/
function TransactionFeeSection({ currency, fee, country }) {
const formattedFee = (+fee).toFixed(2);
const gapClass = country === "US" ? "gap-[2.7rem]" : "gap-4";
return (
<div className={`flex items-center border-b border-gray-600 ${gapClass}`}>
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
<div className={`flex items-center gap-8 border-b border-gray-600`}>
<h1 className="min-w-[150px] text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
Transaction Fee
</h1>
<span className="text-xl font-normal text-dark-gray dark:text-white tracking-tighter my-1">
<span className="min-w-[100px] text-xl text-right font-normal text-dark-gray dark:text-white tracking-tighter my-1">
{formattedFee}
</span>
</div>
@@ -89,14 +87,12 @@ function TotalSection({ currency, amount, fee, country }) {
const total = Number(amount) + Number(fee);
const formattedTotal = (total * 0.01)?.toFixed(2);
const gap = country === "US" ? "gap-[8rem]" : "gap-[6.3rem]";
return (
<div className={`flex items-center ${gap}`}>
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
<div className={`flex items-center gap-8`}>
<h1 className="min-w-[150px] text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
Total
</h1>
<span className="text-xl font-normal text-dark-gray dark:text-white tracking-tighter my-1">
<span className="min-w-[100px] text-xl text-right font-normal text-dark-gray dark:text-white tracking-tighter my-1">
{formattedTotal}
</span>
</div>
@@ -356,103 +352,103 @@ function ConfirmAddFund({
};
return (
<div className="content-wrapper w-full h-[32rem]">
<div className="w-full mb-10">
<div className="add-fund w-full bg-white dark:bg-dark-white rounded-2xl">
<div className="px-4 md:p-8 py-4 add-fund-info">
<div className="field w-full mb-3 min-h-[45px]">
{confirmCredit?.show?.awaitConfirm?.state && (
<div className="flex flex-col gap-2">
<AmountSection
currency={__confirmData?.currency}
amount={__confirmData?.amount}
country={__confirmCountry}
/>
<TransactionFeeSection
currency={__confirmData?.currency}
fee={__confirmData?.fee}
country={__confirmCountry}
/>
<TotalSection
currency={__confirmData?.currency}
amount={__confirmData?.amount}
fee={__confirmData?.fee}
country={__confirmCountry}
/>
{__confirmCountry === "US" && (
<div className="flex items-center gap-8">
<label
htmlFor="payment"
className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1"
>
Payment Method
</label>
<span className="text-[#181c32] dark:text-white">
<ThePaymentText
value={__confirmCardDetails}
type={__confirmData?.cardType}
/>
<>
<div className="content-wrapper w-full h-[32rem]">
<div className="w-full mb-10">
<div className="add-fund w-full bg-white dark:bg-dark-white rounded-2xl">
<div className="px-4 md:p-8 py-4 add-fund-info">
<div className="field w-full mb-3 min-h-[45px]">
{confirmCredit?.show?.awaitConfirm?.state && (
<div className="flex flex-col gap-2">
<AmountSection
currency={__confirmData?.currency}
amount={__confirmData?.amount}
country={__confirmCountry}
/>
<TransactionFeeSection
currency={__confirmData?.currency}
fee={__confirmData?.fee}
country={__confirmCountry}
/>
<TotalSection
currency={__confirmData?.currency}
amount={__confirmData?.amount}
fee={__confirmData?.fee}
country={__confirmCountry}
/>
{__confirmCountry === "US" && (
<div className="flex items-center gap-8">
<label
htmlFor="payment"
className="min-w-[150px] text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1"
>
Payment Method
</label>
<span className="text-[#181c32] dark:text-white">
<ThePaymentText
value={__confirmCardDetails}
type={__confirmData?.cardType}
/>
</span>
</div>
)}
<div
className={`gap-8 flex items-center`}
>
<h1 className="min-w-[150px] text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
Reference No
</h1>
<span className="text-xl font-normal text-dark-gray dark:text-white tracking-tighter my-1">
{__confirmData?.credit_reference}
</span>
</div>
)}
<div
className={`${
__confirmCountry === "US"
? "gap-[3.7rem]"
: "gap-[1.81rem]"
} flex items-center`}
>
<h1 className="text-xl font-bold text-dark-gray dark:text-white tracking-tighter my-1">
Reference No
</h1>
<span className="text-xl font-normal text-dark-gray dark:text-white tracking-tighter my-1">
{__confirmData?.credit_reference}
</span>
</div>
</div>
)}
</div>
</div>
<div
className={
__confirmCountry === "US" ? "min-h-[96px]" : "min-h-[157px]"
}
></div>
<hr />
<div className="md:p-8 p-4 add-fund-btn flex justify-end items-center py-4 gap-4">
<button
className="px-4 py-1 h-11 max-w-[100px] w-full flex justify-center bg-[#f5a430] text-black items-center text-base rounded-full"
onClick={getBack}
>
Back
</button>
{__confirmCountry === "US" && (
<button
className="px-4 h-11 flex justify-center items-center btn-gradient text-white text-base rounded-full"
onClick={
__confirmData?.cardType === "prev"
? handlePrevCard
: handleNewCard
}
>
{confirmCredit?.show?.acceptConfirm?.loader ? (
<LoadingSpinner size="6" color="sky-blue" />
) : (
"Proceed"
)}
</button>
)}
{__confirmCountry === "NG" && (
<FlutterWaveButton
{...fwConfig}
className="px-2 py-1 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
/>
)}
</div>
</div>
<div
className={
__confirmCountry === "US" ? "min-h-[96px]" : "min-h-[157px]"
}
></div>
</div>
</div>
</div>
</div>
<div className="modal-footer-wrapper grid grid-cols-1 xxs:grid-cols-3">
<div className="w-full col-span-1 xxs:col-span-2 xxs:col-start-2 flex justify-between items-center">
<button
className="custom-btn bg-[#f5a430] text-black text-base"
onClick={getBack}
>
Back
</button>
{__confirmCountry === "US" && (
<button
className="custom-btn btn-gradient text-white text-base"
onClick={
__confirmData?.cardType === "prev"
? handlePrevCard
: handleNewCard
}
>
{confirmCredit?.show?.acceptConfirm?.loader ? (
<LoadingSpinner size="6" color="sky-blue" />
) : (
"Proceed"
)}
</button>
)}
{__confirmCountry === "NG" && (
<FlutterWaveButton
{...fwConfig}
className="px-2 py-1 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white"
/>
)}
</div>
</div>
</>
);
}
@@ -58,13 +58,12 @@ function ConfirmNairaWithdraw({
.sendMoney(reqData)
.then((res) => {
if (res.data.internal_return < 0) {
// if (res.data?.status_message?.toLowerCase().includes("limit")) {
// setRequestStatus({
// message: ,
// loading: false,
// status: false,
// });
// }
setRequestStatus({
message: 'Unable to complete, try again',
loading: false,
status: false,
});
return setTimeout(() => {
setRequestStatus({
message: "",
@@ -79,19 +78,19 @@ function ConfirmNairaWithdraw({
}, 5000);
}
setRequestStatus({
message: "Withdrawal sucessful",
loading: false,
status: true,
});
setShowCompleteNairaWithdraw({
show: true,
load: false,
state: res.data,
});
setTimeout(() => {
setRequestStatus({
message: "",
loading: false,
status: false,
});
setShowCompleteNairaWithdraw({
show: true,
load: false,
state: res.data,
});
dispatch(tableReload({ type: "WALLETTABLE" }));
}, 5000);
dispatch(tableReload({ type: "WALLETTABLE" }));
return;
})
.catch((error) => {
@@ -105,10 +104,10 @@ function ConfirmNairaWithdraw({
return (
<ModalCom action={action} situation={situation}>
<div className="logout-modal-wrapper w-[90%] md:w-[768px] h-full lg:h-auto bg-white dark:bg-dark-white lg:rounded-2xl overflow-y-auto">
<div className="logout-modal-wrapper w-[90%] md:w-[768px] h-auto bg-white dark:bg-dark-white lg:rounded-2xl overflow-y-auto">
<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">
<h2 className="text-26 font-bold text-dark-gray dark:text-white tracking-wide">
<div className="modal-header-con">
<h2 className="modal-title">
{completeNairaWithdraw.load ? (
"Confirming..."
) : (
@@ -126,7 +125,7 @@ function ConfirmNairaWithdraw({
</h2>
<button
type="button"
className="text-[#374557] dark:text-red-500"
className="modal-close-btn"
onClick={action}
>
<svg
@@ -151,7 +150,7 @@ function ConfirmNairaWithdraw({
</button>
</div>
<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">
{completeNairaWithdraw.load ? (
<div className="h-[35rem] flex items-center justify-center">
<LoadingSpinner size="12" color="sky-blue" />
@@ -376,28 +375,28 @@ function ConfirmNairaWithdraw({
</div>
</div>
)}
</div>
{!completeNairaWithdraw.load && (
<>
<p
className={`text-lg text-center font-bold ${
requestStatus.status ? "text-emerald-600" : "text-red-500"
} px-4 md:px-8 py-4`}
>
{requestStatus.message && requestStatus.message}
</p>
<div className="modal-footer-wrapper grid grid-cols-1 xxs:grid-cols-3">
<div className="w-full col-span-1 xxs:col-span-2 xxs:col-start-2 flex justify-between items-center">
<button
type="button"
onClick={action}
className="custom-btn bg-[#f5a430] text-black text-base"
>
Cancel
</button>
{!completeNairaWithdraw.load && (
<>
{" "}
<hr />
<p
className={`text-base ${
requestStatus.status ? "text-green-500" : "text-red-500"
} px-4 md:px-8 py-4 h-5`}
>
{requestStatus.message && requestStatus.message}
</p>
<div className="px-4 md:px-8 py-4 add-fund-btn flex justify-end items-center gap-2">
{!completeNairaWithdraw.show && (
<button
type="button"
onClick={action}
className="px-4 py-1 h-11 max-w-[100px] w-full flex justify-center items-center bg-[#f5a430] text-black text-base rounded-full"
>
Cancel
</button>
)}
<button
onClick={
@@ -407,7 +406,7 @@ function ConfirmNairaWithdraw({
? action
: handleSubmit
}
className="btn-gradient text-base tracking-wide px-4 py-2 rounded-full text-white cursor-pointer min-w-[100px]"
className="custom-btn btn-gradient text-base text-white"
>
{requestStatus.loading ? (
<LoadingSpinner size="6" color="sky-blue" />
@@ -420,9 +419,10 @@ function ConfirmNairaWithdraw({
)}
</button>
</div>
</>
)}
</div>
</div>
</>
)}
</div>
</div>
</ModalCom>
+13 -6
View File
@@ -4,6 +4,7 @@ import LoadingSpinner from "../../Spinners/LoadingSpinner";
import AddFundPop from "./AddFundPop";
import CompleteConfirmCredit from "./CompleteConfirmCredit";
import ConfirmAddFund from "./ConfirmAddFund";
import CustomTimer from "../../countdown/CustomTimer";
const CreditPopup = ({ details, onClose, situation, walletItem }) => {
const [input, setInput] = useState("");
@@ -35,16 +36,16 @@ const CreditPopup = ({ details, onClose, situation, walletItem }) => {
situation={situation}
className="assign-task-popup"
>
<div className="logout-modal-wrapper w-[90%] md:w-[768px] h-full lg:h-auto bg-white dark:bg-dark-white lg:rounded-2xl overflow-y-auto">
<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">
<div className="logout-modal-wrapper w-[90%] md:w-[768px] h-auto bg-white dark:bg-dark-white lg:rounded-2xl overflow-y-auto">
<div className="modal-header-con">
<h1 className="modal-title">
{confirmCredit?.show?.acceptConfirm?.loader
? "Confirming Credit..."
: getTitle()}
</h1>
<button
type="button"
className="text-[#374557] dark:text-red-500"
className="modal-close-btn"
onClick={onClose}
>
<svg
@@ -68,10 +69,16 @@ const CreditPopup = ({ details, onClose, situation, walletItem }) => {
</svg>
</button>
</div>
<div className="logout-modal-body w-full flex flex-col items-center">
<div className="w-full">
{confirmCredit?.show?.acceptConfirm?.loader ? (
<div className="h-[32rem] flex items-center justify-center">
<LoadingSpinner size="12" color="sky-blue" />
<div className="h-[32rem] flex flex-col items-center justify-center gap-4">
<p className="text-lg md:text-2xl text-emerald-600 tracking-wide font-bold">Processing payment</p>
<p className="text-lg md:text-2xl text-emerald-600 tracking-wide font-bold">Please do not refresh</p>
<LoadingSpinner size="6" color="sky-blue" height='h-20' />
{/* <p className="text-lg md:text-2xl text-emerald-600 tracking-wide font-bold">Timer countdown</p> */}
<CustomTimer className="text-lg text-center md:text-2xl text-emerald-600 tracking-wide font-bold" />
</div>
</div>
) : (
<>
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -23,14 +23,14 @@ function WalletAction({ walletItem, payment, openPopUp }) {
}}
className={`${
walletItem.code != "NAIRA" && "invisible"
} px-4 h-10 flex justify-center items-center btn-gradient text-base rounded-full text-white`}
} logout-btn btn-gradient text-white`}
>
Spend
</button>
</div>
<div className="w-1/2 flex justify-center items-center">
<button
className="px-4 h-10 flex justify-center items-center btn-gradient text-base rounded-full text-white"
className="logout-btn btn-gradient text-white"
onClick={() => {
openPopUp({
payment: payment,
+1 -1
View File
@@ -81,7 +81,7 @@ export default function WalletItemCard({ walletItem, payment, countries }) {
walletItem.escrow * 0.01,
walletItem.code,
undefined,
"text-[2rem]"
"text-[1.5rem]"
)}
</span>
</p>
+15 -12
View File
@@ -10,6 +10,8 @@ import RightSideBar from "./RightSideBar";
import Sidebar from "./Sidebar";
export default function Layout({ children }) {
const { userDetails } = useSelector((state) => state?.userDetails); // CHECKS FOR USER Details
const { drawer } = useSelector((state) => state.drawer);
const { userJobList } = useSelector((state) => state.userJobList);
const dispatch = useDispatch();
@@ -52,8 +54,8 @@ export default function Layout({ children }) {
return (
<>
<div className="nft-main-wrapper-layout">
<div className={`nft-wrapper-layout-container 2xl:pr-20 md:pr-10 pr-2 pl-2 md:pl-0 w-full min-h-screen flex`}>
<div className="nft-main-wrapper-layout container mx-auto">
<div className={`relative nft-wrapper-layout-container 2xl:pr-20 md:pr-10 pr-2 pl-2 md:pl-0 w-full min-h-screen flex`}>
{/* sidebar */}
<div className={`nft-sidebar xl:block hidden section-shadow ${drawer ? "2xl:w-[335px] w-[280px] 2xl:pl-20 pl-10 pr-6 " : "w-[70px]"} bg-white dark:bg-dark-white h-full overflow-y-scroll overflow-style-none fixed left-0 top-0 pt-[30px]`}>
<Sidebar logoutModalHandler={logoutModalHandler} sidebar={drawer} action={() => dispatch(drawerToggle())} myJobList={userJobList} />
@@ -71,10 +73,11 @@ export default function Layout({ children }) {
<Header sidebarHandler={() => setMobileSidebar.toggle()} logoutModalHandler={logoutModalHandler} />
</div>
{/* container */}
<div className="nft-container 2xl:flex 2xl:space-x-8 h-full mb-12 lg:mt-[140px] mt-24 xl:mt-10 flex flex-col xl:flex-row items-start justify-center gap-4">
<div className="nft-main-container flex-[80%] w-full">
<div className="nft-container container mx-auto 2xl:flex 2xl:space-x-8 h-full mb-12 lg:mt-[140px] mt-24 xl:mt-10 flex flex-col xl:flex-row items-start justify-center gap-4">
<div className="flex-[80%] w-full">
{children && children}
</div>
<div className="nft-right-side-content 2xl:w-[270px] w-full h-full 2xl:flex justify-center relative flex-[20%]">
<RightSideBar myJobList={userJobList} />
</div>
@@ -109,14 +112,14 @@ export default function Layout({ children }) {
Are you sure you want to Logout of your WrenchBoard account?
</p>
</div>
<div className="modal-footer-wrapper flex justify-center items-center gap-5">
<button onClick={logOut} type="button" className="text-white primary-gradient text-18 tracking-wide px-4 py-3 rounded-full">
{`Yes ${process.env.REACT_APP_LOGOUT_TEXT}`}
</button>
<button onClick={logoutModalHandler} type="button" className=" border-gradient text-18 tracking-wide px-4 py-3 rounded-full">
<span className="text-gradient">Not Now</span>
</button>
</div>
</div>
<div className="modal-footer-wrapper flex justify-center items-center gap-5">
<button onClick={logOut} type="button" className="text-white primary-gradient text-18 tracking-wide px-4 py-3 rounded-full">
{`Yes ${process.env.REACT_APP_LOGOUT_TEXT}`}
</button>
<button onClick={logoutModalHandler} type="button" className=" border-gradient text-18 tracking-wide px-4 py-3 rounded-full">
<span className="text-gradient">Not Now</span>
</button>
</div>
</div>
</ModalCom>
+620
View File
@@ -0,0 +1,620 @@
import React, { useContext } from "react";
import { Link, useLocation, useNavigate } from "react-router-dom";
import bank1 from "../../assets/images/bank-1.png";
import bank2 from "../../assets/images/bank-2.png";
import bank3 from "../../assets/images/bank-3.png";
import bank4 from "../../assets/images/bank-4.png";
import profileImg from "../../assets/images/profile.jpg";
import useToggle from "../../hooks/useToggle";
import DarkModeContext from "../Contexts/DarkModeContext";
import Icons from "../Helpers/Icons";
import ModalCom from "../Helpers/ModalCom";
import WalletHeader from "../MyWallet/WalletHeader";
import { useSelector } from "react-redux";
import Flag from "../../assets/images/united-states.svg";
import siteLogo from "../../assets/images/wrenchboard-logo-text.png";
// import { updateWalletDetails } from "../../store/walletDetails";
import TimeDifference from "../Helpers/TimeDifference";
const DEFAULT_PROFILE_IMAGE = require("../../assets/images/profile.jpg");
export default function MediaHeader({ logoutModalHandler, sidebarHandler, backpath, title }) {
const darkMode = useContext(DarkModeContext);
const navigate = useNavigate()
const {userDetails: { account_type }} = useSelector((state) => state?.userDetails);
const [balanceDropdown, setbalanceValue] = useToggle(false);
const [notificationDropdown, setNotificationValue] = useToggle(false);
const [userProfileDropdown, setProfileDropdown] = useToggle(false);
const [moneyPopup, setPopup] = useToggle(false);
const { userDetails } = useSelector((state) => state?.userDetails);
const { notifications } = useSelector((state) => state?.notifications); // NOTIFICATION STORE
const { walletDetails } = useSelector((state) => state?.walletDetails); // WALLET STORE
const image = localStorage.getItem("session_token")
? userDetails.account_type === "FAMILY"
? `${userDetails.session_image_server}${localStorage.getItem(
"session_token"
)}/family/${sessionStorage.getItem("family_uid")}`
: `${userDetails.session_image_server}${localStorage.getItem(
"session_token"
)}/profile/${userDetails.uid}`
: "";
// 9308RDR122
const handlerBalance = () => {
setbalanceValue.toggle();
if (notificationDropdown) {
setNotificationValue.toggle();
}
if (userProfileDropdown) {
setProfileDropdown.toggle();
}
};
const handlerNotification = () => {
setNotificationValue.toggle();
if (balanceDropdown) {
setbalanceValue.toggle();
}
if (userProfileDropdown) {
setProfileDropdown.toggle();
}
};
const handlerProfile = () => {
setProfileDropdown.toggle();
if (balanceDropdown) {
setbalanceValue.toggle();
}
if (notificationDropdown) {
setNotificationValue.toggle();
}
};
const clickAwayhandler = () => {
if (balanceDropdown) {
setbalanceValue.toggle();
}
if (notificationDropdown) {
setNotificationValue.toggle();
}
if (userProfileDropdown) {
setProfileDropdown.toggle();
}
};
const addMoneyHandler = () => {
setPopup.toggle();
setbalanceValue.set(false);
};
// getting the location of head
let { pathname } = useLocation();
const handleWalletBtn = () => {
if (pathname === "/my-wallet") {
setbalanceValue.set(false);
} else return balanceDropdown;
};
// User Profile
let { firstname, lastname, email, profile_pic_url } = userDetails;
let userEmail = email?.split("@")[0];
const userProfileImage = image || DEFAULT_PROFILE_IMAGE;
return (
<>
<div className="header-wrapper backdrop-blur-sm bg-[#efedfe5e]/60 dark:bg-transparent w-full h-full flex items-center xl:px-0 md:px-10 px-5">
<div className="flex justify-between items-center w-full">
{/* <button
className="xl:hidden block mr-10"
type="button"
onClick={sidebarHandler}
>
<svg
width="25"
height="19"
viewBox="0 0 25 19"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M24.3544 8.45953L16.9855 0.271831C16.8283 0.0982522 16.6089 0 16.3763 0H11.4637C11.1411 0 10.848 0.189955 10.7153 0.484712C10.5843 0.781107 10.6384 1.12663 10.8545 1.36571L17.7306 9.00647L10.8545 16.6456C10.6384 16.8863 10.5827 17.2318 10.7153 17.5266C10.848 17.823 11.1411 18.0129 11.4637 18.0129H16.3763C16.6089 18.0129 16.8283 17.913 16.9855 17.7427L24.3544 9.55505C24.6344 9.24391 24.6344 8.76903 24.3544 8.45953Z"
fill="url(#paint0_linear_700_68145)"
/>
<path
d="M13.7104 8.45953L6.34147 0.271831C6.18427 0.0982522 5.96484 0 5.73231 0H0.819691C0.497095 0 0.203976 0.189955 0.071335 0.484712C-0.0596682 0.781107 -0.00562942 1.12663 0.210526 1.36571L7.08656 9.00647L0.210526 16.6456C-0.00562942 16.8863 -0.0613058 17.2318 0.071335 17.5266C0.203976 17.823 0.497095 18.0129 0.819691 18.0129H5.73231C5.96484 18.0129 6.18427 17.913 6.34147 17.7427L13.7104 9.55505C13.9904 9.24391 13.9904 8.76903 13.7104 8.45953Z"
fill="url(#paint1_linear_700_68145)"
/>
<defs>
<linearGradient
id="paint0_linear_700_68145"
x1="10.644"
y1="0"
x2="28.9548"
y2="13.8495"
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#F539F8" />
<stop offset="0.416763" stopColor="#C342F9" />
<stop offset="1" stopColor="#5356FB" />
</linearGradient>
<linearGradient
id="paint1_linear_700_68145"
x1="0"
y1="0"
x2="18.3108"
y2="13.8495"
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#F539F8" />
<stop offset="0.416763" stopColor="#C342F9" />
<stop offset="1" stopColor="#5356FB" />
</linearGradient>
</defs>
</svg>
</button> */}
{/* Home */}
{/* <div className="search-bar xl:hidden justify-center items-center w-[376px]">
<HomeButton />
</div> */}
{/* Back BTN AND TITLE */}
<div className="pl-4 w-full flex justify-start gap-3 items-center">
<button
type="button"
className="min-w-[35px] h-auto text-[#374557] border border-sky-blue p-1 rounded-full"
onClick={() => {
if (backpath == "/manage-family") {
navigate(backpath,
{ replace: true }
);
} else {
navigate(backpath, { replace: true });
}
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="25"
height="25"
viewBox="0 0 24 24"
fill="skyblue"
>
<path d="M19 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H19v-2z" />
</svg>
</button>
<div className="">
{darkMode.theme === "light" ? (
<img className="w-28 h-auto" src={siteLogo} alt="nft" />
) : (
<img className="w-28 h-auto" src={siteLogo} alt="nft" />
)}
</div>
<h1 className="text-base md:text-[20px] font-bold text-dark-gray dark:text-white tracking-wide line-clamp-1">
{title && title}
</h1>
</div>
{/* user info */}
<div className="user-info flex items-center justify-end w-full xl:space-x-7 space-x-2 z-10 ">
{/* dark mode */}
{/* <button
onClick={darkMode.handleThemeSwitch}
type="button"
className="xl:w-[176px] w-[52px] h-[52px] dark:bg-white bg-dark-gray border border-pink rounded-full flex justify-center items-center"
>
<div className="flex space-x-2.5 items-center">
<span className="dark:text-dark-gray text-white">
<svg
width="27"
height="27"
viewBox="0 0 27 27"
fill="none"
xmlns="http://www.w3.org/2000/svg"
className="fill-current"
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M18.3065 16.3771C18.1572 16.6304 17.986 16.8743 17.7937 17.1062C17.7118 17.2044 17.7247 17.3515 17.8228 17.4339C17.9208 17.5163 18.0665 17.5028 18.1484 17.4046C18.3569 17.1532 18.5419 16.8897 18.7043 16.6155C18.7695 16.5051 18.7334 16.3622 18.6238 16.2966C18.5142 16.2304 18.3722 16.2668 18.3065 16.3771ZM18.9591 14.722C18.8948 15.0116 18.8078 15.2975 18.6982 15.5759C18.6511 15.6955 18.7093 15.831 18.8282 15.878C18.9466 15.9255 19.0812 15.8668 19.1283 15.7477C19.2472 15.446 19.3411 15.1368 19.4104 14.8231C19.4382 14.6978 19.3596 14.5735 19.2347 14.5456C19.1103 14.5176 18.9864 14.5968 18.9591 14.722ZM19.0673 12.944C19.0955 13.2411 19.1006 13.5395 19.0825 13.8375C19.0747 13.9655 19.1718 14.0763 19.2994 14.0837C19.4266 14.0917 19.5362 13.9939 19.5441 13.8659C19.564 13.5437 19.5584 13.2206 19.5274 12.8994C19.5154 12.7713 19.4021 12.6777 19.2754 12.6899C19.1482 12.702 19.0548 12.816 19.0673 12.944ZM18.6229 11.2201C18.7422 11.4948 18.8388 11.7769 18.9128 12.0641C18.9447 12.1884 19.071 12.2629 19.1949 12.2308C19.3184 12.1987 19.3924 12.0716 19.3605 11.9473C19.2805 11.6363 19.1755 11.3304 19.0465 11.0334C18.9951 10.9156 18.8587 10.8616 18.7417 10.9133C18.6247 10.9649 18.5715 11.1023 18.6229 11.2201ZM17.6651 9.72283C17.8653 9.94816 18.0448 10.1856 18.2034 10.4333C18.2723 10.5413 18.4157 10.5725 18.523 10.5026C18.6303 10.4333 18.6612 10.2889 18.5919 10.1809C18.4208 9.91324 18.2265 9.65578 18.0092 9.4123C17.9241 9.31639 17.7779 9.30848 17.6827 9.39414C17.5879 9.4798 17.58 9.62738 17.6651 9.72283Z"
/>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M13.4409 5.61267C9.08757 5.61267 5.55359 9.14665 5.55359 13.5C5.55359 17.8533 9.08757 21.3873 13.4409 21.3873C17.7942 21.3873 21.3282 17.8533 21.3282 13.5C21.3282 9.14665 17.7942 5.61267 13.4409 5.61267ZM13.9049 6.5559C17.5298 6.79484 20.4003 9.81475 20.4003 13.5C20.4003 17.1852 17.5298 20.2051 13.9049 20.4441V6.5559Z"
/>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M12.1116 1.32213V3.46343C12.1116 4.19318 12.7072 4.78556 13.4409 4.78556C14.1746 4.78556 14.7702 4.19318 14.7702 3.46343V1.32213C14.7702 0.592374 14.1746 0 13.4409 0C12.7072 0 12.1116 0.592374 12.1116 1.32213Z"
/>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M21.0877 4.01472L19.5511 5.5513C19.0274 6.07499 19.0274 6.92528 19.5511 7.44898C20.0748 7.97267 20.9251 7.97267 21.4488 7.44898L22.9854 5.9124C23.509 5.38871 23.509 4.53841 22.9854 4.01472C22.4617 3.49102 21.6114 3.49102 21.0877 4.01472Z"
/>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M25.6581 12.3649H23.4849C22.7443 12.3649 22.1431 12.9661 22.1431 13.7068C22.1431 14.4474 22.7443 15.0486 23.4849 15.0486H25.6581C26.3988 15.0486 27 14.4474 27 13.7068C27 12.9661 26.3988 12.3649 25.6581 12.3649Z"
/>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M22.9854 21.5012L21.4488 19.9646C20.9251 19.4409 20.0748 19.4409 19.5511 19.9646C19.0274 20.4883 19.0274 21.3386 19.5511 21.8623L21.0877 23.3989C21.6114 23.9226 22.4617 23.9226 22.9854 23.3989C23.509 22.8752 23.509 22.0249 22.9854 21.5012Z"
/>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M14.7702 25.6778V23.5365C14.7702 22.8068 14.1746 22.2144 13.4409 22.2144C12.7072 22.2144 12.1116 22.8068 12.1116 23.5365V25.6778C12.1116 26.4076 12.7072 27 13.4409 27C14.1746 27 14.7702 26.4076 14.7702 25.6778Z"
/>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M5.78958 23.0647L7.29553 21.5372C7.80878 21.0166 7.80878 20.1714 7.29553 19.6508C6.78228 19.1302 5.94893 19.1302 5.43568 19.6508L3.92974 21.1783C3.41649 21.6989 3.41649 22.5441 3.92974 23.0647C4.44299 23.5853 5.27633 23.5853 5.78958 23.0647Z"
/>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M1.32213 14.8293H3.46343C4.19318 14.8293 4.78556 14.2337 4.78556 13.5C4.78556 12.7663 4.19318 12.1707 3.46343 12.1707H1.32213C0.592374 12.1707 0 12.7663 0 13.5C0 14.2337 0.592374 14.8293 1.32213 14.8293Z"
/>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M3.92974 5.82165L5.43568 7.34911C5.94893 7.86969 6.78228 7.86969 7.29553 7.34911C7.80878 6.82853 7.80878 5.98328 7.29553 5.46269L5.78958 3.93524C5.27633 3.41465 4.44299 3.41465 3.92974 3.93524C3.41649 4.45582 3.41649 5.30107 3.92974 5.82165Z"
/>
</svg>
</span>
<span className="dark:text-dark-gray font-medium text-white xl:block hidden">
{darkMode.theme === "light" ? "Dark" : "Light"} Mode
</span>
</div>
</button> */}
{/* balance */}
{/* My Page Button */}
{/* {userDetails.account_type === "FULL" ? <PageButton /> : null} */}
{/*<div className="lg:hidden block"></div>*/}
<WalletHeader
myWalletList={walletDetails.data}
handlerBalance={handlerBalance}
balanceDropdown={balanceDropdown}
addMoneyHandler={addMoneyHandler}
setBalanceDropdown={setbalanceValue}
/>
{/* notification */}
<div className="user-notification lg:block hidden relative">
<div
onClick={() => handlerNotification()}
className="lg:w-[48px] lg:h-[48px] w-[38px] h-[38px] bg-white flex justify-center items-center rounded-full overflow-hidden relative"
>
<Icons name="notification" />
<span className="absolute right-2 top-2 z-10 text-xs lg:w-5 lg:h-5 w-4 h-4 flex justify-center items-center rounded-full primary-gradient text-white cursor-default">
{notifications?.loading ? "●" : notifications?.data?.length}
</span>
</div>
<div
className={`notification-dropdown z-30 w-96 bg-white dark:bg-dark-white absolute -right-12 rounded-lg cursor-pointer ${
notificationDropdown ? "active" : ""
}`}
>
<div className="heading border-b dark:border-[#5356fb29] border-light-purple px-7 py-6">
<h3 className="text-xl font-bold text-dark-gray dark:text-white">
Recent Notifications
</h3>
</div>
<div className="content px-7 pb-7">
<ul>
{notifications?.data?.length &&
notifications?.data?.map((item, idx) => {
if (idx < 5) {
return (
<li
className={`content-item ${
idx == 4
? "py-5 "
: "py-4 border-b dark:border-[#5356fb29] border-light-purple hover:border-purple dark:hover:border-purple"
}`}
key={idx}
>
<div className="notifications flex space-x-4 items-center">
<div className="icon max-w-[52px] max-h-[52px] w-full h-full rounded-full object-cover">
<img
src={require(`../../assets/images/notifications/${item?.icon}`)}
alt="icon"
className="w-full h-full"
/>
</div>
<div className="name">
<p className="text-base text-dark-gray dark:text-white font-medium mb-2">
{item?.title}
{/* <span className="ml-1 font-bold">
successfully done
</span> */}
</p>
<p className="text-sm text-thin-light-gray font-medium">
<TimeDifference
time={item?.date}
key={item?.uid}
/>
</p>
</div>
</div>
</li>
);
}
})}
</ul>
<div className="add-money-btn flex justify-center items-center">
<Link
to="/notification"
className="text-purple text-sm font-medium"
onClick={handlerNotification}
>
See all Notification
</Link>
{/* <button className="text-purple text-sm font-medium" onClick={()=>{
handlerNotification()
navigate('/notification', {replace: true})
}}>See all Notification</button> */}
</div>
</div>
</div>
</div>
<div className="lg:hidden block">
<Link
to="/notification"
className="lg:w-[48px] lg:h-[48px] w-[38px] h-[38px] bg-white flex justify-center items-center rounded-full overflow-hidden relative"
>
<Icons name="notification" />
<span className="absolute right-2 top-2 z-10 text-xs lg:w-5 lg:h-5 w-4 h-4 flex justify-center items-center rounded-full primary-gradient text-white">
10
</span>
</Link>
</div>
{/* profile */}
<div className="user-profile relative">
<div
onClick={() => handlerProfile()}
className="hidden lg:flex items-center space-x-3.5"
>
{/* profile-image */}
<div className="lg:w-[62px] lg:h-[62px] w-[50px] h-[50px] rounded-full overflow-hidden">
<img
src={userProfileImage}
alt="profile"
className="w-full h-full object-cover"
/>
</div>
<div className="lg:block hidden">
<h1 className="text-xl font-bold text-dark-gray dark:text-white">
{firstname}
</h1>
{userDetails && userDetails?.account_type !== "FAMILY" && (
<p className="text-sm text-thin-light-gray">@{userEmail}</p>
)}
</div>
</div>
<div className="for-mobile-profile lg:hidden block">
<div
// to="/profile"
onClick={() => handlerProfile()}
className="lg:w-[62px] lg:h-[62px] w-[50px] h-[50px] rounded-full overflow-hidden block"
>
<img
src={profileImg}
alt="profile"
className="w-full h-full object-cover object-center"
/>
</div>
</div>
<div
className={`profile-dropdown w-[293px] z-30 bg-white dark:bg-dark-white absolute lg:right-16 -right-[16px] rounded-lg ${
userProfileDropdown ? "active" : ""
}`}
>
<div className="heading border-b dark:border-[#5356fb29] border-light-purple px-7 py-2">
<img src={siteLogo} alt="Logo" className="w-[150px]" />
</div>
<div className="heading border-b dark:border-[#5356fb29] border-light-purple px-7 py-2">
<h3 className="text-xl font-bold text-dark-gray dark:text-white">
{`${firstname} ${lastname}`}
</h3>
</div>
<div className="content">
<ul className="px-7">
{userDetails && userDetails?.account_type !== "FAMILY" && (
<li className="content-item my-2 hover:bg-slate-100 transition duration-500 rounded-lg">
<Link to="/settings" className="notifications">
<div className="name">
<p className="text-sm py-2 px-4 text-dark-gray dark:text-white hover:text-sky-blue transition font-medium">
My Profile
</p>
</div>
</Link>
</li>
)}
<li className="content-item my-2 hover:bg-slate-100 transition duration-500 rounded-lg">
<Link to={ account_type == "FULL" ? "/my-wallet" : "/family-wallet"} className="notifications">
<div className="name">
<p className="text-sm py-2 px-4 text-dark-gray dark:text-white hover:text-sky-blue transition font-medium">
My Wallet
</p>
</div>
</Link>
</li>
{userDetails && userDetails?.account_type !== "FAMILY" && (
<li className="content-item my-2 hover:bg-slate-100 transition duration-500 rounded-lg">
<Link to="/yourpage" className="notifications">
<div className="name">
<p className="text-sm py-2 px-4 text-dark-gray dark:text-white hover:text-sky-blue transition font-medium">
My Page
</p>
</div>
</Link>
</li>
)}
{userDetails && userDetails?.account_type !== "FAMILY" && (
<>
<li className="content-item my-2 hover:bg-slate-100 transition duration-500 rounded-lg">
<Link to="#" className="notifications">
<div className="name">
<p className="text-sm py-2 px-4 text-dark-gray dark:text-white font-medium">
My Statements
</p>
</div>
</Link>
</li>
</>
)}
</ul>
<hr />
<ul className="px-7">
{userDetails && userDetails?.account_type !== "FAMILY" && (
<>
<li className="content-item relative my-2 hover:bg-slate-100 transition duration-500 rounded-lg">
<Link to="#" className="notifications">
<div className="name">
<div className="flex items-center justify-between text-sm py-2 px-4 text-dark-gray dark:text-white hover:text-sky-blue transition font-medium">
<p>Language</p>
<div className="px-1 flex items-center space-x-1 bg-slate-100 rounded-sm">
<p className="text-[10px]">English </p>
<img
className="w-[10px] h-[10px]"
src={Flag}
alt="U.S.A Flag"
/>
</div>
</div>
</div>
</Link>
{/* langauge list items*/}
<div className="inner-list-items absolute rounded-lg">
<ul className="p-3">
<li className="content-item my-1 hover:bg-slate-100 transition duration-500 rounded-lg">
<Link to="#" className="notifications">
<div className="name">
<div className="px-1 flex items-center space-x-1 bg-slate-100 rounded-sm text-sm py-1 text-dark-gray dark:text-white hover:text-sky-blue transition font-medium">
<img
className="w-[15px] h-[15px]"
src={Flag}
alt="U.S.A Flag"
/>
<p className="text-sm">English </p>
</div>
</div>
</Link>
</li>
</ul>
</div>
{/* end Language list items*/}
</li>
<li className="content-item my-2 hover:bg-slate-100 transition duration-500 rounded-lg">
<Link to="#" className="notifications">
<div className="name">
<p className="text-sm py-2 px-4 text-dark-gray dark:text-white hover:text-sky-blue transition font-medium">
Account Settings
</p>
</div>
</Link>
</li>
</>
)}
<li className="content-item my-2 hover:bg-slate-100 transition duration-500 rounded-lg cursor-pointer">
<div className="name" onClick={logoutModalHandler}>
<p className="text-sm py-2 px-4 text-dark-gray dark:text-white hover:text-sky-blue transition font-medium">
{process.env.REACT_APP_LOGOUT_TEXT}
</p>
</div>
</li>
</ul>
<hr className="mb-3" />
</div>
</div>
</div>
</div>
</div>
</div>
{balanceDropdown || notificationDropdown || userProfileDropdown ? (
<div
onClick={clickAwayhandler}
className="w-full h-screen fixed left-0"
style={{ zIndex: "-1" }}
></div>
) : (
""
)}
</>
);
}
const PageButton = () => {
return (
<Link
to="/yourpage"
className="lg:flex hidden user-balance cursor-pointer lg:w-[152px] w-[150px] h-[48px] items-center rounded-full relative bg-sky-blue pr-1.5 pl-4"
>
<div className="flex items-center lg:justify-between justify-center w-full h-full">
<span className="lg:block hidden w-[25px]">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 68 50" id="Page">
<path
fillRule="evenodd"
d="M0 13V2a2 2 0 0 1 2-2h64a2 2 0 0 1 2 2v11H0Zm0 4v31a2 2 0 0 0 2 2h20V17H0Zm26 33h40a2 2 0 0 0 2-2V17H26v33Z"
fill="#ffffff"
className="color000000 svgShape"
></path>
</svg>
</span>
<p className="lg:text-xl text-lg font-bold text-white">My Page</p>
<span className="lg:block hidden">
{/* <Icons name="deep-plus" /> */}
</span>
</div>
</Link>
);
};
const HomeButton = () => {
return (
<Link
to="/"
className="flex user-balance cursor-pointer w-[110px] h-[48px] items-center rounded-full relative bg-sky-blue pr-1.5 pl-4"
>
<div className="flex items-center lg:justify-between justify-center w-full h-full">
<span className="">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
strokeWidth={1.5}
stroke="currentColor"
className="w-7 h-7 stroke-white fill-white"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="m2.25 12 8.954-8.955c.44-.439 1.152-.439 1.591 0L21.75 12M4.5 9.75v10.125c0 .621.504 1.125 1.125 1.125H9.75v-4.875c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21h4.125c.621 0 1.125-.504 1.125-1.125V9.75M8.25 21h8.25"
/>
</svg>
</span>
<p className="lg:text-xl text-lg font-bold text-white">Home</p>
<span className=""></span>
</div>
</Link>
);
};
+127
View File
@@ -0,0 +1,127 @@
import React, { useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { useNavigate } from "react-router-dom";
import useToggle from "../../hooks/useToggle";
import { drawerToggle } from "../../store/drawer";
import ModalCom from "../Helpers/ModalCom";
// import Header from "./Header";
import MobileSidebar from "./MobileSideBar";
import RightSideBar from "./RightSideBar";
import Sidebar from "./Sidebar";
import MediaHeader from "./MediaHeader";
export default function MediaLayout({backpath, title, children }) {
const { drawer } = useSelector((state) => state.drawer);
const { userJobList } = useSelector((state) => state.userJobList);
const dispatch = useDispatch();
const [MobileSideBar, setMobileSidebar] = useToggle(false);
const [logoutModal, setLogoutModal] = useState(false);
const logoutModalHandler = () => {
setLogoutModal(!logoutModal);
};
const navigate = useNavigate();
const logOut = () => {
sessionStorage.clear();
localStorage.clear();
// toast.success("Come Back Soon", {
// icon: `🙂`,
// });
navigate("/login", { replace: true });
};
//---------------------------------------
/* LET U DEAL WITH JOB LIST - we need to centralize this list */
// const {jobListTable} = useSelector((state) => state.tableReload)
// const [myJobList, setMyJobList] = useState({loading: true, data:[]});
// const api = new usersService();
// const getMyJobList = async () => {
// setMyJobList({loading: true, data:[]})
// try {
// const res = await api.getMyJobList();
// setMyJobList({loading: false, data:res.data})
// // setMyJobList(res.data);
// } catch (error) {
// setMyJobList({loading: false, data:[]})
// console.log("Error getting mode");
// }
// };
// useEffect(() => {
// getMyJobList();
// }, [jobListTable]);
return (
<>
<div className="nft-main-wrapper-layout media container mx-auto">
<div className={`nft-wrapper-layout-container 2xl:pr-20 md:pr-10 pr-2 pl-2 md:pl-0 w-full min-h-screen flex`}>
{/* sidebar */}
{/*<div className={`nft-sidebar xl:block hidden section-shadow ${drawer ? "2xl:w-[335px] w-[280px] 2xl:pl-20 pl-10 pr-6 " : "w-[70px]"} bg-white dark:bg-dark-white h-full overflow-y-scroll overflow-style-none fixed left-0 top-0 pt-[30px]`}>*/}
{/* <Sidebar logoutModalHandler={logoutModalHandler} sidebar={drawer} action={() => dispatch(drawerToggle())} myJobList={userJobList} />*/}
{/*</div>*/}
{/*{MobileSideBar && (*/}
{/* <div onClick={() => setMobileSidebar.toggle()} className="bg-black bg-opacity-20 fixed left-0 top-0 w-full h-full z-[50] block xl:hidden"></div>*/}
{/*)}*/}
{/*<div className={`nft-sidebar block xl:hidden section-shadow w-[280px] pl-3 bg-white dark:bg-dark-white h-full overflow-y-scroll overflow-style-none fixed z-[60] top-0 pt-8 ${MobileSideBar ? "left-0" : "-left-[290px]"}`}>*/}
{/* <MobileSidebar logoutModalHandler={logoutModalHandler} sidebar={MobileSideBar} action={() => setMobileSidebar.toggle()} myJobList={userJobList} />*/}
{/*</div>*/}
{/* end sidebar */}
<div className={`nft-header-container-wrapper flex-1 md:ml-12 xl:ml-[110px] h-full`}>
{/* header */}
<div className="nft-header w-full lg:h-[100px] h-[70px] default-border-bottom dark:border-[#292967] z-40 xl:sticky fixed top-0 left-0 ">
<MediaHeader backpath={backpath} title={title} sidebarHandler={() => setMobileSidebar.toggle()} logoutModalHandler={logoutModalHandler} />
</div>
{/* container */}
<div className="nft-container container mx-auto 2xl:flex 2xl:space-x-8 h-full mb-12 lg:mt-[140px] mt-24 xl:mt-10 flex flex-col xl:flex-row items-start justify-center gap-4">
<div className="nft-main-container_media flex-[100%] w-full">
{children && children}
</div>
{/*<div className="nft-right-side-content 2xl:w-[270px] w-full h-full 2xl:flex justify-center relative flex-[20%]">*/}
{/* <RightSideBar myJobList={userJobList} />*/}
{/*</div>*/}
</div>
</div>
</div>
</div>
{logoutModal && (
<ModalCom action={logoutModalHandler} situation={logoutModal}>
<div className="logout-modal-wrapper w-11/12 sm:w-[460px] bg-white dark:bg-dark-white lg:rounded-2xl">
<div className="modal-header-con">
<h1 className="modal-title">
Confirm
</h1>
<button type="button" className="modal-close-btn" onClick={logoutModalHandler}>
<svg width="36" height="36" viewBox="0 0 36 36" fill="none" className="fill-current" xmlns="http://www.w3.org/2000/svg">
<path d="M36 16.16C36 17.4399 36 18.7199 36 20.0001C35.7911 20.0709 35.8636 20.2554 35.8385 20.4001C34.5321 27.9453 30.246 32.9248 22.9603 35.2822C21.9006 35.6251 20.7753 35.7657 19.6802 35.9997C18.4003 35.9997 17.1204 35.9997 15.8401 35.9997C15.5896 35.7086 15.2189 35.7732 14.9034 35.7093C7.77231 34.2621 3.08728 30.0725 0.769671 23.187C0.435002 22.1926 0.445997 21.1199 0 20.1599C0 18.7198 0 17.2798 0 15.8398C0.291376 15.6195 0.214408 15.2656 0.270759 14.9808C1.71321 7.69774 6.02611 2.99691 13.0428 0.700951C14.0118 0.383805 15.0509 0.386897 15.9999 0C17.2265 0 18.4532 0 19.6799 0C19.7156 0.124041 19.8125 0.136067 19.9225 0.146719C27.3 0.868973 33.5322 6.21922 35.3801 13.427C35.6121 14.3313 35.7945 15.2484 36 16.16ZM33.011 18.0787C33.0433 9.77105 26.3423 3.00309 18.077 2.9945C9.78479 2.98626 3.00344 9.658 2.98523 17.8426C2.96667 26.1633 9.58859 32.9601 17.7602 33.0079C26.197 33.0577 32.9787 26.4186 33.011 18.0787Z" fill="" fillOpacity="0.6" />
<path d="M15.9309 18.023C13.9329 16.037 12.007 14.1207 10.0787 12.2072C9.60071 11.733 9.26398 11.2162 9.51996 10.506C9.945 9.32677 11.1954 9.0811 12.1437 10.0174C13.9067 11.7585 15.6766 13.494 17.385 15.2879C17.9108 15.8401 18.1633 15.7487 18.6375 15.258C20.3586 13.4761 22.1199 11.7327 23.8822 9.99096C24.8175 9.06632 26.1095 9.33639 26.4967 10.517C26.7286 11.2241 26.3919 11.7413 25.9133 12.2178C24.1757 13.9472 22.4477 15.6855 20.7104 17.4148C20.5228 17.6018 20.2964 17.7495 20.0466 17.9485C22.0831 19.974 24.0372 21.8992 25.9689 23.8468C26.9262 24.8119 26.6489 26.1101 25.4336 26.4987C24.712 26.7292 24.2131 26.3441 23.7455 25.8757C21.9945 24.1227 20.2232 22.3892 18.5045 20.6049C18.0698 20.1534 17.8716 20.2269 17.4802 20.6282C15.732 22.4215 13.9493 24.1807 12.1777 25.951C11.7022 26.4262 11.193 26.7471 10.4738 26.4537C9.31345 25.9798 9.06881 24.8398 9.98589 23.8952C11.285 22.5576 12.6138 21.2484 13.9387 19.9355C14.5792 19.3005 15.2399 18.6852 15.9309 18.023Z" fill="#" fillOpacity="0.6" />
</svg>
</button>
</div>
<div className="logout-modal-body w-full flex flex-col items-center px-10 py-8">
<div className="what-icon mb-6 cursor-pointer">
<svg width="136" height="136" viewBox="0 0 136 136" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="68" cy="68" r="68" fill="#4687ba" />
<path d="M69.8844 35.7891C71.1588 36.0357 72.4569 36.1967 73.7044 36.5423C81.5447 38.7098 87.2705 45.5378 87.9574 53.6156C88.5113 60.1147 86.3075 65.6006 81.5043 70.0195C79.8359 71.5545 78.0497 72.9604 76.3408 74.4534C76.127 74.6397 75.9654 75.0037 75.9604 75.2872C75.9284 77.2752 75.9435 79.2649 75.9435 81.2965C70.8895 81.2965 65.8758 81.2965 60.7915 81.2965C60.7915 81.0616 60.7915 80.8385 60.7915 80.6137C60.7915 76.5454 60.7999 72.4772 60.7797 68.4106C60.778 67.9392 60.9312 67.649 61.2831 67.3537C64.5643 64.5957 67.8271 61.8175 71.1033 59.0545C72.2616 58.0781 72.9215 56.8702 72.9081 55.3419C72.8878 52.916 70.8608 50.9146 68.423 50.8911C65.9701 50.8693 63.9145 52.8053 63.832 55.2328C63.8084 55.8988 63.8286 56.5665 63.8286 57.2695C58.7745 57.2695 53.7744 57.2695 48.6917 57.2695C48.6917 56.3149 48.6462 55.3385 48.6984 54.3655C49.222 44.699 56.7442 36.8745 66.4331 35.8914C66.5762 35.8763 66.7142 35.8243 66.854 35.7891C67.8641 35.7891 68.8742 35.7891 69.8844 35.7891Z" fill="white" />
<path d="M67.485 100.21C66.1617 99.9268 64.9041 99.5091 63.803 98.6787C61.3804 96.8484 60.2877 93.7699 61.0386 90.7888C61.7726 87.8747 64.2138 85.6703 67.2089 85.2157C71.273 84.6 75.2024 87.3681 75.8135 91.277C76.4937 95.6153 73.8202 99.3782 69.544 100.103C69.4429 100.12 69.3487 100.172 69.2527 100.209C68.6635 100.21 68.0742 100.21 67.485 100.21Z" fill="white" />
</svg>
</div>
<div className="mb-6">
<p className="text-2xl tracking-wide text-center text-dark-gray dark:text-white">
Are you sure you want to Logout of your WrenchBoard account?
</p>
</div>
</div>
<div className="modal-footer-wrapper flex justify-center items-center gap-5">
<button onClick={logOut} type="button" className="text-white primary-gradient text-18 tracking-wide px-4 py-3 rounded-full">
{`Yes ${process.env.REACT_APP_LOGOUT_TEXT}`}
</button>
<button onClick={logoutModalHandler} type="button" className=" border-gradient text-18 tracking-wide px-4 py-3 rounded-full">
<span className="text-gradient">Not Now</span>
</button>
</div>
</div>
</ModalCom>
)}
</>
);
}
+2 -2
View File
@@ -13,8 +13,8 @@ export default function VideoElement({videoId}) {
},[videoId])
return (
<video ref={videoRef} className='w-full h-full' controls autoPlay>
<source src={`https://dev-media.wrenchboard.com/videos/${videoId}`} type='video/mp4'></source>
<video ref={videoRef} className='w-full h-full' controls>
<source src={`${process.env.REACT_APP_MEDIA_LINK}/videos/${videoId}`} type='video/mp4'></source>
Your browser does not support the video tag.
</video>
)
+24
View File
@@ -0,0 +1,24 @@
import React, { useEffect, useState } from 'react'
export default function CustomTimer({className='text-emerald-500'}) {
const [time, setTime] = useState(Number(process.env.REACT_APP_CUSTOMTIMER))
useEffect(()=>{
const timer = setInterval(()=>{
setTime(prev => prev - 1)
},1000)
return ()=>{
clearInterval(timer)
}
},[])
let minutes = time == 0 ? 0 : Math.floor(time/60)
let seconds = time == 0 ? 0 :time - (minutes * 60)
return (
<p className={`w-full text-base text-emerald-500 ${className}`}>
{`${minutes > 9 ? minutes : '0'+minutes} : ${seconds > 9 ? seconds : '0'+seconds}`}
</p>
)
}
@@ -0,0 +1,58 @@
import React, { useState } from "react";
import useToggle from "../../hooks/useToggle";
import { drawerToggle } from "../../store/drawer";
import { useSelector } from "react-redux";
import MobileSidebar from "../Partials/MobileSideBar";
export default function DashboardMediaPage({ children }) {
const { drawer } = useSelector((state) => state.drawer);
const [MobileSideBar, setMobileSidebar] = useToggle(false);
return (
<>
<div className="nft-main-wrapper-layout w-full mx-auto">
<div className={`nft-wrapper-layout-container 2xl:pr-20 md:pr-10 pr-2 pl-2 md:pl-0 w-full min-h-screen flex`}>
{/* end sidebar */}
<div className={`nft-header-container-wrapper flex-1 md:ml-10 ${drawer ? "2xl:ml-[375px] xl:ml-[310px]" : "xl:ml-[110px]"} h-full`}>
{/* header */}
<div className="nft-header w-full lg:h-[100px] h-[70px] default-border-bottom dark:border-[#292967] z-40 xl:sticky fixed top-0 left-0 bg-slate-300 animate-pulse duration-100">
</div>
{/* container */}
<div className="nft-container 2xl:flex 2xl:space-x-8 h-full mb-12 lg:mt-[140px] mt-24 xl:mt-10 flex flex-col xl:flex-row items-start justify-center gap-4">
<div className="w-full h-full bg-slate-200 animate-pulse duration-300">
<div className="my-4 lg:flex justify-between items-start space-y-4 lg:space-x-4 lg:space-y-0">
<div className="w-full p-10 mb-4 border-b pb-4 lg:pb-0 lg:mb-0 lg:border-b-0">
<div className="mb-4 w-full min-h-[500px] bg-slate-200 animate-pulse duration-100"></div>
<div className="w-full p-4 h-20 bg-slate-300 animate-pulse duration-200 dark:bg-black rounded-2xl shadow-md md:flex md:justify-between gap-2"></div>
</div>
<div className="p-10 w-full lg:w-2/5 grid grid-cols-1 md:grid-cols-2 lg:grid-cols-1 gap-4">
{/* TEXTAREA SECTION */}
<div className="w-full h-40 mb-3">
<div className="w-full h-full bg-slate-200 dark:bg-black rounded-2xl shadow-md animate-pulse duration-100"></div>
</div>
{/* END OF TEXTAREA */}
{/* MESSAGE SECTION */}
<div className="w-full h-40">
<div className="w-full h-full bg-slate-200 dark:bg-black rounded-2xl shadow-md animate-pulse duration-300"></div>
</div>
{/* END OF MESSAGE */}
</div>
</div>
</div>
{/* <div className="nft-right-side-content 2xl:w-[270px] w-full h-full 2xl:flex justify-center relative flex-[20%]">
<RightSideBar myJobList={userJobList} />
</div> */}
</div>
</div>
</div>
</div>
</>
);
}
+523 -4
View File
@@ -1,10 +1,529 @@
import React from 'react'
import React, { lazy, Suspense, useRef, useState } from 'react'
import Layout from '../Partials/Layout'
import MediaLayout from '../Partials/MediaLayout'
import CustomBreadcrumb from '../Breadcrumb/CustomBreadcrumb'
import ActiveJobMessageMedia from '../MyActiveJobs/ActiveJobMessageMedia'
import LoadingSpinner from '../Spinners/LoadingSpinner'
import usersService from '../../services/UsersService'
import { useNavigate } from 'react-router-dom'
import { useSelector } from 'react-redux'
import { useReactToPrint } from 'react-to-print'
const Iframe = lazy(() => import("../Iframe/Iframe"));
export default function FamGames() {
const ApiCall = new usersService();
const navigate = useNavigate();
const { userDetails } = useSelector((state) => state.userDetails);
const [messageToSend, setMessageToSend] = useState(""); // State to hold the value of message to be sent
const [filesToSend, setFilesToSend] = useState([]); // State to hold the value of files to be sent
const [tab, setTab] = useState("message");
const [requestStatus, setRequestStatus] = useState({
loading: false,
status: false,
message: "",
});
// let [popUp, setPopUp] = useState(false); // STATE FOR POPOUT MODAL
const printRef = useRef();
// to handle printing
const handlePrint = useReactToPrint({
content: () => printRef.current,
});
// FUNCTION TO HANDLE POPOUT
const popUpHandler = () => {
setPopUp((prev) => !prev);
};
// FUNCTION TO HANDLE MESSAGE CHANGE
const handleMessageChange = ({ target: { value } }) => {
setMessageToSend(value);
};
// FUNCTION TO HANDLE FILE UPlOAD CHANGE
const handleFileChange = ({ target: { files } }) => {
setRequestStatus({ loading: false, status: false, message: "" }); // State to determine error state
if (!files[0]) {
// IF NO FILE SELECTED RETURN
return;
}
if (files[0].size > Number(process.env.REACT_APP_MAX_FILE_SIZE)) {
setRequestStatus({
loading: false,
status: false,
message: "File must be <= 1mb",
});
setTimeout(() => {
setRequestStatus({ loading: false, status: false, message: "" });
}, 5000);
return;
}
if (filesToSend.length >= Number(process.env.REACT_APP_TOTAL_NUM_FILE)) {
setRequestStatus({
loading: false,
status: false,
message: `Total number of attachment is ${Number(
process.env.REACT_APP_TOTAL_NUM_FILE
)}`,
});
setTimeout(() => {
setRequestStatus({ loading: false, status: false, message: "" });
}, 5000);
return;
}
// INCLUDE FILE IF NO ERROR
setFilesToSend((prev) => [...prev, files[0]]);
};
// FUNCTION TO CLEAR ALL TYPED MESSAGE OR FILES
const handleClearAll = ({ target: { name } }) => {
if (tab == "message") {
setMessageToSend("");
} else if (tab == "files") {
setFilesToSend([]);
} else {
return;
}
};
// FUNCTION TO REMOVE AND IMAGE
const handleRemoveImage = (imageToDelete) => {
setFilesToSend((prev) =>
prev.filter((item) => item.name != imageToDelete.name)
);
};
// FUNCTION TO SEND TASK MESSAGE
const sendTaskMessage = () => {
let reqData = {
message: messageToSend,
msg_type: "TEXT",
contract: props.details.contract,
};
if (!reqData.message) {
setRequestStatus({
loading: false,
status: false,
message: "Message is empty",
});
return setTimeout(() => {
setRequestStatus({ loading: false, status: false, message: "" });
}, 5000);
}
setRequestStatus({ loading: true, status: false, message: "" });
ApiCall.sendTaskMessage(reqData)
.then((res) => {
if (res.status != 200 || res.data.internal_return < 0) {
setRequestStatus({
loading: false,
status: false,
message: "Message could not be sent, try again later",
});
return;
}
setRequestStatus({
loading: false,
status: true,
message: "Message Sent Successfully",
});
// function to trigger socket to emit 'send_message'
sendMessage(messageToSend, `${props.details.contract}-${props.details.contract_uid}`)
props.reloadActiveJobList((prev) => !prev); // MAKES ACTIVE JOB MESSAGE LIST TO RELOAD
setMessageToSend(""); // SENDS MESSAGE TO SEND BACK TO EMPTY STRINGS
})
.catch((error) => {
setRequestStatus({
loading: false,
status: false,
message: "Opps! something went wrong",
});
})
.finally(() => {
setTimeout(() => {
setRequestStatus({ loading: false, status: false, message: "" });
}, 5000);
});
};
// FUNCTION TO SEND FILES
const sendFile = async () => {
setRequestStatus({ loading: true, status: false, message: "" });
if (!filesToSend.length) {
// checks if file to send is empty
setRequestStatus({
loading: false,
status: false,
message: "No File(s) selected",
});
return setTimeout(() => {
setRequestStatus({ loading: false, status: false, message: "" });
}, 5000);
}
for (let i = 0; i <= filesToSend.length - 1; i++) {
// Loops through files to send array and trigger upload API call
const fileToBase64 = async () => {
// Converts file data to base64 string
try {
const base64String = await convertFileToBase64(filesToSend[i]);
return base64String;
} catch (error) {
return false;
}
};
// if(await !fileToBase64()){
// return
// }
let reqData = {
file_name: filesToSend[i].name,
file_size: filesToSend[i].size,
file_type: "image/png",
file_data: await fileToBase64(),
msg_type: "FILE",
contract: props.details.contract,
};
ApiCall.sendFiles(reqData)
.then((res) => {
// if(res.status != 200 || res.data.internal_return < 0){
// setRequestStatus({loading: false, status: false, message: 'Files(s) could not be sent, try again later'})
// return
// }
// setRequestStatus({loading: false, status: true, message: 'File(s) Uploaded Successfully'})
// props.reloadActiveJobList(prev => !prev) // MAKES ACTIVE JOB MESSAGE LIST TO RELOAD
// setFilesToSend([]) // SETS FILES TO SEND TO SEND BACK TO EMPTY ARRAY
})
.catch((error) => {
// setRequestStatus({loading: false, status: false, message: 'Opps! something went wrong'})
})
.finally(() => {
if (i == filesToSend.length - 1) {
setRequestStatus({
loading: false,
status: true,
message: "File(s) Uploaded Successfully",
});
setFilesToSend([]); // SETS FILES TO SEND TO SEND BACK TO EMPTY ARRAY
props.reloadActiveJobList((prev) => !prev); // MAKES ACTIVE JOB MESSAGE LIST TO RELOAD
setTimeout(() => {
setRequestStatus({ loading: false, status: false, message: "" });
}, 5000);
}
});
}
};
return (
<Layout>
<div>Family Games Page</div>
</Layout>
<MediaLayout
backpath={'/'}
title={'Games'}
>
{/* <div className='mb-4'>
<CustomBreadcrumb
title='Games and Interest'
breadcrumb = {
[
{ link: "/", title: "Home" },
{ link: "/work-in-progress", title: "Games and Interest", active: true},
]
}
/>
</div> */}
<div className="my-4 lg:flex justify-between items-start space-y-4 lg:space-x-4 lg:space-y-0">
<div className="w-full mb-4 border-b pb-4 lg:pb-0 lg:mb-0 lg:border-b-0">
<div className="mb-4 w-full h-screen max-h-[650px]">
<Suspense fallback={<Fallback />}>
<Iframe
src={process.env.REACT_APP_FAM_GAME_LINK}
title='Games'
/>
</Suspense>
</div>
<div className="w-full p-4 bg-white dark:bg-black rounded-2xl shadow-md md:flex md:justify-between gap-8">
<div className="w-full flex flex-col justify-between">
<div className="w-full h-30">
<div className='w-full h-full flex justify-center items-center text-5xl'>COMING SOON</div>
{/* <p className="w-full text-base text-right text-sky-blue">
{props?.details && props.details.job_to}
</p>
<div className="text-base tracking-wide">
<p className="font-semibold text-black dark:text-white tracking-wider">
Description:{" "}
</p>
<p className="p-2 ml-8 border-b border-sky-blue">
{props?.details && props.details.description}
</p>
</div>
<div className="mt-6 w-full lg:flex gap-8">
<div className="w-full text-base tracking-wide">
<p className="font-semibold text-black dark:text-white tracking-wider">
Delivery Detail:{" "}
</p>
<p className="p-2 ml-8">
{props?.details && props.details.job_description}
</p>
</div>
<div className="my-2 lg:my-0">
<IndexJobActions details={props.details} />
</div>
</div> */}
</div>
</div>
{/* job details */}
<div className="w-full md:w-[200px] h-20">
{/* <p className="text-base text-sky-blue">Delivery Detail</p> */}
{/* {passDue ? (
<div className="my-1">
<p className="text-base text-slate-700">
<span className="font-semibold">Due: </span>
{props?.details && props.details.delivery_date.split(" ")[0]}
</p>
{props?.delivery_date && (
<p className="py-2 text-base text-slate-700">
{props.details.delivery_date.split(" ")[1]}
</p>
)}
</div>
) : (
<div className="my-1 flex items-start gap-3">
<p className="font-semibold">Due: </p>
<div className="flex flex-col justify-between">
<p className="text-base text-slate-700 tracking-wide">
<CountDown
lastDate={props?.details && props.details.delivery_date}
/>
</p>
<div className="text-base text-slate-700 tracking-wide flex gap-[5px]">
<span>Hrs</span>
<span>Min</span>
<span>Sec</span>
</div>
</div>
</div>
)} */}
{/* <div className="my-1 text-base text-slate-700 tracking-wide flex items-center gap-3">
<span className="font-semibold text-black dark:text-white">
Reward:{" "}
</span>
<span className="">{thePrice}</span>
</div>
<div className="my-1 text-base text-slate-700 tracking-wide flex items-center gap-3">
<span className="font-semibold text-black dark:text-white">
Duration:{" "}
</span>
<span className="">
{props.details?.timeline_days && props.details.timeline_days}{" "}
day(s)
</span>
</div> */}
</div>
{/* end of job details */}
</div>
</div>
<div className="w-full lg:w-1/6 grid grid-cols-1 md:grid-cols-2 lg:grid-cols-1 gap-4">
{/* TEXTAREA SECTION */}
<div className="w-full mb-3 hidden">
<div className="w-full">
<div className="pl-7 flex items-center gap-3">
<button
name="message"
onClick={(e) => setTab(e.target.name)}
className={`px-4 xl:px-1 xxl:px-4 text-sm py-1 rounded-t-2xl ${
tab == "message"
? "bg-[#4687ba] border-[2px] border-[#4687ba] text-white"
: "bg-white text-[#000] border-t-[2px]"
}`}
>
Send Message
</button>
<button
name="files"
onClick={(e) => setTab(e.target.name)}
className={`px-4 xl:px-1 xxl:px-4 text-sm py-1 rounded-t-2xl ${
tab == "files"
? "bg-[#4687ba] border-[2px] border-[#4687ba] text-white"
: "bg-white text-[#000] border-t-[2px]"
}`}
>
Send Files
</button>
</div>
{tab == "message" ? (
<textarea
className="p-4 w-full h-[150px] text-base text-slate-600 dark:text-white bg-white dark:bg-black border-4 border-[#4687ba] outline-none"
// rows="10"
style={{ resize: "none" }}
name="message"
onChange={handleMessageChange}
value={messageToSend}
autoFocus
/>
) : (
<div className="p-4 mb-2 h-[150px] text-base text-slate-600 border-4 border-[#4687ba]">
<div className="files flex">
<label
htmlFor="file"
className="custom-btn btn-gradient text-base text-white"
>
Select Files to Upload
</label>
<input
type="file"
id="file"
accept="image/*"
style={{ display: "none" }}
onChange={handleFileChange}
/>
</div>
<div className="selected_file my-2 overflow-y-auto">
{filesToSend.length > 0 &&
filesToSend.map((item, index) => (
<p key={index} className="flex items-center space-x-2">
<span>{item.name}</span>
<button
name="remove"
onClick={() => handleRemoveImage(item)}
className="px-2 flex justify-center items-center rounded-full border border-red-500 text-red-500"
>
x
</button>
</p>
))}
</div>
</div>
)}
</div>
{/* ERROR DISPLAY AND SUBMIT BUTTON */}
<div className="w-full">
{/* error or success display */}
{requestStatus.message != "" &&
(!requestStatus.status ? (
<div
className={`relative p-4 my-4 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}
>
{requestStatus.message}
</div>
) : (
requestStatus.status && (
<div
className={`relative p-4 my-4 text-green-700 bg-slate-200 border-slate-800 mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}
>
{requestStatus.message}
</div>
)
))}
</div>
{/* End of error or success display */}
{/* Buttons Sections */}
<div className="py-1 grid grid-cols-1 xxs:grid-cols-3">
<div className="w-full col-span-3 col-start-1 xxs:col-span-2 xxs:col-start-2 flex justify-between items-center gap-4">
<button
type="button"
onClick={handleClearAll}
className="custom-btn border-gradient"
>
<span className="text-gradient">Clear</span>
</button>
{tab == "files" ? (
<button
onClick={sendFile}
type="button"
className="custom-btn btn-gradient text-white"
>
{requestStatus.loading ? (
<LoadingSpinner size="6" color="sky-blue" />
) : (
<>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
width="20"
height="20"
fill="white"
>
<path d="M12 2L2 12h3v8h14v-8h3L12 2zm0 16v-6h-2v6H7l5-5 5 5h-3z" />
</svg>
<span className="text-white">Upload Files</span>
</>
)}
</button>
) : (
<button
onClick={sendTaskMessage}
type="button"
className="custom-btn btn-gradient text-white"
>
{requestStatus.loading ? (
<LoadingSpinner size="6" color="sky-blue" />
) : (
<span className="text-white">Send</span>
)}
</button>
)}
</div>
</div>
{/* end of Buttons Sections */}
</div>
{/* END OF TEXTAREA */}
{/* MESSAGE SECTION */}
<div className="w-full p-4 bg-white dark:bg-black rounded-2xl shadow-md h-[400px]">
<div className='w-full h-full flex justify-center items-center text-5xl'>COMING SOON</div>
{/* <div className="flex justify-between items-center gap-5">
<p className="w-full text-lg font-bold text-dark-gray dark:text-white tracking-wide flex items-center gap-2 justify-between">
<span>Message</span>
<button
type="button"
onClick={popUpHandler}
className="text-[12px] tracking-wider text-gray-400 dark:text-slate-400"
>
View all
</button>
</p>
</div>
{props.activeJobMesList.loading ? (
<LoadingSpinner size="16" color="sky-blue" />
) : (
<ActiveJobMessageMedia activeJobMesList={props.activeJobMesList} />
)} */}
</div>
{/* END OF MESSAGE */}
</div>
</div>
</MediaLayout>
)
}
let Fallback = () => {
return (
<div className="w-full flex justify-center items-center">
<LoadingSpinner size='20' color='skyblue' height='h-screen max-h-[600px]' />
</div>
)
}
+22 -21
View File
@@ -125,27 +125,6 @@ function DeleteJobPopout({ details, onClose, situation }) {
<span className="job-label">Duration: </span>{details.timeline_days} day(s)
</p>
</div>
<div className="flex space-x-2.5">
<button
onClick={onClose}
type="button"
className=" border-gradient text-18 tracking-wide px-4 py-3 rounded-full"
>
<span className="text-gradient">Cancel</span>
</button>
{requestStatus.laoding ? (
<LoadingSpinner size="8" color="sky-blue" />
) : (
<button
onClick={() => deleteJob(details)}
type="button"
className="text-white primary-gradient text-18 tracking-wide px-4 py-3 rounded-full"
>
Confirm Delete
</button>
)}
</div>
{/* ERROR DISPLAY AND SUBMIT BUTTON */}
{requestStatus.message != "" &&
(!requestStatus.status ? (
@@ -165,6 +144,28 @@ function DeleteJobPopout({ details, onClose, situation }) {
))}
{/* End of error or success display */}
</div>
<div className="modal-footer-wrapper grid grid-cols-1 xxs:grid-cols-3">
<div className="w-full col-span-1 xxs:col-span-2 xxs:col-start-2 flex justify-between items-center">
<button
onClick={onClose}
type="button"
className="custom-btn border-gradient"
>
<span className="text-gradient">Cancel</span>
</button>
{requestStatus.laoding ? (
<LoadingSpinner size="8" color="sky-blue" />
) : (
<button
onClick={() => deleteJob(details)}
type="button"
className="custom-btn text-white primary-gradient"
>
Confirm Delete
</button>
)}
</div>
</div>
</div>
</ModalCom>
);
+230 -232
View File
@@ -242,7 +242,6 @@ const EditJobPopOut = ({
</svg>
</button>
</div>
<div className="logout-modal-body w-full flex flex-col items-center px-10 pb-8 pt-2">
<Formik
initialValues={initialValues}
validationSchema={validationSchema}
@@ -250,277 +249,276 @@ const EditJobPopOut = ({
>
{(props) => (
<Form className="w-full">
<div className="flex flex-col-reverse sm:flex-row">
<div className="fields w-full">
<div className="xl:flex xl:space-x-7 mb-[0.5rem]">
<div className="field w-full mb-6 xl:mb-0">
<div className="logout-modal-body w-full flex flex-col items-center px-10 pb-8 pt-2">
<div className="flex flex-col-reverse sm:flex-row">
<div className="fields w-full">
<div className="xl:flex xl:space-x-7 mb-[0.5rem]">
<div className="field w-full mb-6 xl:mb-0">
<InputCom
fieldClass="px-6 cursor-default"
label="Currency"
labelClass="tracking-wide"
inputBg="bg-slate-100"
inputClass="input-curve lg border border-light-purple"
type="text"
name="country"
value={props.values.country}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
disable={true}
/>
</div>
{/* Price */}
<div className="field w-full">
<InputCom
fieldClass="px-6 text-right"
label="Price"
labelClass="tracking-wide"
inputBg="bg-slate-100"
inputClass="input-curve lg border border-light-purple"
type="number"
name="price"
value={props.values.price}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
errorBorder={
props.errors.price && props.touched.price
}
/>
</div>
</div>
{/* Title */}
<div className="field w-full mb-[0.5rem]">
<InputCom
fieldClass="px-6 cursor-default"
label="Currency"
fieldClass="px-6"
label="Title"
labelClass="tracking-wide"
inputBg="bg-slate-100"
inputClass="input-curve lg border border-light-purple"
inputClass=" input-curve lg border border-light-purple"
type="text"
name="country"
value={props.values.country}
name="title"
value={props.values.title}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
disable={true}
errorBorder={props.errors.title && props.touched.title}
/>
</div>
{/* Price */}
<div className="field w-full">
{/* Description */}
<div className="field w-full mb-[0.5rem]">
<InputCom
fieldClass="px-6 text-right"
label="Price"
fieldClass="px-6"
label="Description"
labelClass="tracking-wide"
inputBg="bg-slate-100"
inputClass="input-curve lg border border-light-purple"
type="number"
name="price"
value={props.values.price}
inputClass=" input-curve lg border border-light-purple"
type="text"
name="description"
value={props.values.description}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
errorBorder={
props.errors.price && props.touched.price
props.errors.description && props.touched.description
}
/>
</div>
</div>
{/* Title */}
<div className="field w-full mb-[0.5rem]">
<InputCom
fieldClass="px-6"
label="Title"
labelClass="tracking-wide"
inputBg="bg-slate-100"
inputClass=" input-curve lg border border-light-purple"
type="text"
name="title"
value={props.values.title}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
errorBorder={props.errors.title && props.touched.title}
/>
</div>
{/* Description */}
<div className="field w-full mb-[0.5rem]">
<InputCom
fieldClass="px-6"
label="Description"
labelClass="tracking-wide"
inputBg="bg-slate-100"
inputClass=" input-curve lg border border-light-purple"
type="text"
name="description"
value={props.values.description}
inputHandler={props.handleChange}
blurHandler={props.handleBlur}
errorBorder={
props.errors.description && props.touched.description
}
/>
</div>
{/* Details */}
<div className="field flex flex-col sm:flex-row w-full mb-[5px] gap-2">
<div className="sm:w-[60%] w-full">
<label
htmlFor="job-label"
className='job-label'
>
Job Delivery Details
</label>
<textarea
id="Job Delivery Details"
rows="5"
className={`input-field px-6 py-2 placeholder:text-base text-dark-gray dark:text-white w-full h-[100px] bg-slate-100 dark:bg-[#11131F] focus:ring-0 focus:outline-[#dce4e9] ${
props.errors.job_detail && props.touched.job_detail
? "border-[#ff0a0a63] shadow-red-500 border-[0.5px] animate-shake"
: "border border-[#f5f8fa] dark:border-[#5e6278]"
} rounded-[10px]`}
style={{ resize: "none" }}
name="job_detail"
value={props.values.job_detail}
onChange={props.handleChange}
onBlur={props.handleBlur}
/>
</div>
<div className="sm:w-[35%] w-full">
<div
htmlFor="Job Categories"
className='job-label'
id="checked-group"
>
Categories
{/* Details */}
<div className="field flex flex-col sm:flex-row w-full mb-[5px] gap-2">
<div className="sm:w-[60%] w-full">
<label
htmlFor="job-label"
className='job-label'
>
Job Delivery Details
</label>
<textarea
id="Job Delivery Details"
rows="5"
className={`input-field px-6 py-2 placeholder:text-base text-dark-gray dark:text-white w-full h-[100px] bg-slate-100 dark:bg-[#11131F] focus:ring-0 focus:outline-[#dce4e9] ${
props.errors.job_detail && props.touched.job_detail
? "border-[#ff0a0a63] shadow-red-500 border-[0.5px] animate-shake"
: "border border-[#f5f8fa] dark:border-[#5e6278]"
} rounded-[10px]`}
style={{ resize: "none" }}
name="job_detail"
value={props.values.job_detail}
onChange={props.handleChange}
onBlur={props.handleBlur}
/>
</div>
<div
className="sm:flex-col flex flex-wrap px-3 mt-3"
role="group"
aria-labelledby="checked-group"
>
{categories &&
Object.entries(categories)?.map(([key, value]) => (
<label
key={key}
className="flex gap-1 w-full items-center dark:text-white"
>
<Field
type="checkbox"
name="category"
value={key}
/>
<span className="text-[13.975px]">{value}</span>
</label>
))}
<span className="h-5 text-sm italic text-[#cf3917]">
{props.errors.category &&
props.touched.category &&
"please select a category"}
</span>
</div>
</div>
</div>
<div className="w-full flex items-center gap-2 mb-2">
{/* FOR TASK IMAGE */}
<div className="w-1/2 relative max-h-[130px] min-h-[130px]">
<input
id="task_image"
className="hidden"
type="file"
accept="image/*"
onChange={taskImgChangeHandler}
/>
{taskImage ? (
<div className="w-full absolute -top-5">
<img
src={taskImage}
className="max-h-[150px] min-h-[150px] w-full object-cover"
alt="uploaded task"
/>
<span
onClick={() => setTaskImage("")}
className="p-2 absolute text-sm top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 bg-white/80 hover:bg-white hover:shadow-md transition-all duration-500 cursor-pointer text-slate-800"
>
Remove Image
<div className="sm:w-[35%] w-full">
<div
htmlFor="Job Categories"
className='job-label'
id="checked-group"
>
Categories
</div>
<div
className="sm:flex-col flex flex-wrap px-3 mt-3"
role="group"
aria-labelledby="checked-group"
>
{categories &&
Object.entries(categories)?.map(([key, value]) => (
<label
key={key}
className="flex gap-1 w-full items-center dark:text-white"
>
<Field
type="checkbox"
name="category"
value={key}
/>
<span className="text-[13.975px]">{value}</span>
</label>
))}
<span className="h-5 text-sm italic text-[#cf3917]">
{props.errors.category &&
props.touched.category &&
"please select a category"}
</span>
</div>
) : (
<label
className="absolute -top-5 h-[150px] w-full flex flex-col justify-center items-center bg-slate-100 dark:bg-[#11131F] cursor-pointer input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold"
htmlFor="task_image"
>
Select Task Image
</label>
)}
</div>
{/* END OF TASK IMAGE */}
<div className="field w-1/2">
<div className={`flex items-center justify-between`}>
<label
className="job-label flex flex-col"
htmlFor="timeline_days"
>
Timeline -
<span className="w-full text-center text-green-700 text-sm tracking-wide">
Expected duration of this task
</span>
</label>
</div>
<Field
component="select"
name="timeline_days"
className={`input-field p-2 mt-3 rounded-md placeholder:text-base text-dark-gray dark:text-white w-full h-10 bg-slate-100 dark:bg-[#11131F] focus:ring-0 focus:outline-none ${
props.errors.timeline_days &&
props.touched.timeline_days
? "border-[#ff0a0a63] shadow-red-500 border-[0.5px] animate-shake"
: "border border-[#f5f8fa] dark:border-[#5e6278]"
}`}
value={props.values.timeline_days}
>
<option value="">Select Duration</option>
{publicArray.map(({ name, duration }, idx) => (
<option
key={duration}
className="text-slate-500 text-lg"
value={duration}
</div>
<div className="w-full flex items-center gap-2 mb-2">
{/* FOR TASK IMAGE */}
<div className="w-1/2 relative max-h-[130px] min-h-[130px]">
<input
id="task_image"
className="hidden"
type="file"
accept="image/*"
onChange={taskImgChangeHandler}
/>
{taskImage ? (
<div className="w-full absolute -top-5">
<img
src={taskImage}
className="max-h-[150px] min-h-[150px] w-full object-cover"
alt="uploaded task"
/>
<span
onClick={() => setTaskImage("")}
className="p-2 absolute text-sm top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 bg-white/80 hover:bg-white hover:shadow-md transition-all duration-500 cursor-pointer text-slate-800"
>
Remove Image
</span>
</div>
) : (
<label
className="absolute -top-5 h-[150px] w-full flex flex-col justify-center items-center bg-slate-100 dark:bg-[#11131F] cursor-pointer input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold"
htmlFor="task_image"
>
{name}
</option>
))}
</Field>
Select Task Image
</label>
)}
</div>
{/* END OF TASK IMAGE */}
<div className="field w-1/2">
<div className={`flex items-center justify-between`}>
<label
className="job-label flex flex-col"
htmlFor="timeline_days"
>
Timeline -
<span className="w-full text-center text-green-700 text-sm tracking-wide">
Expected duration of this task
</span>
</label>
</div>
<Field
component="select"
name="timeline_days"
className={`input-field p-2 mt-3 rounded-md placeholder:text-base text-dark-gray dark:text-white w-full h-10 bg-slate-100 dark:bg-[#11131F] focus:ring-0 focus:outline-none ${
props.errors.timeline_days &&
props.touched.timeline_days
? "border-[#ff0a0a63] shadow-red-500 border-[0.5px] animate-shake"
: "border border-[#f5f8fa] dark:border-[#5e6278]"
}`}
value={props.values.timeline_days}
>
<option value="">Select Duration</option>
{publicArray.map(({ name, duration }, idx) => (
<option
key={duration}
className="text-slate-500 text-lg"
value={duration}
>
{name}
</option>
))}
</Field>
</div>
</div>
{/* inputs ends here */}
</div>
{/* inputs ends here */}
</div>
</div>
{/* ERROR DISPLAY AND SUBMIT BUTTON */}
<div className="content-footer w-full">
{/* error or success display */}
{requestStatus.message != "" &&
(!requestStatus.status ? (
<div
className={`relative p-4 my-4 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}
>
{requestStatus.message}
</div>
) : (
requestStatus.status && (
{/* ERROR DISPLAY AND SUBMIT BUTTON */}
<div className="content-footer w-full">
{/* error or success display */}
{requestStatus.message != "" &&
(!requestStatus.status ? (
<div
className={`relative p-4 my-4 text-green-700 bg-slate-200 border-slate-800 mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}
className={`relative p-4 my-4 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}
>
{requestStatus.message}
</div>
)
))}
{/* End of error or success display */}
{/* DISPLAYS TASK IMAGE UPLOADING STATUS */}
<div className="w-full">
{uploadStatus.message && !uploadStatus.loading && (
<p
className={`text-center ${
uploadStatus.status
? "text-green-500"
: "text-red-500"
}`}
>
{uploadStatus.message}
</p>
)}
{uploadStatus.loading && (
<p className="text-center">{uploadStatus.message}</p>
)}
</div>
<div className="w-full border-t border-light-purple dark:border-[#5356fb29] flex justify-end items-center">
<div className="flex items-center space-x-4 mr-2 mt-2">
{requestStatus.loading ? (
<LoadingSpinner size="6" color="sky-blue" />
) : (
<button
type="submit"
className="w-[120px] h-[40px] 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'
disabled={
requestStatus.loading || uploadStatus.loading
}
requestStatus.status && (
<div
className={`relative p-4 my-4 text-green-700 bg-slate-200 border-slate-800 mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}
>
{requestStatus.message}
</div>
)
))}
{/* End of error or success display */}
{/* DISPLAYS TASK IMAGE UPLOADING STATUS */}
<div className="w-full">
{uploadStatus.message && !uploadStatus.loading && (
<p
className={`text-center ${
uploadStatus.status
? "text-green-500"
: "text-red-500"
}`}
>
Save
</button>
{uploadStatus.message}
</p>
)}
{uploadStatus.loading && (
<p className="text-center">{uploadStatus.message}</p>
)}
</div>
</div>
</div>
<div className="modal-footer-wrapper justify-end">
{requestStatus.loading ? (
<LoadingSpinner size="6" color="sky-blue" />
) : (
<button
type="submit"
className="w-[120px] h-[40px] 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'
disabled={
requestStatus.loading || uploadStatus.loading
}
>
Save
</button>
)}
</div>
</Form>
)}
</Formik>
</div>
</div>
</ModalCom>
);
@@ -1,4 +1,4 @@
import React, { useState } from "react";
import React, { Suspense, lazy, useState } from "react";
import Detail from "./popoutcomponent/Detail";
import ModalCom from "../Helpers/ModalCom";
import { useNavigate } from "react-router-dom";
@@ -12,6 +12,9 @@ import { useDispatch } from "react-redux";
import { SocketValues } from "../Contexts/SocketIOContext";
const VideoElement = lazy(() => import("../VideoCom/VideoElement"));
const ImageElement = lazy(() => import("../ImageCon/ImageElement"));
function FamilyOfferJobPopout({ details, onClose, situation }) {
const {parentAssignJobToKid} = SocketValues()
@@ -118,8 +121,6 @@ function FamilyOfferJobPopout({ details, onClose, situation }) {
});
};
console.log(details)
return (
<ModalCom action={onClose} situation={situation}>
<div className="logout-modal-wrapper w-[90%] md:w-[768px] bg-white dark:bg-dark-white lg:rounded-2xl overflow-y-auto">
@@ -153,12 +154,9 @@ function FamilyOfferJobPopout({ details, onClose, situation }) {
</svg>
</button>
</div>
<div className="md:flex bg-white rounded-lg">
<div className="p-4 w-full md:w-3/4 md:border-r-2">
<div className="md:flex bg-white rounded-lg h-[450px] overflow-y-auto">
<div className="p-4 w-full md:w-3/5 md:border-r-2">
<div className="flex gap-2">
<div className="image-wrapper w-32">
<img className="w-full h-auto" src={details?.image} alt='banner' />
</div>
<div className="details-wrapper">
<p className="text-lg my-5 font-semibold text-slate-900 tracking-wide">
{details.title}
@@ -208,16 +206,39 @@ function FamilyOfferJobPopout({ details, onClose, situation }) {
</div>
{/* ACTION SECTION */}
<div className="p-4 w-full md:w-1/4 h-full">
<div className="p-4 w-full md:w-2/5 h-full flex flex-col justify-between">
{ details.job_type == 'TASK' ?
<div className="image-wrapper w-full h-40 flex justify-center items-center">
<Suspense fallback={<p className="w-full text-center">Loading...</p>}>
<ImageElement src={details?.image} alt='banner' className='w-auto h-full' />
</Suspense>
</div>
:
<div className="w-full flex justify-center">
<div className="w-full max-w-xs">
<Suspense fallback={<p className="w-full text-center">Loading...</p>}>
<VideoElement videoId={details.media_uid} />
</Suspense>
</div>
</div>
}
<div className="my-3 md:flex md:justify-center">
{requestStatus.loading && requestStatus.trigger == "offer" ? (
<LoadingSpinner size={8} color="sky-blue" />
) : (
<button
// <button
// name="accept"
// onClick={handleOffer}
// disabled={requestStatus.loading}
// className="px-2 py-2 w-20 flex justify-center items-center border-2 border-green-900 bg-green-500 text-base rounded-2xl text-white"
// >
// I am ready to start
// </button>
<button
name="accept"
onClick={handleOffer}
disabled={requestStatus.loading}
className="px-2 py-2 w-20 flex justify-center items-center border-2 border-green-900 bg-green-500 text-base rounded-2xl text-white"
className="btn-gradient text-white px-2 py-2 w-40 border-4 border-slate-300 text-lg lg:text-xl font-medium rounded-2xl"
>
I am ready to start
</button>
@@ -238,30 +259,19 @@ function FamilyOfferJobPopout({ details, onClose, situation }) {
</button>
)}
</div> */}
{/* ERROR DISPLAY AND SUBMIT BUTTON */}
{requestStatus.message != "" &&
(!requestStatus.status ? (
<div
className={`relative p-4 my-4 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}
>
{requestStatus.message}
</div>
) : (
requestStatus.status && (
<div
className={`relative p-4 my-4 text-green-700 bg-slate-200 border-slate-800 mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px] text-[13px]`}
>
{requestStatus.message}
</div>
)
))}
{/* End of error or success display */}
</div>
</div>
{/* close button */}
<div className="modal-footer-wrapper flex justify-end">
<div className="modal-footer-wrapper flex justify-between">
{/* ERROR DISPLAY AND SUBMIT BUTTON */}
<div
className={`relative text-md font-light leading-[19.5px] text-[13px] ${requestStatus.status ? 'text-green-700' : 'text-[#912741]'}`}
>
{requestStatus.message}
</div>
{/* End of error or success display */}
<button
onClick={onClose}
disabled={requestStatus.loading}
@@ -71,7 +71,9 @@ function PendingJobsPopout({ details, onClose, situation }) {
.pendingJobSendTome(reqData)
.then((res) => {
setRequestMessage({ status: true, message: res.data.status });
dispatch(tableReload({ type: "PENDINGTABLE" }));
setTimeout(() => {
onClose()
setPendingJobLoader({ extend: false, offer: false });
setRequestMessage({ status: false, message: "" });
}, 4000);
+4 -1
View File
@@ -174,7 +174,7 @@
/* modal footer */
.modal-footer-wrapper{
@apply py-2 px-4 border-t-2 flex justify-between items-center
@apply p-4 border-t-2 flex justify-between items-center
}
/* END OF STYLES FOR MODAL BOX */
@@ -182,6 +182,9 @@
.custom-btn {
@apply px-2 min-w-[80px] h-11 flex justify-center items-center text-base rounded-full cursor-pointer
}
.logout-btn {
@apply px-4 min-w-[80px] h-[52px] flex justify-center items-center text-base rounded-full cursor-pointer
}
}
/* ===================== EXTRA ===================== */
+67 -1
View File
@@ -1455,7 +1455,7 @@ class usersService {
"Access-Control-Allow-Origin": "*",
"Access-Control-Expose-Headers": "Access-Control-Allow-Origin",
"Access-Control-Allow-Headers":
"Origin, X-API-KEY, X-Requested-With, Content-Type, Accept, Access-Control-Request-Method, Access-Control-Allow-Headers, Authorization, observe, enctype, Content-Length, X-Csrf-Token",
"Origin, X-API-KEY, X-Requested-With, Content-Type, Accept, Access-Control-Request-Method, Access-Control-Allow-Headers, Authorization, observe, enctype, Content-Length, X-Csrf-Token",
"Content-Type": "application/json;charset=UTF-8",
},
};
@@ -1463,6 +1463,72 @@ class usersService {
// Axios.defaults.headers.post['Access-Control-Allow-Origin'] = '*'; //,axiosConfig
// Axios.defaults.withCredentials = true;
//debugger;
return Axios.post(endPoint, reqData)
.then((response) => {
console.log(response);
console.log("~~~~~~~ WrenchBoard::POST ~~~~~~~~");
if (response.data.internal_return == "-9999") {
localStorage.clear();
window.location.href = `/login?sessionExpired=true`;
}
return response;
})
.catch((error) => {
if (error.response) {
//response status is an error code
console.log(
"ERROR-------------------------------------------------------"
);
console.log(error.response.status);
console.log(
"ERROR-------------------------------------------------------"
);
} else if (error.request) {
//response not received though the request was sent
console.log(
"ERROR2-------------------------------------------------------"
);
console.log(error?.request);
console.log(
"ERROR2-------------------------------------------------------"
);
} else {
//an error occurred when setting up the request
console.log(
"ERROR3-------------------------------------------------------"
);
console.log(error);
console.log(
"ERROR3-------------------------------------------------------"
);
}
});
}
postAuxEnd_BROKE(uri, reqData) {
const endPoint = process.env.REACT_APP_USERS_ENDPOINT + uri;
const endPointKey = process.env.REACT_APP_ENDPOINT_KEY;
const session_token = localStorage.getItem("session_token");
// session_token = session_token !=null ?session_token : '';
// 'Authorization': `Basic ${(session_token !=null) ?session_token : ''}`,
let axiosConfig = {
headers: {
Accept: "application/json",
"Access-Control-Allow-Origin": "*",
"Access-Control-Expose-Headers": "Access-Control-Allow-Origin",
"Access-Control-Allow-Headers":
"Origin, X-API-KEY, X-Requested-With, Content-Type, Accept, Access-Control-Request-Method, Access-Control-Allow-Headers, Authorization, observe, enctype, Content-Length, X-Csrf-Token",
"Content-Type": "application/json;charset=UTF-8"
},
};
//,
// "x-api-key":`${endPointKey}`
// Axios.defaults.headers.post['Content-Type'] ='application/json;charset=utf-8';
// Axios.defaults.headers.post['Access-Control-Allow-Origin'] = '*'; //,axiosConfig
// Axios.defaults.withCredentials = true;
//debugger;
// Set default header. e.g, X-API-KEY
// Axios.defaults.headers['X-API-KEY'] = endPointKey;
return Axios.post(endPoint, reqData)
.then((response) => {
console.log(response);
+18 -3
View File
@@ -1,9 +1,24 @@
import React from 'react'
import FamGames from '../components/familyResources/FamGames'
import React, { lazy, Suspense } from 'react'
import LoadingSpinner from '../components/Spinners/LoadingSpinner';
// import FamGames from '../components/familyResources/FamGames'
const FamGames = lazy(() => import("../components/familyResources/FamGames"));
export default function FamGamesPage() {
return (
<>
<FamGames />
<Suspense fallback={<Fallback />}>
<FamGames />
</Suspense>
</>
)
}
let Fallback = () => {
return (
<div className="w-full flex justify-center items-center">
<LoadingSpinner size='20' color='skyblue' height='h-screen' />
</div>
)
}
+28 -2
View File
@@ -1,8 +1,12 @@
import React, { useEffect, useState } from "react";
import React, { lazy, Suspense, useEffect, useState } from "react";
import { useLocation, useNavigate } from "react-router-dom";
import ActiveJobs from "../components/MyActiveJobs/ActiveJobs";
// import ActiveJobsMedia from "../components/MyActiveJobs/ActiveJobsMedia";
import usersService from "../services/UsersService";
import { useSelector } from "react-redux";
import LoadingSpinner from "../components/Spinners/LoadingSpinner";
const ActiveJobsMedia = lazy(() => import("../components/MyActiveJobs/ActiveJobsMedia"));
/**
* This code defines a React functional component called `ManageActiveJobs`.
@@ -62,12 +66,34 @@ function ManageActiveJobs() {
}, [activeJobMesListReload, chatMessageList]);
return (
<ActiveJobs
<>
{details.job_type == 'MEDIA' ?
<Suspense fallback={<Fallback />}>
<ActiveJobsMedia
details={state}
activeJobMesList={activeJobMesList}
reloadActiveJobList={setActiveJobMesListReload}
/>
</Suspense>
: details.job_type == 'TASK' ?
<ActiveJobs
details={state}
activeJobMesList={activeJobMesList}
reloadActiveJobList={setActiveJobMesListReload}
/>
:
null
}
</>
);
}
export default ManageActiveJobs;
let Fallback = () => {
return (
<div className="w-full flex justify-center items-center">
<LoadingSpinner size='20' color='skyblue' height='h-screen' />
</div>
)
}