mirror of
https://github.com/gabehf/Koito.git
synced 2026-03-07 21:48:18 -08:00
feat: Rewind (#116)
* wip * chore: update counts to allow unix timeframe * feat: add db functions for counting new items * wip: endpoint working * wip * wip: initial ui done * add header, adjust ui * add time listened toggle * fix layout, year param * param fixes
This commit is contained in:
parent
c0a8c64243
commit
d4ac96f780
64 changed files with 2252 additions and 1055 deletions
|
|
@ -1,99 +1,99 @@
|
|||
import { useQuery } from "@tanstack/react-query";
|
||||
import { getAlbum, type Artist } from "api/api";
|
||||
import { useEffect, useState } from "react"
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
interface Props {
|
||||
id: number
|
||||
type: string
|
||||
id: number;
|
||||
type: string;
|
||||
}
|
||||
|
||||
export default function SetPrimaryArtist({ id, type }: Props) {
|
||||
const [err, setErr] = useState('')
|
||||
const [primary, setPrimary] = useState<Artist>()
|
||||
const [success, setSuccess] = useState('')
|
||||
|
||||
const { isPending, isError, data, error } = useQuery({
|
||||
queryKey: [
|
||||
'get-artists-'+type.toLowerCase(),
|
||||
{
|
||||
id: id
|
||||
},
|
||||
],
|
||||
queryFn: () => {
|
||||
return fetch('/apis/web/v1/artists?'+type.toLowerCase()+'_id='+id).then(r => r.json()) as Promise<Artist[]>;
|
||||
},
|
||||
});
|
||||
const [err, setErr] = useState("");
|
||||
const [primary, setPrimary] = useState<Artist>();
|
||||
const [success, setSuccess] = useState("");
|
||||
|
||||
useEffect(() => {
|
||||
if (data) {
|
||||
for (let a of data) {
|
||||
if (a.is_primary) {
|
||||
setPrimary(a)
|
||||
break
|
||||
}
|
||||
}
|
||||
const { isPending, isError, data, error } = useQuery({
|
||||
queryKey: [
|
||||
"get-artists-" + type.toLowerCase(),
|
||||
{
|
||||
id: id,
|
||||
},
|
||||
],
|
||||
queryFn: () => {
|
||||
return fetch(
|
||||
"/apis/web/v1/artists?" + type.toLowerCase() + "_id=" + id
|
||||
).then((r) => r.json()) as Promise<Artist[]>;
|
||||
},
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (data) {
|
||||
for (let a of data) {
|
||||
if (a.is_primary) {
|
||||
setPrimary(a);
|
||||
break;
|
||||
}
|
||||
}, [data])
|
||||
|
||||
if (isError) {
|
||||
return (
|
||||
<p className="error">Error: {error.message}</p>
|
||||
)
|
||||
}
|
||||
if (isPending) {
|
||||
return (
|
||||
<p>Loading...</p>
|
||||
)
|
||||
}
|
||||
}
|
||||
}, [data]);
|
||||
|
||||
const updatePrimary = (artist: number, val: boolean) => {
|
||||
setErr('');
|
||||
setSuccess('');
|
||||
fetch(`/apis/web/v1/artists/primary?artist_id=${artist}&${type.toLowerCase()}_id=${id}&is_primary=${val}`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
"Content-Type": "application/x-www-form-urlencoded"
|
||||
if (isError) {
|
||||
return <p className="error">Error: {error.message}</p>;
|
||||
}
|
||||
if (isPending) {
|
||||
return <p>Loading...</p>;
|
||||
}
|
||||
|
||||
const updatePrimary = (artist: number, val: boolean) => {
|
||||
setErr("");
|
||||
setSuccess("");
|
||||
fetch(
|
||||
`/apis/web/v1/artists/primary?artist_id=${artist}&${type.toLowerCase()}_id=${id}&is_primary=${val}`,
|
||||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
},
|
||||
}
|
||||
).then((r) => {
|
||||
if (r.ok) {
|
||||
setSuccess("successfully updated primary artists");
|
||||
} else {
|
||||
r.json().then((r) => setErr(r.error));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="w-full">
|
||||
<h3>Set Primary Artist</h3>
|
||||
<div className="flex flex-col gap-4">
|
||||
<select
|
||||
name="mark-various-artists"
|
||||
id="mark-various-artists"
|
||||
className="w-60 px-3 py-2 rounded-md"
|
||||
value={primary?.name || ""}
|
||||
onChange={(e) => {
|
||||
for (let a of data) {
|
||||
if (a.name === e.target.value) {
|
||||
setPrimary(a);
|
||||
updatePrimary(a.id, true);
|
||||
}
|
||||
}
|
||||
})
|
||||
.then(r => {
|
||||
if (r.ok) {
|
||||
setSuccess('successfully updated primary artists');
|
||||
} else {
|
||||
r.json().then(r => setErr(r.error));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="w-full">
|
||||
<h2>Set Primary Artist</h2>
|
||||
<div className="flex flex-col gap-4">
|
||||
<select
|
||||
name="mark-various-artists"
|
||||
id="mark-various-artists"
|
||||
className="w-60 px-3 py-2 rounded-md"
|
||||
value={primary?.name || ""}
|
||||
onChange={(e) => {
|
||||
for (let a of data) {
|
||||
if (a.name === e.target.value) {
|
||||
setPrimary(a);
|
||||
updatePrimary(a.id, true);
|
||||
}
|
||||
}
|
||||
}}
|
||||
>
|
||||
<option value="" disabled>
|
||||
Select an artist
|
||||
</option>
|
||||
{data.map((a) => (
|
||||
<option key={a.id} value={a.name}>
|
||||
{a.name}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
{err && <p className="error">{err}</p>}
|
||||
{success && <p className="success">{success}</p>}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<option value="" disabled>
|
||||
Select an artist
|
||||
</option>
|
||||
{data.map((a) => (
|
||||
<option key={a.id} value={a.name}>
|
||||
{a.name}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
{err && <p className="error">{err}</p>}
|
||||
{success && <p className="success">{success}</p>}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue