remove votes

This commit is contained in:
2025-08-18 22:51:57 +02:00
parent 3f777f67ae
commit 0f710c2d1e
3 changed files with 64 additions and 20 deletions

2
.gitignore vendored
View File

@@ -40,3 +40,5 @@ yarn-error.log*
*.tsbuildinfo
next-env.d.ts
.env
RATATOING.mp4

View File

@@ -4,6 +4,7 @@ import { NextResponse } from "next/server";
import { auth } from "../../../auth/auth";
import { headers } from "next/headers";
import { idSchema, validateParams } from "@/lib/validation";
import { authClient } from "@/lib/auth";
const prisma = new PrismaClient();
@@ -11,9 +12,9 @@ export async function POST(
req: Request,
{ params }: { params: Promise<{ id: string }> }
) {
const session = await auth.api.getSession({ headers: await headers() });
const session = await authClient.getSession({ fetchOptions: { headers: await headers() } });
if (!session || !session.user?.id) {
if (!session || !session.data?.user.id) {
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
}
@@ -24,7 +25,7 @@ export async function POST(
}
const movieId = data.id;
const userId = session.user.id;
const userId = session.data.user.id;
// Check if the user has already voted for this movie
const existingVote = await prisma.vote.findUnique({
@@ -37,18 +38,52 @@ export async function POST(
});
if (existingVote) {
return NextResponse.json(
{ error: "You have already voted for this movie" },
{ status: 400 }
);
// If the user has already voted, remove the vote
await prisma.vote.delete({
where: {
id: existingVote.id,
},
});
const movie = await prisma.movie.findUnique({
where: { id: movieId },
});
await fetch(process.env.SLACK_WEBHOOK!, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
text: `User <@${session.data.user.id}> removed their vote for ${movie!.title}`,
}),
});
return NextResponse.json({ message: "Vote removed successfully" });
} else {
// If the user has not voted, add the vote
const vote = await prisma.vote.create({
data: {
movieId,
userId,
},
});
const movie = await prisma.movie.findUnique({
where: { id: movieId },
include: { votes: true },
});
await fetch(process.env.SLACK_WEBHOOK!,
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
text: `User <@${session.data.user.id}> just voted for ${movie!.title}!`,
}),
});
return NextResponse.json(vote);
}
const vote = await prisma.vote.create({
data: {
movieId,
userId,
},
});
return NextResponse.json(vote);
}

View File

@@ -20,7 +20,7 @@ interface Movie {
}
export default function Home() {
const { data: session } = authClient.useSession();
const { data: session, isPending } = authClient.useSession();
const [movies, setMovies] = useState<Movie[]>([]);
const [loading, setLoading] = useState(true);
const [votingMovieId, setVotingMovieId] = useState<string | null>(null);
@@ -48,6 +48,9 @@ export default function Home() {
setVotingMovieId(movieId);
const movieToUpdate = movies.find(movie => movie.id === movieId);
const alreadyVoted = movieToUpdate?.userVote;
try {
const response = await fetch(`/api/movies/${movieId}/vote`, {
method: 'POST',
@@ -59,7 +62,11 @@ export default function Home() {
if (response.ok) {
// Refresh movies to show updated vote count
fetchMovies();
toast.success("Vote recorded successfully!");
if (alreadyVoted) {
toast.success("Vote removed successfully!");
} else {
toast.success("Vote recorded successfully!");
}
} else {
const errorData = await response.json();
toast.error(errorData.error || 'Failed to vote');
@@ -146,14 +153,14 @@ export default function Home() {
<div className="flex justify-between items-center">
<Button
onClick={() => handleVote(movie.id)}
disabled={votingMovieId === movie.id || movie.userVote || movie.isOwnSubmission}
disabled={votingMovieId === movie.id || movie.isOwnSubmission}
className="transition-colors"
variant={movie.userVote ? "secondary" : "default"}
>
{movie.isOwnSubmission
? "Your Submission"
: movie.userVote
? "Already Voted"
? "Remove Vote"
: votingMovieId === movie.id
? "Voting..."
: "Vote"}