Skip to content
This repository was archived by the owner on Mar 13, 2025. It is now read-only.
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit c56fb00

Browse files
authoredAug 10, 2021
Merge pull request #172 from topcoder-platform/dev
My Gigs 2nd Week PROD Release
2 parents 47e22a0 + 4d4d5c5 commit c56fb00

File tree

22 files changed

+722
-200
lines changed

22 files changed

+722
-200
lines changed
 

‎src/App.jsx

Lines changed: 66 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -88,33 +88,89 @@ const App = () => {
8888
if (location.pathname === "/earn/my-gigs" && isLoggedIn) {
8989
if (!location.search) {
9090
store.dispatch(actions.filter.updateGigFilter(initialGigFilter));
91-
91+
const cachedGigs = store.getState().myGigs[initialGigFilter.status];
92+
if (cachedGigs.myGigs && cachedGigs.myGigs.length !== 0) {
93+
return;
94+
}
9295
store.dispatch(
93-
actions.myGigs.getMyGigs(
96+
actions.myGigs.getMyOpenGigs(
9497
constants.GIGS_FILTER_STATUSES_PARAM[initialGigFilter.status]
9598
)
9699
);
97100
return;
98101
}
99102
const params = utils.url.parseUrlQuery(location.search);
100103
if (_.keys(params).length == 1 && params.externalId) {
104+
store.dispatch(actions.myGigs.startCheckingGigs(params.externalId));
101105
return;
102106
}
107+
const s =
108+
_.values(constants.GIGS_FILTER_STATUSES).indexOf(params.status) >= 0
109+
? params.status
110+
: null;
103111
const updatedGigFilter = {
104-
status: params.status || "Open Applications",
112+
status: s || "Open Applications",
105113
};
106114
const currentGig = store.getState().filter.gig;
107115
const diff = !_.isEqual(updatedGigFilter, currentGig);
108116
if (diff) {
109117
store.dispatch(actions.filter.updateGigFilter(updatedGigFilter));
110118
}
111-
getDataDebounced.current(() =>
112-
store.dispatch(
113-
actions.myGigs.getMyGigs(
114-
constants.GIGS_FILTER_STATUSES_PARAM[updatedGigFilter.status]
115-
)
116-
)
117-
);
119+
if (updatedGigFilter.status !== initialGigFilter.status) {
120+
// preload the open application first page data.
121+
const cachedOpenGigs = store.getState().myGigs[initialGigFilter.status];
122+
if (!cachedOpenGigs.myGigs) {
123+
store.dispatch(
124+
actions.myGigs.getMyOpenGigs(
125+
constants.GIGS_FILTER_STATUSES_PARAM[initialGigFilter.status]
126+
)
127+
);
128+
}
129+
}
130+
const cachedGigs = store.getState().myGigs[updatedGigFilter.status];
131+
if (cachedGigs.myGigs) {
132+
return;
133+
}
134+
getDataDebounced.current(() => {
135+
if (
136+
updatedGigFilter.status == constants.GIGS_FILTER_STATUSES.ACTIVE_JOBS
137+
) {
138+
store.dispatch(
139+
actions.myGigs.getMyActiveGigs(
140+
constants.GIGS_FILTER_STATUSES_PARAM[updatedGigFilter.status]
141+
)
142+
);
143+
}
144+
if (
145+
updatedGigFilter.status == constants.GIGS_FILTER_STATUSES.OPEN_JOBS
146+
) {
147+
store.dispatch(
148+
actions.myGigs.getMyOpenGigs(
149+
constants.GIGS_FILTER_STATUSES_PARAM[updatedGigFilter.status]
150+
)
151+
);
152+
}
153+
if (
154+
updatedGigFilter.status ==
155+
constants.GIGS_FILTER_STATUSES.COMPLETED_JOBS
156+
) {
157+
store.dispatch(
158+
actions.myGigs.getMyCompletedGigs(
159+
constants.GIGS_FILTER_STATUSES_PARAM[updatedGigFilter.status]
160+
)
161+
);
162+
}
163+
if (
164+
updatedGigFilter.status ==
165+
constants.GIGS_FILTER_STATUSES.ARCHIVED_JOBS
166+
) {
167+
store.dispatch(
168+
actions.myGigs.getMyArchivedGigs(
169+
constants.GIGS_FILTER_STATUSES_PARAM[updatedGigFilter.status]
170+
)
171+
);
172+
}
173+
});
118174
}
119175
}, [location, isLoggedIn]);
120176

‎src/actions/myGigs.js

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,36 @@ import {
66
} from "../constants";
77
import service from "../services/myGigs";
88

