add sort button

This commit is contained in:
2026-02-05 08:51:44 +01:00
parent 2c5b241c34
commit 380f010a7e
2 changed files with 94 additions and 8 deletions

View File

@@ -4,12 +4,20 @@
--padding-end: 16px;
}
.hero {
background: #ffffff;
border-radius: 20px;
padding: 1.1rem 1.2rem;
box-shadow: 0 10px 24px rgba(0, 0, 0, 0.08);
display: flex;
.library-searchbar {
--background: transparent;
--border-radius: 0;
--padding-top: 8px;
--padding-start: 8px;
--padding-end: 8px;
--padding-bottom: 8px;
}
.action-sheet-button.sort-action-active {
color: #007aff;
font-weight: 600;
}
flex-wrap: wrap;
justify-content: space-between;
gap: 1.5rem;

View File

@@ -1,16 +1,21 @@
import {
IonBadge,
IonActionSheet,
IonButton,
IonContent,
IonHeader,
IonIcon,
IonItem,
IonLabel,
IonList,
IonNote,
IonPage,
IonSearchbar,
IonSpinner,
IonTitle,
IonToolbar,
} from "@ionic/react";
import { swapVerticalOutline } from "ionicons/icons";
import { useEffect, useMemo, useState } from "react";
import "./LibraryPage.css";
@@ -69,6 +74,11 @@ export default function LibraryPage() {
const [games, setGames] = useState<SteamGame[]>([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const [searchText, setSearchText] = useState("");
const [sortBy, setSortBy] = useState<"title" | "playtime" | "lastPlayed">(
"title",
);
const [showSortSheet, setShowSortSheet] = useState(false);
useEffect(() => {
let active = true;
@@ -131,14 +141,76 @@ export default function LibraryPage() {
);
}, [games]);
const filteredAndSortedGames = useMemo(() => {
// Filtere nach Suchtext
let filtered = games.filter((game) =>
game.title.toLowerCase().includes(searchText.toLowerCase()),
);
// Sortiere
filtered.sort((a, b) => {
if (sortBy === "title") {
return a.title.localeCompare(b.title, "de");
} else if (sortBy === "playtime") {
return (b.playtimeHours ?? 0) - (a.playtimeHours ?? 0);
} else {
// lastPlayed
const aDate = a.lastPlayed ? new Date(a.lastPlayed).getTime() : 0;
const bDate = b.lastPlayed ? new Date(b.lastPlayed).getTime() : 0;
return bDate - aDate;
}
});
return filtered;
}, [games, searchText, sortBy]);
return (
<IonPage>
<IonHeader translucent>
<IonToolbar>
<IonTitle>Bibliothek</IonTitle>
<IonButton
slot="end"
fill="clear"
onClick={() => setShowSortSheet(true)}
color="primary"
>
<IonIcon slot="icon-only" icon={swapVerticalOutline} />
</IonButton>
</IonToolbar>
<IonToolbar>
<IonSearchbar
placeholder="Spiele suchen..."
value={searchText}
onIonInput={(e) => setSearchText(e.detail.value || "")}
className="library-searchbar"
/>
</IonToolbar>
</IonHeader>
<IonContent fullscreen className="library-content">
<IonActionSheet
isOpen={showSortSheet}
onDidDismiss={() => setShowSortSheet(false)}
header="Sortieren nach"
buttons={[
{
text: "Titel",
cssClass: sortBy === "title" ? "sort-action-active" : "",
handler: () => setSortBy("title"),
},
{
text: "Spielzeit",
cssClass: sortBy === "playtime" ? "sort-action-active" : "",
handler: () => setSortBy("playtime"),
},
{
text: "Zuletzt gespielt",
cssClass: sortBy === "lastPlayed" ? "sort-action-active" : "",
handler: () => setSortBy("lastPlayed"),
},
{ text: "Abbrechen", role: "cancel" },
]}
/>
<IonContent fullscreen className="library-content" id="library-content">
<IonHeader collapse="condense">
<IonToolbar>
<IonTitle size="large">Bibliothek</IonTitle>
@@ -174,9 +246,15 @@ export default function LibraryPage() {
<div className="state error">
<p>{error}</p>
</div>
) : filteredAndSortedGames.length === 0 ? (
<div className="state">
<p>
{searchText ? "Keine Spiele gefunden" : "Keine Spiele vorhanden"}
</p>
</div>
) : (
<IonList inset className="game-list">
{games.map((game) => (
{filteredAndSortedGames.map((game) => (
<IonItem
key={game.id}
lines="full"