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 *.tsbuildinfo
next-env.d.ts next-env.d.ts
.env .env
RATATOING.mp4

View File

@@ -4,6 +4,7 @@ import { NextResponse } from "next/server";
import { auth } from "../../../auth/auth"; import { auth } from "../../../auth/auth";
import { headers } from "next/headers"; import { headers } from "next/headers";
import { idSchema, validateParams } from "@/lib/validation"; import { idSchema, validateParams } from "@/lib/validation";
import { authClient } from "@/lib/auth";
const prisma = new PrismaClient(); const prisma = new PrismaClient();
@@ -11,9 +12,9 @@ export async function POST(
req: Request, req: Request,
{ params }: { params: Promise<{ id: string }> } { 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 }); return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
} }
@@ -24,7 +25,7 @@ export async function POST(
} }
const movieId = data.id; 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 // Check if the user has already voted for this movie
const existingVote = await prisma.vote.findUnique({ const existingVote = await prisma.vote.findUnique({
@@ -37,18 +38,52 @@ export async function POST(
}); });
if (existingVote) { if (existingVote) {
return NextResponse.json( // If the user has already voted, remove the vote
{ error: "You have already voted for this movie" }, await prisma.vote.delete({
{ status: 400 } 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() { export default function Home() {
const { data: session } = authClient.useSession(); const { data: session, isPending } = authClient.useSession();
const [movies, setMovies] = useState<Movie[]>([]); const [movies, setMovies] = useState<Movie[]>([]);
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
const [votingMovieId, setVotingMovieId] = useState<string | null>(null); const [votingMovieId, setVotingMovieId] = useState<string | null>(null);
@@ -48,6 +48,9 @@ export default function Home() {
setVotingMovieId(movieId); setVotingMovieId(movieId);
const movieToUpdate = movies.find(movie => movie.id === movieId);
const alreadyVoted = movieToUpdate?.userVote;
try { try {
const response = await fetch(`/api/movies/${movieId}/vote`, { const response = await fetch(`/api/movies/${movieId}/vote`, {
method: 'POST', method: 'POST',
@@ -59,7 +62,11 @@ export default function Home() {
if (response.ok) { if (response.ok) {
// Refresh movies to show updated vote count // Refresh movies to show updated vote count
fetchMovies(); fetchMovies();
toast.success("Vote recorded successfully!"); if (alreadyVoted) {
toast.success("Vote removed successfully!");
} else {
toast.success("Vote recorded successfully!");
}
} else { } else {
const errorData = await response.json(); const errorData = await response.json();
toast.error(errorData.error || 'Failed to vote'); toast.error(errorData.error || 'Failed to vote');
@@ -146,14 +153,14 @@ export default function Home() {
<div className="flex justify-between items-center"> <div className="flex justify-between items-center">
<Button <Button
onClick={() => handleVote(movie.id)} onClick={() => handleVote(movie.id)}
disabled={votingMovieId === movie.id || movie.userVote || movie.isOwnSubmission} disabled={votingMovieId === movie.id || movie.isOwnSubmission}
className="transition-colors" className="transition-colors"
variant={movie.userVote ? "secondary" : "default"} variant={movie.userVote ? "secondary" : "default"}
> >
{movie.isOwnSubmission {movie.isOwnSubmission
? "Your Submission" ? "Your Submission"
: movie.userVote : movie.userVote
? "Already Voted" ? "Remove Vote"
: votingMovieId === movie.id : votingMovieId === movie.id
? "Voting..." ? "Voting..."
: "Vote"} : "Vote"}