diff --git a/jam-ui/cypress/e2e/sessions/session-history-page.cy.js b/jam-ui/cypress/e2e/sessions/session-history-page.cy.js
new file mode 100644
index 000000000..f26c9d6b6
--- /dev/null
+++ b/jam-ui/cypress/e2e/sessions/session-history-page.cy.js
@@ -0,0 +1,21 @@
+///
+
+import makeFakeUser from '../../factories/user';
+
+describe('Session History', () => {
+ const currentUser = makeFakeUser();
+ beforeEach(() => {
+ cy.stubAuthenticate({ id: currentUser.id });
+ });
+
+ describe('When user has no sessions', () => {
+ it('should show no sessions message', () => {
+ cy.intercept('GET', /\S+\/api\/sessions\/history/, {
+ body: []
+ }).as('fetchAllSessions')
+ cy.visit('/sessions/history');
+ cy.wait('@fetchAllSessions');
+ cy.contains('No Records!');
+ });
+ });
+});
diff --git a/jam-ui/src/components/page/JKMusicSessionsHistory.js b/jam-ui/src/components/page/JKMusicSessionsHistory.js
new file mode 100644
index 000000000..34fc6705b
--- /dev/null
+++ b/jam-ui/src/components/page/JKMusicSessionsHistory.js
@@ -0,0 +1,63 @@
+import React, { useEffect, useState } from 'react';
+import { Alert, Col, Row, Card, CardBody } from 'reactstrap';
+import FalconCardHeader from '../common/FalconCardHeader';
+import { useTranslation } from 'react-i18next';
+import { useDispatch, useSelector } from 'react-redux';
+import Loader from '../common/Loader';
+import { isIterableArray } from '../../helpers/utils';
+import { useResponsive } from '@farfetch/react-context-responsive';
+import { fetchSessionsHistory } from '../../store/features/sessionsHistorySlice';
+import JKSessionsHistoryList from '../sessions/JKSessionsHistoryList';
+
+const JKMusicSessionsHistory = () => {
+ const { t } = useTranslation();
+ const { greaterThan } = useResponsive();
+ const dispatch = useDispatch();
+ const sessions = useSelector(state => state.sessionsHistory.sessions);
+ const loadingStatus = useSelector(state => state.sessionsHistory.status);
+ const [offset, setOffset] = useState(0);
+ const LIMIT = 10;
+
+ useEffect(() => {
+ const options = {
+ offset,
+ limit: LIMIT
+ };
+ dispatch(fetchSessionsHistory(options));
+ }, [offset]);
+
+ return (
+
+
+
+ {loadingStatus === 'loading' && sessions.length === 0 ? (
+
+ ) : isIterableArray(sessions) ? (
+ <>
+ {greaterThan.sm ? (
+
+
+
+
+
+ ) : (
+
+ {/* */}
+
+ )}
+ >
+ ) : (
+
+
+
+ {t('no_records', { ns: 'common' })}
+
+
+
+ )}
+
+
+ );
+};
+
+export default JKMusicSessionsHistory;
diff --git a/jam-ui/src/components/sessions/JKSessionsHistoryList.js b/jam-ui/src/components/sessions/JKSessionsHistoryList.js
new file mode 100644
index 000000000..f95913f74
--- /dev/null
+++ b/jam-ui/src/components/sessions/JKSessionsHistoryList.js
@@ -0,0 +1,12 @@
+import React from 'react'
+
+const JKSessionsHistoryList = ({sessions}) => {
+ return (
+
+
JKSessionsHistoryList
+
{JSON.stringify(sessions, null, 2)}
+
+ )
+}
+
+export default JKSessionsHistoryList
\ No newline at end of file
diff --git a/jam-ui/src/store/features/sessionsHistorySlice.js b/jam-ui/src/store/features/sessionsHistorySlice.js
new file mode 100644
index 000000000..09bff6f34
--- /dev/null
+++ b/jam-ui/src/store/features/sessionsHistorySlice.js
@@ -0,0 +1,46 @@
+import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
+import { getSessionsHistory } from '../../helpers/rest'
+
+const initialState = {
+ sessions: [],
+ status: 'idel',
+ error: null,
+}
+
+export const fetchSessionsHistory = createAsyncThunk(
+ "sessionsHistory/fetchHistory",
+ async (options, thunkAPI) => {
+ const response = await getSessionsHistory(options);
+ return response.json();
+ }
+)
+
+export const SessionsHistorySlice = createSlice({
+ name: "sessionsHistory",
+ initialState,
+ reducers: {
+ },
+ extraReducers: (builder) => {
+ builder
+ .addCase(fetchSessionsHistory.pending, (state, action) => {
+ state.status = "loading";
+ })
+ .addCase(fetchSessionsHistory.fulfilled, (state, action) => {
+ console.log(action.payload);
+ // state.status = "succeeded";
+ // state.sessions = action.payload;
+
+ const records = new Set([...state.sessions, ...action.payload]);
+ const unique = [];
+ records.map(x => unique.filter(a => a.id === x.id).length > 0 ? null : unique.push(x))
+ state.sessions = unique
+ state.status = 'succeeded'
+ })
+ .addCase(fetchSessionsHistory.rejected, (state, action) => {
+ state.status = 'failed'
+ state.error = action.error.message
+ })
+ }
+})
+
+export default SessionsHistorySlice.reducer
\ No newline at end of file