Jelajahi Sumber

[front] grouped albums list

Innocenty Enikeew 7 tahun lalu
induk
melakukan
67fb62f118
3 mengubah file dengan 70 tambahan dan 13 penghapusan
  1. 1 1
      back/server.lisp
  2. 12 0
      front/src/App.css
  3. 57 12
      front/src/App.js

+ 1 - 1
back/server.lisp

@@ -34,7 +34,7 @@
     (maybe-key-value "publisher" (album-publisher album))
     (maybe-key-value "country" (album-country album))
     (maybe-key-value "genre" (album-genre album))
-    (maybe-key-value "type" (album-type album))
+    (maybe-key-value "type" (or (album-type album) "album"))
     (maybe-key-value "status" (album-status album))
     (maybe-key-value "mb_id" (album-mb-id album))
     (maybe-key-value "track_count" (album-track-count album))

+ 12 - 0
front/src/App.css

@@ -27,6 +27,11 @@
   to { transform: rotate(360deg); }
 }
 
+.Player {
+  text-align: left;
+  padding: 0 20px;
+}
+
 .category-list {
   float: left;
   padding: 0 10px;
@@ -38,4 +43,11 @@
 .AlbumList {
   clear: both;
   padding-top: 15px;
+}
+.AlbumList img {
+  width: 128px;
+  height: 128px;
+}
+.AlbumList table td {
+  width: 200px;
 }

+ 57 - 12
front/src/App.js

@@ -27,6 +27,32 @@ function CategoryFlatList(props) {
   );
 }
 
+function formatDuration(duration) {
+  var seconds = duration % 60;
+  const minutes = Math.floor(duration / 60);
+  if (seconds < 10) {
+    seconds = '0' + seconds;
+  }
+  return minutes + ':' + seconds;
+}
+
+function mapAlbums(items) {
+  var artists = [], curArtist = {}, curType = {};
+  for (const album of items) {
+    if (album.artist !== curArtist.name) {
+      curArtist = {name: album.artist, types: []}
+      curType = {}
+      artists.push(curArtist)
+    }
+    if (album.type !== curType.type) {
+      curType = {type: album.type, albums: []}
+      curArtist.types.push(curType)
+    }
+    curType.albums.push(album);
+  }
+  return artists;
+}
+
 function AlbumList(props) {
   const { error, isLoaded, items } = props.state;
 
@@ -36,16 +62,35 @@ function AlbumList(props) {
   } else if (!isLoaded) {
     content = <div>Loading</div>
   } else {
-    content = (
-        <ul>
-        {items.map(item => (
-            <li key={item.id}>{item.artist} - {item.year} - {item.album}</li>
+    const artists = mapAlbums(items);
+
+    content = artists.map(artist => (
+      <div key={artist.name}>
+        <h3>{artist.name}</h3>
+        {artist.types.map(type => (
+          <div key={type.type}>
+            <h4>{type.type}</h4>
+            <table><tbody>
+            {type.albums.map(album => (
+              <tr key={album.id}>
+                <td><img src={album.cover} alt={album.album} /></td>
+                <td>{album.year}</td>
+                <td>{album.album}</td>
+                <td>{album.publisher}</td>
+                <td>{album.country}</td>
+                <td>{album.genre}</td>
+                <td>{album.track_count}</td>
+                <td>{formatDuration(album.total_duration)}</td>
+              </tr>
+            ))}
+            </tbody></table>
+          </div>
         ))}
-      </ul>
-    );
+      </div>
+    ))
   }
   return (
-      <div className="AlbumList">
+    <div className="AlbumList">
       <h2>{props.title}</h2>
       {content}
     </div>
@@ -142,12 +187,12 @@ class Player extends Component {
   }
   render() {
     return (
-        <div>
+      <div className="Player">
         <div className="PlayerFilters">
         {this.categories.map(({type, title}) => (
-            <CategoryFlatList key={type} title={title} state={this.state[type]} onChange={e => this.handleCategoryChange(type, e.target.value)}/>
-          ))}
-      </div><div style={{clear:'both', paddingBottom:'20px'}}/>
+          <CategoryFlatList key={type} title={title} state={this.state[type]} onChange={e => this.handleCategoryChange(type, e.target.value)}/>
+        ))}
+        </div><div style={{clear:'both', paddingBottom:'20px'}}/>
         <input type="text" placeholder="Search albums" onChange={this.handleFilterChange} size={150} />
         <AlbumList title="Albums" state={this.state.album} />
       </div>
@@ -163,7 +208,7 @@ class App extends Component {
           <img src={logo} className="App-logo" alt="logo" />
           <h1 className="App-title">Chad Music</h1>
         </header>
-        <Player/>
+        <Player />
       </div>
     );
   }