forked from nihonium/nyanimedb
93 lines
3.5 KiB
TypeScript
93 lines
3.5 KiB
TypeScript
import { useEffect, useState } from "react";
|
||
import { DefaultService } from "../../api";
|
||
import type { UserTitleStatus } from "../../api";
|
||
import { useCookies } from 'react-cookie';
|
||
|
||
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 [cookies] = useCookies(['xsrf_token']);
|
||
const xsrfToken = cookies['xsrf_token'] || null;
|
||
|
||
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(xsrfToken, 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(xsrfToken, 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>
|
||
);
|
||
}
|