Add sort direction controls to ModList

This commit is contained in:
Tyler Hallada 2022-03-18 19:51:30 -04:00
parent e1c0c5b4fa
commit 0b85e30043
4 changed files with 78 additions and 4 deletions

View File

@ -1,3 +1,4 @@
/* eslint-disable @next/next/no-img-element */
import { format } from "date-fns"; import { format } from "date-fns";
import React, { useEffect, useRef, useState } from "react"; import React, { useEffect, useRef, useState } from "react";
import MiniSearch from "minisearch"; import MiniSearch from "minisearch";
@ -28,6 +29,7 @@ type ModWithCounts = Mod & {
const ModList: React.FC<Props> = ({ mods, files, counts }) => { const ModList: React.FC<Props> = ({ mods, files, counts }) => {
const [includeTranslations, setIncludeTranslations] = useState(true); const [includeTranslations, setIncludeTranslations] = useState(true);
const [sortBy, setSortBy] = useState<keyof ModWithCounts>("unique_downloads"); const [sortBy, setSortBy] = useState<keyof ModWithCounts>("unique_downloads");
const [sortAsc, setSortAsc] = useState<boolean>(false);
const [filter, setFilter] = useState<string>(""); const [filter, setFilter] = useState<string>("");
const [category, setCategory] = useState<string>("All"); const [category, setCategory] = useState<string>("All");
const [filterResults, setFilterResults] = useState<Set<number>>(new Set()); const [filterResults, setFilterResults] = useState<Set<number>>(new Set());
@ -60,15 +62,17 @@ const ModList: React.FC<Props> = ({ mods, files, counts }) => {
const aVal = a[sortBy]; const aVal = a[sortBy];
const bVal = b[sortBy]; const bVal = b[sortBy];
if (typeof aVal === "number" && typeof bVal === "number") { if (typeof aVal === "number" && typeof bVal === "number") {
return bVal - aVal; return sortAsc ? aVal - bVal : bVal - aVal;
} else if ( } else if (
typeof aVal === "string" && typeof aVal === "string" &&
typeof bVal === "string" && typeof bVal === "string" &&
["first_upload_at", "last_update_at"].includes(sortBy) ["first_upload_at", "last_update_at"].includes(sortBy)
) { ) {
return new Date(bVal).getTime() - new Date(aVal).getTime(); const aTime = new Date(aVal).getTime();
const bTime = new Date(bVal).getTime();
return sortAsc ? aTime - bTime : bTime - aTime;
} else if (typeof aVal === "string" && typeof bVal === "string") { } else if (typeof aVal === "string" && typeof bVal === "string") {
return aVal.localeCompare(bVal); return sortAsc ? aVal.localeCompare(bVal) : bVal.localeCompare(aVal);
} }
return 0; return 0;
}); });
@ -129,6 +133,38 @@ const ModList: React.FC<Props> = ({ mods, files, counts }) => {
</option> </option>
<option value="nexus_mod_id">ID</option> <option value="nexus_mod_id">ID</option>
</select> </select>
<div className={styles["sort-direction"]}>
<button
title="Sort ascending"
className={sortAsc ? styles.active : ""}
onClick={() => setSortAsc(true)}
>
<img
alt="Sort ascending"
src={
sortAsc
? "/img/arrow-selected.svg"
: "/img/arrow-disabled.svg"
}
className={styles.asc}
/>
</button>
<button
title="Sort descending"
className={!sortAsc ? styles.active : ""}
onClick={() => setSortAsc(false)}
>
<img
alt="Sort descending"
src={
!sortAsc
? "/img/arrow-selected.svg"
: "/img/arrow-disabled.svg"
}
className={styles.desc}
/>
</button>
</div>
</div> </div>
<div className={styles["filter-row"]}> <div className={styles["filter-row"]}>
<label htmlFor="filter">Filter:</label> <label htmlFor="filter">Filter:</label>

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Pro 6.0.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path fill="grey" d="M438.6 278.6l-160 160C272.4 444.9 264.2 448 256 448s-16.38-3.125-22.62-9.375c-12.5-12.5-12.5-32.75 0-45.25L338.8 288H32C14.33 288 .0016 273.7 .0016 256S14.33 224 32 224h306.8l-105.4-105.4c-12.5-12.5-12.5-32.75 0-45.25s32.75-12.5 45.25 0l160 160C451.1 245.9 451.1 266.1 438.6 278.6z"/></svg>

After

Width:  |  Height:  |  Size: 541 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Pro 6.0.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path fill="purple" d="M438.6 278.6l-160 160C272.4 444.9 264.2 448 256 448s-16.38-3.125-22.62-9.375c-12.5-12.5-12.5-32.75 0-45.25L338.8 288H32C14.33 288 .0016 273.7 .0016 256S14.33 224 32 224h306.8l-105.4-105.4c-12.5-12.5-12.5-32.75 0-45.25s32.75-12.5 45.25 0l160 160C451.1 245.9 451.1 266.1 438.6 278.6z"/></svg>

After

Width:  |  Height:  |  Size: 543 B

View File

@ -56,7 +56,13 @@
} }
.sort-by { .sort-by {
min-width: 175px; min-width: 119px;
}
.sort-asc {
margin-left: 8px;
min-width: 50px;
max-width: 50px;
} }
.category { .category {
@ -71,3 +77,33 @@
.include-translations input { .include-translations input {
margin-right: 8px; margin-right: 8px;
} }
.sort-direction {
display: flex;
flex-direction: row;
margin-left: 8px;
}
.sort-direction button {
width: 24px;
height: 20px;
display: block;
outline: none;
border: 0;
background-color: transparent;
cursor: pointer;
overflow: hidden;
}
.sort-direction button img {
width: 100%;
height: 100%;
}
.asc {
transform: rotate(-90deg);
}
.desc {
transform: rotate(90deg);
}