67 lines
2.5 KiB
TypeScript
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>
|
|
);
|
|
}
|