Skip to content
This repository was archived by the owner on Mar 13, 2025. It is now read-only.

Feature/fix issue #40

Merged
merged 4 commits into from
Jan 6, 2021
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"dev": "webpack-dev-server --port 8501 --host 0.0.0.0",
"dev-https": "webpack-dev-server --https --port 8501 --host 0.0.0.0",
"build": "webpack --mode=${APPMODE:-development} --env.config=${APPENV:-dev}",
"build:prod": "webpack --mode=${APPMODE:-production} --env.config=${APPENV:-prod}",
"analyze": "webpack --mode=production --env.analyze=true",
"lint": "eslint src --ext js",
"format": "prettier --write \"./**\"",
Expand Down Expand Up @@ -74,7 +75,8 @@
"redux": "^4.0.5",
"redux-logger": "^3.0.6",
"redux-promise-middleware": "^6.1.2",
"redux-thunk": "^2.3.0"
"redux-thunk": "^2.3.0",
"use-debounce": "^5.2.0"
},
"browserslist": [
"last 1 version",
Expand Down
5 changes: 5 additions & 0 deletions src/constants/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ export const DAY_FORMAT = "MM/DD/YYYY";
*/
export const TEAM_MEMBERS_PER_PAGE = 5;

/**
* How many teams show per page by default
*/
export const TEAMS_PER_PAGE = 20;

/**
* How many position candidates show per page by default
*/
Expand Down
7 changes: 1 addition & 6 deletions src/routes/MyTeamsDetails/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,9 @@ import TeamSummary from "./components/TeamSummary";
import TeamMembers from "./components/TeamMembers";
import TeamPositions from "./components/TeamPositions";
import { useAsync } from "react-use";
import {
getAuthUserTokens,
} from "@topcoder/micro-frontends-navbar-app";

const MyTeamsDetails = ({ teamId }) => {
const authUserTokens = useAsync(getAuthUserTokens);
const tokenV3 = authUserTokens.value ? authUserTokens.value.tokenV3 : null;
const [team, loadingError] = useData(getTeamById, tokenV3, teamId);
const [team, loadingError] = useData(getTeamById, teamId);

return (
<LayoutContainer>
Expand Down
77 changes: 63 additions & 14 deletions src/routes/MyTeamsList/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,35 +3,84 @@
*
* Page for the list of teams.
*/
import React from "react";
import React, { useCallback, useState, useEffect } from "react";
import _ from "lodash";
import LayoutContainer from "components/LayoutContainer";
import { useDebouncedCallback } from "use-debounce";
import PageHeader from "components/PageHeader";
import { useData } from "../../hooks/useData";
import Input from "components/Input";
import Pagination from "components/Pagination";
import { getMyTeams } from "../../services/teams";
import TeamCard from "./components/TeamCard";
import TeamCardGrid from "./components/TeamCardGrid";
import LoadingIndicator from "../../components/LoadingIndicator";
import { useAsync } from "react-use";
import {
getAuthUserTokens,
} from "@topcoder/micro-frontends-navbar-app";
import { TEAMS_PER_PAGE } from "constants";
import "./styles.module.scss";

const MyTeamsList = () => {
const authUserTokens = useAsync(getAuthUserTokens);
const tokenV3 = authUserTokens.value ? authUserTokens.value.tokenV3 : null;
const [myTeams, loadingError] = useData(getMyTeams, tokenV3);
// let [myTeams, loadingError] = useData(getMyTeams);
let [myTeams, setMyTeams] = useState();
const [filter, setFilter] = useState("");
const [loadingError, setLoadingError] = useState(false);
const [page, setPage] = useState(1);
const [total, setTotal] = useState(0);

const onFilterChange = useDebouncedCallback((value) => {
setFilter(value);
setPage(1);
}, 200);

useEffect(() => {
getMyTeams(filter, page, TEAMS_PER_PAGE)
.then((response) => {
setMyTeams(response.data);
setTotal(response.headers["x-total"]);
})
.catch((responseError) => {
setLoadingError(responseError);
});
}, [filter, page]);

const onPageClick = useCallback(
(newPage) => {
setPage(newPage);
},
[setPage]
);

return (
<LayoutContainer>
<PageHeader title="My Teams" />
<PageHeader
title="My Teams"
aside={
<Input
placeholder="Filter by team name"
styleName="filter-input"
onChange={(e) => onFilterChange.callback(e.target.value)}
/>
}
/>
{!myTeams ? (
<LoadingIndicator error={loadingError && loadingError.toString()} />
) : (
<TeamCardGrid>
{myTeams.map((team) => (
<TeamCard key={team.id} team={team} />
))}
</TeamCardGrid>
<>
<TeamCardGrid>
{myTeams.map((team) => (
<TeamCard key={team.id} team={team} />
))}
</TeamCardGrid>
{myTeams.length > 0 && (
<div styleName="pagination-wrapper">
<Pagination
total={total}
currentPage={page}
perPage={TEAMS_PER_PAGE}
onPageClick={onPageClick}
/>
</div>
)}
</>
)}
</LayoutContainer>
);
Expand Down
33 changes: 33 additions & 0 deletions src/routes/MyTeamsList/styles.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
@import "styles/include";

.filter-input {
width: 380px;
background-color: #FFFFFF;
border: 1px solid #AAAAAA;
border-radius: 6px;
box-sizing: border-box;
color: #2A2A2A;
font-size: 14px;
height: 40px;
line-height: 38px;
outline: none;
padding: 0 15px;

&::placeholder {
color: #AAAAAA;
}
}


.pagination-wrapper {
margin-top: 20px;
margin-right: 20px;
display: flex;
justify-content: flex-end;
}

@media (max-width: 650px) {
.filter-input {
width: 100%;
}
}
12 changes: 2 additions & 10 deletions src/routes/PositionDetails/actions/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
* Position Details page actions
*/
import { getPositionDetails, patchPositionCandidate } from "services/teams";
import { getAuthUserTokens } from "@topcoder/micro-frontends-navbar-app";
import { ACTION_TYPE } from "constants";

/**
Expand All @@ -16,12 +15,7 @@ import { ACTION_TYPE } from "constants";
export const loadPosition = (teamId, positionId) => ({
type: ACTION_TYPE.LOAD_POSITION,
payload: async () => {
const tokens = await getAuthUserTokens();
const response = await getPositionDetails(
tokens.tokenV3,
teamId,
positionId
);
const response = await getPositionDetails(teamId, positionId);

return response.data;
},
Expand All @@ -42,9 +36,7 @@ export const loadPosition = (teamId, positionId) => ({
export const updateCandidate = (candidateId, partialCandidateData) => ({
type: ACTION_TYPE.UPDATE_CANDIDATE,
payload: async () => {
const tokens = await getAuthUserTokens();
const response = await patchPositionCandidate(
tokens.tokenV3,
candidateId,
partialCandidateData
);
Expand All @@ -61,4 +53,4 @@ export const updateCandidate = (candidateId, partialCandidateData) => ({
*/
export const resetPositionState = () => ({
type: ACTION_TYPE.RESET_POSITION_STATE,
})
});
2 changes: 1 addition & 1 deletion src/routes/PositionDetails/hooks/useTeamPositionsState.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export const useTeamPositionsState = (teamId, positionId) => {
// clear state when we leave the page
return () => {
dispatch(resetPositionState());
}
};
}, [dispatch, teamId, positionId]);

