Skip to content

Commit 285a297

Browse files
authored
Merge pull request #251 from wbbly/dev
ADD | search bar , filters on team-page + small fixes
2 parents 87a85cd + 46be905 commit 285a297

File tree

24 files changed

+964
-63
lines changed

24 files changed

+964
-63
lines changed

project/application/src/actions/MainPageAction.js

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,25 +14,40 @@ export const INC_PAGINATION = 'INC_PAGINATION';
1414
export const GET_TIME_ENTRIES_LIST_PAGINATION = 'GET_TIME_ENTRIES_LIST_PAGINATION';
1515
export const DISABLE_PAGINATION = 'DISABLE_PAGINATION';
1616
export const RESTORE_PAGINATION = 'RESTORE_PAGINATION';
17+
export const START_SEARCH_MODE = 'START_SEARCH_MODE';
18+
export const END_SEARCH_MODE = 'END_SEARCH_MODE';
1719

1820
const setTimeEntriesListAction = payload => ({
1921
type: GET_TIME_ENTRIES_LIST,
2022
payload,
2123
});
2224

2325
export const getTimeEntriesListAction = byPage => async dispatch => {
24-
const { page, limit, disabled } = store.getState().mainPageReducer.pagination;
26+
const { searchValue, searchDateRange, isSearchMode, pagination } = store.getState().mainPageReducer;
27+
const { page, limit, disabled } = pagination;
28+
2529
let res = [];
2630

2731
if (disabled) {
28-
res = await getTimeEntriesList();
32+
res = await getTimeEntriesList(isSearchMode ? { ...searchDateRange, searchValue } : undefined);
2933
} else if (page === 1) {
30-
res = await getTimeEntriesList({ page, limit });
34+
res = await getTimeEntriesList(
35+
isSearchMode ? { page, limit, ...searchDateRange, searchValue } : { page, limit }
36+
);
3137
} else {
32-
res = await getTimeEntriesList({
33-
page: 1,
34-
limit: page * limit,
35-
});
38+
res = await getTimeEntriesList(
39+
isSearchMode
40+
? {
41+
page: 1,
42+
limit: page * limit,
43+
...searchDateRange,
44+
searchValue,
45+
}
46+
: {
47+
page: 1,
48+
limit: page * limit,
49+
}
50+
);
3651
}
3752
const parsedList = getTodayTimeEntriesParseFunction(res.data.data);
3853
const { timerV2 } = parsedList;
@@ -86,9 +101,16 @@ const disablePaginationAction = () => ({
86101
});
87102

88103
export const getTimeEntriesListPaginationAction = () => async dispatch => {
89-
const { page, limit } = store.getState().mainPageReducer.pagination;
104+
const { searchValue, searchDateRange, isSearchMode, pagination } = store.getState().mainPageReducer;
105+
const { page, limit } = pagination;
106+
107+
let res = [];
108+
if (isSearchMode) {
109+
res = await getTimeEntriesList({ page, limit, ...searchDateRange, searchValue });
110+
} else {
111+
res = await getTimeEntriesList({ page, limit });
112+
}
90113

91-
const res = await getTimeEntriesList({ page, limit });
92114
if (res.data.data.timer_v2.length) {
93115
const parsedList = getTodayTimeEntriesParseFunction(res.data.data);
94116
const { timerV2 } = parsedList;
@@ -97,3 +119,12 @@ export const getTimeEntriesListPaginationAction = () => async dispatch => {
97119
dispatch(disablePaginationAction());
98120
}
99121
};
122+
123+
export const startSearchMode = payload => ({
124+
type: START_SEARCH_MODE,
125+
payload,
126+
});
127+
128+
export const endSearchMode = () => ({
129+
type: END_SEARCH_MODE,
130+
});

project/application/src/components/PageHeader/index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ import React from 'react';
33
// Styles
44
import './style.scss';
55

6-
const PageHeader = ({ title, children }) => {
6+
const PageHeader = ({ title, children, disabledTitle }) => {
77
return (
88
<div className="header-wrapper">
9-
<h1 className="header-wrapper__title">{title}</h1>
9+
{!disabledTitle && <h1 className="header-wrapper__title">{title}</h1>}
1010
<div className="header-wrapper__child">{children}</div>
1111
</div>
1212
);

project/application/src/components/PageHeader/style.scss

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,14 @@
22
display: flex;
33
align-items: center;
44
justify-content: space-between;
5-
margin-bottom: 32px;
5+
margin-bottom: 3.2rem;
6+
@media screen and (max-width: 768px) {
7+
flex-direction: column;
8+
margin-bottom: 2rem;
9+
}
610
&__title {
711
font-size: 26px;
12+
line-height: 3.5rem;
813
margin: 0;
914
color: #ffffff;
1015
@media screen and (max-width: 414px) {
@@ -15,6 +20,7 @@
1520
@media screen and (max-width: 500px) {
1621
display: flex;
1722
flex-direction: column;
23+
width: 100%;
1824
}
1925
&-button {
2026
display: inline-block;
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import React, { useRef } from 'react';
2+
import Proptypes from 'prop-types';
3+
import { connect } from 'react-redux';
4+
5+
import './style.scss';
6+
7+
const SearchSVG = () => (
8+
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
9+
<path
10+
d="M8.25 14.25C11.5637 14.25 14.25 11.5637 14.25 8.25C14.25 4.93629 11.5637 2.25 8.25 2.25C4.93629 2.25 2.25 4.93629 2.25 8.25C2.25 11.5637 4.93629 14.25 8.25 14.25Z"
11+
stroke="white"
12+
strokeWidth="1.5"
13+
strokeLinecap="round"
14+
strokeLinejoin="round"
15+
/>
16+
<path
17+
d="M15.75 15.75L12.4875 12.4875"
18+
stroke="white"
19+
strokeWidth="1.5"
20+
strokeLinecap="round"
21+
strokeLinejoin="round"
22+
/>
23+
</svg>
24+
);
25+
26+
const CloseSVG = () => (
27+
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
28+
<path d="M12 4L4 12" stroke="white" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
29+
<path d="M4 4L12 12" stroke="white" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
30+
</svg>
31+
);
32+
33+
const SearchComponent = ({ value, setValue, handleSearch, handleReset, vocabulary }) => {
34+
const { v_search } = vocabulary;
35+
const inputRef = useRef(null);
36+
return (
37+
<div className="search-component">
38+
<div className="search-component__icon-container" onClick={() => handleSearch()}>
39+
<SearchSVG />
40+
</div>
41+
<form
42+
action="true"
43+
className={'search-component__form'}
44+
onSubmit={e => {
45+
e.preventDefault();
46+
}}
47+
>
48+
<input
49+
className="search-component__input"
50+
type="search"
51+
ref={inputRef}
52+
placeholder={v_search}
53+
value={value}
54+
onChange={event => setValue(event.target.value)}
55+
// onBlur={() => {
56+
// if (!value.length) {
57+
// handleReset();
58+
// }
59+
// }}
60+
onKeyUp={e => {
61+
if (e.keyCode === 13) {
62+
// e.target.blur();
63+
handleSearch();
64+
} else {
65+
return;
66+
}
67+
}}
68+
/>
69+
</form>
70+
{!!value.length && (
71+
<div
72+
className="search-component__icon-container"
73+
onClick={() => {
74+
setValue('');
75+
inputRef.current.focus();
76+
// handleReset();
77+
}}
78+
>
79+
<CloseSVG />
80+
</div>
81+
)}
82+
</div>
83+
);
84+
};
85+
86+
SearchComponent.propTypes = {
87+
value: Proptypes.string,
88+
setValue: Proptypes.func,
89+
handleSearch: Proptypes.func,
90+
handleReset: Proptypes.func,
91+
vocabulary: Proptypes.object,
92+
};
93+
94+
const mapStateToProps = store => ({
95+
vocabulary: store.languageReducer.vocabulary,
96+
});
97+
98+
export default connect(mapStateToProps)(SearchComponent);
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
.search-component {
2+
width: 100%;
3+
border-bottom: 1px solid rgba(193, 192, 192, 0.4);
4+
display: flex;
5+
align-items: center;
6+
padding: 0.4rem 0;
7+
@media screen and (max-width: 768px) {
8+
border-bottom: none;
9+
}
10+
&__form {
11+
width: 100%;
12+
display: flex;
13+
}
14+
&__input {
15+
width: 100%;
16+
margin-left: 0.8rem;
17+
background: transparent;
18+
border: none;
19+
font-size: 1.4rem;
20+
line-height: 1.9rem;
21+
color: #ffffff;
22+
padding: 0;
23+
24+
&::placeholder {
25+
color: #BEBBBB;
26+
}
27+
&::-webkit-search-decoration,
28+
&::-webkit-search-cancel-button,
29+
&::-webkit-search-results-button,
30+
&::-webkit-search-results-decoration {
31+
display: none;
32+
}
33+
&::-ms-clear {
34+
display: none;
35+
width: 0;
36+
height: 0;
37+
}
38+
&::-ms-reveal {
39+
display: none;
40+
width: 0;
41+
height: 0;
42+
}
43+
}
44+
&__icon-container {
45+
display: flex;
46+
cursor: pointer;
47+
}
48+
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import React, { Component } from 'react';
2+
import { connect } from 'react-redux';
3+
4+
import './style.scss';
5+
6+
class SelectTeamRoleAccess extends Component {
7+
state = {
8+
isOpenDropdown: false,
9+
value: this.props.value,
10+
list: {
11+
role: ['all', 'member', 'admin'],
12+
access: ['all', 'granted', 'denied'],
13+
},
14+
};
15+
16+
tooggleDropdown = event => {
17+
if (this.state.isOpenDropdown) {
18+
document.removeEventListener('click', this.tooggleDropdown);
19+
} else {
20+
document.addEventListener('click', this.tooggleDropdown);
21+
}
22+
this.setState({ isOpenDropdown: !this.state.isOpenDropdown });
23+
};
24+
25+
setValue = value => {
26+
const { setTeamRoleAccess } = this.props;
27+
setTeamRoleAccess(value);
28+
this.setState({ value });
29+
this.tooggleDropdown();
30+
};
31+
32+
componentDidMount() {}
33+
34+
render() {
35+
const { value, list, isOpenDropdown } = this.state;
36+
const { vocabulary, type } = this.props;
37+
const { v_all_role, v_all_access, v_active, v_not_active } = vocabulary;
38+
const listMap = {
39+
role: {
40+
all: v_all_role,
41+
member: 'Member',
42+
admin: 'Admin',
43+
},
44+
access: {
45+
all: v_all_access,
46+
granted: v_active,
47+
denied: v_not_active,
48+
},
49+
};
50+
51+
return (
52+
<div className="team-role-access">
53+
<div className="team-role-access_select">
54+
<div onClick={this.tooggleDropdown}>
55+
<span>{listMap[type][value]}</span>
56+
<i
57+
className={`team-role-access__icon-arrow ${
58+
isOpenDropdown ? 'team-role-access__icon-arrow-open' : ''
59+
}`}
60+
/>
61+
</div>
62+
63+
{isOpenDropdown && (
64+
<div className="team-role-access__list">
65+
{list[type].map(item => (
66+
<div
67+
key={item}
68+
className="team-role-access__list-item"
69+
onClick={event => {
70+
this.setValue(item);
71+
}}
72+
>
73+
{listMap[type][item]}
74+
</div>
75+
))}
76+
</div>
77+
)}
78+
</div>
79+
</div>
80+
);
81+
}
82+
}
83+
84+
const mapStateToProps = state => ({
85+
vocabulary: state.languageReducer.vocabulary,
86+
});
87+
88+
export default connect(mapStateToProps)(SelectTeamRoleAccess);

0 commit comments

Comments
 (0)