diff --git a/src/App.jsx b/src/App.jsx
index c50708b..43c9253 100644
--- a/src/App.jsx
+++ b/src/App.jsx
@@ -88,9 +88,12 @@ const App = () => {
if (location.pathname === "/earn/my-gigs" && isLoggedIn) {
if (!location.search) {
store.dispatch(actions.filter.updateGigFilter(initialGigFilter));
-
+ const cachedGigs = store.getState().myGigs[initialGigFilter.status];
+ if (cachedGigs.myGigs && cachedGigs.myGigs.length !== 0) {
+ return;
+ }
store.dispatch(
- actions.myGigs.getMyGigs(
+ actions.myGigs.getMyOpenGigs(
constants.GIGS_FILTER_STATUSES_PARAM[initialGigFilter.status]
)
);
@@ -98,23 +101,76 @@ const App = () => {
}
const params = utils.url.parseUrlQuery(location.search);
if (_.keys(params).length == 1 && params.externalId) {
+ store.dispatch(actions.myGigs.startCheckingGigs(params.externalId));
return;
}
+ const s =
+ _.values(constants.GIGS_FILTER_STATUSES).indexOf(params.status) >= 0
+ ? params.status
+ : null;
const updatedGigFilter = {
- status: params.status || "Open Applications",
+ status: s || "Open Applications",
};
const currentGig = store.getState().filter.gig;
const diff = !_.isEqual(updatedGigFilter, currentGig);
if (diff) {
store.dispatch(actions.filter.updateGigFilter(updatedGigFilter));
}
- getDataDebounced.current(() =>
- store.dispatch(
- actions.myGigs.getMyGigs(
- constants.GIGS_FILTER_STATUSES_PARAM[updatedGigFilter.status]
- )
- )
- );
+ if (updatedGigFilter.status !== initialGigFilter.status) {
+ // preload the open application first page data.
+ const cachedOpenGigs = store.getState().myGigs[initialGigFilter.status];
+ if (!cachedOpenGigs.myGigs) {
+ store.dispatch(
+ actions.myGigs.getMyOpenGigs(
+ constants.GIGS_FILTER_STATUSES_PARAM[initialGigFilter.status]
+ )
+ );
+ }
+ }
+ const cachedGigs = store.getState().myGigs[updatedGigFilter.status];
+ if (cachedGigs.myGigs) {
+ return;
+ }
+ getDataDebounced.current(() => {
+ if (
+ updatedGigFilter.status == constants.GIGS_FILTER_STATUSES.ACTIVE_JOBS
+ ) {
+ store.dispatch(
+ actions.myGigs.getMyActiveGigs(
+ constants.GIGS_FILTER_STATUSES_PARAM[updatedGigFilter.status]
+ )
+ );
+ }
+ if (
+ updatedGigFilter.status == constants.GIGS_FILTER_STATUSES.OPEN_JOBS
+ ) {
+ store.dispatch(
+ actions.myGigs.getMyOpenGigs(
+ constants.GIGS_FILTER_STATUSES_PARAM[updatedGigFilter.status]
+ )
+ );
+ }
+ if (
+ updatedGigFilter.status ==
+ constants.GIGS_FILTER_STATUSES.COMPLETED_JOBS
+ ) {
+ store.dispatch(
+ actions.myGigs.getMyCompletedGigs(
+ constants.GIGS_FILTER_STATUSES_PARAM[updatedGigFilter.status]
+ )
+ );
+ }
+ if (
+ updatedGigFilter.status ==
+ constants.GIGS_FILTER_STATUSES.ARCHIVED_JOBS
+ ) {
+ store.dispatch(
+ actions.myGigs.getMyArchivedGigs(
+ constants.GIGS_FILTER_STATUSES_PARAM[updatedGigFilter.status]
+ )
+ );
+ }
+ });
}
}, [location, isLoggedIn]);
diff --git a/src/actions/myGigs.js b/src/actions/myGigs.js
index 0c9c8c8..2e14a3c 100644
--- a/src/actions/myGigs.js
+++ b/src/actions/myGigs.js
@@ -6,24 +6,36 @@ import {
} from "../constants";
import service from "../services/myGigs";
-/**
- * Action to get my gigs.
- * @param {number} page page to fetch
- * @param {number} perPage items per page. by default is 10.
- * @returns
- */
-async function getMyGigs(status = "open_jobs", page = 1, perPage = PER_PAGE) {
+async function getMyActiveGigs(
+ status = "active_jobs",
+ page = 1,
+ perPage = PER_PAGE
+) {
return service.getMyGigs(status, page, perPage);
}
-/**
- * Action to load more pages of my gigs
- * @param {number} nextPage page to fetch
- * @param {*} perPage items per page. by default is 10
- * @returns
- */
-async function loadMoreMyGigs(status, nextPage, perPage = PER_PAGE) {
- return service.getMyGigs(status, nextPage, perPage);
+async function getMyOpenGigs(
+ status = "open_jobs",
+ page = 1,
+ perPage = PER_PAGE
+) {
+ return service.getMyGigs(status, page, perPage);
+}
+
+async function getMyCompletedGigs(
+ status = "completed_jobs",
+ page = 1,
+ perPage = PER_PAGE
+) {
+ return service.getMyGigs(status, page, perPage);
+}
+
+async function getMyArchivedGigsDone(
+ status = "archived_jobs",
+ page = 1,
+ perPage = PER_PAGE
+) {
+ return service.getMyGigs(status, page, perPage);
}
async function getProfile() {
@@ -54,8 +66,10 @@ async function startCheckingGigs(externalId) {
}
export default createActions({
- GET_MY_GIGS: getMyGigs,
- LOAD_MORE_MY_GIGS: loadMoreMyGigs,
+ GET_MY_ACTIVE_GIGS: getMyActiveGigs,
+ GET_MY_OPEN_GIGS: getMyOpenGigs,
+ GET_MY_COMPLETED_GIGS: getMyCompletedGigs,
+ GET_MY_ARCHIVED_GIGS: getMyArchivedGigsDone,
GET_PROFILE: getProfile,
UPDATE_PROFILE: updateProfile,
START_CHECKING_GIGS: startCheckingGigs,
diff --git a/src/api/common/helper.js b/src/api/common/helper.js
index 85729a4..3f36bbb 100644
--- a/src/api/common/helper.js
+++ b/src/api/common/helper.js
@@ -299,7 +299,7 @@ async function getJobCandidates(criteria) {
* @param {*} userId
* @returns
*/
-async function handlePlacedJobCandidates(jobCandidates, userId) {
+async function handlePlacedJobCandidates(jobCandidates, userId, userHandle) {
if (!jobCandidates || jobCandidates.length == 0 || !userId) {
return;
}
@@ -345,13 +345,71 @@ async function handlePlacedJobCandidates(jobCandidates, userId) {
new Date(rb.endDate).toDateString() != new Date().toDateString()
) {
jc.status = "completed";
+ jc.rbStartDate = rb.startDate;
+ jc.rbEndDate = rb.endDate;
+ jc.rbId = rb.id;
+ jc.userHandle = userHandle;
}
}
}
});
+ await getWorkingPeriods(jobCandidates, userHandle, rbRes);
return;
}
+/**
+ * Get payment Total for working period
+ *
+ * @param {*} jobCandidates job candidates we will process
+ * @param {*} userHandle the user's handle
+ * @param {*} resourceBookings the resource booking belongs to this user
+ * @returns
+ */
+async function getWorkingPeriods(jobCandidates, userHandle, resourceBookings) {
+ if (
+ !userHandle ||
+ !resourceBookings ||
+ resourceBookings.length == 0 ||
+ !jobCandidates ||
+ jobCandidates.length == 0
+ ) {
+ return;
+ }
+ const rbIds = resourceBookings.map((item) => item.id);
+ const token = await getM2MToken();
+ const url = `${config.API.V5}/work-periods`;
+ const criteria = {
+ userHandle: userHandle,
+ resourceBookingIds: rbIds.join(","),
+ };
+ const res = await request
+ .get(url)
+ .query(criteria)
+ .set("Authorization", `Bearer ${token}`)
+ .set("Accept", "application/json");
+ localLogger.debug({
+ context: "getWorkingPeriods",
+ message: `response body: ${JSON.stringify(res.body)}`,
+ });
+ if (res.body && res.body.length == 0) {
+ return;
+ }
+ // All the working periods for the rbs.
+ const wpRes = res.body;
+ _.each(rbIds, (rbId) => {
+ const wps = wpRes.filter(
+ (wp) => wp.userHandle == userHandle && wp.resourceBookingId == rbId
+ );
+ const paymentTotal = wps.reduce((total, wp) => total + wp.paymentTotal, 0);
+ const jc = jobCandidates.find(
+ (item) => item.rbId == rbId && item.userHandle == userHandle
+ );
+ if (jc) {
+ jc.paymentTotal = paymentTotal;
+ }
+ });
+}
+
/**
* Return jobs by given criteria
* @param {string} criteria the search criteria
diff --git a/src/api/docs/swagger.yaml b/src/api/docs/swagger.yaml
index 24ab579..3fd5238 100644
--- a/src/api/docs/swagger.yaml
+++ b/src/api/docs/swagger.yaml
@@ -273,6 +273,23 @@ components:
example: "Dummy title"
description: "The title."
maxLength: 64
+ paymentTotal:
+ type: integer
+ example: 20
+ description: "the amount of payment that a member has received for a completed job"
+ rbStartDate:
+ type: string
+ example: "2021-06-05"
+ description: "the official start time for a job"
+ rbEndDate:
+ type: string
+ example: "2021-07-05"
+ description: "the official end time for a job"
+ updatedAt:
+ type: string
+ format: date-time
+ example: "2021-06-21T03:57:17.774Z"
+ description: "The latest updated date time for a jobCandidate."
payment:
$ref: "#/components/schemas/Payment"
hoursPerWeek:
diff --git a/src/api/services/JobApplicationService.js b/src/api/services/JobApplicationService.js
index c44ef24..7d0d8db 100644
--- a/src/api/services/JobApplicationService.js
+++ b/src/api/services/JobApplicationService.js
@@ -30,12 +30,12 @@ async function getMyJobApplications(currentUser, criteria) {
return emptyResult;
}
// get user id by calling taas-api with current user's token
- const { id: userId } = await helper.getCurrentUserDetails(
+ const { id: userId, handle: userHandle } = await helper.getCurrentUserDetails(
currentUser.jwtToken
);
- if (!userId) {
+ if (!userId || !userHandle) {
throw new errors.NotFoundError(
- `Id for user: ${currentUser.userId} not found`
+ `Id for user: ${currentUser.userId} or handle for user: ${currentUser.handle} not found`
);
}
// get jobCandidates of current user by calling taas-api
@@ -54,7 +54,11 @@ async function getMyJobApplications(currentUser, criteria) {
let jcResult = jobCandidates.result;
// handle placed status for completed_jobs, archived_jobs query
if (status && (status == "active_jobs" || status == "completed_jobs")) {
- await helper.handlePlacedJobCandidates(jobCandidates.result, userId);
+ await helper.handlePlacedJobCandidates(
+ jobCandidates.result,
+ userId,
+ userHandle
+ );
if (status == "completed_jobs") {
jcResult = jobCandidates.result.filter(
(item) => item.status == "completed"
@@ -76,6 +80,10 @@ async function getMyJobApplications(currentUser, criteria) {
const job = _.find(jobs, ["id", jobCandidate.jobId]);
return {
title: job.title,
+ paymentTotal: jobCandidate.paymentTotal,
+ rbStartDate: jobCandidate.rbStartDate,
+ rbEndDate: jobCandidate.rbEndDate,
+ updatedAt: jobCandidate.updatedAt,
payment: {
min: job.minSalary,
max: job.maxSalary,
diff --git a/src/assets/images/completed.svg b/src/assets/images/completed.svg
new file mode 100644
index 0000000..8b63802
--- /dev/null
+++ b/src/assets/images/completed.svg
@@ -0,0 +1,11 @@
+
+
\ No newline at end of file
diff --git a/src/components/Empty/styles.scss b/src/components/Empty/styles.scss
index c2c49b6..84f4f2d 100644
--- a/src/components/Empty/styles.scss
+++ b/src/components/Empty/styles.scss
@@ -8,6 +8,7 @@
background-color: #ffffff;
padding: 81px 0px 330px 0px;
min-width: 650px;
+ min-height: 551px;
.empty-inner {
display: flex;
flex-direction: column;
diff --git a/src/constants/index.js b/src/constants/index.js
index 152179d..31c4635 100644
--- a/src/constants/index.js
+++ b/src/constants/index.js
@@ -353,10 +353,10 @@ export const SORT_STATUS_ORDER = [
MY_GIG_PHASE.PHONE_SCREEN,
MY_GIG_PHASE.SKILLS_TEST,
MY_GIG_PHASE.APPLIED,
+ MY_GIG_PHASE.WITHDRAWN,
MY_GIG_PHASE.JOB_CLOSED,
MY_GIG_PHASE.NOT_SELECTED,
MY_GIG_PHASE.COMPLETED,
- MY_GIG_PHASE.WITHDRAWN,
];
export const PER_PAGE = 10;
@@ -373,6 +373,8 @@ export const AVAILABLE_REMARK_BY_JOB_STATUS = [
MY_GIGS_JOB_STATUS.REJECTED_OTHER,
MY_GIGS_JOB_STATUS.REJECTED_PRE_SCREEN,
MY_GIGS_JOB_STATUS.JOB_CLOSED,
+ MY_GIGS_JOB_STATUS.WITHDRAWN,
+ MY_GIGS_JOB_STATUS.WITHDRAWN_PRESCREEN,
];
export const MY_GIG_STATUS_PLACED = "PLACED";
@@ -387,7 +389,8 @@ export const GIG_STATUS_TOOLTIP = {
};
export const MY_GIGS_STATUS_EMPTY_TEXT = {
- [GIGS_FILTER_STATUSES.ACTIVE_JOBS]: "YOU DON'T HAVE ANY ACTIVE GIGS YET.",
+ [GIGS_FILTER_STATUSES.ACTIVE_JOBS]:
+ "YOU ARE NOT ENGAGED IN ANY GIGS AT THE MOMENT.",
[GIGS_FILTER_STATUSES.OPEN_JOBS]:
"LOOKS LIKE YOU HAVEN'T APPLIED TO ANY GIG OPPORTUNITIES YET.",
[GIGS_FILTER_STATUSES.COMPLETED_JOBS]:
@@ -395,6 +398,14 @@ export const MY_GIGS_STATUS_EMPTY_TEXT = {
[GIGS_FILTER_STATUSES.ARCHIVED_JOBS]: "YOU DON'T HAVE ANY ARCHIVED GIGS YET.",
};
+export const MY_GIGS_STATUS_REMARK_TEXT = {
+ [MY_GIGS_JOB_STATUS.WITHDRAWN]:
+ "You withdrew your application for this gig or you have been placed in another gig.",
+ [MY_GIGS_JOB_STATUS.WITHDRAWN_PRESCREEN]:
+ "You withdrew your application for this gig or you have been placed in another gig.",
+ [MY_GIGS_JOB_STATUS.COMPLETED]: "Congrats on completing the gig!",
+};
+
export const CHECKING_GIG_TIMES = 3;
export const DELAY_CHECK_GIG_TIME = 2000;
diff --git a/src/containers/MyGigs/JobListing/JobCard/index.jsx b/src/containers/MyGigs/JobListing/JobCard/index.jsx
index 2828366..2da84b4 100644
--- a/src/containers/MyGigs/JobListing/JobCard/index.jsx
+++ b/src/containers/MyGigs/JobListing/JobCard/index.jsx
@@ -1,4 +1,4 @@
-import React, { useEffect, useRef, useState } from "react";
+import React, { useEffect, useRef, useState, useMemo } from "react";
import PT from "prop-types";
import ProgressBar from "./ProgressBar";
import Ribbon from "../../../../components/Ribbon";
@@ -6,14 +6,18 @@ import Button from "../../../../components/Button";
import IconChevronDown from "assets/icons/button-chevron-down.svg";
import ProgressTooltip from "./tooltips/ProgressTooltip";
import NoteTooltip from "./tooltips/NoteTooltip";
+import EarnTooltip from "./tooltips/EarnTooltip";
import {
MY_GIG_PHASE_LABEL,
MY_GIG_PHASE_ACTION,
MY_GIGS_JOB_STATUS,
PHASES_FOR_JOB_STATUS,
+ MY_GIGS_STATUS_REMARK_TEXT,
} from "../../../../constants";
import { formatMoneyValue } from "../../../../utils";
+import { getDateRange } from "../../../../utils/myGig";
import IconNote from "../../../../assets/icons/note.svg";
+import IconInfo from "../../../../assets/icons/ribbon-icon.svg";
import "./styles.scss";
@@ -30,108 +34,158 @@ const JobCard = ({ job }) => {
setFooterHeight(footerRef.current.offsetHeight);
}, [expanded]);
+ const paymentInfo = useMemo(() => {
+ if (job.paymentRangeFrom && job.paymentRangeTo && job.currency) {
+ return `${job.currency}
+ ${formatMoneyValue(job.paymentRangeFrom, "")}
+ ${" - "}
+ ${formatMoneyValue(job.paymentRangeTo, "")}
+ ${" (USD)"}
+ ${" / "}
+ ${job.paymentRangeRateType}`;
+ }
+ return "";
+ }, [
+ job.paymentRangeFrom,
+ job.paymentRangeTo,
+ job.currency,
+ job.paymentRangeRateType,
+ ]);
+
return (
-
-
-
-
-
-
-
- -
-
-
Payment Range
-
- {job.paymentRangeFrom &&
- job.paymentRangeTo &&
- job.currency && (
- <>
- {job.currency}
- {formatMoneyValue(job.paymentRangeFrom, "")}
- {" - "}
- {formatMoneyValue(job.paymentRangeTo, "")}
- {" (USD)"}
- {" / "}
- {job.paymentRangeRateType}
- >
- )}
+
+
+
+
{job.title}
+
+ -
+
+ {MY_GIGS_JOB_STATUS.COMPLETED === job.status && (
+ <>
+
Duration
+
+ {getDateRange(job.rbStartDate, job.rbEndDate)}
+
+ >
+ )}
+ {MY_GIGS_JOB_STATUS.COMPLETED !== job.status && (
+ <>
+
Payment Range
+
{paymentInfo}
+ >
+ )}
-
-
-
-
-
-
Location
-
{job.location}
-
-
-
-
-
-
Duration
-
- {job.duration && `${job.duration} Weeks`}
+
+
-
+
+ {MY_GIGS_JOB_STATUS.COMPLETED === job.status && (
+ <>
+
+ Total Earnings
+
+
+
+
+
+
+
{`${job.currency}${job.paymentTotal}`}
+ >
+ )}
+ {MY_GIGS_JOB_STATUS.COMPLETED !== job.status && (
+ <>
+
Location
+
{job.location}
+ >
+ )}
-
-
-
-
-
-
Hours
-
- {job.hours && `${job.hours} hours / week`}
+
+ {MY_GIGS_JOB_STATUS.COMPLETED !== job.status && (
+
-
+
+
Duration
+
+ {job.duration && `${job.duration} Weeks`}
+
+
+
+ )}
+
-
+
+
Hours
+
+ {job.hours && `${job.hours} hours / week`}
+
-
-
-
-
-
-
Working Hours
-
- {job.workingHours && `${job.workingHours} hours`}
+
+
-
+
+
Working Hours
+
+ {job.workingHours && `${job.workingHours} hours`}
+
-
-
-
-
-
- {job.phaseAction && }
+
+
+
+
+ {job.phaseAction && }
+
-
+
- {job.remark && (
+ {(job.remark ||
+ [
+ MY_GIGS_JOB_STATUS.WITHDRAWN,
+ MY_GIGS_JOB_STATUS.WITHDRAWN_PRESCREEN,
+ MY_GIGS_JOB_STATUS.COMPLETED,
+ ].includes(job.status)) && (
)}
-
{job.remark}
+
+ {[
+ MY_GIGS_JOB_STATUS.WITHDRAWN,
+ MY_GIGS_JOB_STATUS.WITHDRAWN_PRESCREEN,
+ MY_GIGS_JOB_STATUS.COMPLETED,
+ ].includes(job.status)
+ ? MY_GIGS_STATUS_REMARK_TEXT[job.status]
+ : job.remark}
+
{![
MY_GIGS_JOB_STATUS.JOB_CLOSED,
MY_GIGS_JOB_STATUS.REJECTED_OTHER,
diff --git a/src/containers/MyGigs/JobListing/JobCard/styles.scss b/src/containers/MyGigs/JobListing/JobCard/styles.scss
index c0f1523..b1a69f8 100644
--- a/src/containers/MyGigs/JobListing/JobCard/styles.scss
+++ b/src/containers/MyGigs/JobListing/JobCard/styles.scss
@@ -10,6 +10,7 @@
border-radius: $border-radius-lg;
box-shadow: $shadow;
z-index:0;
+ min-width: 780px;
}
.card-header {
@@ -53,7 +54,8 @@
.job-card {
&.label-selected,
&.label-offered,
- &.label-placed {
+ &.label-placed,
+ &.label-completed {
.job-card-content {
color: $white;
}
@@ -89,6 +91,23 @@
}
}
+ &.label-withdrawn {
+ :global(.ribbon) {
+ color: $white;
+ background: linear-gradient(221.5deg, #2A2A2A 0%, #555555 100%);
+ }
+ }
+
+ &.label-completed {
+ :global(.ribbon) {
+ color: $tc-black;
+ background: $tc-white;
+ }
+ .card-image {
+ background: url('https://github.com/assets/images/completed.svg') no-repeat right 24px center / auto, linear-gradient(52.91deg, #2984BD 0%, #50ADE8 100%);
+ }
+ }
+
&.label-not-selected {
:global(.ribbon) {
color: $white;
@@ -132,6 +151,19 @@
font-size: $font-size-xs;
color: $tc-gray-70;
line-height: $line-height-xs;
+
+ .earn-tip {
+ position: absolute;
+ line-height: 22px;
+
+ svg {
+ transform: scale(0.71);
+
+ path {
+ fill: currentColor
+ }
+ }
+ }
}
.text {
@@ -158,6 +190,7 @@
color: $tc-gray-70;
background-color: $gray1;
border-color: $gray2;
+ cursor: default;
}
}
diff --git a/src/containers/MyGigs/JobListing/JobCard/tooltips/EarnTooltip/index.jsx b/src/containers/MyGigs/JobListing/JobCard/tooltips/EarnTooltip/index.jsx
new file mode 100644
index 0000000..9fb1b06
--- /dev/null
+++ b/src/containers/MyGigs/JobListing/JobCard/tooltips/EarnTooltip/index.jsx
@@ -0,0 +1,25 @@
+import React from "react";
+import PT from "prop-types";
+import Tooltip from "../../../../../../components/Tooltip";
+
+import "./styles.scss";
+
+const EarnTooltip = ({ children }) => {
+ const Content = () => (
+
+ Amount may not reflect any pending payments
+
+ );
+
+ return (
+
} placement="bottom">
+ {children}
+
+ );
+};
+
+EarnTooltip.propTypes = {
+ children: PT.node,
+};
+
+export default EarnTooltip;
diff --git a/src/containers/MyGigs/JobListing/JobCard/tooltips/EarnTooltip/styles.scss b/src/containers/MyGigs/JobListing/JobCard/tooltips/EarnTooltip/styles.scss
new file mode 100644
index 0000000..1593d64
--- /dev/null
+++ b/src/containers/MyGigs/JobListing/JobCard/tooltips/EarnTooltip/styles.scss
@@ -0,0 +1,9 @@
+@import "https://github.com/styles/variables";
+
+.earn-tooltip {
+ width: 280px;
+ padding: 7px 10px;
+ line-height: $line-height-base;
+ font-size: 12px;
+ text-align: center;
+}
diff --git a/src/containers/MyGigs/JobListing/index.jsx b/src/containers/MyGigs/JobListing/index.jsx
index 8e5caa0..14608b6 100644
--- a/src/containers/MyGigs/JobListing/index.jsx
+++ b/src/containers/MyGigs/JobListing/index.jsx
@@ -7,9 +7,9 @@ import * as constants from "../../../constants";
import "./styles.scss";
-const JobListing = ({ jobs, loadMore, total, numLoaded, gigStatus }) => {
+const JobListing = ({ jobs, loadMore, total, numLoaded, gigStatus, page }) => {
const scrollLock = useScrollLock();
- const [page, setPage] = useState(1);
+ // const [page, setPage] = useState(1);
const varsRef = useRef();
varsRef.current = { scrollLock };
@@ -17,7 +17,7 @@ const JobListing = ({ jobs, loadMore, total, numLoaded, gigStatus }) => {
const handleLoadMoreClick = () => {
const nextPage = page + 1;
scrollLock(true);
- setPage(nextPage);
+ // setPage(nextPage);
loadMore(constants.GIGS_FILTER_STATUSES_PARAM[gigStatus], nextPage);
};
@@ -25,17 +25,40 @@ const JobListing = ({ jobs, loadMore, total, numLoaded, gigStatus }) => {
varsRef.current.scrollLock(false);
}, [jobs]);
- useEffect(() => {
- setPage(1);
- }, [gigStatus]);
-
+ // useEffect(() => {
+ // setPage(1);
+ // }, [gigStatus]);
return (
- {jobs.map((job, index) => (
-
-
-
- ))}
+ {![
+ constants.GIGS_FILTER_STATUSES.COMPLETED_JOBS,
+ constants.GIGS_FILTER_STATUSES.ARCHIVED_JOBS,
+ ].includes(gigStatus) &&
+ jobs.map((job, index) => (
+
+
+
+ ))}
+
+ {[
+ constants.GIGS_FILTER_STATUSES.COMPLETED_JOBS,
+ constants.GIGS_FILTER_STATUSES.ARCHIVED_JOBS,
+ ].includes(gigStatus) &&
+ jobs
+ .sort((a, b) => {
+ if (a.sortPrio == b.sortPrio) {
+ return (
+ new Date(b.updatedAt).getTime() -
+ new Date(a.updatedAt).getTime()
+ );
+ }
+ return a.sortPrio - b.sortPrio;
+ })
+ .map((job, index) => (
+
+
+
+ ))}
{numLoaded < total && page * constants.PER_PAGE < total && (
@@ -52,6 +75,7 @@ JobListing.propTypes = {
total: PT.number,
numLoaded: PT.number,
gigStatus: PT.string,
+ page: PT.number,
};
export default JobListing;
diff --git a/src/containers/MyGigs/index.jsx b/src/containers/MyGigs/index.jsx
index e30da7b..6c755b9 100644
--- a/src/containers/MyGigs/index.jsx
+++ b/src/containers/MyGigs/index.jsx
@@ -1,5 +1,5 @@
-import React, { useEffect, useRef, useState } from "react";
-import { useLocation } from "@reach/router";
+import React, { useEffect, useRef, useState, useCallback } from "react";
+// import { useLocation } from "@reach/router";
import PT from "prop-types";
import { connect } from "react-redux";
import Modal from "../../components/Modal";
@@ -8,7 +8,7 @@ import Loading from "../../components/Loading";
import Empty from "../../components/Empty";
import JobListing from "./JobListing";
import actions from "../../actions";
-import * as utils from "../../utils";
+import * as constants from "../../constants";
import UpdateGigProfile from "./modals/UpdateGigProfile";
import UpdateSuccess from "./modals/UpdateSuccess";
@@ -16,11 +16,10 @@ import UpdateSuccess from "./modals/UpdateSuccess";
import "./styles.scss";
const MyGigs = ({
- myGigs,
- getMyGigs,
- loadMore,
- total,
- numLoaded,
+ myActiveGigs,
+ myOpenGigs,
+ myCompletedGigs,
+ myArchivedGigs,
profile,
getProfile,
updateProfile,
@@ -29,26 +28,23 @@ const MyGigs = ({
checkingGigs,
startCheckingGigs,
gigStatus,
+ loadingMyGigs,
+ getMyActiveGigs,
+ getMyOpenGigs,
+ getMyCompletedGigs,
+ getMyArchivedGigs,
}) => {
- const location = useLocation();
- const params = utils.url.parseUrlQuery(location.search);
const propsRef = useRef();
propsRef.current = {
- getMyGigs,
+ getMyOpenGigs,
getProfile,
getAllCountries,
startCheckingGigs,
- params,
};
useEffect(() => {
propsRef.current.getProfile();
propsRef.current.getAllCountries();
- if (propsRef.current.params.externalId) {
- propsRef.current.startCheckingGigs(propsRef.current.params.externalId);
- } else {
- // propsRef.current.getMyGigs();
- }
}, []);
const isInitialMount = useRef(true);
@@ -58,12 +54,28 @@ const MyGigs = ({
return;
}
if (!checkingGigs) {
- propsRef.current.getMyGigs();
+ propsRef.current.getMyOpenGigs();
}
}, [checkingGigs]);
const [openUpdateProfile, setOpenUpdateProfile] = useState(false);
const [openUpdateSuccess, setOpenUpdateSuccess] = useState(false);
+ const [currentGigs, setCurrentGigs] = useState({});
+
+ useEffect(() => {
+ if (gigStatus == constants.GIGS_FILTER_STATUSES.ACTIVE_JOBS) {
+ setCurrentGigs(myActiveGigs);
+ }
+ if (gigStatus == constants.GIGS_FILTER_STATUSES.OPEN_JOBS) {
+ setCurrentGigs(myOpenGigs);
+ }
+ if (gigStatus == constants.GIGS_FILTER_STATUSES.COMPLETED_JOBS) {
+ setCurrentGigs(myCompletedGigs);
+ }
+ if (gigStatus == constants.GIGS_FILTER_STATUSES.ARCHIVED_JOBS) {
+ setCurrentGigs(myArchivedGigs);
+ }
+ }, [gigStatus, myActiveGigs, myOpenGigs, myCompletedGigs, myArchivedGigs]);
useEffect(() => {
if (updateProfileSuccess) {
@@ -73,6 +85,30 @@ const MyGigs = ({
}
}, [updateProfileSuccess]);
+ const currentLoadMore = useCallback(
+ (status, page) => {
+ if (gigStatus == constants.GIGS_FILTER_STATUSES.ACTIVE_JOBS) {
+ getMyActiveGigs(status, page);
+ }
+ if (gigStatus == constants.GIGS_FILTER_STATUSES.OPEN_JOBS) {
+ getMyOpenGigs(status, page);
+ }
+ if (gigStatus == constants.GIGS_FILTER_STATUSES.COMPLETED_JOBS) {
+ getMyCompletedGigs(status, page);
+ }
+ if (gigStatus == constants.GIGS_FILTER_STATUSES.ARCHIVED_JOBS) {
+ getMyArchivedGigs(status, page);
+ }
+ },
+ [
+ gigStatus,
+ getMyActiveGigs,
+ getMyOpenGigs,
+ getMyCompletedGigs,
+ getMyArchivedGigs,
+ ]
+ );
+
return (
<>
@@ -99,19 +135,25 @@ const MyGigs = ({
- {!checkingGigs && myGigs && myGigs.length == 0 && (
-
- )}
- {!checkingGigs && myGigs && myGigs.length > 0 && (
-
+ {!checkingGigs &&
+ !loadingMyGigs &&
+ currentGigs.myGigs &&
+ currentGigs.myGigs.length == 0 &&
}
+ {!checkingGigs &&
+ currentGigs.myGigs &&
+ currentGigs.myGigs.length > 0 && (
+
+ )}
+ {(checkingGigs || (loadingMyGigs && !currentGigs.myGigs)) && (
+
)}
- {checkingGigs &&
}
({
gigStatus: state.filter.gig.status,
checkingGigs: state.myGigs.checkingGigs,
- myGigs: state.myGigs.myGigs,
- total: state.myGigs.total,
- numLoaded: state.myGigs.numLoaded,
+ loadingMyGigs: state.myGigs.loadingMyGigs,
+ myActiveGigs: state.myGigs[constants.GIGS_FILTER_STATUSES.ACTIVE_JOBS],
+ myOpenGigs: state.myGigs[constants.GIGS_FILTER_STATUSES.OPEN_JOBS],
+ myCompletedGigs: state.myGigs[constants.GIGS_FILTER_STATUSES.COMPLETED_JOBS],
+ myArchivedGigs: state.myGigs[constants.GIGS_FILTER_STATUSES.ARCHIVED_JOBS],
profile: state.myGigs.profile,
updateProfileSuccess: state.myGigs.updatingProfileSucess,
});
const mapDispatchToProps = {
- getMyGigs: actions.myGigs.getMyGigs,
- loadMore: actions.myGigs.loadMoreMyGigs,
+ getMyActiveGigs: actions.myGigs.getMyActiveGigs,
+ getMyOpenGigs: actions.myGigs.getMyOpenGigs,
+ getMyCompletedGigs: actions.myGigs.getMyCompletedGigs,
+ getMyArchivedGigs: actions.myGigs.getMyArchivedGigs,
getProfile: actions.myGigs.getProfile,
updateProfile: actions.myGigs.updateProfile,
getAllCountries: actions.lookup.getAllCountries,
diff --git a/src/containers/MyGigs/modals/UpdateGigProfile/index.jsx b/src/containers/MyGigs/modals/UpdateGigProfile/index.jsx
index 851c744..7ee22bb 100644
--- a/src/containers/MyGigs/modals/UpdateGigProfile/index.jsx
+++ b/src/containers/MyGigs/modals/UpdateGigProfile/index.jsx
@@ -214,9 +214,7 @@ const UpdateGigProfile = ({
/>
-
-
-
+
diff --git a/src/containers/MyGigsFilter/GigsFilter/index.jsx b/src/containers/MyGigsFilter/GigsFilter/index.jsx
index c62f014..e65ed26 100644
--- a/src/containers/MyGigsFilter/GigsFilter/index.jsx
+++ b/src/containers/MyGigsFilter/GigsFilter/index.jsx
@@ -1,4 +1,4 @@
-import React from "react";
+import React, { useEffect, useRef } from "react";
import PT from "prop-types";
import _ from "lodash";
import RadioButton from "../../../components/RadioButton";
@@ -6,12 +6,35 @@ import * as utils from "../../../utils";
import "./styles.scss";
-const GigsFilter = ({ gigStatus, gigsStatuses, updateGigFilter }) => {
+const GigsFilter = ({
+ gigStatus,
+ gigsStatuses,
+ updateGigFilter,
+ openJobsCount,
+}) => {
const bucketOptions = utils.createRadioOptions(gigsStatuses, gigStatus);
+ const ref = useRef(null);
+
+ useEffect(() => {
+ if (!ref.current) {
+ return;
+ }
+
+ const openJobsElement = ref.current.children[0].children[1];
+ const badgeElement = utils.icon.createBadgeElement(
+ openJobsElement,
+ `${openJobsCount}`
+ );
+
+ return () => {
+ badgeElement.parentElement.removeChild(badgeElement);
+ };
+ }, [openJobsCount]);
+
return (
-
+
{
@@ -31,6 +54,7 @@ GigsFilter.propTypes = {
gigStatus: PT.string,
gigsStatuses: PT.arrayOf(PT.string),
updateGigFilter: PT.func,
+ openJobsCount: PT.number,
};
export default GigsFilter;
diff --git a/src/containers/MyGigsFilter/GigsFilter/styles.scss b/src/containers/MyGigsFilter/GigsFilter/styles.scss
index 7e538c4..327a793 100644
--- a/src/containers/MyGigsFilter/GigsFilter/styles.scss
+++ b/src/containers/MyGigsFilter/GigsFilter/styles.scss
@@ -25,4 +25,19 @@ $filter-padding-y: 3 * $base-unit;
margin: $base-unit 0;
}
}
+ :global {
+ .count-badge {
+ display: inline-block;
+ margin: -2px 0 0 $base-unit;
+ padding: 2px 5px 0;
+ font-weight: bold;
+ font-size: 11px;
+ line-height: 14px;
+ text-align: center;
+ color: white;
+ vertical-align: middle;
+ background: #EF476F;
+ border-radius: 13px;
+ }
+ }
}
diff --git a/src/containers/MyGigsFilter/index.jsx b/src/containers/MyGigsFilter/index.jsx
index 6e3dfcf..fa58450 100644
--- a/src/containers/MyGigsFilter/index.jsx
+++ b/src/containers/MyGigsFilter/index.jsx
@@ -5,8 +5,14 @@ import { connect } from "react-redux";
import GigsFilter from "./GigsFilter";
import actions from "../../actions";
import { updateQuery } from "../../utils/url";
+import * as constants from "../../constants";
-const MyGigsFilter = ({ gigStatus, gigsStatuses, updateGigFilter }) => {
+const MyGigsFilter = ({
+ gigStatus,
+ gigsStatuses,
+ updateGigFilter,
+ openJobsCount,
+}) => {
const location = useLocation();
const propsRef = useRef(null);
propsRef.current = { location };
@@ -16,6 +22,7 @@ const MyGigsFilter = ({ gigStatus, gigsStatuses, updateGigFilter }) => {
{
updateGigFilter(gigFilterChanged);
updateQuery(gigFilterChanged);
@@ -31,11 +38,13 @@ MyGigsFilter.propTypes = {
gigStatus: PT.string,
gigsStatuses: PT.arrayOf(PT.string),
updateGigFilter: PT.func,
+ openJobsCount: PT.number,
};
const mapStateToProps = (state) => ({
state: state,
gigStatus: state.filter.gig.status,
+ openJobsCount: state.myGigs[constants.GIGS_FILTER_STATUSES.OPEN_JOBS].total,
gigsStatuses: state.lookup.gigsStatuses,
});
diff --git a/src/reducers/myGigs.js b/src/reducers/myGigs.js
index c4c8e76..bb2bdd2 100644
--- a/src/reducers/myGigs.js
+++ b/src/reducers/myGigs.js
@@ -1,14 +1,34 @@
import { size, sortBy } from "lodash";
import { handleActions } from "redux-actions";
+import * as constants from "../constants";
const defaultState = {
loadingMyGigs: false,
loadingMyGigsError: null,
- myGigs: null,
- total: 0,
- numLoaded: 0,
- loadingMore: false,
- loadingMoreError: null,
+ [constants.GIGS_FILTER_STATUSES.ACTIVE_JOBS]: {
+ myGigs: null,
+ page: 1,
+ numLoaded: 0,
+ total: 0,
+ },
+ [constants.GIGS_FILTER_STATUSES.OPEN_JOBS]: {
+ myGigs: null,
+ page: 1,
+ numLoaded: 0,
+ total: 0,
+ },
+ [constants.GIGS_FILTER_STATUSES.COMPLETED_JOBS]: {
+ myGigs: null,
+ page: 1,
+ numLoaded: 0,
+ total: 0,
+ },
+ [constants.GIGS_FILTER_STATUSES.ARCHIVED_JOBS]: {
+ myGigs: null,
+ page: 1,
+ numLoaded: 0,
+ total: 0,
+ },
profile: {},
loadingProfile: false,
loadingProfileError: null,
@@ -18,48 +38,84 @@ const defaultState = {
checkingGigs: false,
};
-function onGetMyGigsInit(state) {
+function onGetMyActiveGigsInit(state) {
return { ...state, loadingMyGigs: true, loadingMyGigsError: null };
}
-function onGetMyGigsDone(state, { payload }) {
+function onGetMyActiveGigsDone(state, { payload }) {
+ const currentGigs =
+ state[constants.GIGS_FILTER_STATUSES.ACTIVE_JOBS].myGigs || [];
return {
...state,
- myGigs: sortBy(payload.myGigs, ["sortPrio"]),
- total: payload.total,
- numLoaded: payload.myGigs.length,
+ [constants.GIGS_FILTER_STATUSES.ACTIVE_JOBS]: {
+ myGigs: sortBy(currentGigs.concat(payload.myGigs), ["sortPrio"]),
+ total: payload.total,
+ numLoaded: currentGigs.length + payload.myGigs.length,
+ page: payload.page,
+ },
loadingMyGigs: false,
loadingMyGigsError: null,
};
}
-function onGetMyGigsFailure(state, { payload }) {
+function onGetMyOpenGigsInit(state) {
+ return { ...state, loadingMyGigs: true, loadingMyGigsError: null };
+}
+
+function onGetMyOpenGigsDone(state, { payload }) {
+ const currentGigs =
+ state[constants.GIGS_FILTER_STATUSES.OPEN_JOBS].myGigs || [];
return {
...state,
+ [constants.GIGS_FILTER_STATUSES.OPEN_JOBS]: {
+ myGigs: sortBy(currentGigs.concat(payload.myGigs), ["sortPrio"]),
+ total: payload.total,
+ numLoaded: currentGigs.length + payload.myGigs.length,
+ page: payload.page,
+ },
loadingMyGigs: false,
- loadingMyGigsError: payload,
- myGigs: null,
- total: 0,
- numLoaded: 0,
+ loadingMyGigsError: null,
};
}
-function onLoadMoreMyGigsInit(state) {
- return { ...state, loadingMore: true, loadingMoreError: null };
+function onGetMyCompletedGigsInit(state) {
+ return { ...state, loadingMyGigs: true, loadingMyGigsError: null };
}
-function onLoadMoreMyGigsDone(state, { payload: { myGigs } }) {
+function onGetMyCompletedGigsDone(state, { payload }) {
+ const currentGigs =
+ state[constants.GIGS_FILTER_STATUSES.COMPLETED_JOBS].myGigs || [];
return {
...state,
- myGigs: sortBy(state.myGigs.concat(myGigs), ["sortPrio"]),
- numLoaded: state.numLoaded + size(myGigs),
- loadingMore: false,
- loadingMoreError: null,
+ [constants.GIGS_FILTER_STATUSES.COMPLETED_JOBS]: {
+ myGigs: sortBy(currentGigs.concat(payload.myGigs), ["sortPrio"]),
+ total: payload.total,
+ numLoaded: currentGigs.length + payload.myGigs.length,
+ page: payload.page,
+ },
+ loadingMyGigs: false,
+ loadingMyGigsError: null,
};
}
-function onLoadMoreMyGigsFailure(state, { payload }) {
- return { ...state, loadingMore: false, loadingMoreError: payload };
+function onGetMyArchivedGigsInit(state) {
+ return { ...state, loadingMyGigs: true, loadingMyGigsError: null };
+}
+
+function onGetMyArchivedGigsDone(state, { payload }) {
+ const currentGigs =
+ state[constants.GIGS_FILTER_STATUSES.ARCHIVED_JOBS].myGigs || [];
+ return {
+ ...state,
+ [constants.GIGS_FILTER_STATUSES.ARCHIVED_JOBS]: {
+ myGigs: sortBy(currentGigs.concat(payload.myGigs), ["sortPrio"]),
+ total: payload.total,
+ numLoaded: currentGigs.length + payload.myGigs.length,
+ page: payload.page,
+ },
+ loadingMyGigs: false,
+ loadingMyGigsError: null,
+ };
}
function onGetProfileInit(state) {
@@ -128,12 +184,15 @@ function onCheckingGigsDone(state) {
export default handleActions(
{
- GET_MY_GIGS_INIT: onGetMyGigsInit,
- GET_MY_GIGS_DONE: onGetMyGigsDone,
- GET_MY_GIGS_FAILURE: onGetMyGigsFailure,
- LOAD_MORE_MY_GIGS_INIT: onLoadMoreMyGigsInit,
- LOAD_MORE_MY_GIGS_DONE: onLoadMoreMyGigsDone,
- LOAD_MORE_MY_GIGS_FAILURE: onLoadMoreMyGigsFailure,
+ GET_MY_ACTIVE_GIGS_INIT: onGetMyActiveGigsInit,
+ GET_MY_ACTIVE_GIGS_DONE: onGetMyActiveGigsDone,
+ GET_MY_OPEN_GIGS_INIT: onGetMyOpenGigsInit,
+ GET_MY_OPEN_GIGS_DONE: onGetMyOpenGigsDone,
+ GET_MY_COMPLETED_GIGS_INIT: onGetMyCompletedGigsInit,
+ GET_MY_COMPLETED_GIGS_DONE: onGetMyCompletedGigsDone,
+ GET_MY_ARCHIVED_GIGS_INIT: onGetMyArchivedGigsInit,
+ GET_MY_ARCHIVED_GIGS_DONE: onGetMyArchivedGigsDone,
+
GET_PROFILE_INIT: onGetProfileInit,
GET_PROFILE_DONE: onGetProfileDone,
GET_PROFILE_FAILURE: onGetProfileFailure,
diff --git a/src/services/myGigs.js b/src/services/myGigs.js
index 56e8cb6..ecbb41a 100644
--- a/src/services/myGigs.js
+++ b/src/services/myGigs.js
@@ -40,6 +40,10 @@ const mapMyGigsData = (serverResponse) => {
return {
label: (gigPhase || "").toUpperCase(),
title: myGig.title,
+ rbStartDate: myGig.rbStartDate || "",
+ rbEndDate: myGig.rbEndDate || "",
+ paymentTotal: myGig.paymentTotal || 0,
+ updatedAt: myGig.updatedAt || "",
jobExternalId: myGig.jobExternalId,
paymentRangeFrom: myGig.payment.min,
paymentRangeTo: myGig.payment.max,
@@ -92,6 +96,7 @@ async function getMyGigs(status, page, perPage) {
return {
myGigs: mapMyGigsData(response),
total: response.meta.total,
+ page: response.meta.page,
};
}
diff --git a/src/utils/icon.js b/src/utils/icon.js
index 1e00043..3dcced0 100644
--- a/src/utils/icon.js
+++ b/src/utils/icon.js
@@ -146,3 +146,29 @@ export function createBadgeElement(htmlElement, content) {
return badgeElement;
}
+
+// export function createCompanyLogo() {
+// return (
+//
+// )
+// }
\ No newline at end of file
diff --git a/src/utils/myGig.js b/src/utils/myGig.js
index efaa6d1..c8ef9b0 100644
--- a/src/utils/myGig.js
+++ b/src/utils/myGig.js
@@ -106,3 +106,18 @@ export function validatePhone(phoneNumber, country) {
return error ? error : null;
}
+
+export function getDateRange(startDate, endDate) {
+ const yearStart = new Date(startDate).getFullYear();
+ const yearEnd = new Date(endDate).getFullYear();
+ if (yearStart > yearEnd) {
+ return "";
+ }
+ const options = { month: "long", day: "numeric" };
+ const first = new Date(startDate).toLocaleDateString("en-us", options);
+ const second = new Date(endDate).toLocaleDateString("en-us", options);
+ if (yearStart == yearEnd) {
+ return `${first} - ${second}, ${yearStart}`;
+ }
+ return `${first}, ${yearStart} - ${second}, ${yearEnd}`;
+}