100 lines
No EOL
3.6 KiB
TypeScript
100 lines
No EOL
3.6 KiB
TypeScript
import { Card, CardActions, CardContent, IconButton, Typography } from "@mui/material";
|
|
import { ArrowDownward, ArrowUpward, Comment, Share } from "@mui/icons-material";
|
|
import { useState } from "react";
|
|
|
|
export interface Post {
|
|
uuid: string,
|
|
title: string,
|
|
content: string,
|
|
votes: { up: number, down: number },
|
|
}
|
|
|
|
// const URL = "http://localhost:8080/api/";
|
|
|
|
function sendVote(post: Post, direction: string): void {
|
|
fetch('/api/vote/' + post.uuid + '/' + direction, { method: 'POST' });
|
|
}
|
|
|
|
enum VoteDirection { UP = 1, DOWN = -1, NONE = 0 }
|
|
|
|
// // Single post
|
|
export function PostCard({ post }: { post: Post }): JSX.Element {
|
|
// const [myVote, setMyVote] = useState({ up: 0, down: 0 });
|
|
const [myVote, setMyVote] = useState(VoteDirection.NONE);
|
|
const [voteCount, setVoteCount] = useState({
|
|
upvotes: post.votes.up,
|
|
downvotes: post.votes.down
|
|
});
|
|
setVoteCount; // To silence the linter, peak coding right here
|
|
|
|
// Atrocious code
|
|
const votePress = (vote: VoteDirection): void => {
|
|
console.log(vote);
|
|
if (vote === VoteDirection.UP) {
|
|
if (myVote === VoteDirection.NONE) { // Upvote
|
|
sendVote(post, 'up');
|
|
setMyVote(VoteDirection.UP);
|
|
}
|
|
else if (myVote === VoteDirection.UP) { // Unvote
|
|
sendVote(post, 'unupvote');
|
|
setMyVote(VoteDirection.NONE);
|
|
}
|
|
else if (myVote === VoteDirection.DOWN) { // Change vote
|
|
sendVote(post, 'undownvote');
|
|
sendVote(post, 'up');
|
|
setMyVote(VoteDirection.UP);
|
|
}
|
|
}
|
|
|
|
if (vote === VoteDirection.DOWN) {
|
|
if (myVote === VoteDirection.NONE) { // Downvote
|
|
sendVote(post, 'down');
|
|
setMyVote(VoteDirection.DOWN);
|
|
}
|
|
else if (myVote === VoteDirection.DOWN) { // Unvote
|
|
sendVote(post, 'undownvote');
|
|
setMyVote(VoteDirection.NONE);
|
|
}
|
|
else if (myVote === VoteDirection.UP) { // Change vote
|
|
sendVote(post, 'unupvote');
|
|
sendVote(post, 'down');
|
|
setMyVote(VoteDirection.DOWN);
|
|
}
|
|
}
|
|
}
|
|
|
|
return (
|
|
<>
|
|
<Card key={post.uuid} sx={{ width: 1, bgcolor: "background.default" }}>
|
|
<CardContent>
|
|
<Typography variant="h6">
|
|
{post.title}
|
|
</Typography>
|
|
|
|
<Typography sx={{ overflowWrap: 'break-word' }} variant="body2">
|
|
{post.content ? post.content : "No content"}
|
|
</Typography>
|
|
|
|
</CardContent>
|
|
|
|
<CardActions>
|
|
<IconButton size='small' color='primary' aria-label="Comment"><Comment /></IconButton>
|
|
|
|
<IconButton color={myVote > 0 ? 'success' : 'default'}
|
|
onClick={(): void => votePress(VoteDirection.UP)} size='small' aria-label="Upvote"><ArrowUpward />
|
|
{voteCount.upvotes + Math.max(myVote, 0)}
|
|
</IconButton>
|
|
|
|
<IconButton color={myVote < 0 ? 'secondary' : 'default'}
|
|
onClick={(): void => votePress(VoteDirection.DOWN)} size='small' aria-label="Downvote"><ArrowDownward />
|
|
{voteCount.downvotes + Math.max(-myVote, 0)}
|
|
</IconButton>
|
|
|
|
<div style={{ marginLeft: 'auto' }}>
|
|
<IconButton size='small' aria-label="Share"><Share /></IconButton>
|
|
</div>
|
|
</CardActions>
|
|
</Card>
|
|
</>
|
|
)
|
|
} |