AlbumPage.js 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. import './AlbumPage.css';
  2. import { Link } from 'react-router5'
  3. import {useRouteNode} from 'react-router5'
  4. import {unslugify, formatDuration} from './utils.js';
  5. import {useReducer, useEffect} from 'react';
  6. import {fetchAlbums} from './AlbumList';
  7. import {fetchTracks} from './Album';
  8. function pageReducer(state, action) {
  9. console.log(action);
  10. switch (action.type) {
  11. case 'LOAD_ALBUMS':
  12. if (!action.payload.items || !action.payload.items.length)
  13. return {error: 'Not found'};
  14. const album = action.payload.items[0];
  15. return {...state, album};
  16. case 'SHOW_ALBUM':
  17. const tracks = action.payload.tracks;
  18. return {...state, tracks, loading: false};
  19. default: throw new Error(`Unknown action type: ${action.type}`);
  20. }
  21. }
  22. export default function AlbumPage({dispatch, scrollRef}) {
  23. const { route } = useRouteNode('album');
  24. const { artist: artistSlug, album: albumSlug } = route.params;
  25. const artistName = unslugify(artistSlug);
  26. const albumName = unslugify(albumSlug);
  27. const [{album, tracks, loading, error}, dispatchPage] = useReducer(pageReducer, {loading: true});
  28. useEffect(()=>{
  29. if (album)
  30. fetchTracks(album.id, 'SHOW_ALBUM', dispatchPage)
  31. else
  32. fetchAlbums({categories: {artist: artistName,
  33. album: albumName},
  34. filter: ''}, 0, dispatchPage);
  35. }, [artistName, albumName, album, dispatch]);
  36. return (
  37. <div className="AlbumPage">
  38. <h1>
  39. <Link routeName="artist" routeParams={{artist: artistSlug}}>
  40. {artistName}
  41. </Link>
  42. </h1>
  43. <h2>{albumName}</h2>{tracks && (<div className="Album-actions">
  44. <button onClick={(e)=>dispatch({type:'ALBUM_PLAY', payload: {tracks, pos: 0}})}>
  45. <svg viewBox="0 0 24 24"><g><path d="M8 5v14l11-7z"/></g></svg>
  46. </button>
  47. <button onClick={(e)=>dispatch({type: 'ALBUM_ENQUEUE', payload: {tracks}})}>
  48. <svg viewBox="0 0 24 24"><g><path d="M10 6h4v4h4v4h-4v4h-4v-4h-4v-4h4z"/></g></svg>
  49. </button>
  50. </div>)}
  51. {album && (<>
  52. {album.date && <h3>Date: {album.year}</h3>}
  53. {album.country && <h3>Country: {album.country}</h3>}
  54. {album.track_count && <h3>Tracks: {album.track_count}</h3>}
  55. {album.total_duration && <h3>Duration: {formatDuration(album.total_duration)}</h3>}
  56. {album.publisher && <h3>Publisher: {album.publisher}</h3>}
  57. {album.genre && <h3>Genre: {album.genre}</h3>}
  58. </>)}
  59. <Link routeName="browser">Browse</Link>
  60. {loading && <h3>Loading...</h3>}
  61. {error && <h3>{ error }</h3>}
  62. {tracks && (
  63. <table><tbody>
  64. {tracks.map((track, i) => (
  65. <tr key={i}>
  66. <td>{track.no}.</td>
  67. <td>{track.title}</td>
  68. <td>{track.bit_rate} kbps</td>
  69. <td>{formatDuration(track.duration)}</td>
  70. <td><button onClick={() => dispatch({type:'ALBUM_PLAY', payload: {tracks, pos: i}})}>
  71. <svg viewBox="0 0 24 24"><g><path d="M8 5v14l11-7z"/></g></svg>
  72. </button></td>
  73. </tr>))
  74. }
  75. </tbody></table>
  76. )}
  77. </div>
  78. );
  79. }