diff --git a/src/config/constants.ts b/src/config/constants.ts index fea4ab3b..9f2019b1 100644 --- a/src/config/constants.ts +++ b/src/config/constants.ts @@ -56,7 +56,7 @@ export const PRONOUN_PLACEHOLDER = 'Pronouns'; export const GENDER_LABEL = 'Gender'; export const GENDER_PLACEHOLDER = 'Gender'; export const PHONE_NUMBER_LABEL = 'Phone number'; -export const BIRTH_DATE_LABEL = 'Birth date'; +export const AGE_LABEL = 'Age'; export const FIRST_NAME_LABEL = 'First name'; export const LAST_NAME_LABEL = 'Last name'; @@ -102,6 +102,10 @@ export const COC_ACCEPTANCE_PHRASE = 'I accept the'; export const COC_MCHACKS_REQUEST_LABEL = 'McHacks Code of Conduct'; export const COC_MLH_REQUEST_LABEL = 'MLH terms, conditions and guidelines.'; export const COMMENTS_LABEL = "Is there anything you'd like us to know?"; +export const COUNTRY_LABEL = 'Country of Residence'; +export const COUNTRY_PLACEHOLDER = 'Country of Residence'; +export const COUNTRY_TEXT = + 'Please indicate your current country of residence.'; export const DEGREE_LABEL = 'Degree'; export const DEGREE_PLACEHOLDER = 'High School, Undergraduate...'; export const DRIBBBLE_LINK_LABEL = 'Dribbble URL'; diff --git a/src/config/countries.ts b/src/config/countries.ts new file mode 100644 index 00000000..f39e0980 --- /dev/null +++ b/src/config/countries.ts @@ -0,0 +1,259 @@ +// Used MLH's recommendation to use the ISO 3166 Standard for Country Names https://www.iso.org/iso-3166-country-codes.html + +export const CountriesList = [ + "Canada", + "Afghanistan", + "Åland Islands", + "Albania", + "Algeria", + "American Samoa", + "Andorra", + "Angola", + "Anguilla", + "Antarctica", + "Antigua and Barbuda", + "Argentina", + "Armenia", + "Aruba", + "Australia", + "Austria", + "Azerbaijan", + "Bahamas", + "Bahrain", + "Bangladesh", + "Barbados", + "Belarus", + "Belgium", + "Belize", + "Benin", + "Bermuda", + "Bhutan", + "Bolivia, Plurinational State of", + "Bonaire, Sint Eustatius and Saba", + "Bosnia and Herzegovina", + "Botswana", + "Bouvet Island", + "Brazil", + "British Indian Ocean Territory", + "Brunei Darussalam", + "Bulgaria", + "Burkina Faso", + "Burundi", + "Cabo Verde", + "Cambodia", + "Cameroon", + "Cayman Islands", + "Central African Republic", + "Chad", + "Chile", + "China", + "Christmas Island", + "Cocos (Keeling) Islands", + "Colombia", + "Comoros", + "Congo", + "Congo, Democratic Republic of the", + "Cook Islands", + "Costa Rica", + "Côte d'Ivoire", + "Croatia", + "Cuba", + "Curaçao", + "Cyprus", + "Czechia", + "Denmark", + "Djibouti", + "Dominica", + "Dominican Republic", + "Ecuador", + "Egypt", + "El Salvador", + "Equatorial Guinea", + "Eritrea", + "Estonia", + "Eswatini", + "Ethiopia", + "Falkland Islands (Malvinas)", + "Faroe Islands", + "Fiji", + "Finland", + "France", + "French Guiana", + "French Polynesia", + "French Southern Territories", + "Gabon", + "Gambia", + "Georgia", + "Germany", + "Ghana", + "Gibraltar", + "Greece", + "Greenland", + "Grenada", + "Guadeloupe", + "Guam", + "Guatemala", + "Guernsey", + "Guinea", + "Guinea-Bissau", + "Guyana", + "Haiti", + "Heard Island and McDonald Islands", + "Holy See", + "Honduras", + "Hong Kong", + "Hungary", + "Iceland", + "India", + "Indonesia", + "Iran, Islamic Republic of", + "Iraq", + "Ireland", + "Isle of Man", + "Israel", + "Italy", + "Jamaica", + "Japan", + "Jersey", + "Jordan", + "Kazakhstan", + "Kenya", + "Kiribati", + "Korea, Democratic People's Republic of", + "Korea, Republic of", + "Kuwait", + "Kyrgyzstan", + "Lao People's Democratic Republic", + "Latvia", + "Lebanon", + "Lesotho", + "Liberia", + "Libya", + "Liechtenstein", + "Lithuania", + "Luxembourg", + "Macao", + "Madagascar", + "Malawi", + "Malaysia", + "Maldives", + "Mali", + "Malta", + "Marshall Islands", + "Martinique", + "Mauritania", + "Mauritius", + "Mayotte", + "Mexico", + "Micronesia, Federated States of", + "Moldova, Republic of", + "Monaco", + "Mongolia", + "Montenegro", + "Montserrat", + "Morocco", + "Mozambique", + "Myanmar", + "Namibia", + "Nauru", + "Nepal", + "Netherlands, Kingdom of the", + "New Caledonia", + "New Zealand", + "Nicaragua", + "Niger", + "Nigeria", + "Niue", + "Norfolk Island", + "North Macedonia", + "Northern Mariana Islands", + "Norway", + "Oman", + "Pakistan", + "Palau", + "Palestine, State of", + "Panama", + "Papua New Guinea", + "Paraguay", + "Peru", + "Philippines", + "Pitcairn", + "Poland", + "Portugal", + "Puerto Rico", + "Qatar", + "Réunion", + "Romania", + "Russian Federation", + "Rwanda", + "Saint Barthélemy", + "Saint Helena, Ascension and Tristan da Cunha", + "Saint Kitts and Nevis", + "Saint Lucia", + "Saint Martin (French part)", + "Saint Pierre and Miquelon", + "Saint Vincent and the Grenadines", + "Samoa", + "San Marino", + "Sao Tome and Principe", + "Saudi Arabia", + "Senegal", + "Serbia", + "Seychelles", + "Sierra Leone", + "Singapore", + "Sint Maarten (Dutch part)", + "Slovakia", + "Slovenia", + "Solomon Islands", + "Somalia", + "South Africa", + "South Georgia and the South Sandwich Islands", + "South Sudan", + "Spain", + "Sri Lanka", + "Sudan", + "Suriname", + "Svalbard and Jan Mayen", + "Sweden", + "Switzerland", + "Syrian Arab Republic", + "Taiwan, Province of China", + "Tajikistan", + "Tanzania, United Republic of", + "Thailand", + "Timor-Leste", + "Togo", + "Tokelau", + "Tonga", + "Trinidad and Tobago", + "Tunisia", + "Türkiye", + "Turkmenistan", + "Turks and Caicos Islands", + "Tuvalu", + "Uganda", + "Ukraine", + "United Arab Emirates", + "United Kingdom of Great Britain and Northern Ireland", + "United States of America", + "United States Minor Outlying Islands", + "Uruguay", + "Uzbekistan", + "Vanuatu", + "Venezuela, Bolivarian Republic of", + "Viet Nam", + "Virgin Islands (British)", + "Virgin Islands (U.S.)", + "Wallis and Futuna", + "Western Sahara", + "Yemen", + "Zambia", + "Zimbabwe" +]; + +export const Countries = CountriesList.map((v) => ({ label: v, value: v })); +export default Countries; + + + \ No newline at end of file diff --git a/src/config/degrees.ts b/src/config/degrees.ts index a27a5325..14da8c1d 100644 --- a/src/config/degrees.ts +++ b/src/config/degrees.ts @@ -1,7 +1,15 @@ export enum Degrees { - HIGHSCHOOL = 'High School', + LESS_THAN_SECONDARY = 'Less than Secondary / High School', + SECONDARY = 'Secondary / High School', CEGEP = 'CEGEP', - UNDERGRADUATE = 'Undergraduate', - GRADUATE = 'Graduate', + COLLEGE = 'Undergraduate University (2 year - community college or similar)', + UNDERGRADUATE = 'Undergraduate University (3+ year)', + GRADUATE = 'Graduate University (Masters, Professional, Doctoral, etc)', + CODE_SCHOOL = 'Code School / Bootcamp', + VOCATIONAL = 'Other Vocational / Trade Program or Apprenticeship', + POSTDOC = 'Post Doctorate', + OTHER = 'Other', + NOT_STUDENT = "I'm not currently a student", + NO_ANSWER = 'Prefer not to answer' } export default Degrees; diff --git a/src/config/index.ts b/src/config/index.ts index 33f87687..de903183 100644 --- a/src/config/index.ts +++ b/src/config/index.ts @@ -2,6 +2,7 @@ export * from './APIRoute'; export * from './attendanceOptions'; export * from './authToken'; export * from './constants'; +export * from './countries'; export * from './degrees'; export * from './dietaryRestrictions'; export * from './ethnicity'; diff --git a/src/config/statsResponse.ts b/src/config/statsResponse.ts index 1190775b..78b2944f 100644 --- a/src/config/statsResponse.ts +++ b/src/config/statsResponse.ts @@ -15,6 +15,7 @@ export interface IStatsResponse { gender: { [key: string]: number }; travel: { true: number; false: number }; ethnicity: { [key: string]: number }; + country: { [key: string]: number }; jobInterest: { [key in JobInterest]: number }; major: { [key: string]: number }; graduationYear: { [key: string]: number }; diff --git a/src/config/userTypes.ts b/src/config/userTypes.ts index 6eb535c8..e6b35a7c 100644 --- a/src/config/userTypes.ts +++ b/src/config/userTypes.ts @@ -18,8 +18,8 @@ export interface IAccount { password: string; // The user's phone number phoneNumber: string; - // The birthdate - birthDate: string; + // The user's age + age: string; // The preferred pronoun pronoun: string; // The database id (if new, leave blank / make '') @@ -62,6 +62,7 @@ export interface IHacker { }; other: { // no enum for these + country: string; ethnicity: string[]; privacyPolicy: boolean; codeOfConduct: boolean; diff --git a/src/features/Account/ManageAccountForm.tsx b/src/features/Account/ManageAccountForm.tsx index 2910f580..0243caca 100644 --- a/src/features/Account/ManageAccountForm.tsx +++ b/src/features/Account/ManageAccountForm.tsx @@ -69,7 +69,7 @@ const ManageAccountForm: React.FC = (props) => { const [accountDetails, setAccountDetails] = useState({ accountType: (getValueFromQuery('accountType') as UserType) || UserType.UNKNOWN, - birthDate: '', + age: '', confirmed: false, email: getNestedAttr(props, ['location', 'state', 'email']) || '', firstName: '', @@ -101,7 +101,10 @@ const ManageAccountForm: React.FC = (props) => { try { const response = await Account.getSelf(); const newAccountDetails = response.data.data; - newAccountDetails.birthDate = date2input(newAccountDetails.birthDate); + + // Changed birthdate to age + //newAccountDetails.age = date2input(newAccountDetails.age); + setAccountDetails(newAccountDetails); } catch (e) { // If can't find self's account, shouldn't be logged in. Redirect to home page @@ -121,7 +124,7 @@ const ManageAccountForm: React.FC = (props) => { accountId: string = '' ): IAccount => ({ accountType: UserType.UNKNOWN, - birthDate: input2date(values.birthDate), + age: values.age, confirmed: false, email: values.email, firstName: values.firstName, @@ -245,15 +248,13 @@ const ManageAccountForm: React.FC = (props) => { - + = (props) => { gender: accountDetails.gender, dietaryRestrictions: accountDetails.dietaryRestrictions, phoneNumber: accountDetails.phoneNumber, - birthDate: accountDetails.birthDate, + age: accountDetails.age, }} onSubmit={handleSubmit} validationSchema={getValidationSchema( diff --git a/src/features/Account/validationSchema.ts b/src/features/Account/validationSchema.ts index 477f2d07..343c9c0e 100644 --- a/src/features/Account/validationSchema.ts +++ b/src/features/Account/validationSchema.ts @@ -1,4 +1,4 @@ -import { array, object, string } from 'yup'; +import { array, object, string, number } from 'yup'; const getValidationSchema = (isCreate: boolean) => { const password = isCreate @@ -25,19 +25,10 @@ const getValidationSchema = (isCreate: boolean) => { return !value || value.length === 11; } ), - birthDate: string() - .test('validDate', 'Must be valid date', (value) => { - if (!value || value.length !== 8) { - return false; - } else { - // Assume MMDDYYYY - const month = parseInt(value.substr(0, 2), 10); - const day = parseInt(value.substr(2, 2), 10); - const year = parseInt(value.substr(4, 4), 10); - return month <= 12 && day <= 31 && year >= 1901 && year <= 2018; - } - }) - .required('Required'), + age: number() + .required('Required') + .min(0, 'Age must be a positive number') // Minimum age + .max(100, 'Age must be less than or equal to 100'), // Maximum age }); }; diff --git a/src/features/Application/ManageApplicationForm.tsx b/src/features/Application/ManageApplicationForm.tsx index db3b1c97..cfde7a6a 100644 --- a/src/features/Application/ManageApplicationForm.tsx +++ b/src/features/Application/ManageApplicationForm.tsx @@ -20,6 +20,7 @@ import PaginationHeader from './PaginationHeader/PaginationHeader'; import getValidationSchema from './validationSchema'; import { + Countries, Degrees, FrontendRoute, HackerStatus, @@ -110,6 +111,7 @@ const ManageApplicationForm: React.FunctionComponent< }, other: { ethnicity: [], + country: '', privacyPolicy: false, codeOfConduct: false, }, @@ -464,6 +466,22 @@ const ManageApplicationForm: React.FunctionComponent< component={FormikElements.Error} name="hacker.application.other.ethnicity" /> + + + @@ -1097,6 +1115,12 @@ const ManageApplicationForm: React.FunctionComponent< {hackerDetails.application.other.ethnicity} +
+
{CONSTANTS.COUNTRY_LABEL}
+
+ {hackerDetails.application.other.country} +
+

diff --git a/src/features/Application/validationSchema.ts b/src/features/Application/validationSchema.ts index b0d6da78..d462f887 100644 --- a/src/features/Application/validationSchema.ts +++ b/src/features/Application/validationSchema.ts @@ -66,6 +66,7 @@ const getValidationSchema = (isCreate: boolean, pageNumber: number) => { }), other: object().shape({ ethnicity: array().required('Required'), + country: string().required('Required'), }), }), }), @@ -151,6 +152,7 @@ const getValidationSchema = (isCreate: boolean, pageNumber: number) => { }), other: object().shape({ ethnicity: array().required('Required'), + country: string().required('Required'), }), }), }), @@ -247,6 +249,7 @@ const getValidationSchema = (isCreate: boolean, pageNumber: number) => { }), other: object().shape({ ethnicity: array().required('Required'), + country: string().required('Required'), }), }), }), @@ -354,6 +357,7 @@ const getValidationSchema = (isCreate: boolean, pageNumber: number) => { }), other: object().shape({ ethnicity: array().required('Required'), + country: string().required('Required'), privacyPolicy: boolean() .required('Required') .test( diff --git a/src/features/Search/Search.tsx b/src/features/Search/Search.tsx index eb013f1b..138e475c 100644 --- a/src/features/Search/Search.tsx +++ b/src/features/Search/Search.tsx @@ -262,6 +262,10 @@ class SearchContainer extends React.Component<{}, ISearchState> { label: CONSTANTS.ETHNICITY_LABEL, key: 'application.other.ethnicity', }); + headers.push({ + label: CONSTANTS.COUNTRY_LABEL, + key: 'application.other.country', + }); headers.push({ label: CONSTANTS.GENDER_LABEL, key: 'accountId.gender' }); headers.push({ label: CONSTANTS.PRONOUN_LABEL, @@ -272,7 +276,7 @@ class SearchContainer extends React.Component<{}, ISearchState> { headers.forEach((header) => { tempHeaders.push(header.label); }); - const csvData: string[] = [tempHeaders.join('\t')]; + const csvData: string[] = [tempHeaders.join(',')]; this.filter().forEach((result) => { if (result.selected) { const row: string[] = []; @@ -286,10 +290,10 @@ class SearchContainer extends React.Component<{}, ISearchState> { } row.push(value); }); - csvData.push(row.join('\t')); + csvData.push(row.join(',')); } }); - fileDownload(csvData.join('\n'), 'hackerData.tsv', 'text/tsv'); + fileDownload(csvData.join('\n'), 'hackerData.csv', 'text/csv'); } private async triggerSearch(): Promise { diff --git a/src/features/SingleHacker/SingleHackerView.tsx b/src/features/SingleHacker/SingleHackerView.tsx index b4ad7adf..1cb7f76e 100644 --- a/src/features/SingleHacker/SingleHackerView.tsx +++ b/src/features/SingleHacker/SingleHackerView.tsx @@ -23,6 +23,8 @@ import ViewPDFComponent from '../../shared/Elements/ViewPDF'; import { Form, StyledSelect } from '../../shared/Form'; import ValidationErrorGenerator from '../../shared/Form/validationErrorGenerator'; import theme from '../../shared/Styles/theme'; + +//date2age is currently unused import { date2age, getOptionsFromEnum } from '../../util'; import SHField from './SingleHackerField'; @@ -134,7 +136,7 @@ const SingleHackerView: React.FC = (props) => { justifyContent="space-between" alignItems="center" > - +