Compare commits
10 Commits
3f0e459236
...
0373572eb7
| Author | SHA1 | Date | |
|---|---|---|---|
| 0373572eb7 | |||
| 6773d6d9bc | |||
| 7c6ba261f8 | |||
| 0b69162d0b | |||
| 740cee3d44 | |||
| be55bb91dc | |||
| b3cefa32b7 | |||
| 30b9bdf37c | |||
| 008ec35176 | |||
| fda41d1bdd |
23
karaokatalog/ui/static/components/pages/All.js
Normal file
23
karaokatalog/ui/static/components/pages/All.js
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import Base from "./Base.js"
|
||||||
|
import SongList from "../pieces/SongList.js"
|
||||||
|
import Song from "../../model/Song.js"
|
||||||
|
import search from "../../model/search.js"
|
||||||
|
|
||||||
|
export default {
|
||||||
|
oncreate() {
|
||||||
|
document.title = "Alle Songs · Karaokatalog"
|
||||||
|
},
|
||||||
|
oninit() {
|
||||||
|
Song.load()
|
||||||
|
},
|
||||||
|
view() {
|
||||||
|
const songs = search.apply(Song.all)
|
||||||
|
const message = !songs ? "Lade Songs..." : songs.length === 0 ? "Keine Songs gefunden." : null
|
||||||
|
|
||||||
|
return m(
|
||||||
|
Base,
|
||||||
|
message && m("p", message),
|
||||||
|
songs && m(SongList, { songs })
|
||||||
|
)
|
||||||
|
},
|
||||||
|
}
|
||||||
7
karaokatalog/ui/static/components/pages/Base.js
Normal file
7
karaokatalog/ui/static/components/pages/Base.js
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import Header from "../pieces/Header.js"
|
||||||
|
|
||||||
|
export default {
|
||||||
|
view(vnode) {
|
||||||
|
return [m(Header), m("main", vnode.children)]
|
||||||
|
},
|
||||||
|
}
|
||||||
41
karaokatalog/ui/static/components/pages/Favorites.js
Normal file
41
karaokatalog/ui/static/components/pages/Favorites.js
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import Base from "./Base.js"
|
||||||
|
import SongList from "../pieces/SongList.js"
|
||||||
|
import Song from "../../model/Song.js"
|
||||||
|
import search from "../../model/search.js"
|
||||||
|
import ClearSearchLink from "../pieces/ClearSearchLink.js"
|
||||||
|
|
||||||
|
export default {
|
||||||
|
oncreate() {
|
||||||
|
document.title = "Favoriten · Karaokatalog"
|
||||||
|
},
|
||||||
|
oninit() {
|
||||||
|
Song.load()
|
||||||
|
},
|
||||||
|
view() {
|
||||||
|
const allFavorites = Song.all?.filter(song => song.favorite)
|
||||||
|
const favoritesToShow = search.apply(allFavorites)
|
||||||
|
|
||||||
|
let message = null
|
||||||
|
if(!allFavorites) {
|
||||||
|
message = "Lade Songs..."
|
||||||
|
} else if(allFavorites.length === 0) {
|
||||||
|
message = "Du hast noch keine Favoriten markiert."
|
||||||
|
} else if(favoritesToShow.length === 0) {
|
||||||
|
message = [
|
||||||
|
`Deine Suche ergab keine Treffer unter deinen ${allFavorites.length} Favoriten. `,
|
||||||
|
m(ClearSearchLink, { totalFavoriteCount: allFavorites.length}),
|
||||||
|
]
|
||||||
|
} else if(allFavorites.length > favoritesToShow.length) {
|
||||||
|
message = [
|
||||||
|
`Deine Suche zeigt ${favoritesToShow.length} von deinen insgesamt ${allFavorites.length} Favoriten. `,
|
||||||
|
m(ClearSearchLink, { totalFavoriteCount: allFavorites.length}),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
return m(
|
||||||
|
Base,
|
||||||
|
message && m("p", message),
|
||||||
|
favoritesToShow && m(SongList, { songs: favoritesToShow }),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
}
|
||||||
14
karaokatalog/ui/static/components/pieces/Artist.js
Normal file
14
karaokatalog/ui/static/components/pieces/Artist.js
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import Song from "./Song.js"
|
||||||
|
|
||||||
|
export default {
|
||||||
|
view: function (vnode) {
|
||||||
|
const { artist, songs } = vnode.attrs
|
||||||
|
return m(
|
||||||
|
"section.artist",
|
||||||
|
[
|
||||||
|
m("h2", artist),
|
||||||
|
songs.map(song => m(Song, { song })),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
},
|
||||||
|
}
|
||||||
8
karaokatalog/ui/static/components/pieces/Header.js
Normal file
8
karaokatalog/ui/static/components/pieces/Header.js
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import SearchBar from "./SearchBar.js"
|
||||||
|
import TabBar from "./TabBar.js"
|
||||||
|
|
||||||
|
export default {
|
||||||
|
view() {
|
||||||
|
return m("header", [m(SearchBar), m(TabBar)])
|
||||||
|
},
|
||||||
|
}
|
||||||
16
karaokatalog/ui/static/components/pieces/Pagination.js
Normal file
16
karaokatalog/ui/static/components/pieces/Pagination.js
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import PaginationControls from "./PaginationControls.js"
|
||||||
|
|
||||||
|
const ELEMENTS_PER_PAGE = 25
|
||||||
|
|
||||||
|
export default {
|
||||||
|
view(vnode) {
|
||||||
|
const elements = vnode.attrs.elements.toArray()
|
||||||
|
const totalPages = Math.ceil(elements.length / ELEMENTS_PER_PAGE)
|
||||||
|
|
||||||
|
const startIndex = (this.currentPageIndex || 0) * ELEMENTS_PER_PAGE
|
||||||
|
return [
|
||||||
|
elements.slice(startIndex, startIndex + ELEMENTS_PER_PAGE),
|
||||||
|
m(PaginationControls, { currentPage: (this.currentPageIndex || 0) + 1, totalPages, onPageChange: i => this.currentPageIndex = i - 1 })
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
15
karaokatalog/ui/static/components/pieces/SearchBar.js
Normal file
15
karaokatalog/ui/static/components/pieces/SearchBar.js
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import search from "../../model/search.js"
|
||||||
|
|
||||||
|
export default {
|
||||||
|
view: function () {
|
||||||
|
return m("search", [
|
||||||
|
m("input[type=search]", {
|
||||||
|
value: search.query,
|
||||||
|
placeholder: "Songs oder Interpreten suchen...",
|
||||||
|
oninput: e => {
|
||||||
|
search.query = e.target.value
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
},
|
||||||
|
}
|
||||||
11
karaokatalog/ui/static/components/pieces/SongList.js
Normal file
11
karaokatalog/ui/static/components/pieces/SongList.js
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import Artist from "./Artist.js"
|
||||||
|
import Pagination from "./Pagination.js"
|
||||||
|
|
||||||
|
export default {
|
||||||
|
view: function (vnode) {
|
||||||
|
const sortedSongs = vnode.attrs.songs.toSorted((a, b) => a.artist.localeCompare(b.artist) || a.title.localeCompare(b.title))
|
||||||
|
const songsByArtist = Map.groupBy(sortedSongs, song => song.artist)
|
||||||
|
|
||||||
|
return m(Pagination, { elements: songsByArtist.entries().map(([artist, songs]) => m(Artist, { artist, songs })) })
|
||||||
|
},
|
||||||
|
}
|
||||||
16
karaokatalog/ui/static/components/pieces/TabBar.js
Normal file
16
karaokatalog/ui/static/components/pieces/TabBar.js
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { Tab } from "./Tab.js"
|
||||||
|
|
||||||
|
export default {
|
||||||
|
view() {
|
||||||
|
return m("nav", [
|
||||||
|
m(Tab, {
|
||||||
|
href: "/all",
|
||||||
|
label: "Alle",
|
||||||
|
}),
|
||||||
|
m(Tab, {
|
||||||
|
href: "/favorites",
|
||||||
|
label: "Favoriten",
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
},
|
||||||
|
}
|
||||||
24
karaokatalog/ui/static/index.html
Normal file
24
karaokatalog/ui/static/index.html
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="de">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>Karaokatalog</title>
|
||||||
|
<link
|
||||||
|
href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap"
|
||||||
|
rel="stylesheet"
|
||||||
|
/>
|
||||||
|
<link
|
||||||
|
href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@24,400,0..1,0"
|
||||||
|
rel="stylesheet"
|
||||||
|
/>
|
||||||
|
<link rel="stylesheet" href="style.css" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<main>
|
||||||
|
<p>Lade Karaokatalog-App...</p>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<script type="module" src="karaokatalog.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Loading…
x
Reference in New Issue
Block a user