// bind actions to dispatch method
Expand Down
14 changes: 5 additions & 9 deletions src/routes/PositionDetails/reducers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,14 +76,10 @@ const reducer = (state = initialState, action) => {
});

case ACTION_TYPE.UPDATE_CANDIDATE_SUCCESS:
return patchCandidateInState(
state,
action.meta.candidateId,
{
updating: false,
...action.payload,
}
);
return patchCandidateInState(state, action.meta.candidateId, {
updating: false,
...action.payload,
});

case ACTION_TYPE.UPDATE_CANDIDATE_ERROR:
return patchCandidateInState(state, action.meta.candidateId, {
Expand All @@ -92,7 +88,7 @@ const reducer = (state = initialState, action) => {
});

default:
return state
return state;
}
};

Expand Down
33 changes: 33 additions & 0 deletions src/services/requestInterceptor.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import axios from "axios";
import store from "../store";
import { getAuthUserTokens } from "@topcoder/micro-frontends-navbar-app";

export const getToken = () => {
return new Promise((resolve, reject) => {
return getAuthUserTokens()
.then(({ tokenV3: token }) => {
return resolve(token);
})
.catch((err) => {
reject(err);
});
});
};

export const axiosInstance = axios.create({
headers: {
"Content-Type": "application/json",
},
});

// request interceptor to pass auth token
axiosInstance.interceptors.request.use((config) => {
return getToken()
.then((token) => {
config.headers["Authorization"] = `Bearer ${token}`;
return config;
})
.catch((err) => {
return config;
});
});
Loading