-
-
- { `${education.schoolCollegeName} ${education.type}` }
-
-
- { `${moment(education.timePeriodFrom).format('YYYY')} - ${moment(education.timePeriodTo).format('YYYY')}${education.graduated ? ' | Graduated' : ''}` }
-
-
-
- {`${moment(education.timePeriodFrom).format('YYYY')} - ${moment(education.timePeriodTo).format('YYYY')}`}
-
- {
- education.graduated && (
-
- Graduated
-
- )
- }
+
+
+ { `${education.schoolCollegeName}` }
+ {
+ hasSecondLine() && (
+
+
+ {
+ `${getDate()}${getGraduated()}`
+ }
+
+
+ {
+ !_.isEmpty(getDate()) && (
+
+ {`${getDate()}`}
+
+ )
+ }
+ {
+ education.graduated && (
+
+ Graduated
+
+ )
+ }
+
+
+ )
+ }
-
onDeleteItem(index)}
- tabIndex={0}
- role="button"
- onClick={() => onDeleteItem(index)}
- >
-
-
- Delete
-
-
+
);
}
@@ -68,4 +150,5 @@ Item.propTypes = {
education: PT.shape().isRequired,
index: PT.number.isRequired,
onDeleteItem: PT.func.isRequired,
+ onEditItem: PT.func.isRequired,
};
diff --git a/src/shared/components/Settings/Profile/Education/List/Item/styles.scss b/src/shared/components/Settings/Profile/Education/List/Item/styles.scss
index 1f9610afa3..2f9a2117a3 100644
--- a/src/shared/components/Settings/Profile/Education/List/Item/styles.scss
+++ b/src/shared/components/Settings/Profile/Education/List/Item/styles.scss
@@ -36,6 +36,11 @@
line-height: 20px;
text-transform: capitalize;
padding-right: 20px;
+
+ &.single-line {
+ flex-direction: row;
+ align-items: center;
+ }
}
.parameter-first-line {
@@ -44,6 +49,10 @@
margin-bottom: 10px;
word-break: break-all;
+ &.single-line {
+ margin-bottom: 0;
+ }
+
@include upto-sm {
margin-bottom: 0;
}
@@ -74,32 +83,70 @@
}
}
-.delete {
+.operation-container {
display: flex;
- flex-direction: column;
- justify-items: center;
- justify-content: center;
- cursor: pointer;
- outline-style: none;
+ flex-direction: row;
+ justify-content: space-between;
- img {
- margin-bottom: 10px;
+ .delete {
+ display: flex;
+ flex-direction: column;
+ justify-items: center;
+ justify-content: center;
+ cursor: pointer;
+ outline-style: none;
+ margin-left: 10px;
+
+ img {
+ margin-bottom: 10px;
+
+ @include upto-sm {
+ margin-bottom: 0;
+ }
+ }
+
+ p {
+ @include roboto-regular;
- @include upto-sm {
- margin-bottom: 0;
+ font-size: 11px;
+ line-height: 15px;
+ font-weight: 400;
+ color: $tc-gray-50;
+
+ @include upto-sm {
+ display: none;
+ }
}
}
- p {
- @include roboto-regular;
+ .edit {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ cursor: pointer;
+ outline-style: none;
+ margin-left: 10px;
+
+ img {
+ margin-bottom: 10px;
+
+ @include upto-sm {
+ margin-bottom: 0;
+ }
+ }
- font-size: 11px;
- line-height: 15px;
- font-weight: 400;
- color: $tc-gray-50;
+ p {
+ @include roboto-regular;
+
+ font-size: 11px;
+ line-height: 15px;
+ font-weight: 400;
+ color: $tc-gray-50;
- @include upto-sm {
- display: none;
+ @include upto-sm {
+ display: none;
+ }
}
}
}
diff --git a/src/shared/components/Settings/Profile/Education/List/index.jsx b/src/shared/components/Settings/Profile/Education/List/index.jsx
index b8eaf68c7c..624afdc5f3 100644
--- a/src/shared/components/Settings/Profile/Education/List/index.jsx
+++ b/src/shared/components/Settings/Profile/Education/List/index.jsx
@@ -11,6 +11,7 @@ export default function EducationList(props) {
const {
educationList,
onDeleteItem,
+ onEditItem,
} = props;
return (
@@ -19,7 +20,12 @@ export default function EducationList(props) {
{
educationList.items.map((education, index) => (
-
+
))
}
@@ -31,4 +37,5 @@ export default function EducationList(props) {
EducationList.propTypes = {
educationList: PT.shape().isRequired,
onDeleteItem: PT.func.isRequired,
+ onEditItem: PT.func.isRequired,
};
diff --git a/src/shared/components/Settings/Profile/Education/dropdowns.json b/src/shared/components/Settings/Profile/Education/dropdowns.json
deleted file mode 100644
index 3821590f7a..0000000000
--- a/src/shared/components/Settings/Profile/Education/dropdowns.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "type": [
- {
- "key": "type",
- "name": "Secondary School"
- },
- {
- "key": "type",
- "name": "University"
- }
- ]
-}
\ No newline at end of file
diff --git a/src/shared/components/Settings/Profile/Education/index.jsx b/src/shared/components/Settings/Profile/Education/index.jsx
index 326ce05fc5..ffc9d7cecb 100644
--- a/src/shared/components/Settings/Profile/Education/index.jsx
+++ b/src/shared/components/Settings/Profile/Education/index.jsx
@@ -10,11 +10,12 @@ import React from 'react';
import PT from 'prop-types';
import _ from 'lodash';
import moment from 'moment';
-import Select from 'components/Select';
import ConsentComponent from 'components/Settings/ConsentComponent';
import { PrimaryButton } from 'topcoder-react-ui-kit';
import DatePicker from 'components/challenge-listing/Filters/DatePicker';
-import dropdowns from './dropdowns.json';
+import ErrorMessage from 'components/Settings/ErrorMessage';
+import { validateStartDate, validateEndDate } from 'utils/settings';
+import ConfirmationModal from '../../CofirmationModal';
import EducationList from './List';
import './styles.scss';
@@ -25,6 +26,7 @@ export default class Education extends ConsentComponent {
super(props);
this.onHandleDeleteEducation = this.onHandleDeleteEducation.bind(this);
this.onDeleteEducation = this.onDeleteEducation.bind(this);
+ this.onEditEducation = this.onEditEducation.bind(this);
this.onUpdateSelect = this.onUpdateSelect.bind(this);
this.loadEducationTrait = this.loadEducationTrait.bind(this);
this.onUpdateInput = this.onUpdateInput.bind(this);
@@ -33,23 +35,30 @@ export default class Education extends ConsentComponent {
this.loadPersonalizationTrait = this.loadPersonalizationTrait.bind(this);
this.updatePredicate = this.updatePredicate.bind(this);
this.onUpdateDate = this.onUpdateDate.bind(this);
+ this.onCancelEditStatus = this.onCancelEditStatus.bind(this);
const { userTraits } = props;
this.state = {
formInvalid: false,
- errorMessage: '',
+ startDateInvalid: false,
+ startDateInvalidMsg: '',
+ endDateInvalid: false,
+ endDateInvalidMsg: '',
educationTrait: this.loadEducationTrait(userTraits),
personalizationTrait: this.loadPersonalizationTrait(userTraits),
newEducation: {
- type: '',
schoolCollegeName: '',
major: '',
timePeriodFrom: '',
timePeriodTo: '',
graduated: false,
},
+ isSubmit: false,
isMobileView: false,
screenSM: 767,
+ isEdit: false,
+ indexNo: null,
+ showConfirmation: false,
};
}
@@ -65,9 +74,12 @@ export default class Education extends ConsentComponent {
educationTrait,
personalizationTrait,
formInvalid: false,
- errorMessage: '',
+ startDateInvalid: false,
+ startDateInvalidMsg: '',
+ endDateInvalid: false,
+ endDateInvalidMsg: '',
+ isSubmit: false,
newEducation: {
- type: '',
schoolCollegeName: '',
major: '',
timePeriodFrom: '',
@@ -88,71 +100,84 @@ export default class Education extends ConsentComponent {
*/
onCheckFormValue(newEducation) {
let invalid = false;
- let dateInvalid = false;
- let errorMessage = '';
- let dateCount = 0;
- let dateError = '';
- let haveDate = false;
-
- if (!_.trim(newEducation.type).length) {
- errorMessage += 'Type, ';
- invalid = true;
- }
if (!_.trim(newEducation.schoolCollegeName).length) {
- errorMessage += 'Name, ';
invalid = true;
}
- if (!_.trim(newEducation.major).length) {
- errorMessage += 'Major, ';
- invalid = true;
- }
+ const fromDateValidResult = validateStartDate(newEducation.graduated,
+ newEducation.timePeriodFrom, newEducation.timePeriodTo);
+ const endDateValidResult = validateEndDate(newEducation.graduated,
+ newEducation.timePeriodFrom, newEducation.timePeriodTo);
+ const formInvalid = invalid || fromDateValidResult.invalid || endDateValidResult.invalid;
- if (errorMessage.length > 0) {
- errorMessage += ' cannot be empty';
- }
+ this.setState({
+ formInvalid,
+ startDateInvalid: fromDateValidResult.invalid,
+ startDateInvalidMsg: fromDateValidResult.message,
+ endDateInvalidMsg: endDateValidResult.message,
+ endDateInvalid: endDateValidResult.invalid,
+ });
+ return formInvalid;
+ }
- const fromDate = new Date(newEducation.timePeriodFrom).getTime();
- const toDate = new Date(newEducation.timePeriodTo).getTime();
+ onCheckStartDate() {
+ const { newEducation } = this.state;
+ const currentDate = new Date().setHours(0, 0, 0, 0);
+ const result = {
+ invalid: false,
+ message: '',
+ };
- if (fromDate > toDate) {
- dateError += 'From Date value should be smaller than To Date value. ';
- dateInvalid = true;
- haveDate = true;
- }
+ if (!_.isEmpty(newEducation.timePeriodFrom) && _.isEmpty(newEducation.timePeriodTo)) {
+ const fromDate = new Date(newEducation.timePeriodFrom).setHours(0, 0, 0, 0);
- if (!haveDate) {
- if (!_.trim(newEducation.timePeriodFrom).length) {
- dateError += 'From Date, ';
- dateInvalid = true;
- dateCount += 1;
+ if (fromDate > currentDate) {
+ result.invalid = true;
+ result.message = 'Start Date should be in past or current';
}
+ } else if (!_.isEmpty(newEducation.timePeriodFrom) && !_.isEmpty(newEducation.timePeriodTo)) {
+ const fromDate = new Date(newEducation.timePeriodFrom).setHours(0, 0, 0, 0);
+ const toDate = new Date(newEducation.timePeriodTo).setHours(0, 0, 0, 0);
- if (!_.trim(newEducation.timePeriodTo).length) {
- dateError += 'To Date, ';
- dateInvalid = true;
- dateCount += 1;
+ if (fromDate > currentDate) {
+ result.invalid = true;
+ result.message = 'Start Date should be in past or current';
}
- if (dateError.length > 0) {
- dateError = `The ${dateError} ${dateCount > 1 ? 'are' : 'is'} incomplete or ${dateCount > 1 ? 'have' : 'has'} an invalid date.`;
+
+ if (fromDate >= toDate) {
+ result.invalid = true;
+ result.message = 'Start Date should be before End Date';
}
}
+ return result;
+ }
- if (errorMessage.length > 0) {
- errorMessage = `${errorMessage}. \n${dateError}`;
- } else if (dateError.length > 0) {
- errorMessage = dateError;
- invalid = dateInvalid;
- }
+ onCheckEndDate() {
+ const { newEducation } = this.state;
+ const currentDate = new Date().setHours(0, 0, 0, 0);
+ const result = {
+ invalid: false,
+ message: '',
+ };
+
+ if (!_.isEmpty(newEducation.timePeriodFrom) && !_.isEmpty(newEducation.timePeriodTo)) {
+ const toDate = new Date(newEducation.timePeriodTo).setHours(0, 0, 0, 0);
- this.setState({ errorMessage, formInvalid: invalid });
- return invalid;
+ if (newEducation.graduated && (toDate > currentDate)) {
+ result.invalid = true;
+ result.message = 'End Date should be in past or current';
+ }
+ }
+ return formInvalid;
}
onHandleDeleteEducation(indexNo) {
- this.showConsent(this.onDeleteEducation.bind(this, indexNo));
+ this.setState({
+ showConfirmation: true,
+ indexNo,
+ });
}
onUpdateDate(date, timePeriod) {
@@ -160,7 +185,7 @@ export default class Education extends ConsentComponent {
const { newEducation: oldEducation } = this.state;
const newEducation = { ...oldEducation };
newEducation[timePeriod] = date;
- this.setState({ newEducation });
+ this.setState({ newEducation, isSubmit: false });
}
}
@@ -188,6 +213,43 @@ export default class Education extends ConsentComponent {
} else {
deleteUserTrait(handle, 'education', tokenV3);
}
+
+ this.setState({
+ showConfirmation: false,
+ indexNo: null,
+ isSubmit: false,
+ isEdit: false,
+ formInvalid: false,
+ startDateInvalid: false,
+ startDateInvalidMsg: '',
+ endDateInvalid: false,
+ endDateInvalidMsg: '',
+ });
+ }
+
+ /**
+ * Edit Education by index
+ * @param indexNo the education index no
+ */
+ onEditEducation(indexNo) {
+ const { educationTrait } = this.state;
+ this.setState({
+ newEducation: {
+ schoolCollegeName: educationTrait.traits.data[indexNo].schoolCollegeName,
+ major: _.isEmpty(educationTrait.traits.data[indexNo].major) ? '' : educationTrait.traits.data[indexNo].major,
+ timePeriodFrom: _.isEmpty(educationTrait.traits.data[indexNo].timePeriodFrom) ? '' : educationTrait.traits.data[indexNo].timePeriodFrom,
+ timePeriodTo: _.isEmpty(educationTrait.traits.data[indexNo].timePeriodTo) ? '' : educationTrait.traits.data[indexNo].timePeriodTo,
+ graduated: educationTrait.traits.data[indexNo].graduated,
+ },
+ isSubmit: false,
+ isEdit: true,
+ indexNo,
+ formInvalid: false,
+ startDateInvalid: false,
+ startDateInvalidMsg: '',
+ endDateInvalid: false,
+ endDateInvalidMsg: '',
+ });
}
/**
@@ -195,7 +257,9 @@ export default class Education extends ConsentComponent {
* @param answer user consent answer value
*/
onAddEducation(answer) {
- const { newEducation, personalizationTrait } = this.state;
+ const {
+ newEducation, personalizationTrait, isEdit, indexNo,
+ } = this.state;
if (this.onCheckFormValue(newEducation)) {
return;
@@ -210,32 +274,46 @@ export default class Education extends ConsentComponent {
const { educationTrait } = this.state;
- newEducation.timePeriodFrom = new Date(newEducation.timePeriodFrom).getTime();
- newEducation.timePeriodTo = new Date(newEducation.timePeriodTo).getTime();
+ const education = _.clone(newEducation);
+ if (_.isEmpty(education.major)) {
+ delete education.major;
+ }
+ if (_.isEmpty(education.timePeriodFrom)) {
+ delete education.timePeriodFrom;
+ } else {
+ education.timePeriodFrom = new Date(newEducation.timePeriodFrom).getTime();
+ }
+ if (_.isEmpty(education.timePeriodTo)) {
+ delete education.timePeriodTo;
+ } else {
+ education.timePeriodTo = new Date(newEducation.timePeriodTo).getTime();
+ }
if (educationTrait.traits && educationTrait.traits.data.length > 0) {
- const newEducationTrait = { ...educationTrait };
- newEducationTrait.traits.data.push(newEducation);
- this.setState({ educationTrait: newEducationTrait });
+ const newEducationTrait = _.cloneDeep(educationTrait);
+ if (isEdit) {
+ newEducationTrait.traits.data.splice(indexNo, 1);
+ }
+ newEducationTrait.traits.data.push(education);
updateUserTrait(handle, 'education', newEducationTrait.traits.data, tokenV3);
} else {
const newEducations = [];
- newEducations.push(newEducation);
- const traits = {
- data: newEducations,
- };
- this.setState({ educationTrait: { traits } });
+ newEducations.push(education);
addUserTrait(handle, 'education', newEducations, tokenV3);
}
const empty = {
- type: '',
schoolCollegeName: '',
major: '',
timePeriodFrom: '',
timePeriodTo: '',
graduated: false,
};
- this.setState({ newEducation: empty });
+ this.setState({
+ newEducation: empty,
+ isEdit: false,
+ indexNo: null,
+ isSubmit: false,
+ });
// save personalization
if (_.isEmpty(personalizationTrait)) {
const personalizationData = { userConsent: answer };
@@ -256,8 +334,20 @@ export default class Education extends ConsentComponent {
onUpdateInput(e) {
const { newEducation: oldEducation } = this.state;
const newEducation = { ...oldEducation };
- newEducation[e.target.name] = e.target.type !== 'checkbox' ? e.target.value : e.target.checked;
- this.setState({ newEducation });
+ if (e.target.type !== 'checkbox') {
+ newEducation[e.target.name] = e.target.value;
+ } else {
+ newEducation[e.target.name] = e.target.checked;
+ if (e.target.checked) { // if graduated and toDate is in Future, nullify it
+ const toDate = new Date(newEducation.timePeriodTo).setHours(0, 0, 0, 0);
+ const currentDate = new Date().setHours(0, 0, 0, 0);
+ if (toDate > currentDate) {
+ newEducation.timePeriodTo = '';
+ }
+ }
+ }
+
+ this.setState({ newEducation, isSubmit: false });
}
/**
@@ -269,7 +359,7 @@ export default class Education extends ConsentComponent {
const { newEducation: oldEducation } = this.state;
const newEducation = { ...oldEducation };
newEducation[option.key] = option.name;
- this.setState({ newEducation });
+ this.setState({ newEducation, isSubmit: false });
}
}
@@ -280,6 +370,7 @@ export default class Education extends ConsentComponent {
onHandleAddEducation(e) {
e.preventDefault();
const { newEducation } = this.state;
+ this.setState({ isSubmit: true });
if (this.onCheckFormValue(newEducation)) {
return;
}
@@ -311,6 +402,29 @@ export default class Education extends ConsentComponent {
this.setState({ isMobileView: window.innerWidth <= screenSM });
}
+ onCancelEditStatus() {
+ const { isEdit } = this.state;
+ if (isEdit) {
+ this.setState({
+ isEdit: false,
+ isSubmit: false,
+ indexNo: null,
+ newEducation: {
+ schoolCollegeName: '',
+ major: '',
+ timePeriodFrom: '',
+ timePeriodTo: '',
+ graduated: false,
+ },
+ formInvalid: false,
+ startDateInvalid: false,
+ startDateInvalidMsg: '',
+ endDateInvalid: false,
+ endDateInvalidMsg: '',
+ });
+ }
+ }
+
render() {
const {
settingsUI,
@@ -318,13 +432,22 @@ export default class Education extends ConsentComponent {
const {
educationTrait,
isMobileView,
+ isEdit,
+ showConfirmation,
+ indexNo,
+ formInvalid,
+ startDateInvalid,
+ startDateInvalidMsg,
+ endDateInvalid,
+ endDateInvalidMsg,
+ isSubmit,
} = this.state;
const tabs = settingsUI.TABS.PROFILE;
const currentTab = settingsUI.currentProfileTab;
const containerStyle = currentTab === tabs.EDUCATION ? '' : 'hide';
const educationItems = educationTrait.traits
? educationTrait.traits.data.slice() : [];
- const { newEducation, formInvalid, errorMessage } = this.state;
+ const { newEducation } = this.state;
return (
@@ -332,10 +455,19 @@ export default class Education extends ConsentComponent {
{
this.shouldRenderConsent() && this.renderConsent()
}
+ {
+ showConfirmation && (
+
this.showConsent(this.onDeleteEducation.bind(this, indexNo))}
+ onCancel={() => this.setState({
+ showConfirmation: false,
+ indexNo: null,
+ })}
+ name={educationTrait.traits.data[indexNo].schoolCollegeName}
+ />
+ )
+ }
-
- { errorMessage }
-
Education
@@ -347,98 +479,113 @@ export default class Education extends ConsentComponent {
&& (
)
}
0 ? 'second' : 'first'}`}>
- Add a new education
+ {
+ isEdit ? (Edit education)
+ : (Add a new education)
+ }