9-
/**
10-
* Action to get my gigs.
11-
* @param {number} page page to fetch
12-
* @param {number} perPage items per page. by default is 10.
13-
* @returns
14-
*/
15-
async function getMyGigs(status = "open_jobs", page = 1, perPage = PER_PAGE) {
9+
async function getMyActiveGigs(
10+
status = "active_jobs",
11+
page = 1,
12+
perPage = PER_PAGE
13+
) {
1614
return service.getMyGigs(status, page, perPage);
1715
}
1816

19-
/**
20-
* Action to load more pages of my gigs
21-
* @param {number} nextPage page to fetch
22-
* @param {*} perPage items per page. by default is 10
23-
* @returns
24-
*/
25-
async function loadMoreMyGigs(status, nextPage, perPage = PER_PAGE) {
26-
return service.getMyGigs(status, nextPage, perPage);
17+
async function getMyOpenGigs(
18+
status = "open_jobs",
19+
page = 1,
20+
perPage = PER_PAGE
21+
) {
22+
return service.getMyGigs(status, page, perPage);
23+
}
24+
25+
async function getMyCompletedGigs(
26+
status = "completed_jobs",
27+
page = 1,
28+
perPage = PER_PAGE
29+
) {
30+
return service.getMyGigs(status, page, perPage);
31+
}
32+
33+
async function getMyArchivedGigsDone(
34+
status = "archived_jobs",
35+
page = 1,
36+
perPage = PER_PAGE
37+
) {
38+
return service.getMyGigs(status, page, perPage);
2739
}
2840

2941
async function getProfile() {
@@ -54,8 +66,10 @@ async function startCheckingGigs(externalId) {
5466
}
5567

5668
export default createActions({
57-
GET_MY_GIGS: getMyGigs,
58-
LOAD_MORE_MY_GIGS: loadMoreMyGigs,
69+
GET_MY_ACTIVE_GIGS: getMyActiveGigs,
70+
GET_MY_OPEN_GIGS: getMyOpenGigs,
71+
GET_MY_COMPLETED_GIGS: getMyCompletedGigs,
72+
GET_MY_ARCHIVED_GIGS: getMyArchivedGigsDone,
5973
GET_PROFILE: getProfile,
6074
UPDATE_PROFILE: updateProfile,
6175
START_CHECKING_GIGS: startCheckingGigs,

‎src/api/common/helper.js

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ async function getJobCandidates(criteria) {
299299
* @param {*} userId
300300
* @returns
301301
*/
302-
async function handlePlacedJobCandidates(jobCandidates, userId) {
302+
async function handlePlacedJobCandidates(jobCandidates, userId, userHandle) {
303303
if (!jobCandidates || jobCandidates.length == 0 || !userId) {
304304
return;
305305
}
@@ -345,13 +345,71 @@ async function handlePlacedJobCandidates(jobCandidates, userId) {
345345
new Date(rb.endDate).toDateString() != new Date().toDateString()
346346
) {
347347
jc.status = "completed";
348+
jc.rbStartDate = rb.startDate;
349+
jc.rbEndDate = rb.endDate;
350+
jc.rbId = rb.id;
351+
jc.userHandle = userHandle;
348352
}
349353
}
350354
}
351355
});
356+
await getWorkingPeriods(jobCandidates, userHandle, rbRes);
352357
return;
353358
}
354359

360+
/**
361+
* Get payment Total for working period
362+
*
363+
* @param {*} jobCandidates job candidates we will process
364+
* @param {*} userHandle the user's handle
365+
* @param {*} resourceBookings the resource booking belongs to this user
366+
* @returns
367+
*/
368+
async function getWorkingPeriods(jobCandidates, userHandle, resourceBookings) {
369+
if (
370+
!userHandle ||
371+
!resourceBookings ||
372+
resourceBookings.length == 0 ||
373+
!jobCandidates ||
374+
jobCandidates.length == 0
375+
) {
376+
return;
377+
}
378+
const rbIds = resourceBookings.map((item) => item.id);
379+
const token = await getM2MToken();
380+
const url = `${config.API.V5}/work-periods`;
381+
const criteria = {
382+
userHandle: userHandle,
383+
resourceBookingIds: rbIds.join(","),
384+
};
385+
const res = await request
386+
.get(url)
387+
.query(criteria)
388+
.set("Authorization", `Bearer ${token}`)
389+
.set("Accept", "application/json");
390+
localLogger.debug({
391+
context: "getWorkingPeriods",
392+
message: `response body: ${JSON.stringify(res.body)}`,
393+
});
394+
if (res.body && res.body.length == 0) {
395+
return;
396+
}
397+
// All the working periods for the rbs.
398+
const wpRes = res.body;
399+
_.each(rbIds, (rbId) => {
400+
const wps = wpRes.filter(
401+
(wp) => wp.userHandle == userHandle && wp.resourceBookingId == rbId
402+
);
403+
const paymentTotal = wps.reduce((total, wp) => total + wp.paymentTotal, 0);
404+
const jc = jobCandidates.find(
405+
(item) => item.rbId == rbId && item.userHandle == userHandle
406+
);
407+
if (jc) {
408+
jc.paymentTotal = paymentTotal;
409+
}
410+
});
411+
}
412+
355413
/**
356414
* Return jobs by given criteria
357415
* @param {string} criteria the search criteria

‎src/api/docs/swagger.yaml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,23 @@ components:
273273
example: "Dummy title"
274274
description: "The title."
275275
maxLength: 64
276+
paymentTotal:
277+
type: integer
278+
example: 20
279+
description: "the amount of payment that a member has received for a completed job"
280+
rbStartDate:
281+
type: string
282+
example: "2021-06-05"
283+
description: "the official start time for a job"
284+
rbEndDate:
285+
type: string
286+
example: "2021-07-05"
287+
description: "the official end time for a job"
288+
updatedAt:
289+
type: string
290+
format: date-time
291+
example: "2021-06-21T03:57:17.774Z"
292+
description: "The latest updated date time for a jobCandidate."
276293
payment:
277294
$ref: "#/components/schemas/Payment"
278295
hoursPerWeek:

‎src/api/services/JobApplicationService.js

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,12 @@ async function getMyJobApplications(currentUser, criteria) {
3030
return emptyResult;
3131
}
3232
// get user id by calling taas-api with current user's token
33-
const { id: userId } = await helper.getCurrentUserDetails(
33+
const { id: userId, handle: userHandle } = await helper.getCurrentUserDetails(
3434
currentUser.jwtToken
3535
);
36-
if (!userId) {
36+
if (!userId || !userHandle) {
3737
throw new errors.NotFoundError(
38-
`Id for user: ${currentUser.userId} not found`
38+
`Id for user: ${currentUser.userId} or handle for user: ${currentUser.handle} not found`
3939
);
4040
}
4141
// get jobCandidates of current user by calling taas-api
@@ -54,7 +54,11 @@ async function getMyJobApplications(currentUser, criteria) {
5454
let jcResult = jobCandidates.result;
5555
// handle placed status for completed_jobs, archived_jobs query
5656
if (status && (status == "active_jobs" || status == "completed_jobs")) {
57-
await helper.handlePlacedJobCandidates(jobCandidates.result, userId);
57+
await helper.handlePlacedJobCandidates(
58+
jobCandidates.result,
59+
userId,
60+
userHandle
61+
);
5862
if (status == "completed_jobs") {
5963
jcResult = jobCandidates.result.filter(
6064
(item) => item.status == "completed"
@@ -76,6 +80,10 @@ async function getMyJobApplications(currentUser, criteria) {
7680
const job = _.find(jobs, ["id", jobCandidate.jobId]);
7781
return {
7882
title: job.title,
83+
paymentTotal: jobCandidate.paymentTotal,
84+
rbStartDate: jobCandidate.rbStartDate,
85+
rbEndDate: jobCandidate.rbEndDate,
86+
updatedAt: jobCandidate.updatedAt,
7987
payment: {
8088
min: job.minSalary,
8189
max: job.maxSalary,

‎src/assets/images/completed.svg

Lines changed: 11 additions & 0 deletions
Loading

‎src/components/Empty/styles.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
background-color: #ffffff;
99
padding: 81px 0px 330px 0px;
1010
min-width: 650px;
11+
min-height: 551px;
1112
.empty-inner {
1213
display: flex;
1314
flex-direction: column;

‎src/constants/index.js

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -353,10 +353,10 @@ export const SORT_STATUS_ORDER = [
353353
MY_GIG_PHASE.PHONE_SCREEN,
354354
MY_GIG_PHASE.SKILLS_TEST,
355355
MY_GIG_PHASE.APPLIED,
356+
MY_GIG_PHASE.WITHDRAWN,
356357
MY_GIG_PHASE.JOB_CLOSED,
357358
MY_GIG_PHASE.NOT_SELECTED,
358359
MY_GIG_PHASE.COMPLETED,
359-
MY_GIG_PHASE.WITHDRAWN,
360360
];
361361

362362
export const PER_PAGE = 10;
@@ -373,6 +373,8 @@ export const AVAILABLE_REMARK_BY_JOB_STATUS = [
373373
MY_GIGS_JOB_STATUS.REJECTED_OTHER,
374374
MY_GIGS_JOB_STATUS.REJECTED_PRE_SCREEN,
375375
MY_GIGS_JOB_STATUS.JOB_CLOSED,
376+
MY_GIGS_JOB_STATUS.WITHDRAWN,
377+
MY_GIGS_JOB_STATUS.WITHDRAWN_PRESCREEN,
376378
];
377379
export const MY_GIG_STATUS_PLACED = "PLACED";
378380

@@ -387,14 +389,23 @@ export const GIG_STATUS_TOOLTIP = {
387389
};
388390

389391
export const MY_GIGS_STATUS_EMPTY_TEXT = {
390-
[GIGS_FILTER_STATUSES.ACTIVE_JOBS]: "YOU DON'T HAVE ANY ACTIVE GIGS YET.",
392+
[GIGS_FILTER_STATUSES.ACTIVE_JOBS]:
393+
"YOU ARE NOT ENGAGED IN ANY GIGS AT THE MOMENT.",
391394
[GIGS_FILTER_STATUSES.OPEN_JOBS]:
392395
"LOOKS LIKE YOU HAVEN'T APPLIED TO ANY GIG OPPORTUNITIES YET.",
393396
[GIGS_FILTER_STATUSES.COMPLETED_JOBS]:
394397
"YOU DON'T HAVE ANY COMPLETED GIGS YET.",
395398
[GIGS_FILTER_STATUSES.ARCHIVED_JOBS]: "YOU DON'T HAVE ANY ARCHIVED GIGS YET.",
396399
};
397400

401+
export const MY_GIGS_STATUS_REMARK_TEXT = {
402+
[MY_GIGS_JOB_STATUS.WITHDRAWN]:
403+
"You withdrew your application for this gig or you have been placed in another gig.",
404+
[MY_GIGS_JOB_STATUS.WITHDRAWN_PRESCREEN]:
405+
"You withdrew your application for this gig or you have been placed in another gig.",
406+
[MY_GIGS_JOB_STATUS.COMPLETED]: "Congrats on completing the gig!",
407+
};
408+
398409
export const CHECKING_GIG_TIMES = 3;
399410

400411
export const DELAY_CHECK_GIG_TIME = 2000;

‎src/containers/MyGigs/JobListing/JobCard/index.jsx

Lines changed: 130 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,23 @@
1-
import React, { useEffect, useRef, useState } from "react";
1+
import React, { useEffect, useRef, useState, useMemo } from "react";
22
import PT from "prop-types";
33
import ProgressBar from "./ProgressBar";
44
import Ribbon from "../../../../components/Ribbon";
55
import Button from "../../../../components/Button";
66
import IconChevronDown from "assets/icons/button-chevron-down.svg";
77
import ProgressTooltip from "./tooltips/ProgressTooltip";
88
import NoteTooltip from "./tooltips/NoteTooltip";
9+
import EarnTooltip from "./tooltips/EarnTooltip";
910
import {
1011
MY_GIG_PHASE_LABEL,
1112
MY_GIG_PHASE_ACTION,
1213
MY_GIGS_JOB_STATUS,
1314
PHASES_FOR_JOB_STATUS,
15+
MY_GIGS_STATUS_REMARK_TEXT,
1416
} from "../../../../constants";
1517
import { formatMoneyValue } from "../../../../utils";
18+
import { getDateRange } from "../../../../utils/myGig";
1619
import IconNote from "../../../../assets/icons/note.svg";
20+
import IconInfo from "../../../../assets/icons/ribbon-icon.svg";
1721

1822
import "./styles.scss";
1923

@@ -30,108 +34,158 @@ const JobCard = ({ job }) => {
3034
setFooterHeight(footerRef.current.offsetHeight);
3135
}, [expanded]);
3236

37+
const paymentInfo = useMemo(() => {
38+
if (job.paymentRangeFrom && job.paymentRangeTo && job.currency) {
39+
return `${job.currency}
40+
${formatMoneyValue(job.paymentRangeFrom, "")}
41+
${" - "}
42+
${formatMoneyValue(job.paymentRangeTo, "")}
43+
${" (USD)"}
44+
${" / "}
45+
${job.paymentRangeRateType}`;
46+
}
47+
return "";
48+
}, [
49+
job.paymentRangeFrom,
50+
job.paymentRangeTo,
51+
job.currency,
52+
job.paymentRangeRateType,
53+
]);
54+
3355
return (
3456
<div
3557
styleName={`card job-card ${
3658
job.label === MY_GIG_PHASE_LABEL.SELECTED ? "label-selected" : ""
3759
} ${job.label === MY_GIG_PHASE_LABEL.OFFERED ? "label-offered" : ""} ${
3860
job.label === MY_GIG_PHASE_LABEL.PLACED ? "label-placed" : ""
61+
} ${
62+
job.label === MY_GIG_PHASE_LABEL.WITHDRAWN ? "label-withdrawn" : ""
63+
} ${
64+
job.label === MY_GIG_PHASE_LABEL.COMPLETED ? "label-completed" : ""
3965
} ${
4066
job.label === MY_GIG_PHASE_LABEL.NOT_SELECTED
4167
? "label-not-selected"
4268
: ""
4369
}`}
4470
>
45-
<div styleName="card-header job-card-header">
46-
<div styleName="ribbon">
47-
<Ribbon
48-
text={job.label}
49-
tooltip={({ children }) => (
50-
<ProgressTooltip job={job}>{children}</ProgressTooltip>
51-
)}
52-
/>
71+
<a href={`${process.env.URL.BASE}/gigs/${job.jobExternalId}`}>
72+
<div styleName="card-header job-card-header">
73+
<div styleName="ribbon">
74+
<Ribbon
75+
text={job.label}
76+
tooltip={({ children }) => (
77+
<ProgressTooltip job={job}>{children}</ProgressTooltip>
78+
)}
79+
/>
80+
</div>
5381
</div>
54-
</div>
55-
<div styleName="card-body">
56-
<div styleName="job-card-content">
57-
<div styleName="content">
58-
<h4 styleName="title">
59-
<a
60-
href={`${process.env.URL.BASE}/gigs/${job.jobExternalId}`} // eslint-disable-line no-undef
61-
>
62-
{job.title}
63-
</a>
64-
</h4>
65-
<ul styleName="job-items">
66-
<li>
67-
<div styleName="job-item">
68-
<div styleName="caption">Payment Range</div>
69-
<div styleName="text">
70-
{job.paymentRangeFrom &&
71-
job.paymentRangeTo &&
72-
job.currency && (
73-
<>
74-
{job.currency}
75-
{formatMoneyValue(job.paymentRangeFrom, "")}
76-
{" - "}
77-
{formatMoneyValue(job.paymentRangeTo, "")}
78-
{" (USD)"}
79-
{" / "}
80-
{job.paymentRangeRateType}
81-
</>
82-
)}
82+
<div styleName="card-body">
83+
<div styleName="job-card-content">
84+
<div styleName="content">
85+
<h4 styleName="title">{job.title}</h4>
86+
<ul styleName="job-items">
87+
<li>
88+
<div styleName="job-item">
89+
{MY_GIGS_JOB_STATUS.COMPLETED === job.status && (
90+
<>
91+
<div styleName="caption">Duration</div>
92+
<div styleName="text">
93+
{getDateRange(job.rbStartDate, job.rbEndDate)}
94+
</div>
95+
</>
96+
)}
97+
{MY_GIGS_JOB_STATUS.COMPLETED !== job.status && (
98+
<>
99+
<div styleName="caption">Payment Range</div>
100+
<div styleName="text">{paymentInfo}</div>
101+
</>
102+
)}
83103
</div>
84-
</div>
85-
</li>
86-
<li>
87-
<div styleName="job-item">
88-
<div styleName="caption">Location</div>
89-
<div styleName="text">{job.location}</div>
90-
</div>
91-
</li>
92-
<li>
93-
<div styleName="job-item">
94-
<div styleName="caption">Duration</div>
95-
<div styleName="text">
96-
{job.duration && `${job.duration} Weeks`}
104+
</li>
105+
<li>
106+
<div styleName="job-item">
107+
{MY_GIGS_JOB_STATUS.COMPLETED === job.status && (
108+
<>
109+
<div styleName="caption">
110+
<span>Total Earnings</span>
111+
<span styleName="earn-tip">
112+
<EarnTooltip>
113+
<IconInfo />
114+
</EarnTooltip>
115+
</span>
116+
</div>
117+
<div styleName="text">{`${job.currency}${job.paymentTotal}`}</div>
118+
</>
119+
)}
120+
{MY_GIGS_JOB_STATUS.COMPLETED !== job.status && (
121+
<>
122+
<div styleName="caption">Location</div>
123+
<div styleName="text">{job.location}</div>
124+
</>
125+
)}
97126
</div>
98-
</div>
99-
</li>
100-
<li>
101-
<div styleName="job-item">
102-
<div styleName="caption">Hours</div>
103-
<div styleName="text">
104-
{job.hours && `${job.hours} hours / week`}
127+
</li>
128+
{MY_GIGS_JOB_STATUS.COMPLETED !== job.status && (
129+
<li>
130+
<div styleName="job-item">
131+
<div styleName="caption">Duration</div>
132+
<div styleName="text">
133+
{job.duration && `${job.duration} Weeks`}
134+
</div>
135+
</div>
136+
</li>
137+
)}
138+
<li>
139+
<div styleName="job-item">
140+
<div styleName="caption">Hours</div>
141+
<div styleName="text">
142+
{job.hours && `${job.hours} hours / week`}
143+
</div>
105144
</div>
106-
</div>
107-
</li>
108-
<li>
109-
<div styleName="job-item">
110-
<div styleName="caption">Working Hours</div>
111-
<div styleName="text">
112-
{job.workingHours && `${job.workingHours} hours`}
145+
</li>
146+
<li>
147+
<div styleName="job-item">
148+
<div styleName="caption">Working Hours</div>
149+
<div styleName="text">
150+
{job.workingHours && `${job.workingHours} hours`}
151+
</div>
113152
</div>
114-
</div>
115-
</li>
116-
</ul>
117-
</div>
118-
<div
119-
styleName={`right-side stand-by ${!job.phaseAction ? "none" : ""}`}
120-
>
121-
{job.phaseAction && <Button size="lg">{job.phaseAction}</Button>}
153+
</li>
154+
</ul>
155+
</div>
156+
<div
157+
styleName={`right-side stand-by ${
158+
!job.phaseAction ? "none" : ""
159+
}`}
160+
>
161+
{job.phaseAction && <Button size="lg">{job.phaseAction}</Button>}
162+
</div>
122163
</div>
123164
</div>
124-
</div>
165+
</a>
125166
<div styleName="card-footer job-card-footer" ref={footerRef}>
126167
<div styleName="note-container">
127-
{job.remark && (
168+
{(job.remark ||
169+
[
170+
MY_GIGS_JOB_STATUS.WITHDRAWN,
171+
MY_GIGS_JOB_STATUS.WITHDRAWN_PRESCREEN,
172+
MY_GIGS_JOB_STATUS.COMPLETED,
173+
].includes(job.status)) && (
128174
<NoteTooltip>
129175
<i styleName="icon">
130176
<IconNote />
131177
</i>
132178
</NoteTooltip>
133179
)}
134-
<span styleName="note">{job.remark}</span>
180+
<span styleName="note">
181+
{[
182+
MY_GIGS_JOB_STATUS.WITHDRAWN,
183+
MY_GIGS_JOB_STATUS.WITHDRAWN_PRESCREEN,
184+
MY_GIGS_JOB_STATUS.COMPLETED,
185+
].includes(job.status)
186+
? MY_GIGS_STATUS_REMARK_TEXT[job.status]
187+
: job.remark}
188+
</span>
135189
{![
136190
MY_GIGS_JOB_STATUS.JOB_CLOSED,
137191
MY_GIGS_JOB_STATUS.REJECTED_OTHER,

‎src/containers/MyGigs/JobListing/JobCard/styles.scss

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
border-radius: $border-radius-lg;
1111
box-shadow: $shadow;
1212
z-index:0;
13+
min-width: 780px;
1314
}
1415

1516
.card-header {
@@ -53,7 +54,8 @@
5354
.job-card {
5455
&.label-selected,
5556
&.label-offered,
56-
&.label-placed {
57+
&.label-placed,
58+
&.label-completed {
5759
.job-card-content {
5860
color: $white;
5961
}
@@ -89,6 +91,23 @@
8991
}
9092
}
9193

94+
&.label-withdrawn {
95+
:global(.ribbon) {
96+
color: $white;
97+
background: linear-gradient(221.5deg, #2A2A2A 0%, #555555 100%);
98+
}
99+
}
100+
101+
&.label-completed {
102+
:global(.ribbon) {
103+
color: $tc-black;
104+
background: $tc-white;
105+
}
106+
.card-image {
107+
background: url('../../../../assets/images/completed.svg') no-repeat right 24px center / auto, linear-gradient(52.91deg, #2984BD 0%, #50ADE8 100%);
108+
}
109+
}
110+
92111
&.label-not-selected {
93112
:global(.ribbon) {
94113
color: $white;
@@ -132,6 +151,19 @@
132151
font-size: $font-size-xs;
133152
color: $tc-gray-70;
134153
line-height: $line-height-xs;
154+
155+
.earn-tip {
156+
position: absolute;
157+
line-height: 22px;
158+
159+
svg {
160+
transform: scale(0.71);
161+
162+
path {
163+
fill: currentColor
164+
}
165+
}
166+
}
135167
}
136168

137169
.text {
@@ -158,6 +190,7 @@
158190
color: $tc-gray-70;
159191
background-color: $gray1;
160192
border-color: $gray2;
193+
cursor: default;
161194
}
162195
}
163196

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import React from "react";
2+
import PT from "prop-types";
3+
import Tooltip from "../../../../../../components/Tooltip";
4+
5+
import "./styles.scss";
6+
7+
const EarnTooltip = ({ children }) => {
8+
const Content = () => (
9+
<div styleName="earn-tooltip">
10+
Amount may not reflect any pending payments
11+
</div>
12+
);
13+
14+
return (
15+
<Tooltip overlay={<Content />} placement="bottom">
16+
{children}
17+
</Tooltip>
18+
);
19+
};
20+
21+
EarnTooltip.propTypes = {
22+
children: PT.node,
23+
};
24+
25+
export default EarnTooltip;
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
@import "styles/variables";
2+
3+
.earn-tooltip {
4+
width: 280px;
5+
padding: 7px 10px;
6+
line-height: $line-height-base;
7+
font-size: 12px;
8+
text-align: center;
9+
}

‎src/containers/MyGigs/JobListing/index.jsx

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,35 +7,58 @@ import * as constants from "../../../constants";
77

88
import "./styles.scss";
99

10-
const JobListing = ({ jobs, loadMore, total, numLoaded, gigStatus }) => {
10+
const JobListing = ({ jobs, loadMore, total, numLoaded, gigStatus, page }) => {
1111
const scrollLock = useScrollLock();
12-
const [page, setPage] = useState(1);
12+
// const [page, setPage] = useState(1);
1313

1414
const varsRef = useRef();
1515
varsRef.current = { scrollLock };
1616

1717
const handleLoadMoreClick = () => {
1818
const nextPage = page + 1;
1919
scrollLock(true);
20-
setPage(nextPage);
20+
// setPage(nextPage);
2121
loadMore(constants.GIGS_FILTER_STATUSES_PARAM[gigStatus], nextPage);
2222
};
2323

2424
useEffect(() => {
2525
varsRef.current.scrollLock(false);
2626
}, [jobs]);
2727

28-
useEffect(() => {
29-
setPage(1);
30-
}, [gigStatus]);
31-
28+
// useEffect(() => {
29+
// setPage(1);
30+
// }, [gigStatus]);
3231
return (
3332
<div styleName="card-container">
34-
{jobs.map((job, index) => (
35-
<div styleName="card-item" key={`${job.title}-${index}`}>
36-
<JobCard job={job} />
37-
</div>
38-
))}
33+
{![
34+
constants.GIGS_FILTER_STATUSES.COMPLETED_JOBS,
35+
constants.GIGS_FILTER_STATUSES.ARCHIVED_JOBS,
36+
].includes(gigStatus) &&
37+
jobs.map((job, index) => (
38+
<div styleName="card-item" key={`${job.title}-${index}`}>
39+
<JobCard job={job} />
40+
</div>
41+
))}
42+
43+
{[
44+
constants.GIGS_FILTER_STATUSES.COMPLETED_JOBS,
45+
constants.GIGS_FILTER_STATUSES.ARCHIVED_JOBS,
46+
].includes(gigStatus) &&
47+
jobs
48+
.sort((a, b) => {
49+
if (a.sortPrio == b.sortPrio) {
50+
return (
51+
new Date(b.updatedAt).getTime() -
52+
new Date(a.updatedAt).getTime()
53+
);
54+
}
55+
return a.sortPrio - b.sortPrio;
56+
})
57+
.map((job, index) => (
58+
<div styleName="card-item" key={`${job.title}-${index}`}>
59+
<JobCard job={job} />
60+
</div>
61+
))}
3962

4063
{numLoaded < total && page * constants.PER_PAGE < total && (
4164
<div styleName="load-more">
@@ -52,6 +75,7 @@ JobListing.propTypes = {
5275
total: PT.number,
5376
numLoaded: PT.number,
5477
gigStatus: PT.string,
78+
page: PT.number,
5579
};
5680

5781
export default JobListing;

‎src/containers/MyGigs/index.jsx

Lines changed: 90 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import React, { useEffect, useRef, useState } from "react";
2-
import { useLocation } from "@reach/router";
1+
import React, { useEffect, useRef, useState, useCallback } from "react";
2+
// import { useLocation } from "@reach/router";
33
import PT from "prop-types";
44
import { connect } from "react-redux";
55
import Modal from "../../components/Modal";
@@ -8,19 +8,18 @@ import Loading from "../../components/Loading";
88
import Empty from "../../components/Empty";
99
import JobListing from "./JobListing";
1010
import actions from "../../actions";
11-
import * as utils from "../../utils";
11+
import * as constants from "../../constants";
1212

1313
import UpdateGigProfile from "./modals/UpdateGigProfile";
1414
import UpdateSuccess from "./modals/UpdateSuccess";
1515

1616
import "./styles.scss";
1717

1818
const MyGigs = ({
19-
myGigs,
20-
getMyGigs,
21-
loadMore,
22-
total,
23-
numLoaded,
19+
myActiveGigs,
20+
myOpenGigs,
21+
myCompletedGigs,
22+
myArchivedGigs,
2423
profile,
2524
getProfile,
2625
updateProfile,
@@ -29,26 +28,23 @@ const MyGigs = ({
2928
checkingGigs,
3029
startCheckingGigs,
3130
gigStatus,
31+
loadingMyGigs,
32+
getMyActiveGigs,
33+
getMyOpenGigs,
34+
getMyCompletedGigs,
35+
getMyArchivedGigs,
3236
}) => {
33-
const location = useLocation();
34-
const params = utils.url.parseUrlQuery(location.search);
3537
const propsRef = useRef();
3638
propsRef.current = {
37-
getMyGigs,
39+
getMyOpenGigs,
3840
getProfile,
3941
getAllCountries,
4042
startCheckingGigs,
41-
params,
4243
};
4344

4445
useEffect(() => {
4546
propsRef.current.getProfile();
4647
propsRef.current.getAllCountries();
47-
if (propsRef.current.params.externalId) {
48-
propsRef.current.startCheckingGigs(propsRef.current.params.externalId);
49-
} else {
50-
// propsRef.current.getMyGigs();
51-
}
5248
}, []);
5349

5450
const isInitialMount = useRef(true);
@@ -58,12 +54,28 @@ const MyGigs = ({
5854
return;
5955
}
6056
if (!checkingGigs) {
61-
propsRef.current.getMyGigs();
57+
propsRef.current.getMyOpenGigs();
6258
}
6359
}, [checkingGigs]);
6460

6561
const [openUpdateProfile, setOpenUpdateProfile] = useState(false);
6662
const [openUpdateSuccess, setOpenUpdateSuccess] = useState(false);
63+
const [currentGigs, setCurrentGigs] = useState({});
64+
65+
useEffect(() => {
66+
if (gigStatus == constants.GIGS_FILTER_STATUSES.ACTIVE_JOBS) {
67+
setCurrentGigs(myActiveGigs);
68+
}
69+
if (gigStatus == constants.GIGS_FILTER_STATUSES.OPEN_JOBS) {
70+
setCurrentGigs(myOpenGigs);
71+
}
72+
if (gigStatus == constants.GIGS_FILTER_STATUSES.COMPLETED_JOBS) {
73+
setCurrentGigs(myCompletedGigs);
74+
}
75+
if (gigStatus == constants.GIGS_FILTER_STATUSES.ARCHIVED_JOBS) {
76+
setCurrentGigs(myArchivedGigs);
77+
}
78+
}, [gigStatus, myActiveGigs, myOpenGigs, myCompletedGigs, myArchivedGigs]);
6779

6880
useEffect(() => {
6981
if (updateProfileSuccess) {
@@ -73,6 +85,30 @@ const MyGigs = ({
7385
}
7486
}, [updateProfileSuccess]);
7587

88+
const currentLoadMore = useCallback(
89+
(status, page) => {
90+
if (gigStatus == constants.GIGS_FILTER_STATUSES.ACTIVE_JOBS) {
91+
getMyActiveGigs(status, page);
92+
}
93+
if (gigStatus == constants.GIGS_FILTER_STATUSES.OPEN_JOBS) {
94+
getMyOpenGigs(status, page);
95+
}
96+
if (gigStatus == constants.GIGS_FILTER_STATUSES.COMPLETED_JOBS) {
97+
getMyCompletedGigs(status, page);
98+
}
99+
if (gigStatus == constants.GIGS_FILTER_STATUSES.ARCHIVED_JOBS) {
100+
getMyArchivedGigs(status, page);
101+
}
102+
},
103+
[
104+
gigStatus,
105+
getMyActiveGigs,
106+
getMyOpenGigs,
107+
getMyCompletedGigs,
108+
getMyArchivedGigs,
109+
]
110+
);
111+
76112
return (
77113
<>
78114
<div styleName="page">
@@ -99,19 +135,25 @@ const MyGigs = ({
99135
</Button>
100136
</div>
101137
</h1>
102-
{!checkingGigs && myGigs && myGigs.length == 0 && (
103-
<Empty gigStatus={gigStatus} />
104-
)}
105-
{!checkingGigs && myGigs && myGigs.length > 0 && (
106-
<JobListing
107-
gigStatus={gigStatus}
108-
jobs={myGigs}
109-
loadMore={loadMore}
110-
total={total}
111-
numLoaded={numLoaded}
112-
/>
138+
{!checkingGigs &&
139+
!loadingMyGigs &&
140+
currentGigs.myGigs &&
141+
currentGigs.myGigs.length == 0 && <Empty gigStatus={gigStatus} />}
142+
{!checkingGigs &&
143+
currentGigs.myGigs &&
144+
currentGigs.myGigs.length > 0 && (
145+
<JobListing
146+
gigStatus={gigStatus}
147+
jobs={currentGigs.myGigs}
148+
loadMore={currentLoadMore}
149+
total={currentGigs.total}
150+
numLoaded={currentGigs.numLoaded}
151+
page={currentGigs.page}
152+
/>
153+
)}
154+
{(checkingGigs || (loadingMyGigs && !currentGigs.myGigs)) && (
155+
<Loading />
113156
)}
114-
{checkingGigs && <Loading />}
115157
</div>
116158
<Modal open={openUpdateProfile}>
117159
<UpdateGigProfile
@@ -138,33 +180,41 @@ const MyGigs = ({
138180

139181
MyGigs.propTypes = {
140182
gigStatus: PT.string,
141-
myGigs: PT.arrayOf(PT.shape()),
142-
getMyGigs: PT.func,
143-
loadMore: PT.func,
144-
total: PT.number,
145-
numLoaded: PT.number,
146183
profile: PT.shape(),
147184
getProfile: PT.func,
148185
updateProfile: PT.func,
149186
updateProfileSuccess: PT.bool,
150187
getAllCountries: PT.func,
151188
checkingGigs: PT.bool,
152189
startCheckingGigs: PT.func,
190+
myActiveGigs: PT.shape(),
191+
myOpenGigs: PT.shape(),
192+
myCompletedGigs: PT.shape(),
193+
myArchivedGigs: PT.shape(),
194+
loadingMyGigs: PT.bool,
195+
getMyActiveGigs: PT.func,
196+
getMyOpenGigs: PT.func,
197+
getMyCompletedGigs: PT.func,
198+
getMyArchivedGigs: PT.func,
153199
};
154200

155201
const mapStateToProps = (state) => ({
156202
gigStatus: state.filter.gig.status,
157203
checkingGigs: state.myGigs.checkingGigs,
158-
myGigs: state.myGigs.myGigs,
159-
total: state.myGigs.total,
160-
numLoaded: state.myGigs.numLoaded,
204+
loadingMyGigs: state.myGigs.loadingMyGigs,
205+
myActiveGigs: state.myGigs[constants.GIGS_FILTER_STATUSES.ACTIVE_JOBS],
206+
myOpenGigs: state.myGigs[constants.GIGS_FILTER_STATUSES.OPEN_JOBS],
207+
myCompletedGigs: state.myGigs[constants.GIGS_FILTER_STATUSES.COMPLETED_JOBS],
208+
myArchivedGigs: state.myGigs[constants.GIGS_FILTER_STATUSES.ARCHIVED_JOBS],
161209
profile: state.myGigs.profile,
162210
updateProfileSuccess: state.myGigs.updatingProfileSucess,
163211
});
164212

165213
const mapDispatchToProps = {
166-
getMyGigs: actions.myGigs.getMyGigs,
167-
loadMore: actions.myGigs.loadMoreMyGigs,
214+
getMyActiveGigs: actions.myGigs.getMyActiveGigs,
215+
getMyOpenGigs: actions.myGigs.getMyOpenGigs,
216+
getMyCompletedGigs: actions.myGigs.getMyCompletedGigs,
217+
getMyArchivedGigs: actions.myGigs.getMyArchivedGigs,
168218
getProfile: actions.myGigs.getProfile,
169219
updateProfile: actions.myGigs.updateProfile,
170220
getAllCountries: actions.lookup.getAllCountries,

‎src/containers/MyGigs/modals/UpdateGigProfile/index.jsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -214,9 +214,7 @@ const UpdateGigProfile = ({
214214
/>
215215
</div>
216216
<StatusTooltip statuses={statuses}>
217-
<i styleName="icon">
218-
<IconInfo />
219-
</i>
217+
<IconInfo />
220218
</StatusTooltip>
221219
</div>
222220
</div>

‎src/containers/MyGigsFilter/GigsFilter/index.jsx

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,40 @@
1-
import React from "react";
1+
import React, { useEffect, useRef } from "react";
22
import PT from "prop-types";
33
import _ from "lodash";
44
import RadioButton from "../../../components/RadioButton";
55
import * as utils from "../../../utils";
66

77
import "./styles.scss";
88

9-
const GigsFilter = ({ gigStatus, gigsStatuses, updateGigFilter }) => {
9+
const GigsFilter = ({
10+
gigStatus,
11+
gigsStatuses,
12+
updateGigFilter,
13+
openJobsCount,
14+
}) => {
1015
const bucketOptions = utils.createRadioOptions(gigsStatuses, gigStatus);
1116

17+
const ref = useRef(null);
18+
19+
useEffect(() => {
20+
if (!ref.current) {
21+
return;
22+
}
23+
24+
const openJobsElement = ref.current.children[0].children[1];
25+
const badgeElement = utils.icon.createBadgeElement(
26+
openJobsElement,
27+
`${openJobsCount}`
28+
);
29+
30+
return () => {
31+
badgeElement.parentElement.removeChild(badgeElement);
32+
};
33+
}, [openJobsCount]);
34+
1235
return (
1336
<div styleName="filter">
14-
<div styleName="buckets vertical-list">
37+
<div styleName="buckets vertical-list" ref={ref}>
1538
<RadioButton
1639
options={bucketOptions}
1740
onChange={(newBucketOptions) => {
@@ -31,6 +54,7 @@ GigsFilter.propTypes = {
3154
gigStatus: PT.string,
3255
gigsStatuses: PT.arrayOf(PT.string),
3356
updateGigFilter: PT.func,
57+
openJobsCount: PT.number,
3458
};
3559

3660
export default GigsFilter;

‎src/containers/MyGigsFilter/GigsFilter/styles.scss

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,19 @@ $filter-padding-y: 3 * $base-unit;
2525
margin: $base-unit 0;
2626
}
2727
}
28+
:global {
29+
.count-badge {
30+
display: inline-block;
31+
margin: -2px 0 0 $base-unit;
32+
padding: 2px 5px 0;
33+
font-weight: bold;
34+
font-size: 11px;
35+
line-height: 14px;
36+
text-align: center;
37+
color: white;
38+
vertical-align: middle;
39+
background: #EF476F;
40+
border-radius: 13px;
41+
}
42+
}
2843
}

‎src/containers/MyGigsFilter/index.jsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,14 @@ import { connect } from "react-redux";
55
import GigsFilter from "./GigsFilter";
66
import actions from "../../actions";
77
import { updateQuery } from "../../utils/url";
8+
import * as constants from "../../constants";
89

9-
const MyGigsFilter = ({ gigStatus, gigsStatuses, updateGigFilter }) => {
10+
const MyGigsFilter = ({
11+
gigStatus,
12+
gigsStatuses,
13+
updateGigFilter,
14+
openJobsCount,
15+
}) => {
1016
const location = useLocation();
1117
const propsRef = useRef(null);
1218
propsRef.current = { location };
@@ -16,6 +22,7 @@ const MyGigsFilter = ({ gigStatus, gigsStatuses, updateGigFilter }) => {
1622
<GigsFilter
1723
gigStatus={gigStatus}
1824
gigsStatuses={gigsStatuses}
25+
openJobsCount={openJobsCount}
1926
updateGigFilter={(gigFilterChanged) => {
2027
updateGigFilter(gigFilterChanged);
2128
updateQuery(gigFilterChanged);
@@ -31,11 +38,13 @@ MyGigsFilter.propTypes = {
3138
gigStatus: PT.string,
3239
gigsStatuses: PT.arrayOf(PT.string),
3340
updateGigFilter: PT.func,
41+
openJobsCount: PT.number,
3442
};
3543

3644
const mapStateToProps = (state) => ({
3745
state: state,
3846
gigStatus: state.filter.gig.status,
47+
openJobsCount: state.myGigs[constants.GIGS_FILTER_STATUSES.OPEN_JOBS].total,
3948
gigsStatuses: state.lookup.gigsStatuses,
4049
});
4150

‎src/reducers/myGigs.js

Lines changed: 89 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,34 @@
11
import { size, sortBy } from "lodash";
22
import { handleActions } from "redux-actions";
3+
import * as constants from "../constants";
34

45
const defaultState = {
56
loadingMyGigs: false,
67
loadingMyGigsError: null,
7-
myGigs: null,
8-
total: 0,
9-
numLoaded: 0,
10-
loadingMore: false,
11-
loadingMoreError: null,
8+
[constants.GIGS_FILTER_STATUSES.ACTIVE_JOBS]: {
9+
myGigs: null,
10+
page: 1,
11+
numLoaded: 0,
12+
total: 0,
13+
},
14+
[constants.GIGS_FILTER_STATUSES.OPEN_JOBS]: {
15+
myGigs: null,
16+
page: 1,
17+
numLoaded: 0,
18+
total: 0,
19+
},
20+
[constants.GIGS_FILTER_STATUSES.COMPLETED_JOBS]: {
21+
myGigs: null,
22+
page: 1,
23+
numLoaded: 0,
24+
total: 0,
25+
},
26+
[constants.GIGS_FILTER_STATUSES.ARCHIVED_JOBS]: {
27+
myGigs: null,
28+
page: 1,
29+
numLoaded: 0,
30+
total: 0,
31+
},
1232
profile: {},
1333
loadingProfile: false,
1434
loadingProfileError: null,
@@ -18,48 +38,84 @@ const defaultState = {
1838
checkingGigs: false,
1939
};
2040

21-
function onGetMyGigsInit(state) {
41+
function onGetMyActiveGigsInit(state) {
2242
return { ...state, loadingMyGigs: true, loadingMyGigsError: null };
2343
}
2444

25-
function onGetMyGigsDone(state, { payload }) {
45+
function onGetMyActiveGigsDone(state, { payload }) {
46+
const currentGigs =
47+
state[constants.GIGS_FILTER_STATUSES.ACTIVE_JOBS].myGigs || [];
2648
return {
2749
...state,
28-
myGigs: sortBy(payload.myGigs, ["sortPrio"]),
29-
total: payload.total,
30-
numLoaded: payload.myGigs.length,
50+
[constants.GIGS_FILTER_STATUSES.ACTIVE_JOBS]: {
51+
myGigs: sortBy(currentGigs.concat(payload.myGigs), ["sortPrio"]),
52+
total: payload.total,
53+
numLoaded: currentGigs.length + payload.myGigs.length,
54+
page: payload.page,
55+
},
3156
loadingMyGigs: false,
3257
loadingMyGigsError: null,
3358
};
3459
}
3560

36-
function onGetMyGigsFailure(state, { payload }) {
61+
function onGetMyOpenGigsInit(state) {
62+
return { ...state, loadingMyGigs: true, loadingMyGigsError: null };
63+
}
64+
65+
function onGetMyOpenGigsDone(state, { payload }) {
66+
const currentGigs =
67+
state[constants.GIGS_FILTER_STATUSES.OPEN_JOBS].myGigs || [];
3768
return {
3869
...state,
70+
[constants.GIGS_FILTER_STATUSES.OPEN_JOBS]: {
71+
myGigs: sortBy(currentGigs.concat(payload.myGigs), ["sortPrio"]),
72+
total: payload.total,
73+
numLoaded: currentGigs.length + payload.myGigs.length,
74+
page: payload.page,
75+
},
3976
loadingMyGigs: false,
40-
loadingMyGigsError: payload,
41-
myGigs: null,
42-
total: 0,
43-
numLoaded: 0,
77+
loadingMyGigsError: null,
4478
};
4579
}
4680

47-
function onLoadMoreMyGigsInit(state) {
48-
return { ...state, loadingMore: true, loadingMoreError: null };
81+
function onGetMyCompletedGigsInit(state) {
82+
return { ...state, loadingMyGigs: true, loadingMyGigsError: null };
4983
}
5084

51-
function onLoadMoreMyGigsDone(state, { payload: { myGigs } }) {
85+
function onGetMyCompletedGigsDone(state, { payload }) {
86+
const currentGigs =
87+
state[constants.GIGS_FILTER_STATUSES.COMPLETED_JOBS].myGigs || [];
5288
return {
5389
...state,
54-
myGigs: sortBy(state.myGigs.concat(myGigs), ["sortPrio"]),
55-
numLoaded: state.numLoaded + size(myGigs),
56-
loadingMore: false,
57-
loadingMoreError: null,
90+
[constants.GIGS_FILTER_STATUSES.COMPLETED_JOBS]: {
91+
myGigs: sortBy(currentGigs.concat(payload.myGigs), ["sortPrio"]),
92+
total: payload.total,
93+
numLoaded: currentGigs.length + payload.myGigs.length,
94+
page: payload.page,
95+
},
96+
loadingMyGigs: false,
97+
loadingMyGigsError: null,
5898
};
5999
}
60100

61-
function onLoadMoreMyGigsFailure(state, { payload }) {
62-
return { ...state, loadingMore: false, loadingMoreError: payload };
101+
function onGetMyArchivedGigsInit(state) {
102+
return { ...state, loadingMyGigs: true, loadingMyGigsError: null };
103+
}
104+
105+
function onGetMyArchivedGigsDone(state, { payload }) {
106+
const currentGigs =
107+
state[constants.GIGS_FILTER_STATUSES.ARCHIVED_JOBS].myGigs || [];
108+
return {
109+
...state,
110+
[constants.GIGS_FILTER_STATUSES.ARCHIVED_JOBS]: {
111+
myGigs: sortBy(currentGigs.concat(payload.myGigs), ["sortPrio"]),
112+
total: payload.total,
113+
numLoaded: currentGigs.length + payload.myGigs.length,
114+
page: payload.page,
115+
},
116+
loadingMyGigs: false,
117+
loadingMyGigsError: null,
118+
};
63119
}
64120

65121
function onGetProfileInit(state) {
@@ -128,12 +184,15 @@ function onCheckingGigsDone(state) {
128184

129185
export default handleActions(
130186
{
131-
GET_MY_GIGS_INIT: onGetMyGigsInit,
132-
GET_MY_GIGS_DONE: onGetMyGigsDone,
133-
GET_MY_GIGS_FAILURE: onGetMyGigsFailure,
134-
LOAD_MORE_MY_GIGS_INIT: onLoadMoreMyGigsInit,
135-
LOAD_MORE_MY_GIGS_DONE: onLoadMoreMyGigsDone,
136-
LOAD_MORE_MY_GIGS_FAILURE: onLoadMoreMyGigsFailure,
187+
GET_MY_ACTIVE_GIGS_INIT: onGetMyActiveGigsInit,
188+
GET_MY_ACTIVE_GIGS_DONE: onGetMyActiveGigsDone,
189+
GET_MY_OPEN_GIGS_INIT: onGetMyOpenGigsInit,
190+
GET_MY_OPEN_GIGS_DONE: onGetMyOpenGigsDone,
191+
GET_MY_COMPLETED_GIGS_INIT: onGetMyCompletedGigsInit,
192+
GET_MY_COMPLETED_GIGS_DONE: onGetMyCompletedGigsDone,
193+
GET_MY_ARCHIVED_GIGS_INIT: onGetMyArchivedGigsInit,
194+
GET_MY_ARCHIVED_GIGS_DONE: onGetMyArchivedGigsDone,
195+
137196
GET_PROFILE_INIT: onGetProfileInit,
138197
GET_PROFILE_DONE: onGetProfileDone,
139198
GET_PROFILE_FAILURE: onGetProfileFailure,

‎src/services/myGigs.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ const mapMyGigsData = (serverResponse) => {
4040
return {
4141
label: (gigPhase || "").toUpperCase(),
4242
title: myGig.title,
43+
rbStartDate: myGig.rbStartDate || "",
44+
rbEndDate: myGig.rbEndDate || "",
45+
paymentTotal: myGig.paymentTotal || 0,
46+
updatedAt: myGig.updatedAt || "",
4347
jobExternalId: myGig.jobExternalId,
4448
paymentRangeFrom: myGig.payment.min,
4549
paymentRangeTo: myGig.payment.max,
@@ -92,6 +96,7 @@ async function getMyGigs(status, page, perPage) {
9296
return {
9397
myGigs: mapMyGigsData(response),
9498
total: response.meta.total,
99+
page: response.meta.page,
95100
};
96101
}
97102

‎src/utils/icon.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,3 +146,29 @@ export function createBadgeElement(htmlElement, content) {
146146

147147
return badgeElement;
148148
}
149+
150+
// export function createCompanyLogo() {
151+
// return (
152+
// <svg width="44px" height="64px" viewBox="0 0 44 64" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
153+
// <title>9825381A-BF03-46A3-AD6D-206A06A2B45D</title>
154+
// <g id="Screens" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
155+
// <g id="03_2_My-Gigs" transform="translate(-346.000000, -807.000000)" fill-rule="nonzero">
156+
// <g id="Group-11" transform="translate(305.000000, 182.000000)">
157+
// <g id="Group-10-Copy-7" transform="translate(0.000000, 412.000000)">
158+
// <g id="Group-9" transform="translate(0.000000, 142.000000)">
159+
// <g id="Group-10" transform="translate(19.000000, 47.000000)">
160+
// <g id="Group-Copy-2" transform="translate(22.000000, 24.000000)">
161+
// <path d="M43.125,0 L43.125,64 L40.946,63.81 C37.299,63.21 33.573,62.777 29.87,62.521 L28.125,62.4 L28.125,7.5 L43.125,0 Z" id="Path_80" fill="#D5011D"></path>
162+
// <polygon id="Path_81" fill="#AA011A" points="15 0.166 15 56.666 0 63.998 0 0.166"></polygon>
163+
// <path d="M21.563,16.264 L25.313,16.264 L21.563,47.854 L14.982,62.408 L13.875,62.479 C9.965,62.729 6.029,63.179 2.175,63.81 L-0.004,64 L21.563,16.264 Z" id="Path_82" fill="#D5011D"></path>
164+
// <polygon id="Path_83" fill="#FF0021" points="28.808 0.166 43.124 0.166 21.561 47.855 21.561 16.265"></polygon>
165+
// </g>
166+
// </g>
167+
// </g>
168+
// </g>
169+
// </g>
170+
// </g>
171+
// </g>
172+
// </svg>
173+
// )
174+
// }

‎src/utils/myGig.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,3 +106,18 @@ export function validatePhone(phoneNumber, country) {
106106

107107
return error ? error : null;
108108
}
109+
110+
export function getDateRange(startDate, endDate) {
111+
const yearStart = new Date(startDate).getFullYear();
112+
const yearEnd = new Date(endDate).getFullYear();
113+
if (yearStart > yearEnd) {
114+
return "";
115+
}
116+
const options = { month: "long", day: "numeric" };
117+
const first = new Date(startDate).toLocaleDateString("en-us", options);
118+
const second = new Date(endDate).toLocaleDateString("en-us", options);
119+
if (yearStart == yearEnd) {
120+
return `${first} - ${second}, ${yearStart}`;
121+
}
122+
return `${first}, ${yearStart} - ${second}, ${yearEnd}`;
123+
}

0 commit comments

Comments
 (0)
This repository has been archived.