Compare commits

...

5 Commits

5 changed files with 157 additions and 191 deletions
+11 -3
View File
@@ -13,7 +13,7 @@ const validationSchema = Yup.object().shape({
.max(25, "Maximum 25 characters") .max(25, "Maximum 25 characters")
.required("Country is required"), .required("Country is required"),
price: Yup.number() price: Yup.number()
.typeError("you must specify a number") .typeError("you must specify a number")
.min(1, "Price must be greater than 0") .min(1, "Price must be greater than 0")
.required("Price is required"), .required("Price is required"),
title: Yup.string() title: Yup.string()
@@ -36,7 +36,7 @@ const validationSchema = Yup.object().shape({
let initialValues = { // initial values for formik let initialValues = { // initial values for formik
country: '', country: '',
price: '', price: 0,
title: '', title: '',
description: '', description: '',
job_detail: '', job_detail: '',
@@ -137,8 +137,10 @@ function AddJob() {
<select <select
id='country' id='country'
name='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`} 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`}
onChange={props.handleChange} onChange={props.handleChange}
onBlur={props.handleBlur}
> >
{country.loading ? ( {country.loading ? (
<option className="text-slate-500 text-lg" value=""> <option className="text-slate-500 text-lg" value="">
@@ -179,11 +181,13 @@ function AddJob() {
label="Price" label="Price"
labelClass='tracking-wide' labelClass='tracking-wide'
inputBg = 'bg-slate-100' inputBg = 'bg-slate-100'
type="text" type="number"
name="price" name="price"
fieldClass='text-right'
// placeholder="Please Enter Amount" // placeholder="Please Enter Amount"
value={props.values.price} value={props.values.price}
inputHandler={props.handleChange} inputHandler={props.handleChange}
blurHandler={props.handleBlur}
/> />
{props.errors.price && props.touched.price && ( {props.errors.price && props.touched.price && (
<p className="text-sm text-red-500"> <p className="text-sm text-red-500">
@@ -206,6 +210,7 @@ function AddJob() {
// placeholder="Enter Job Title" // placeholder="Enter Job Title"
value={props.values.title} value={props.values.title}
inputHandler={props.handleChange} inputHandler={props.handleChange}
blurHandler={props.handleBlur}
/> />
{props.errors.title && props.touched.title && ( {props.errors.title && props.touched.title && (
<p className="text-sm text-red-500"> <p className="text-sm text-red-500">
@@ -226,6 +231,7 @@ function AddJob() {
// placeholder="Enter a description" // placeholder="Enter a description"
value={props.values.description} value={props.values.description}
inputHandler={props.handleChange} inputHandler={props.handleChange}
blurHandler={props.handleBlur}
/> />
{props.errors.description && props.touched.description && ( {props.errors.description && props.touched.description && (
<p className="text-sm text-red-500"> <p className="text-sm text-red-500">
@@ -258,6 +264,7 @@ function AddJob() {
name='job_detail' name='job_detail'
value={props.values.job_detail} value={props.values.job_detail}
onChange={props.handleChange} onChange={props.handleChange}
onBlur={props.handleBlur}
/> />
{props.errors.job_detail && props.touched.job_detail && ( {props.errors.job_detail && props.touched.job_detail && (
<p className="text-sm text-red-500"> <p className="text-sm text-red-500">
@@ -278,6 +285,7 @@ function AddJob() {
// placeholder="Please Enter Detail Description of Job" // placeholder="Please Enter Detail Description of Job"
value={props.values.timeline_days} value={props.values.timeline_days}
inputHandler={props.handleChange} inputHandler={props.handleChange}
blurHandler={props.handleBlur}
/> />
{props.errors.timeline_days && props.touched.timeline_days && ( {props.errors.timeline_days && props.touched.timeline_days && (
<p className="text-sm text-red-500"> <p className="text-sm text-red-500">
+41 -106
View File
@@ -20,119 +20,28 @@ export default function InputCom({
disable, disable,
blurHandler, blurHandler,
spanTag, spanTag,
inputBg inputBg,
direction
}) { }) {
const inputRef = useRef(null); const inputRef = useRef(null);
// Entry Validation // Entry Validation
// for Min Length: // for Min Length:
const minLengthValidation = () => { const minLengthValidation = () => {
if (inputRef && inputRef?.current && inputRef?.current?.name === "email") { const inputConfig = inputConfigs[inputRef?.current?.name]?.minLength;
return 7; return inputConfig || 0;
} else if (
inputRef &&
inputRef?.current &&
inputRef?.current?.name === "first_name"
) {
return 3;
} else if (
inputRef &&
inputRef?.current &&
inputRef?.current?.name === "last_name"
) {
return 3;
} else if (
inputRef &&
inputRef?.current &&
inputRef?.current?.name === "address"
) {
return 5;
} else if (
inputRef &&
inputRef?.current &&
inputRef?.current?.name === "password"
) {
return 8;
} else if (
inputRef &&
inputRef?.current &&
inputRef?.current?.name === "state"
) {
return 3;
} else if (
inputRef &&
inputRef?.current &&
inputRef?.current?.name === "province"
) {
return 3;
} else if (
inputRef &&
inputRef?.current &&
inputRef?.current?.name === "city"
) {
return 3;
} else if (
inputRef &&
inputRef?.current &&
inputRef?.current?.name === "amount"
) {
return 1;
}
}; };
// for MaxLength // for MaxLength
const maxLengthValidation = () => { const maxLengthValidation = () => {
if (inputRef && inputRef?.current && inputRef?.current?.name === "email") { const inputConfig = inputConfigs[inputRef?.current?.name]?.maxLength;
return 35; return inputConfig || 30;
} else if (
inputRef &&
inputRef?.current &&
inputRef?.current?.name === "first_name"
) {
return 25;
} else if (
inputRef &&
inputRef?.current &&
inputRef?.current?.name === "last_name"
) {
return 25;
} else if (
inputRef &&
inputRef?.current &&
inputRef?.current?.name === "address"
) {
return 49;
} else if (
inputRef &&
inputRef?.current &&
inputRef?.current?.name === "password"
) {
return 15;
} else if (
inputRef &&
inputRef?.current &&
inputRef?.current?.name === "state"
) {
return 25;
} else if (
inputRef &&
inputRef?.current &&
inputRef?.current?.name === "province"
) {
return 25;
} else if (
inputRef &&
inputRef?.current &&
inputRef?.current?.name === "city"
) {
return 25;
} else if (
inputRef &&
inputRef?.current &&
inputRef?.current?.name === "amount"
) {
return 9;
}
}; };
// for Patterns
const inputPatterns = () => {
const inputConfig = inputConfigs[inputRef?.current?.name]?.pattern;
return inputConfig || ""
}
return ( return (
<div className={`input-com ${parentClass}`}> <div className={`input-com ${parentClass}`}>
<div className={`flex items-center justify-between mb-2.5 ${labelClass}`}> <div className={`flex items-center justify-between mb-2.5 ${labelClass}`}>
@@ -140,9 +49,13 @@ export default function InputCom({
<label <label
className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold block" className="input-label text-[#181c32] dark:text-white text-[13.975px] leading-[20.9625px] font-semibold block"
htmlFor={name} htmlFor={name}
> >
{label} {label}
{spanTag && <span className="text-green-700 text-sm tracking-wide">{spanTag}</span>} {spanTag && (
<span className="text-green-700 text-sm tracking-wide">
{spanTag}
</span>
)}
</label> </label>
)} )}
{forgotPassword && ( {forgotPassword && (
@@ -161,15 +74,19 @@ export default function InputCom({
placeholder={placeholder} placeholder={placeholder}
value={value} value={value}
onChange={inputHandler} onChange={inputHandler}
className={`input-field placeholder:text-base text-bese px-12 text-dark-gray w-full h-full ${inputBg ? inputBg: 'bg-[#FAFAFA]'} dark:bg-[#11131F] focus:ring-0 focus:outline-none ${fieldClass}`} className={`input-field placeholder:text-base text-dark-gray w-full h-full ${
inputBg ? inputBg : "bg-[#FAFAFA]"
} dark:bg-[#11131F] focus:ring-0 focus:outline-none ${fieldClass}`}
type={type} type={type}
id={name} id={name}
name={name} name={name}
minLength={minLengthValidation()} minLength={minLengthValidation()}
maxLength={maxLengthValidation()} maxLength={maxLengthValidation()}
pattern={() => inputPatterns}
ref={inputRef} ref={inputRef}
readOnly={disable} readOnly={disable}
onBlur={blurHandler} onBlur={blurHandler}
dir={direction}
/> />
{iconName && ( {iconName && (
<div className="absolute right-6 bottom-[10px] z-10"> <div className="absolute right-6 bottom-[10px] z-10">
@@ -188,3 +105,21 @@ export default function InputCom({
</div> </div>
); );
} }
const inputConfigs = {
email: { minLength: 7, maxLength: 30 },
first_name: { minLength: 3, maxLength: 25, pattern: "[a-zA-Z]+" },
last_name: { minLength: 3, maxLength: 25, pattern: "[a-zA-Z]+" },
address: { minLength: 5, maxLength: 49, pattern: "[a-zA-Z0-9]+" },
password: { minLength: 8, maxLength: 15, pattern: ".{8,}" },
state: { minLength: 3, maxLength: 25, pattern: "[a-zA-Z]+" },
province: { minLength: 3, maxLength: 25, pattern: "[a-zA-Z]+" },
city: { minLength: 3, maxLength: 25, pattern: "[a-zA-Z]+" },
amount: { minLength: 1, maxLength: 9, pattern: "[0-9]+" },
};
/* Numbers Only: <input type="text" pattern="[0-9]*" /> strictly numbers
Alphabets Only: <input type="text" pattern="[a-zA-Z]+" /> strictly alphabets
Alphanumeric: <input type="text" pattern="[a-zA-Z0-9]+" /> mix
Password: <input type="text" pattern=".{8,}" /> a minimum of 8 characters
*/
+86 -78
View File
@@ -136,21 +136,25 @@ function TransferFund({ payment, wallet }) {
</h2> </h2>
) : wallet.error ? ( ) : wallet.error ? (
<h2 className="my-4 py-2 text-slate-900 dark:text-white text-xl lg:text-2xl font-medium"> <h2 className="my-4 py-2 text-slate-900 dark:text-white text-xl lg:text-2xl font-medium">
Opps! An Error Occured Opps! An Error Occurred
</h2> </h2>
) : ( ) : (
<h2 className="my-4 py-2 text-slate-900 dark:text-white text-xl lg:text-2xl font-medium"> <h2 className="my-4 py-2 text-slate-900 dark:text-white text-xl lg:text-2xl font-medium">
No Wallet Information Found! No Wallet Information Found!
</h2> </h2>
)} )}
<div className="xl:flex xl:space-x-7 mb-6"> <div className=" mb-6 gap-4 flex flex-col">
<div className="field w-full mb-6 xl:mb-0"> <div className="field w-full">
<InputCom <InputCom
fieldClass="px-6" fieldClass="px-4"
label="Amount" parentClass="flex items-center gap-1 justify-between"
type="text" labelClass="flex-[0.2] mb-0"
inputClass="flex-[0.8] max-w-[12rem]"
label="Amount:"
type="number"
name="amount" name="amount"
placeholder="0" placeholder="0"
direction="rtl"
value={props.values.amount} value={props.values.amount}
inputHandler={props.handleChange} inputHandler={props.handleChange}
blurHandler={(e) => { blurHandler={(e) => {
@@ -160,7 +164,7 @@ function TransferFund({ payment, wallet }) {
// onMouseLeave={(e)=>{getSendMoneyFee(e)}} // onMouseLeave={(e)=>{getSendMoneyFee(e)}}
/> />
{props.errors.amount && props.touched.amount && ( {props.errors.amount && props.touched.amount && (
<p className="text-sm text-red-500"> <p className="sm:text-sm text-[12px] text-red-500 sm:text-left text-right sm:translate-y-0 translate-y-1">
{props.errors.amount} {props.errors.amount}
</p> </p>
)} )}
@@ -168,25 +172,31 @@ function TransferFund({ payment, wallet }) {
<div className="field w-full"> <div className="field w-full">
<InputCom <InputCom
fieldClass="px-6" fieldClass="px-4 transfer-field"
label="Fee" parentClass="flex items-center gap-1 justify-between"
labelClass="flex-[0.2] mb-0"
inputClass="flex-[0.8] transfer-field max-w-[12rem]"
label="Fee:"
type="text" type="text"
name="fee" name="fee"
direction="rtl"
value={ value={
sendMoneyFee.loading ? "loading" : sendMoneyFee.fee sendMoneyFee.loading ? "loading" : sendMoneyFee.fee
} }
disable={true} disable={true}
/> />
</div> </div>
</div>
<div className="md:flex items-center justify-end"> <div className="field w-full mb-6">
<div className="field w-full lg:w-1/2 mb-6">
<InputCom <InputCom
fieldClass="px-6" fieldClass="px-4 transfer-field"
label="Total" parentClass="flex items-center gap-1 justify-between"
labelClass="flex-[0.2] mb-0"
inputClass="flex-[0.8] transfer-field max-w-[12rem]"
label="Total:"
type="text" type="text"
name="total" name="total"
direction="rtl"
value={ value={
sendMoneyFee.loading ? "loading" : sendMoneyFee.total sendMoneyFee.loading ? "loading" : sendMoneyFee.total
} }
@@ -197,87 +207,85 @@ function TransferFund({ payment, wallet }) {
<div className="w-full"> <div className="w-full">
<div className="relative my-3 md:flex items-center"> <div className="relative my-3 md:flex items-center">
<div className="transfer-input w-full"> <div className="transfer-input w-full flex items-start gap-1 justify-between">
<div className="flex items-center justify-start py-2"> <label className="text-[#181c32] dark:text-white text-base font-semibold block flex-[0.2] mb-0 mt-3">
<label className="text-[#181c32] dark:text-white text-base font-semibold block mb-2.5"> Recipient:
Recipient </label>
<span className="text-red-500 mx-2">*</span> <div className="flex flex-col gap-3 flex-[0.8] sm:items-start items-end">
<span <select
title="Transfer Recipient" className="sm:w-full w-48 text-base p-2 text-dark-gray dark:text-white rounded-md border border-slate-300 outline-0 flex-[0.8]"
className={`text-white text-sm bg-slate-500 w-1 h-1 rounded-full px-3 py-1 cursor-pointer`} value={props.values.recipientID}
> name="recipientID"
! onChange={props.handleChange}
</span> onBlur={props.handleBlur}
</label>
<Link
to="add-recipient"
className="mx-1 text-base text-white p-2 bg-[orange] rounded-md hover:opacity-80"
> >
Add New {recipients.loading ? (
</Link>
</div>
<select
className="w-full text-base p-2 text-dark-gray dark:text-white rounded-md border border-slate-300 outline-0"
value={props.values.recipientID}
name="recipientID"
onChange={props.handleChange}
onBlur={props.handleBlur}
>
{recipients.loading ? (
<option className="text-slate-500 text-lg" value="">
Loading...
</option>
) : recipients.data.length ? (
<>
<option <option
className="text-slate-500 text-lg" className="text-slate-500 text-lg"
value="" value=""
> >
Select... Loading...
</option> </option>
{recipients.data.map((item, index) => ( ) : recipients.data.length ? (
<>
<option <option
key={index}
value={item.recipient_id}
className="text-slate-500 text-lg" className="text-slate-500 text-lg"
value=""
> >
{item.recipient} Select...
</option> </option>
))} {recipients.data.map((item, index) => (
</> <option
) : recipients.error ? ( key={index}
<option className="text-slate-500 text-lg" value=""> value={item.recipient_id}
Could'nt Load, try again! className="text-slate-500 text-lg"
</option> >
) : ( {item.recipient}
<option className="text-slate-500 text-lg" value=""> </option>
No Recipient Found! Click Add to Add ))}
</option> </>
)} ) : recipients.error ? (
</select> <option
className="text-slate-500 text-lg"
value=""
>
Could'nt load, try again!
</option>
) : (
<option
className="text-slate-500 text-lg"
value=""
>
No Recipient Found!
</option>
)}
</select>
<div className="flex justify-end relative w-full">
{props.errors.recipientID &&
props.touched.recipientID && (
<p className="sm:text-sm text-[12px] text-red-500 absolute sm:top-1 -top-20 sm:left-0 left-[160px]">
{props.errors.recipientID}
</p>
)}
<Link
to="add-recipient"
className="mx-1 text-base text-white p-2 bg-[orange] rounded-md hover:opacity-80 max-w-[5rem]"
>
Add New
</Link>
</div>
</div>
</div> </div>
</div> </div>
{props.errors.recipientID && props.touched.recipientID && (
<p className="text-sm text-red-500">
{props.errors.recipientID}
</p>
)}
</div> </div>
<div className="field w-full mb-6"> <div className="field w-full mb-6 flex gap-1 justify-between">
{/* <InputCom fieldClass="px-6" <label className="text-[#181c32] dark:text-white text-base font-semibold flex flex-[0.2] mt-2.5">
label="Comment" Comment:
type="text"
name="comment"
value={inputs.comment}
inputHandler={handleChange}
/> */}
<label className="text-[#181c32] dark:text-white text-base font-semibold block mb-2.5">
Comment
</label> </label>
<textarea <textarea
style={{ resize: "none" }} style={{ resize: "none" }}
className="text-base px-6 text-dark-gray dark:text-white w-full bg-slate-100 dark:bg-[#11131F] focus:ring-0 focus:outline-none" className="text-base px-4 py-2 rounded-md min-h-[100px] sm:max-w-[550px] max-w-[250px] text-dark-gray dark:text-white w-full bg-slate-100 dark:bg-[#11131F] focus:ring-0 focus:outline-none flex-[0.8]"
name="comment" name="comment"
value={props.values.comment} value={props.values.comment}
onChange={props.handleChange} onChange={props.handleChange}
+7 -4
View File
@@ -10,14 +10,15 @@ function DeleteJobPopout({details, onClose, situation}) {
let [requestStatus, setRequestStatus] = useState({laoding: false, status:false, message: ''}) // STATE FOR KNOWING WHEN A REQUEST IS MADE TO THE SERVER let [requestStatus, setRequestStatus] = useState({laoding: false, status:false, message: ''}) // STATE FOR KNOWING WHEN A REQUEST IS MADE TO THE SERVER
// FUNCTION CALLED ONCE USER CONFIRM DELETE JOB
const deleteJob = (details) => { const deleteJob = (details) => {
setRequestStatus({laoding: true, status:false, message: ''}) setRequestStatus({laoding: true, status:false, message: ''})
const {job_id} = details
let reqData = { let reqData = {
job_id: details.job_id job_id: details.job_id,
job_uid: details.job_uid
} // DATA NEEDED BY THE API } // DATA NEEDED BY THE API
console.log(reqData)
// API CALL TO DELETE A JOB
ApiCall.deleteJob(reqData).then(res => { ApiCall.deleteJob(reqData).then(res => {
if(res.data.internal_return < 0){ if(res.data.internal_return < 0){
setRequestStatus({laoding: false, status:false, message: 'Could not perform the request, try again!'}) setRequestStatus({laoding: false, status:false, message: 'Could not perform the request, try again!'})
@@ -26,6 +27,8 @@ function DeleteJobPopout({details, onClose, situation}) {
setRequestStatus({laoding: false, status:true, message: 'Job deleted successfully'}) setRequestStatus({laoding: false, status:true, message: 'Job deleted successfully'})
setTimeout(()=>{ setTimeout(()=>{
navigate('/myjobs', {replace: true}) navigate('/myjobs', {replace: true})
onClose()
window.location.reload()
}, 1000) }, 1000)
}).catch(error => { }).catch(error => {
setRequestStatus({laoding: false, status:false, message: 'Opps! something went wrong, try again'}) setRequestStatus({laoding: false, status:false, message: 'Opps! something went wrong, try again'})
+12
View File
@@ -105,6 +105,11 @@ input::-webkit-inner-spin-button {
input[type="number"] { input[type="number"] {
-moz-appearance: textfield; -moz-appearance: textfield;
} }
input[type="text"][dir="rtl"] {
text-align: right;
}
.default-border-bottom { .default-border-bottom {
border-bottom: 1px solid #d3d2fe; border-bottom: 1px solid #d3d2fe;
} }
@@ -364,6 +369,13 @@ input[type="number"] {
margin: 0 16px; margin: 0 16px;
} }
.transfer-field, .transfer-field:focus, .transfer-field:focus-within{
background: #FFF !important;
border: none !important;
outline: none !important;
box-shadow: none !important;
}
/* the parent */ /* the parent */
.trending-products .slick-list { .trending-products .slick-list {
margin: 0 -16px; margin: 0 -16px;