forked from nihonium/nyanimedb
feat: TitleStatusControls
This commit is contained in:
parent
3f0456ba01
commit
8a3e14a5e5
5 changed files with 179 additions and 69 deletions
|
|
@ -0,0 +1,88 @@
|
|||
import { useEffect, useState } from "react";
|
||||
import { DefaultService } from "../../api";
|
||||
import type { UserTitleStatus } from "../../api";
|
||||
import {
|
||||
ClockIcon,
|
||||
CheckCircleIcon,
|
||||
PlayCircleIcon,
|
||||
XCircleIcon,
|
||||
} from "@heroicons/react/24/solid";
|
||||
|
||||
// Статусы с иконками и подписью
|
||||
const STATUS_BUTTONS: { status: UserTitleStatus; icon: React.ReactNode; label: string }[] = [
|
||||
{ status: "planned", icon: <ClockIcon className="w-5 h-5" />, label: "Planned" },
|
||||
{ status: "finished", icon: <CheckCircleIcon className="w-5 h-5" />, label: "Finished" },
|
||||
{ status: "in-progress", icon: <PlayCircleIcon className="w-5 h-5" />, label: "In Progress" },
|
||||
{ status: "dropped", icon: <XCircleIcon className="w-5 h-5" />, label: "Dropped" },
|
||||
];
|
||||
|
||||
export function TitleStatusControls({ titleId }: { titleId: number }) {
|
||||
const [currentStatus, setCurrentStatus] = useState<UserTitleStatus | null>(null);
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
const userIdStr = localStorage.getItem("userId");
|
||||
const userId = userIdStr ? Number(userIdStr) : null;
|
||||
|
||||
// --- Load initial status ---
|
||||
useEffect(() => {
|
||||
if (!userId) return;
|
||||
|
||||
DefaultService.getUserTitle(userId, titleId)
|
||||
.then((res) => setCurrentStatus(res.status))
|
||||
.catch(() => setCurrentStatus(null)); // 404 = user title does not exist
|
||||
}, [titleId, userId]);
|
||||
|
||||
// --- Handle click ---
|
||||
const handleStatusClick = async (status: UserTitleStatus) => {
|
||||
if (!userId || loading) return;
|
||||
|
||||
setLoading(true);
|
||||
|
||||
try {
|
||||
// 1) Если кликнули на текущий статус — DELETE
|
||||
if (currentStatus === status) {
|
||||
await DefaultService.deleteUserTitle(userId, titleId);
|
||||
setCurrentStatus(null);
|
||||
return;
|
||||
}
|
||||
|
||||
// 2) Если другой статус — POST или PATCH
|
||||
if (!currentStatus) {
|
||||
// ещё нет записи — POST
|
||||
const added = await DefaultService.addUserTitle(userId, {
|
||||
title_id: titleId,
|
||||
status,
|
||||
});
|
||||
setCurrentStatus(added.status);
|
||||
} else {
|
||||
// уже есть запись — PATCH
|
||||
const updated = await DefaultService.updateUserTitle(userId, titleId, { status });
|
||||
setCurrentStatus(updated.status);
|
||||
}
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex gap-2 flex-wrap justify-center mt-2">
|
||||
{STATUS_BUTTONS.map(btn => (
|
||||
<button
|
||||
key={btn.status}
|
||||
onClick={() => handleStatusClick(btn.status)}
|
||||
disabled={loading}
|
||||
className={`
|
||||
px-3 py-1 rounded-md border flex items-center gap-1 transition
|
||||
${currentStatus === btn.status
|
||||
? "bg-blue-600 text-white border-blue-700"
|
||||
: "bg-gray-200 text-black border-gray-300 hover:bg-gray-300"}
|
||||
`}
|
||||
title={btn.label}
|
||||
>
|
||||
{btn.icon}
|
||||
<span>{btn.label}</span>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue