diff --git a/jam-ui/src/components/dashboard/JKDashboardMain.js b/jam-ui/src/components/dashboard/JKDashboardMain.js
index dcd7b1c50..ba780ee43 100644
--- a/jam-ui/src/components/dashboard/JKDashboardMain.js
+++ b/jam-ui/src/components/dashboard/JKDashboardMain.js
@@ -32,6 +32,8 @@ import JKMusicSessions from '../page/JKMusicSessions';
import JKNewMusicSession from '../page/JKNewMusicSession';
import JKMusicSessionsLobby from '../page/JKMusicSessionsLobby';
+import JKEditProfile from '../page/JKEditProfile';
+
//import loadable from '@loadable/component';
//const DashboardRoutes = loadable(() => import('../../layouts/JKDashboardRoutes'));
//const PublicRoutes = loadable(() => import('../../layouts/JKPublicRoutes'))
@@ -195,6 +197,7 @@ function JKDashboardMain() {
+
{/*Redirect*/}
diff --git a/jam-ui/src/components/page/JKEditProfile.js b/jam-ui/src/components/page/JKEditProfile.js
new file mode 100644
index 000000000..a1b606507
--- /dev/null
+++ b/jam-ui/src/components/page/JKEditProfile.js
@@ -0,0 +1,654 @@
+import React, { useRef, useEffect, useState, useReducer } from 'react';
+import { Card, CardBody, Col, Row, CardHeader, Form, FormGroup, Label, Input, Button } from 'reactstrap';
+import Select from 'react-select';
+import FalconCardHeader from '../common/FalconCardHeader';
+import { useTranslation } from 'react-i18next';
+import JKCurrentUserAvatar from '../navbar/JKCurrentUserAvatar';
+import { useAuth } from '../../context/UserAuth';
+import { useForm, Controller } from 'react-hook-form';
+import {
+ getPersonById,
+ getInstruments,
+ getGenres,
+ updateUser,
+ getCountries,
+ getRegions,
+ getCities
+} from '../../helpers/rest';
+import { set } from 'lodash';
+
+function JKEditProfile() {
+ const { t } = useTranslation();
+ const { currentUser } = useAuth();
+ const [musicInstruments, setMusicInstruments] = useState([]);
+ const [genres, setGenres] = useState([]);
+ const [instrumentsInitialLoadingDone, setInstrumentsInitialLoadingDone] = useState(false);
+ const [genreInitialLoadingDone, setGenreInitialLoadingDone] = useState(false);
+ const [countries, setCountries] = useState([]);
+ const [regions, setRegions] = useState([]);
+ const [cities, setCities] = useState([]);
+
+ const [_, forceUpdate] = useReducer(x => x + 1, 0);
+
+ const saveTimeoutRef = useRef(null);
+ const cityRef = useRef(null);
+ const regionRef = useRef(null);
+
+ const PROFICIENCIES = [
+ { value: '1', label: 'Beginner' },
+ { value: '2', label: 'Intermediate' },
+ { value: '3', label: 'Advanced' }
+ ];
+
+ const { register, control, handleSubmit, setValue, getValues } = useForm({
+ defaultValues: {
+ firstName: '',
+ lastName: '',
+ country: '',
+ state: '',
+ city: '',
+ biography: '',
+ subscribeEmail: false,
+ virtualBand: false,
+ traditionalBand: false,
+ cowriting: false,
+ instruments: [],
+ genres: []
+ }
+ });
+
+ useEffect(() => {
+ if (currentUser) {
+ fetchCurentUser().then(userData => {
+ console.log('_DEBUG userData', userData);
+ fetchInstruments();
+ fetchGenres();
+ fetchCountries();
+ });
+ }
+ }, [currentUser]);
+
+ const fetchCurentUser = () => {
+ return new Promise((resolve, reject) => {
+ getPersonById(currentUser.id)
+ .then(response => {
+ if (response.ok) {
+ return response.json();
+ }
+ })
+ .then(data => {
+ setValue('firstName', data.first_name);
+ setValue('lastName', data.last_name);
+ setValue('country', data.country);
+ setValue('state', data.state);
+ setValue('city', data.city);
+ setValue('biography', data.biography);
+ setValue('subscribeEmail', data.subscribe_email);
+ setValue('virtualBand', data.virtual_band);
+ setValue('traditionalBand', data.traditional_band);
+ setValue('cowriting', data.cowriting);
+ setValue('instruments', data.instruments);
+ setValue('genres', data.genres);
+ if (data.country) {
+ fetchRegions(data.country);
+ }
+ if (data.country && data.state) {
+ fetchCities(data.country, data.state);
+ }
+ resolve(getValues());
+ })
+ .catch(error => reject(error));
+ });
+ };
+
+ const fetchInstruments = () => {
+ getInstruments()
+ .then(response => {
+ if (response.ok) {
+ return response.json();
+ }
+ })
+ .then(data => {
+ setMusicInstruments(data);
+ })
+ .catch(error => console.log(error));
+ };
+
+ useEffect(() => {
+ if (!musicInstruments.length || !getValues('instruments') || instrumentsInitialLoadingDone) return;
+ const updatedMusicInstruments = musicInstruments.map(musicInstrument => {
+ const instrument = getValues('instruments').find(instrument => instrument.instrument_id === musicInstrument.id);
+ if (instrument) {
+ musicInstrument.proficiency_level = instrument.proficiency_level;
+ musicInstrument.checked = true;
+ musicInstrument.instrument_id = instrument.instrument_id;
+ } else {
+ musicInstrument.proficiency_level = null;
+ musicInstrument.checked = false;
+ musicInstrument.instrument_id = null;
+ }
+ return musicInstrument;
+ });
+ setMusicInstruments(updatedMusicInstruments);
+ setInstrumentsInitialLoadingDone(true);
+ }, [musicInstruments, getValues('instruments')]);
+
+ const fetchGenres = () => {
+ getGenres()
+ .then(response => {
+ if (response.ok) {
+ return response.json();
+ }
+ })
+ .then(data => {
+ setGenres(data);
+ })
+ .catch(error => {
+ console.log(error);
+ });
+ };
+
+ useEffect(() => {
+ if (!genres.length || !getValues('genres') || genreInitialLoadingDone) return;
+ const updatedGenres = genres.map(genre => {
+ const userGenre = getValues('genres').find(userGenre => userGenre.genre_id === genre.id);
+ if (userGenre) {
+ genre.checked = true;
+ } else {
+ genre.checked = false;
+ }
+ genre.genre_id = genre.id;
+ return genre;
+ });
+ setGenres(updatedGenres);
+ setGenreInitialLoadingDone(true);
+ }, [genres, getValues('genres')]);
+
+ const fetchCountries = () => {
+ getCountries()
+ .then(response => {
+ if (response.ok) {
+ return response.json();
+ }
+ })
+ .then(data => {
+ setCountries(data.countriesx);
+ })
+ .catch(error => console.log(error));
+ };
+
+ const fetchRegions = countryCode => {
+ getRegions(countryCode)
+ .then(response => {
+ if (response.ok) {
+ return response.json();
+ }
+ })
+ .then(data => {
+ setRegions(data.regions);
+ })
+ .catch(error => console.log(error));
+ };
+
+ const fetchCities = (country, region) => {
+ getCities(country, region)
+ .then(response => {
+ if (response.ok) {
+ return response.json();
+ }
+ })
+ .then(data => {
+ setCities(data.cities);
+ })
+ .catch(error => console.log(error));
+ };
+
+ const onSubmit = data => console.log(data);
+
+ const handleInstrumentSelect = (e, musicInstrument) => {
+ //alert(e.target.checked)
+ if (e.target.checked) {
+ const userInstruments = getValues('instruments');
+ const thisInstrument = userInstruments.find(
+ instrument => instrument.instrument_id === musicInstrument.instrument_id
+ );
+ if (thisInstrument) return;
+ const { id } = musicInstrument;
+ const updatedInstruments = [...userInstruments, { ...musicInstrument, instrument_id: id }];
+ setValue('instruments', updatedInstruments);
+ } else {
+ const updatedInstruments = getValues('instruments').filter(
+ instrument => instrument.instrument_id !== musicInstrument.instrument_id
+ );
+ setValue('instruments', updatedInstruments);
+ }
+
+ const updatedMusicInstruments = musicInstruments.map(instrument => {
+ if (instrument.id === musicInstrument.id) {
+ instrument.checked = e.target.checked;
+ } else {
+ instrument.checked = instrument.checked;
+ }
+ return instrument;
+ });
+
+ setMusicInstruments(updatedMusicInstruments);
+ handleChange();
+ };
+
+ const handleInstrumentProficiencyChange = (option, musicInstrument) => {
+ const userInstrument = getValues('instruments').find(instrument => instrument.instrument_id === musicInstrument.id);
+ if (!userInstrument) return;
+ userInstrument.proficiency_level = option.value;
+ forceUpdate();
+ handleChange();
+ };
+
+ const handleGenreChange = (e, genre) => {
+ if (e.target.checked) {
+ const userGenres = getValues('genres');
+ const thisGenre = userGenres.find(userGenre => userGenre.genre_id === genre.genre_id);
+ if (thisGenre) return;
+ const updatedGenres = [...userGenres, { ...genre }];
+ setValue('genres', updatedGenres);
+ } else {
+ const updatedGenres = getValues('genres').filter(userGenre => userGenre.genre_id !== genre.genre_id);
+ setValue('genres', updatedGenres);
+ }
+
+ const updatedGenres = genres.map(genreItem => {
+ if (genreItem.genre_id === genre.genre_id) {
+ genreItem.checked = e.target.checked;
+ } else {
+ genreItem.checked = genreItem.checked;
+ }
+ return genreItem;
+ });
+
+ setGenres(updatedGenres);
+ handleChange();
+ };
+
+ const handleTextInputChage = () => {
+ clearTimeout(saveTimeoutRef.current);
+ saveTimeoutRef.current = setTimeout(() => {
+ handleChange();
+ }, 2000);
+ };
+
+ const skipRegionChange = useRef(false);
+
+ const handleCountryChange = selectedOpt => {
+ const country = selectedOpt.value;
+ setValue('country', country);
+ setValue('state', null);
+ setValue('city', null);
+ setRegions([]);
+ skipRegionChange.current = true;
+ regionRef.current.select.clearValue();
+ setCities([]);
+ cityRef.current.select.clearValue();
+ fetchRegions(country.value);
+ forceUpdate();
+ handleChange();
+ };
+
+ const handleRegionChange = selectedOpt => {
+ if (skipRegionChange.current) {
+ skipRegionChange.current = false;
+ return;
+ }
+ const state = selectedOpt.value;
+ const country = getValues('country');
+ setValue('state', state);
+ setValue('city', null);
+ setCities([]);
+ cityRef.current.select.clearValue();
+ fetchCities(country, state);
+ handleChange();
+ };
+
+ const handleChange = () => {
+ const params = getValues();
+ const data = {
+ first_name: params.firstName,
+ last_name: params.lastName,
+ country: params.country,
+ state: params.state,
+ city: params.city,
+ biography: params.biography,
+ subscribe_email: params.subscribeEmail,
+ virtual_band: params.virtualBand,
+ traditional_band: params.traditionalBand,
+ cowriting: params.cowriting,
+ instruments: params.instruments,
+ genres: params.genres
+ };
+ console.log('_DEBUG data', data);
+ // updateUser(currentUser.id, data).then(response => {
+ // if (response.ok) {
+ // return response.json();
+ // }
+ // }).then(data => {
+ // console.log('_DEBUG data', data);
+ // }
+ // ).catch(error => console.log(error));
+ };
+
+ return (
+
+
+
+
+
+
+ );
+}
+
+export default JKEditProfile;
diff --git a/jam-ui/src/helpers/rest.js b/jam-ui/src/helpers/rest.js
index 586ea2a30..f6ec11d3d 100644
--- a/jam-ui/src/helpers/rest.js
+++ b/jam-ui/src/helpers/rest.js
@@ -182,3 +182,40 @@ export const getLobbyChatMessages = (options = {}) => {
.catch(error => reject(error))
})
}
+
+
+export const updateUser = (userId, options) => {
+ return new Promise((resolve, reject) => {
+ apiFetch(`/users/${userId}`, {
+ method: 'PATCH',
+ body: JSON.stringify(options)
+ })
+ .then(response => resolve(response))
+ .catch(error => reject(error))
+ })
+}
+
+
+export const getCountries = () => {
+ return new Promise((resolve, reject) => {
+ apiFetch(`/countries`)
+ .then(response => resolve(response))
+ .catch(error => reject(error))
+ })
+}
+
+export const getRegions = (countryId) => {
+ return new Promise((resolve, reject) => {
+ apiFetch(`/regions?country=${countryId}`)
+ .then(response => resolve(response))
+ .catch(error => reject(error))
+ })
+}
+
+export const getCities = (countryId, regionId) => {
+ return new Promise((resolve, reject) => {
+ apiFetch(`/cities?country=${countryId}®ion=${regionId}`)
+ .then(response => resolve(response))
+ .catch(error => reject(error))
+ })
+}
\ No newline at end of file
diff --git a/jam-ui/src/i18n/config.js b/jam-ui/src/i18n/config.js
index 8d6c08072..56c791242 100644
--- a/jam-ui/src/i18n/config.js
+++ b/jam-ui/src/i18n/config.js
@@ -7,6 +7,7 @@ import peopleTranslationsEN from './locales/en/people.json'
import authTranslationsEN from './locales/en/auth.json'
import sessTranslationsEN from './locales/en/sessions.json'
import unsubscribeTranslationsEN from './locales/en/unsubscribe.json'
+import profileEN from './locales/en/profile.json'
import commonTranslationsES from './locales/es/common.json'
import homeTranslationsES from './locales/es/home.json'
@@ -14,6 +15,7 @@ import peopleTranslationsES from './locales/es/people.json'
import authTranslationsES from './locales/es/auth.json'
import sessTranslationsES from './locales/es/sessions.json'
import unsubscribeTranslationsES from './locales/es/unsubscribe.json'
+import profileES from './locales/es/profile.json'
i18n.use(initReactI18next).init({
fallbackLng: 'en',
@@ -27,6 +29,7 @@ i18n.use(initReactI18next).init({
auth: authTranslationsEN,
sessions: sessTranslationsEN,
unsubscribe: unsubscribeTranslationsEN,
+ profile: profileEN
},
es: {
//translations: require('./locales/es/translations.json')
@@ -36,6 +39,7 @@ i18n.use(initReactI18next).init({
auth: authTranslationsES,
sessions: sessTranslationsES,
unsubscribe: unsubscribeTranslationsES,
+ profile: profileES
}
},
//ns: ['translations'],
diff --git a/jam-ui/src/i18n/locales/en/profile.json b/jam-ui/src/i18n/locales/en/profile.json
new file mode 100644
index 000000000..2eade7bb7
--- /dev/null
+++ b/jam-ui/src/i18n/locales/en/profile.json
@@ -0,0 +1,3 @@
+{
+ "page_title": "Profile"
+}
diff --git a/jam-ui/src/i18n/locales/es/profile.json b/jam-ui/src/i18n/locales/es/profile.json
new file mode 100644
index 000000000..2eade7bb7
--- /dev/null
+++ b/jam-ui/src/i18n/locales/es/profile.json
@@ -0,0 +1,3 @@
+{
+ "page_title": "Profile"
+}