diff --git a/jam-ui/src/hooks/useNotifications.js b/jam-ui/src/hooks/useNotifications.js
new file mode 100644
index 000000000..5e040bc06
--- /dev/null
+++ b/jam-ui/src/hooks/useNotifications.js
@@ -0,0 +1,67 @@
+import { useState, useEffect } from 'react';
+import { fetchNotifications } from '../store/features/notificationSlice';
+import { fetchPeopleByIds } from '../store/features/peopleSlice';
+import { useDispatch, useSelector } from 'react-redux';
+
+const useNotifications = user => {
+ const LIMIT = 20;
+ const [offset, setOffset] = useState(0);
+ const [notifications, setNotifications] = useState([]);
+
+ const reduxNotifications = useSelector(state => state.notification.notifications);
+ const next = useSelector(state => state.notification.next);
+ const notificationStatus = useSelector(state => state.notification.status);
+ const unread_total = useSelector(state => state.notification.unread_total);
+ const peopleStatus = useSelector(state => state.people.status);
+ const people = useSelector(state => state.people.people);
+
+ const dispatch = useDispatch();
+
+ const loadNotifications = async () => {
+ const options = {
+ userId: user.id,
+ offset: offset,
+ limit: LIMIT
+ };
+ try {
+ await dispatch(fetchNotifications(options)).unwrap();
+ } catch (error) {
+ console.log(error);
+ }
+ };
+
+ const fetchNotificationSourceUsers = async () => {
+ const sourceUserIds = reduxNotifications.map(notification => notification.source_user_id).filter((value, index, self) => self.indexOf(value) === index);
+ const options = { userId: user.id, ids: sourceUserIds };
+ try {
+ await dispatch(fetchPeopleByIds(options)).unwrap();
+ } catch (error) {
+ console.log(error);
+ }
+ };
+
+ useEffect(() => {
+ if (reduxNotifications && reduxNotifications.length && notificationStatus === 'succeeded') {
+ fetchNotificationSourceUsers();
+ }
+ }, [reduxNotifications, notificationStatus]);
+
+
+ useEffect(() => {
+ const newNotifications = reduxNotifications.filter(notification => !notifications.find(n => n.id === notification.id));
+ setNotifications(prev => [...prev, ...newNotifications]);
+ }, [people]);
+
+ return {
+ notifications,
+ offset,
+ setOffset,
+ loadNotifications,
+ next,
+ unread_total,
+ notificationStatus,
+ peopleStatus
+ };
+};
+
+export default useNotifications;
diff --git a/jam-ui/src/hooks/useUserProfile.js b/jam-ui/src/hooks/useUserProfile.js
index 6f3de8228..71bfc4e04 100644
--- a/jam-ui/src/hooks/useUserProfile.js
+++ b/jam-ui/src/hooks/useUserProfile.js
@@ -1,44 +1,46 @@
-import { getPersonById } from '../helpers/rest';
import { useEffect, useState, useMemo } from 'react';
+import { useSelector, useDispatch } from 'react-redux';
+import { fetchPerson } from '../store/features/peopleSlice';
-const useUserProfile = (user) => {
- const [userProfile, setUserProfile] = useState(null)
+const useUserProfile = user => {
+ const [userProfile, setUserProfile] = useState(null);
+ const people = useSelector(state => state.people.people);
+ const dispatch = useDispatch();
useEffect(() => {
if (!user) {
setUserProfile(null);
return;
}
- getPersonById(user.id)
- .then(response => {
- if (response.ok) {
- return response.json();
- }
- })
- .then(data => {
- setUserProfile(data)
- })
- .catch(error => console.error(error));
+ const person = people.find(person => person.id === user.id);
+ if (person) {
+ setUserProfile(person);
+ } else {
+ dispatch(fetchPerson({ userId: user.id }))
+ .unwrap()
+ .then(resp => {
+ setUserProfile(resp);
+ });
+ }
- return () => {
- setUserProfile(null);
- }
+ return () => {
+ setUserProfile(null);
+ };
}, [user]);
-
const photoUrl = useMemo(() => {
- if(userProfile && userProfile.v2_photo_uploaded){
- return userProfile.v2_photo_url
- }else if(userProfile && !userProfile.v2_photo_uploaded){
- return user.photo_url
+ if (userProfile && userProfile.v2_photo_uploaded) {
+ return userProfile.v2_photo_url;
+ } else if (userProfile && !userProfile.v2_photo_uploaded) {
+ return user.photo_url;
}
- return null
- }, [userProfile])
+ return null;
+ }, [userProfile]);
- return{
+ return {
userProfile,
photoUrl
- }
-}
+ };
+};
export default useUserProfile;
diff --git a/jam-ui/src/store/features/notificationSlice.js b/jam-ui/src/store/features/notificationSlice.js
index 9bf0916ca..78fc80e64 100644
--- a/jam-ui/src/store/features/notificationSlice.js
+++ b/jam-ui/src/store/features/notificationSlice.js
@@ -1,6 +1,5 @@
import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
import {getNotifications, deleteNotification} from '../../helpers/rest'
-
const initialState = {
notifications: [],
next: null,
diff --git a/jam-ui/src/store/features/peopleSlice.js b/jam-ui/src/store/features/peopleSlice.js
index f3ba7f2da..f73ca694f 100644
--- a/jam-ui/src/store/features/peopleSlice.js
+++ b/jam-ui/src/store/features/peopleSlice.js
@@ -1,5 +1,5 @@
import { createSlice, createAsyncThunk } from "@reduxjs/toolkit"
-import { getPeople, getPersonById, acceptFriendRequest as accept } from '../../helpers/rest';
+import { getPeople, getPeopleByIds, getPersonById, acceptFriendRequest as accept } from '../../helpers/rest';
const initialState = {
people: [],
@@ -21,12 +21,19 @@ export const fetchPeople = createAsyncThunk(
export const preFetchPeople = createAsyncThunk(
'people/preFetchPeople',
async (options, thunkAPI) => {
-
const response = await getPeople(options)
return response.json()
}
)
+export const fetchPeopleByIds = createAsyncThunk(
+ 'people/fetchPeopleByIds',
+ async (options, thunkAPI) => {
+ const response = await getPeopleByIds(options)
+ return response.json()
+ }
+)
+
export const fetchPerson = createAsyncThunk(
'people/fetchPerson',
async (options, thunkAPI) => {
@@ -135,6 +142,20 @@ export const peopleSlice = createSlice({
state.people.push(action.payload)
}
})
+ .addCase(fetchPeopleByIds.pending, (state, action) => {
+ state.status = 'loading'
+ })
+ .addCase(fetchPeopleByIds.fulfilled, (state, action) => {
+ const records = new Set([...state.people, ...action.payload.musicians]);
+ const unique = [];
+ records.map(x => unique.filter(p => p.id === x.id).length > 0 ? null : unique.push(x))
+ state.people = unique
+ state.status = 'succeeded'
+ })
+ .addCase(fetchPeopleByIds.rejected, (state, action) => {
+ state.error = action.error.message
+ state.status = 'failed'
+ })
}
})
diff --git a/web/app/views/api_search/filter.rabl b/web/app/views/api_search/filter.rabl
index fcabade58..cb23075b5 100644
--- a/web/app/views/api_search/filter.rabl
+++ b/web/app/views/api_search/filter.rabl
@@ -25,7 +25,7 @@ node :is_blank_filter do |foo|
end
child(:results => :musicians) {
- attributes :id, :first_name, :last_name, :name, :city, :state, :country, :online, :musician, :photo_url, :biography, :regionname, :score, :full_score, :is_friend, :is_following, :pending_friend_request, :last_active_timestamp
+ attributes :id, :first_name, :last_name, :name, :city, :state, :country, :online, :musician, :photo_url, :biography, :regionname, :score, :full_score, :is_friend, :is_following, :pending_friend_request, :last_active_timestamp, :v2_photo_url, :v2_photo_uploaded
# node :is_friend do |musician|
# @search.is_friend?(musician)