Compare commits

...

8 Commits

7 changed files with 310 additions and 273 deletions
+2 -2
View File
@@ -38,8 +38,8 @@ export default function LoginLayout({ slogan, children }) {
</div>
</div>
<div className="flex-1 flex justify-center items-center px-10 py-1">
<p className="text-black text-[15px] px-2 font-medium flex items-center">
<span className="text-3xl mt-2 mr-1">©</span> 2023 - {" "}
<p className="text-black text-[15px] px-2 font-medium flex items-center gap-1">
<span className="">&copy; {new Date().getFullYear()} -</span>
<Link to="/" className="text-[#009ef7] ml-1">
WrenchBoard
</Link>{" "}
+6 -6
View File
@@ -210,8 +210,8 @@ export default function Login() {
<div className="ml-7 flex justify-start items-center gap-3">
<button
name="full"
className={`login-type-btn px-4 py-1 rounded-t-2xl transition duration-200 ${
loginType=='full' ? "bg-white text-[#000] border-t-[2px]" : "bg-[#4687ba] text-white"
className={`login-type-btn px-4 py-1 rounded-t-2xl ${
loginType=='full' ? "bg-white text-[#000] border-t-[2px]" : "bg-[#4687ba] border-[2px] border-[#4687ba] text-white"
}`}
onClick={handleLoginType}
>
@@ -219,8 +219,8 @@ export default function Login() {
</button>
<button
name="family"
className={`login-type-btn px-4 py-1 rounded-t-2xl transition duration-200 ${
loginType=='family' ? "bg-white text-[#000] border-t-[2px]" : "bg-[#4687ba] text-white"
className={`login-type-btn px-4 py-1 rounded-t-2xl ${
loginType=='family' ? "bg-white text-[#000] border-t-[2px]" : "bg-[#4687ba] border-[2px] border-[#4687ba] text-white"
}`}
onClick={handleLoginType}
>
@@ -234,7 +234,7 @@ export default function Login() {
{
loginType == 'full' ? (
//user login component
<div className="p-2 input-area login-area border-2 rounded-2xl">
<div className="p-2 input-area login-area border-2 border-[#4687ba] rounded-2xl">
<div className="input-item mb-5">
<InputCom
labelClass="tracking-wider"
@@ -322,7 +322,7 @@ export default function Login() {
) : (
// END of user login compoenent
// family login compoenent
<div className="p-2 input-area login-area border-2 rounded-2xl">
<div className="p-2 input-area login-area border-2 border-[#4687ba] rounded-2xl">
<div className="input-item mb-5">
<InputCom
labelClass="tracking-wider"
+150 -195
View File
@@ -4,6 +4,7 @@ import facebookLogo from "../../../assets/images/facebook-4.svg";
import WrenchBoard from "../../../assets/images/wrenchboard.png";
import usersService from "../../../services/UsersService";
import InputCom from "../../Helpers/Inputs/InputCom";
import AuthLayout from "../AuthLayout";
export default function SignUp() {
const [signUpLoading, setSignUpLoading] = useState(false);
@@ -64,6 +65,13 @@ export default function SignUp() {
last_name !== "" &&
country !== ""
) {
//checks if email is a valid email address
let regEx = /^[^0-9][a-zA-Z0-9._%+-]+@[a-zA-Z]+(\.[a-zA-Z]+)+$/;
if (regEx.test(email) == false) {
setMsgError("Invalid Email");
return setTimeout(()=>{setMsgError("");},3000)
}
setSignUpLoading(true);
const reqData = {
country: country,
@@ -112,212 +120,159 @@ export default function SignUp() {
return (
<>
<div className="layout-wrapper login">
<div className="main-wrapper login-wrapper w-full xl:h-screen h-full xl:py-10 py-12 overflow-y-auto">
<div className=" h-full">
<div className="flex-1 flex justify-center items-center">
<div className="w-full">
<div className="mb-12">
<Link to="#">
<img
src={WrenchBoard}
alt="wrenchboard"
className="h-10 mx-auto"
/>
<AuthLayout slogan="Welcome to WrenchBoard">
<div className="w-full">
<div className="mb-5">
<Link to="#">
<img
src={WrenchBoard}
alt="wrenchboard"
className="h-10 mx-auto"
/>
</Link>
</div>
<div className="content-wrapper login shadow-md w-full lg:max-w-[500px] mx-auto flex justify-center items-center xl:bg-white dark:bg-dark-white 2xl:w-[828px] rounded-[0.475rem] sm:p-7 p-5 mb-0">
<div>
<div className="title-area flex flex-col justify-center items-center relative text-center mb-7">
<h1 className="text-[#181c32] font-semibold dark:text-white mb-3 leading-[27.3px] text-[22.75px]">
Create Account
</h1>
<span className="text-gray-400 font-medium text-[16.25px] leading-[24.375px]">
Already have an account?{" "}
<Link
to="/login"
className="font-semibold text-[#4687ba] hover:text-[#009ef7] transition"
>
Sign in here
</Link>
</span>
</div>
<div className="w-full flex items-center gap-2">
<div className="border-b border-[#eff2f5] max-w-[50%] w-full"></div>
<span className="text-[#b5b5c3] font-medium text-[0.7rem] w-[2%]">
OR
</span>
<div className="border-b border-[#eff2f5] max-w-[50%] w-full"></div>
</div>
<div className="input-area">
<SelectOption
label="Country"
data={countries}
name="country"
value={formData.country}
inputHandler={handleInputChange}
/>
<div className="input-fl-name mb-5 sm:flex w-full sm:space-x-6 ">
<div className="input-item sm:w-1/2 w-full mb-5 sm:mb-0">
<InputCom
fieldClass="px-6"
placeholder="Firstname"
label="First Name"
name="first_name"
type="text"
value={formData.first_name}
inputHandler={handleInputChange}
/>
</div>
<div className="input-item flex-1">
<InputCom
fieldClass="px-6"
placeholder="Lastname"
label="Last Name"
name="last_name"
type="text"
value={formData.last_name}
inputHandler={handleInputChange}
/>
</div>
</div>
<div className="content-wrapper login shadow-md w-full lg:max-w-[600px] mx-auto flex justify-center items-center xl:bg-white dark:bg-dark-white 2xl:w-[828px] rounded-[0.475rem] sm:p-7 p-5 mb-7">
<div>
<div className="title-area flex flex-col justify-center items-center relative text-center mb-7">
<h1 className="text-[#181c32] font-semibold dark:text-white mb-3 leading-[27.3px] text-[22.75px]">
Create Account
</h1>
<span className="text-gray-400 font-medium text-[16.25px] leading-[24.375px]">
Already have an account?{" "}
<Link
to="/login"
className="font-semibold text-[#4687ba] hover:text-[#009ef7] transition"
<div className="input-item mb-5">
<InputCom
fieldClass="px-6"
placeholder="support@mermsemr.com"
label="Email"
name="email"
type="email"
value={formData.email}
inputHandler={handleInputChange}
/>
</div>
<div className="input-item mb-5">
<InputCom
fieldClass="px-6"
placeholder="● ● ● ● ● ●"
label="Password"
name="password"
type={showPassword ? "text" : "password"}
onClick={togglePasswordVisibility}
passIcon={
showPassword ? "show-password" : "hide-password"
}
value={formData.password}
inputHandler={handleInputChange}
/>
</div>
{msgError && (
<div className="relative p-4 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px]">
{msgError}
</div>
)}
<div className="forgot-password-area flex justify-between items-center mb-6">
<div className="remember-checkbox flex items-center space-x-2.5">
<button
onClick={rememberMe}
type="button"
className="w-6 h-6 bg-[#4687ba] text-white flex justify-center items-center border border-light-gray rounded-[.45em]"
>
{checked && (
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-5 w-5"
viewBox="0 0 20 20"
fill="currentColor"
>
Sign in here
</Link>
</span>
</div>
{/*<button*/}
{/* type="button"*/}
{/* className={`rounded-[0.475rem] w-full mb-6 text-[15px] h-[42px] font-semibold text-[#009ef7] hover:text-white flex justify-center bg-[#f1faff] hover:bg-[#009ef7] transition-all duration-300 items-center py-[0.8875rem] px-[1.8125rem]`}*/}
{/*>*/}
{/* <img*/}
{/* className="mr-3 h-6"*/}
{/* src={facebookLogo}*/}
{/* alt="logo-icon(s)"*/}
{/* />*/}
{/* Sign in with Facebook*/}
{/*</button>*/}
<div className="w-full flex items-center gap-2">
<div className="border-b border-[#eff2f5] max-w-[50%] w-full"></div>
<span className="text-[#b5b5c3] font-medium text-[0.7rem] w-[2%]">
OR
</span>
<div className="border-b border-[#eff2f5] max-w-[50%] w-full"></div>
</div>
<div className="input-area">
<SelectOption
label="Country"
data={countries}
name="country"
value={formData.country}
inputHandler={handleInputChange}
/>
<div className="input-fl-name mb-5 sm:flex w-full sm:space-x-6 ">
<div className="input-item sm:w-1/2 w-full mb-5 sm:mb-0">
<InputCom
fieldClass="px-6"
placeholder="Firstname"
label="First Name"
name="first_name"
type="text"
value={formData.first_name}
inputHandler={handleInputChange}
<path
fillRule="evenodd"
d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z"
clipRule="evenodd"
/>
</div>
<div className="input-item flex-1">
<InputCom
fieldClass="px-6"
placeholder="Lastname"
label="Last Name"
name="last_name"
type="text"
value={formData.last_name}
inputHandler={handleInputChange}
/>
</div>
</div>
<div className="input-item mb-5">
<InputCom
fieldClass="px-6"
placeholder="support@mermsemr.com"
label="Email"
name="email"
type="email"
value={formData.email}
inputHandler={handleInputChange}
/>
</div>
<div className="input-item mb-5">
<InputCom
fieldClass="px-6"
placeholder="● ● ● ● ● ●"
label="Password"
name="password"
type={showPassword ? "text" : "password"}
onClick={togglePasswordVisibility}
passIcon={
showPassword ? "show-password" : "hide-password"
}
value={formData.password}
inputHandler={handleInputChange}
/>
</div>
{msgError && (
<div className="relative p-4 text-[#912741] bg-[#fcd9e2] border-[#fbc6d3] mb-4 rounded-[0.475rem] text-md font-light leading-[19.5px]">
{msgError}
</div>
</svg>
)}
<div className="forgot-password-area flex justify-between items-center mb-6">
<div className="remember-checkbox flex items-center space-x-2.5">
<button
onClick={rememberMe}
type="button"
className="w-6 h-6 bg-[#4687ba] text-white flex justify-center items-center border border-light-gray rounded-[.45em]"
>
{checked && (
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-5 w-5"
viewBox="0 0 20 20"
fill="currentColor"
>
<path
fillRule="evenodd"
d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z"
clipRule="evenodd"
/>
</svg>
)}
</button>
<span
onClick={rememberMe}
className="cursor-default text-dark-gray dark:text-white text-[15px]"
>
I agree with all
<Link
href="#"
className="text-base text-[#4687ba] hover:text-[#009ef7] mx-1 inline-block"
>
terms and condition
</Link>
</span>
</div>
</div>
<div className="signin-area mb-1">
<div className="flex justify-center">
<button
type="button"
onClick={handleSignUp}
className={`rounded-[0.475rem] mb-6 text-white flex justify-center bg-[#4687ba] hover:bg-[#009ef7] transition-all duration-300 items-center h-[42px] py-[0.8875rem] px-[1.81rem] text-[14.95px] btn-login`}
>
{signUpLoading ? (
<div className="signup btn-loader"></div>
) : (
<span>Sign Up</span>
)}
</button>
</div>
</div>
</div>
</button>
<span
onClick={rememberMe}
className="cursor-default text-dark-gray dark:text-white text-[15px]"
>
I agree with all
<Link
href="#"
className="text-base text-[#4687ba] hover:text-[#009ef7] mx-1 inline-block"
>
terms and condition
</Link>
</span>
</div>
</div>
<div className="signin-area mb-1">
<div className="flex justify-center">
<button
type="button"
onClick={handleSignUp}
className={`rounded-[0.475rem] mb-6 text-white flex justify-center bg-[#4687ba] hover:bg-[#009ef7] transition-all duration-300 items-center h-[42px] py-[0.8875rem] px-[1.81rem] text-[14.95px] btn-login`}
>
{signUpLoading ? (
<div className="signup btn-loader"></div>
) : (
<span>Sign Up</span>
)}
</button>
</div>
</div>
</div>
</div>
<div className="flex-1 flex justify-center items-center p-10">
<div className="flex items-center">
<a
href="https://www.wrenchboard.com/about-us"
className="text-[#a1a5b7] text-[15px] px-2 font-medium hover:text-[#009ef7]"
target="_blank"
rel="noreferrer"
>
About
</a>
<a
href="https://www.wrenchboard.com/service"
className="text-[#a1a5b7] text-[15px] px-2 font-medium hover:text-[#009ef7]"
target="_blank"
rel="noreferrer"
>
Services
</a>
<a
href="https://www.wrenchboard.com/contact"
className="text-[#a1a5b7] text-[15px] px-2 font-medium hover:text-[#009ef7]"
target="_blank"
rel="noreferrer"
>
Contact Us
</a>
</div>
</div>
<div className="flex-1 flex justify-center items-center p-10">
<p className="text-black text-[15px] px-2 font-medium flex items-center">
<span className="text-3xl mt-2 mr-1">©</span> 2023 -{" "}
<Link to="/" className="text-[#009ef7] ml-1">
WrenchBoard
</Link>{" "}
</p>
</div>
</div>
</div>
</div>
</AuthLayout>
</>
);
}
+17 -4
View File
@@ -19,6 +19,7 @@ import {
ProfileInfo,
FamilyPending,
} from "./Tabs";
import localImgLoad from "../../lib/localImgLoad";
export default function FamilyManageTabs({
className,
@@ -118,9 +119,7 @@ export default function FamilyManageTabs({
const tabs = [
{ id: 1, name: "Tasks" },
{ id: 2, name: "Waiting" },
{ id: 3, name: "Pending" },
{ id: 4, name: "Account" },
{ id: 5, name: "Profile" },
{ id: 3, name: "Pending" }
];
const [tab, setTab] = useState(tabs[0].name);
@@ -193,7 +192,7 @@ export default function FamilyManageTabs({
}
>
<div className="w-full h-full text-sm text-left text-gray-500 dark:text-gray-400 relative grid grid-cols-4 min-h-[520px]">
<div className="border-r border-[#E3E4FE] dark:border-[#a7a9b533] p-6 h-full">
<div className="border-r border-[#E3E4FE] dark:border-[#a7a9b533] p-6 h-full flex flex-col justify-between">
<ProfileInfo
profileImg={profileImg}
profileImgInput={profileImgInput}
@@ -201,6 +200,20 @@ export default function FamilyManageTabs({
browseProfileImg={browseProfileImg}
accountDetails={accountDetails}
/>
<div className="mt-4 flex justify-center items-center gap-2">
<button
onClick={() => tabHandler('Account')}
className="family-icon p-2 border-2 border-sky-blue rounded-2xl flex flex-col justify-between items-center">
<img src={localImgLoad('images/icons/account.svg')} className="w-[70px] h-[70px]" alt='Settings-Icon' />
<p className="mt-2 text-lg text-sky-blue">Account</p>
</button>
<button
onClick={() => tabHandler('Profile')}
className="family-icon p-2 border-2 border-sky-blue rounded-2xl flex flex-col justify-between items-center">
<img src={localImgLoad('images/icons/profile.svg')} className="w-[70px] h-[70px]" alt='Settings-Icon' />
<p className="mt-2 text-lg text-sky-blue">Profile</p>
</button>
</div>
</div>
<div className="col-span-3 justify-self-end h-full w-full">
<div className="flex flex-col w-full">
@@ -31,6 +31,19 @@ function AssignTaskPopout({ action, situation, familyDetails }) {
setActiveTask({ id, data });
};
// New Task
const [formState, setFormState] = useState({
// Initialize form state with desired fields
banner: "" || "default.jpg",
country: "" || "",
price: "" || "",
title: "" || "",
description: "" || "",
job_detail: "" || "",
timeline_days: "" || "",
category: [] || "",
});
const assignFamilyTask = () => {
setRequestStatus({ loading: true, status: false, message: "" });
let reqData = {};
@@ -54,46 +67,93 @@ function AssignTaskPopout({ action, situation, familyDetails }) {
job_description: activeTask.data?.description,
assign_mode: 110011,
};
}
apiCall
.assignFamilyTask(reqData)
.then((res) => {
if (res.status != 200 || res.data.internal_return < 0) {
setRequestStatus({
loading: false,
status: false,
message: "failed to assign task",
});
return setTimeout(() => {
setRequestStatus({ loading: false, status: false, message: "" });
}, 5000);
}
setRequestStatus({
loading: false,
status: true,
message: "action successful",
});
setTimeout(() => {
setRequestStatus({ loading: false, status: false, message: "" });
action(); // FUNCTION THAT CLOSES THE MODAL BOX
}, 5000);
})
.catch((err) => {
if (taskType === "new") {
const {
banner,
category,
country,
description,
job_detail,
price,
timeline_days,
title,
} = formState;
const requiredFields = [
banner,
category,
country,
description,
job_detail,
price,
timeline_days,
title,
];
if (requiredFields.some((field) => !field)) {
const emptyField = requiredFields.find((field) => !field);
setRequestStatus({
loading: false,
status: false,
message: `${emptyField} Empty`,
});
setTimeout(() => {
setRequestStatus({ loading: false, status: false, message: "" });
}, 3000);
return;
}
reqData = {
banner,
category,
country,
description,
job_detail,
price: price * 100,
timeline_days,
title,
assign_mode: 110055,
family_uid: familyDetails.uid,
};
}
apiCall
.assignFamilyTask(reqData)
.then((res) => {
if (res.status != 200 || res.data.internal_return < 0) {
setRequestStatus({
loading: false,
status: false,
message: "An Error occured, try again",
message: "failed to assign task",
});
setTimeout(() => {
return setTimeout(() => {
setRequestStatus({ loading: false, status: false, message: "" });
}, 5000);
}
setRequestStatus({
loading: false,
status: true,
message: "action successful",
});
}
if (taskType == "new") {
// RUNS HERE IF TASK TYPE IS NEW TASK
console.log("TESTING");
}
setTimeout(() => {
setRequestStatus({ loading: false, status: false, message: "" });
action(); // FUNCTION THAT CLOSES THE MODAL BOX
}, 5000);
})
.catch((err) => {
setRequestStatus({
loading: false,
status: false,
message: "An Error occured, try again",
});
setTimeout(() => {
setRequestStatus({ loading: false, status: false, message: "" });
}, 5000);
});
};
useEffect(() => {
@@ -120,16 +180,10 @@ function AssignTaskPopout({ action, situation, familyDetails }) {
});
}, []);
// New Task
const [newTaskData, setNewTaskData] = useState({})
const handleNewTaskData = (data) => {
setNewTaskData(data)
}
console.log("Trying to see form data >>", newTaskData)
console.log("Trying to see form data >>", formState);
return (
<>
<ModalCom action={action} situation={situation}>
<ModalCom action={action} situation={situation} className="assign-task-popup">
<div className="w-full h-full lg:w-[700px] lg:h-auto bg-white dark:bg-dark-white lg:rounded-2xl">
<div className="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">
@@ -231,9 +285,12 @@ function AssignTaskPopout({ action, situation, familyDetails }) {
)}
</div>
)}
{taskType !== "select" && (
{taskType == "new" && (
<div className="p-4 w-full h-[400px]">
<NewTasks onChange={handleNewTaskData} />
<NewTasks
formState={formState}
setFormState={setFormState}
/>
</div>
)}
</div>
@@ -335,7 +392,7 @@ function AssignTaskPopout({ action, situation, familyDetails }) {
<div className="">
{requestStatus.loading ? (
<LoadingSpinner color="sky-blue" size="8" />
) : (
) : taskType == "select" ? (
<button
type="button"
disabled={requestStatus.loading}
@@ -344,6 +401,15 @@ function AssignTaskPopout({ action, situation, familyDetails }) {
>
Assign
</button>
) : (
<button
type="button"
disabled={requestStatus.loading}
onClick={assignFamilyTask}
className="px-1 w-40 h-11 flex justify-center items-center btn-gradient text-base rounded-full text-white cursor-pointer"
>
{`Assign to ${familyDetails?.firstname}`}
</button>
)}
</div>
</div>
@@ -1,25 +1,16 @@
import React, { useEffect, useState } from "react";
import usersService from "../../../../services/UsersService";
import InputCom from "../../../Helpers/Inputs/InputCom";
import debounce from "../../../../hooks/debounce";
export default function NewTasks({ onChange }) {
const DEFAULT_IMAGE = require("../../../../assets/images/taskbanners/default.jpg");
export default function NewTasks({ formState, setFormState }) {
let [currency, setCurrency] = useState({
loading: true,
status: false,
data: null,
});
const [formState, setFormState] = useState({
// Initialize form state with desired fields
country: "",
price: "",
title: "",
description: "",
job_detail: "",
timeline_days: "",
category: [],
});
const ApiCall = new usersService();
// FUNCTION TO GET Currency
@@ -49,7 +40,6 @@ export default function NewTasks({ onChange }) {
...prevState,
[name]: value,
}));
onChange(formState); // Pass the form data to the parent on every change
};
useEffect(() => {
@@ -57,8 +47,8 @@ export default function NewTasks({ onChange }) {
}, []);
return (
<form className="w-full">
<div className="flex flex-col gap-3">
<form className="w-full flex justify-between items-center">
<div className="flex flex-col gap-3 max-w-[77%]">
{/* inputs starts here */}
<div className="grid md:grid-cols-3 grid-cols-1 gap-6 mb-[5px]">
{/* Currency */}
@@ -79,13 +69,13 @@ export default function NewTasks({ onChange }) {
// onBlur={props.handleBlur}
>
{currency.loading ? (
<option className="text-slate-500 text-lg" value="">
<option className="text-slate-500 text-[13.975px]" value="">
Loading...
</option>
) : currency.data.length ? (
<>
<option className="text-slate-500 text-lg" value="">
Select a currency
<option className="text-slate-500 text-[13.975px]" value="">
Currency
</option>
{currency.data?.map((item, index) => (
<option
@@ -141,11 +131,14 @@ export default function NewTasks({ onChange }) {
>
{publicArray.length && (
<>
<option className="text-slate-500 text-lg" value="">
Select Duration
<option className="text-slate-500 text-[13.975px]" value="">
Duration
</option>
{publicArray.map(({ name, duration }, idx) => (
<option className="text-slate-500 text-lg" value={duration}>
<option
className="text-slate-500 text-[13.975px]"
value={duration}
>
{name}
</option>
))}
@@ -210,6 +203,16 @@ export default function NewTasks({ onChange }) {
</div>
</div>
</div>
{/* Banner Image */}
<div className="max-w-[20%] w-full">
<div className="h-32 w-full">
<img
src={DEFAULT_IMAGE}
alt="task_banner_img"
className="w-full h-full object-contain"
/>
</div>
</div>
</form>
);
}
+2 -2
View File
@@ -939,6 +939,6 @@ TODO: Responsive ===========================
margin: 0;
}
.login-type-btn{
box-shadow: 0 0 0.8rem #00000080;
.assign-task-popup{
top: 75px;
}