FrostByte/client/src/Post.tsx

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>
</>
)
}