Files
voidea/webui/src/components/VoteButtons.tsx
T

67 lines
2.5 KiB
TypeScript

import { useEffect, useState } from "react";
import { getVotes, toggleVote, type VoteCount } from "../api/collaboration";
interface Props {
ideaId: string;
}
export default function VoteButtons({ ideaId }: Props) {
const [votes, setVotes] = useState<VoteCount>({ up: 0, down: 0, user_vote: null });
const [sending, setSending] = useState(false);
useEffect(() => {
getVotes(ideaId).then(setVotes).catch(console.error);
}, [ideaId]);
async function handleVote(vote: "up" | "down") {
if (sending) return;
setSending(true);
try {
const updated = await toggleVote(ideaId, vote);
setVotes(updated);
} catch (e) {
console.error(e);
} finally {
setSending(false);
}
}
const upActive = votes.user_vote === "up";
const downActive = votes.user_vote === "down";
return (
<div className="flex items-center gap-1">
<button
onClick={() => handleVote("up")}
disabled={sending}
className={`flex items-center gap-1 rounded-lg px-2 py-1 text-sm transition ${
upActive
? "bg-green-100 text-green-700 dark:bg-green-900 dark:text-green-300"
: "hover:bg-gray-100 dark:hover:bg-gray-800"
} disabled:opacity-50`}
aria-label="Нравится"
>
<svg className="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M14 10h4.764a2 2 0 011.789 2.894l-3.5 7A2 2 0 0115.263 21h-4.017c-.163 0-.326-.02-.485-.06L7 20m7-10V5a2 2 0 00-2-2h-.095c-.5 0-.905.405-.905.905 0 .714-.211 1.412-.608 2.006L7 11v9m7-10h-2M7 20H5a2 2 0 01-2-2v-6a2 2 0 012-2h2.5" />
</svg>
{votes.up}
</button>
<button
onClick={() => handleVote("down")}
disabled={sending}
className={`flex items-center gap-1 rounded-lg px-2 py-1 text-sm transition ${
downActive
? "bg-red-100 text-red-700 dark:bg-red-900 dark:text-red-300"
: "hover:bg-gray-100 dark:hover:bg-gray-800"
} disabled:opacity-50`}
aria-label="Не нравится"
>
<svg className="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10 14H5.236a2 2 0 01-1.789-2.894l3.5-7A2 2 0 018.736 3h4.018a2 2 0 01.485.06l3.76.94m-7 10v5a2 2 0 002 2h.096c.5 0 .905-.405.905-.904 0-.715.211-1.413.608-2.008L17 13V4m-7 10h2m5-10h2a2 2 0 012 2v6a2 2 0 01-2 2h-2.5" />
</svg>
{votes.down}
</button>
</div>
);
}