join_gamenight #8
@ -5,6 +5,8 @@ import Login from './components/Login';
 | 
			
		||||
import Gamenights from './components/Gamenights';
 | 
			
		||||
import Gamenight from './components/Gamenight';
 | 
			
		||||
 | 
			
		||||
import { get_gamenights, get_games, unpack_api_result, login } from './api/Api';
 | 
			
		||||
 | 
			
		||||
const localStorageUserKey = 'user';
 | 
			
		||||
 | 
			
		||||
function App() {
 | 
			
		||||
@ -15,24 +17,14 @@ function App() {
 | 
			
		||||
  const [games, setGames] = useState([]);
 | 
			
		||||
  const [activeGamenight, setActiveGamenight] = useState(null);
 | 
			
		||||
 | 
			
		||||
  const POST_HEADER = {'Content-Type': 'application/json'};
 | 
			
		||||
  const AUTH_HEADER = {'Authorization': `Bearer ${user?.jwt}`};
 | 
			
		||||
 | 
			
		||||
  const handleLogin = (input) => {
 | 
			
		||||
    const requestOptions = {
 | 
			
		||||
      method: 'POST',
 | 
			
		||||
      headers: { 'Content-Type': 'application/json' },
 | 
			
		||||
      body: JSON.stringify(input)
 | 
			
		||||
    };
 | 
			
		||||
    fetch('api/login', requestOptions)
 | 
			
		||||
      .then(response => response.json())
 | 
			
		||||
      .then(data => {
 | 
			
		||||
        if(data.result === "Ok") {
 | 
			
		||||
          setUser(data.user);
 | 
			
		||||
          localStorage.setItem(localStorageUserKey, JSON.stringify(data.user));
 | 
			
		||||
        } else {
 | 
			
		||||
          setFlashData({
 | 
			
		||||
            type: "Error",
 | 
			
		||||
            message: data.message
 | 
			
		||||
          });
 | 
			
		||||
        }
 | 
			
		||||
    unpack_api_result(login(input), setFlashData)
 | 
			
		||||
      .then(result => {
 | 
			
		||||
        setUser(result.user);
 | 
			
		||||
        localStorage.setItem(localStorageUserKey, JSON.stringify(result.user));
 | 
			
		||||
      });
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
@ -55,43 +47,15 @@ function App() {
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    if (user !== null) {
 | 
			
		||||
      const requestOptions = {
 | 
			
		||||
        method: 'GET',
 | 
			
		||||
        headers: { 'Authorization': `Bearer ${user.jwt}` },
 | 
			
		||||
      };
 | 
			
		||||
      fetch('api/gamenights', requestOptions)
 | 
			
		||||
        .then(response => response.json())
 | 
			
		||||
        .then(data => {
 | 
			
		||||
          if(data.result === "Ok") {
 | 
			
		||||
            setGamenights(data.gamenights)
 | 
			
		||||
          } else {
 | 
			
		||||
            setFlashData({
 | 
			
		||||
              type: "Error",
 | 
			
		||||
              message: data.message
 | 
			
		||||
            });
 | 
			
		||||
          }
 | 
			
		||||
        });
 | 
			
		||||
      unpack_api_result(get_gamenights(user.jwt), setFlashData)
 | 
			
		||||
        .then(result => setGamenights(result.gamenights));
 | 
			
		||||
    }
 | 
			
		||||
  }, [user])
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    if (user !== null) {
 | 
			
		||||
      const requestOptions = {
 | 
			
		||||
        method: 'GET',
 | 
			
		||||
        headers: { 'Authorization': `Bearer ${user.jwt}` },
 | 
			
		||||
      };
 | 
			
		||||
      fetch('api/games', requestOptions)
 | 
			
		||||
        .then(response => response.json())
 | 
			
		||||
        .then(data => {
 | 
			
		||||
          if(data.result === "Ok") {
 | 
			
		||||
            setGames(data.games)
 | 
			
		||||
          } else {
 | 
			
		||||
            setFlashData({
 | 
			
		||||
              type: "Error",
 | 
			
		||||
              message: data.message
 | 
			
		||||
            });
 | 
			
		||||
          }
 | 
			
		||||
        });
 | 
			
		||||
      unpack_api_result(get_games(user.jwt), setFlashData)
 | 
			
		||||
        .then(result => setGames(result.games));
 | 
			
		||||
    }        
 | 
			
		||||
  }, [user])
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										70
									
								
								frontend/src/api/Api.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								frontend/src/api/Api.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,70 @@
 | 
			
		||||
 | 
			
		||||
import fetchResource from './FetchResource'
 | 
			
		||||
 | 
			
		||||
export function unpack_api_result(promise, onError) {
 | 
			
		||||
  promise.then(result => {
 | 
			
		||||
    if(result.result !== 'Ok') {
 | 
			
		||||
      onError({
 | 
			
		||||
        type: 'Error',
 | 
			
		||||
        message: result.message
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
  })
 | 
			
		||||
  .catch(error => {
 | 
			
		||||
      onError({
 | 
			
		||||
      type: 'Error',
 | 
			
		||||
      message: `${error.status} ${error.message}`
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
  return promise;      
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function get_gamenights(token) {
 | 
			
		||||
  return fetchResource('api/gamenights', {
 | 
			
		||||
    method: 'GET',
 | 
			
		||||
    headers: {
 | 
			
		||||
      'Authorization': `Bearer ${token}`
 | 
			
		||||
    },
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function post_gamenight(input, token) {
 | 
			
		||||
  return fetchResource('api/gamenights', {
 | 
			
		||||
    method: 'POST',
 | 
			
		||||
    headers: {
 | 
			
		||||
      'Content-Type': 'application/json',
 | 
			
		||||
      'Authorization': `Bearer ${token}`
 | 
			
		||||
    },
 | 
			
		||||
    body: JSON.stringify(input)
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function delete_gamenight(input, token) {
 | 
			
		||||
  return fetchResource('api/gamenights', {
 | 
			
		||||
    method: 'DELETE',
 | 
			
		||||
    headers: {
 | 
			
		||||
      'Content-Type': 'application/json',
 | 
			
		||||
      'Authorization': `Bearer ${token}`
 | 
			
		||||
    },
 | 
			
		||||
    body: JSON.stringify(input)
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function get_games(token) {
 | 
			
		||||
  return fetchResource('api/games', {
 | 
			
		||||
    method: 'GET',
 | 
			
		||||
    headers: {
 | 
			
		||||
      'Authorization': `Bearer ${token}`
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function login(body) {
 | 
			
		||||
  return fetchResource('api/login', {
 | 
			
		||||
    method: 'POST',
 | 
			
		||||
    headers: {
 | 
			
		||||
        'Content-Type': 'application/json'
 | 
			
		||||
    },
 | 
			
		||||
    body: JSON.stringify(body)
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										75
									
								
								frontend/src/api/FetchResource.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								frontend/src/api/FetchResource.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,75 @@
 | 
			
		||||
const API_URL = '';
 | 
			
		||||
 | 
			
		||||
function ApiError(message, data, status) {
 | 
			
		||||
  let response = null;
 | 
			
		||||
  let isObject = false;
 | 
			
		||||
 | 
			
		||||
  try {
 | 
			
		||||
    response = JSON.parse(data);
 | 
			
		||||
    isObject = true;
 | 
			
		||||
  } catch (e) {
 | 
			
		||||
    response = data;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  this.response = response;
 | 
			
		||||
  this.message = message;
 | 
			
		||||
  this.status = status;
 | 
			
		||||
  this.toString = function () {
 | 
			
		||||
    return `${ this.message }\nResponse:\n${ isObject ? JSON.stringify(this.response, null, 2) : this.response }`;
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const fetchResource = (path, userOptions = {}) => {
 | 
			
		||||
  const defaultOptions = {};
 | 
			
		||||
  const defaultHeaders = {
 | 
			
		||||
    'Content-Type': 'application/json'
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const options = {
 | 
			
		||||
    ...defaultOptions,
 | 
			
		||||
    ...userOptions,
 | 
			
		||||
    headers: {
 | 
			
		||||
      ...defaultHeaders,
 | 
			
		||||
      ...userOptions.headers,
 | 
			
		||||
    },
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const url = `${ API_URL }/${ path }`;
 | 
			
		||||
  const isFile = options.body instanceof File;
 | 
			
		||||
 | 
			
		||||
  if (options.body && typeof options.body === 'object' && !isFile) {
 | 
			
		||||
    options.body = JSON.stringify(options.body);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  let response = null;
 | 
			
		||||
 | 
			
		||||
  return fetch(url, options)
 | 
			
		||||
    .then(responseObject => {
 | 
			
		||||
      response = responseObject;
 | 
			
		||||
 | 
			
		||||
      if (response.status === 401) {
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (response.status < 200 || response.status >= 300) {
 | 
			
		||||
        return response.text();
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      return response.json();
 | 
			
		||||
    })
 | 
			
		||||
    .then(parsedResponse => {
 | 
			
		||||
      if (response.status < 200 || response.status >= 300) {
 | 
			
		||||
        throw parsedResponse;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      return parsedResponse;
 | 
			
		||||
    })
 | 
			
		||||
    .catch(error => {
 | 
			
		||||
      if (response) {
 | 
			
		||||
        throw new ApiError(`Request failed with status ${ response.status }.`, error, response.status);
 | 
			
		||||
      } else {
 | 
			
		||||
        throw new ApiError(error.toString(), null, 'REQUEST_FAILED');
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default fetchResource;
 | 
			
		||||
@ -9,6 +9,7 @@ import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns';
 | 
			
		||||
import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
 | 
			
		||||
 | 
			
		||||
import GameAdder from './GameAdder';
 | 
			
		||||
import { post_gamenight, unpack_api_result} from '../api/Api';
 | 
			
		||||
 | 
			
		||||
function AddGameNight(props) {
 | 
			
		||||
  const [expanded, setExpanded] = useState(false);
 | 
			
		||||
@ -44,32 +45,14 @@ function AddGameNight(props) {
 | 
			
		||||
        game_list: gameList,
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      const requestOptions = {
 | 
			
		||||
        method: 'POST',
 | 
			
		||||
        headers: {
 | 
			
		||||
          'Content-Type': 'application/json',
 | 
			
		||||
          'Authorization': `Bearer ${props.user.jwt}`
 | 
			
		||||
        },
 | 
			
		||||
        body: JSON.stringify(input)
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      fetch('api/gamenights', requestOptions)
 | 
			
		||||
        .then(response => response.json())
 | 
			
		||||
        .then(data => {
 | 
			
		||||
          if(data.result !== "Ok") {
 | 
			
		||||
            props.setFlash({
 | 
			
		||||
              type: "Error",
 | 
			
		||||
              message: data.message
 | 
			
		||||
            });
 | 
			
		||||
          } else {
 | 
			
		||||
            setExpanded(false);
 | 
			
		||||
            setGameName("");
 | 
			
		||||
            setDate(null);
 | 
			
		||||
          }
 | 
			
		||||
      unpack_api_result(post_gamenight(input, props.user.jwt), props.setFlash)
 | 
			
		||||
        .then(result => {
 | 
			
		||||
          setExpanded(false);
 | 
			
		||||
          setGameName("");
 | 
			
		||||
          setDate(null);
 | 
			
		||||
        })
 | 
			
		||||
        .then(() => props.refetchGamenights())
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  if(expanded) {
 | 
			
		||||
 | 
			
		||||
@ -9,35 +9,15 @@ import GamesIcon from '@mui/icons-material/Games';
 | 
			
		||||
import DeleteIcon from '@mui/icons-material/Delete';
 | 
			
		||||
 | 
			
		||||
import AddGameNight from './AddGameNight';
 | 
			
		||||
import {delete_gamenight, unpack_api_result} from '../api/Api';
 | 
			
		||||
 | 
			
		||||
function Gamenights(props) {
 | 
			
		||||
  const [dense, setDense] = React.useState(false);
 | 
			
		||||
 | 
			
		||||
  const DeleteGamenight = (gameId) => {
 | 
			
		||||
  const DeleteGamenight = (game_id) => {
 | 
			
		||||
    if (props.user !== null) {
 | 
			
		||||
      let input = {
 | 
			
		||||
        game_id: gameId,
 | 
			
		||||
      }
 | 
			
		||||
  
 | 
			
		||||
      const requestOptions = {
 | 
			
		||||
        method: 'DELETE',
 | 
			
		||||
        headers: {
 | 
			
		||||
          'Content-Type': 'application/json',
 | 
			
		||||
          'Authorization': `Bearer ${props.user.jwt}`
 | 
			
		||||
        },
 | 
			
		||||
        body: JSON.stringify(input)
 | 
			
		||||
      };
 | 
			
		||||
  
 | 
			
		||||
      fetch('api/gamenights', requestOptions)
 | 
			
		||||
        .then(response => response.json())
 | 
			
		||||
        .then(data => {
 | 
			
		||||
          if(data.result !== "Ok") {
 | 
			
		||||
            props.setFlash({
 | 
			
		||||
              type: "Error",
 | 
			
		||||
              message: data.message
 | 
			
		||||
            });
 | 
			
		||||
          }
 | 
			
		||||
        })
 | 
			
		||||
      const input = { game_id: game_id };
 | 
			
		||||
      unpack_api_result(delete_gamenight(input, props.user.jwt), props.setFlash)
 | 
			
		||||
        .then(() => props.refetchGamenights());
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user