Test meme voting

This commit is contained in:
Bruno Rybársky 2024-04-27 10:30:01 +02:00
parent 154cff0372
commit cd487d155c
5 changed files with 110 additions and 12 deletions

@ -622,3 +622,23 @@ async function getMemeImages() {
}); });
} }
async function reloadMemeVotes(memeID) {
let memeVoteCounterElement = document.getElementById(`meme_votes_counter_${memeID}`);
let memeVoteResponse = await doAction('/meme', {
action: "getMemeVotes",
meme_id: memeID
}, "Počet hlasov k meme-u bol stiahnutý", "Nastala chyba pri sťahovaní počtu hlasov k meme-u", true);
memeVoteCounterElement.innerText = memeVoteResponse.NetVotes;
}
async function voteMeme(memeID, isUpvote){
await doAction("/meme", {
action: "voteMeme",
meme_id: memeID,
is_upvote: isUpvote
}, "Meme bol upvotenutý", "Nastala chyba pri upvoteovaní meme-u", true);
await reloadMemeVotes(memeID);
}

@ -356,6 +356,21 @@ div#articleslist>article{
height: auto; height: auto;
} }
.meme_info {
display: flex;
flex-direction: row;
}
.meme {
display: flex;
flex-direction: column;
}
.meme_body {
display: flex;
flex-direction: column;
}
@media (max-width: 1050px) { @media (max-width: 1050px) {
div#articleslist { div#articleslist {

@ -9,6 +9,8 @@ function endpoint($endpoint_data): array
"addMeme" => addMeme($endpoint_data['meme_title'], $endpoint_data['meme_text'], $endpoint_data['meme_image_id']), "addMeme" => addMeme($endpoint_data['meme_title'], $endpoint_data['meme_text'], $endpoint_data['meme_image_id']),
"renderGallery" => renderMemeGallery(), "renderGallery" => renderMemeGallery(),
"deleteMeme" => deleteMeme($endpoint_data['meme_id']), "deleteMeme" => deleteMeme($endpoint_data['meme_id']),
default => ["Status" => "Fail", "message" => "Invalid action"], "getMemeVotes" => getMemeVotes($endpoint_data['meme_id']),
"voteMeme" => voteMeme($endpoint_data['meme_id'], $endpoint_data['is_upvote']),
default => ["Status" => "Fail", "Message" => "Invalid action"],
}; };
} }

@ -27,6 +27,14 @@ function renderMeme(int $id, int $authorId, string $title, string $textContent,
$meme_out = str_replace('__TEMPLATE_MEME_IMAGE__', '/' . htmlspecialchars($filePath), $meme_out); $meme_out = str_replace('__TEMPLATE_MEME_IMAGE__', '/' . htmlspecialchars($filePath), $meme_out);
$meme_out = str_replace('__TEMPLATE_MEME_DELETE_BUTTON__', (isModerator() || $_SESSION['ID'] == $authorId) ? "<button onclick=\"deleteMeme($id);\"><i class='ri-delete-bin-line'></i></button>" : '', $meme_out); $meme_out = str_replace('__TEMPLATE_MEME_DELETE_BUTTON__', (isModerator() || $_SESSION['ID'] == $authorId) ? "<button onclick=\"deleteMeme($id);\"><i class='ri-delete-bin-line'></i></button>" : '', $meme_out);
$meme_votes = calculateNetVotes($id);
$meme_upvote = isLoggedIn() ? "<button onclick=\"voteMeme($id, true);\"> <i class=\"ri-arrow-up-line\"></i></button>" : '';
$meme_downvote = isLoggedIn() ? "<button onclick=\"voteMeme($id, false);\"> <i class=\"ri-arrow-down-line\"></i></button>" : '';
$meme_out = str_replace('__TEMPLATE_MEME_VOTES_NUMBER__', $meme_votes, $meme_out);
$meme_out = str_replace('__TEMPLATE_MEME_UPVOTE__', $meme_upvote, $meme_out);
$meme_out = str_replace('__TEMPLATE_MEME_DOWNVOTE__', $meme_downvote, $meme_out);
$meme_out = str_replace('__TEMPLATE_MEME_ID__', $id, $meme_out);
return str_replace('__TEMPLATE_MEME_TEXT__', htmlspecialchars($textContent), $meme_out); return str_replace('__TEMPLATE_MEME_TEXT__', htmlspecialchars($textContent), $meme_out);
} }
@ -69,7 +77,7 @@ function renderMemeGallery(): string
return $meme_gallery_out; return $meme_gallery_out;
} }
function deleteMeme(int $memeId): array function deleteMeme(int $memeID): array
{ {
global $mysqli; global $mysqli;
$out = ["Status" => "Fail"]; $out = ["Status" => "Fail"];
@ -77,14 +85,58 @@ function deleteMeme(int $memeId): array
$query = !isModerator() ? 'DELETE FROM Memes WHERE ID = ? AND AuthorID = ?' : 'DELETE FROM Memes WHERE ID = ?'; $query = !isModerator() ? 'DELETE FROM Memes WHERE ID = ? AND AuthorID = ?' : 'DELETE FROM Memes WHERE ID = ?';
$stmtDelete = $mysqli->prepare($query); $stmtDelete = $mysqli->prepare($query);
if (!isModerator()) { if (!isModerator()) {
$stmtDelete->bind_param('ii', $memeId, $_SESSION['ID']); $stmtDelete->bind_param('ii', $memeID, $_SESSION['ID']);
} else { } else {
$stmtDelete->bind_param('i', $memeId); $stmtDelete->bind_param('i', $memeID);
} }
$stmtDelete->execute(); $stmtDelete->execute();
if ($stmtDelete->affected_rows > 0) { if ($stmtDelete->affected_rows > 0) {
$out['Status'] = 'Success'; $out['Status'] = 'Success';
} }
$stmtDelete->close();
} }
return $out; return $out;
} }
function voteMeme(int $memeID, bool $isUpvote): array
{
global $mysqli;
$out = ["Status" => "Fail"];
$vote = $isUpvote ? 1 : 0;
$memeVoteConn = $mysqli->prepare('INSERT INTO MemeVotes (MemeID, UserID, isUpvote) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE isUpvote = VALUES(isUpvote)');
$memeVoteConn->bind_param('iii', $memeID, $_SESSION['ID'], $vote);
$memeVoteConn->execute();
if ($memeVoteConn->affected_rows > 0) {
$out['Status'] = 'Success';
}
$memeVoteConn->close();
return $out;
}
function calculateNetVotes(int $memeID): int
{
global $mysqli;
$query = 'SELECT isUpvote FROM MemeVotes WHERE MemeID = ?';
$stmt = $mysqli->prepare($query);
$stmt->bind_param('i', $memeID);
$stmt->execute();
$result = $stmt->get_result();
$netVotes = 0;
while ($row = $result->fetch_assoc()) {
$netVotes += ($row['isUpvote'] == 1) ? 1 : -1;
}
$stmt->close();
return $netVotes;
}
function getMemeVotes(int $memeID): array
{
return [
"Status" => "Success",
"NetVotes" => calculateNetVotes($memeID)
];
}

@ -1,10 +1,19 @@
<article class="meme"> <article class="meme" id="meme___TEMPLATE_MEME_ID__">
<h2 class='meme_title'>__TEMPLATE_MEME_TITLE__</h2> <div class="meme_header" id="meme_header___TEMPLATE_MEME_ID__">
<div class="meme_body"> <h2 class='meme_title' id="meme_title___TEMPLATE_MEME_ID__">__TEMPLATE_MEME_TITLE__</h2>
<p class='meme_author'><i class="ri-user-line"></i>__TEMPLATE_MEME_AUTHOR__</p> <div class="meme_info" id="meme_info___TEMPLATE_MEME_ID__">
__TEMPLATE_MEME_DELETE_BUTTON__ <div class="meme_voting" id="meme_voting___TEMPLATE_MEME_ID__">
<p class='meme_date'><i class="ri-calendar-line"></i>__TEMPLATE_MEME_DATE__</p> __TEMPLATE_MEME_UPVOTE__
<img src="__TEMPLATE_MEME_IMAGE__" width="500" alt="meme image" class="meme_image"> <p class="votes_counter" id="meme_votes_counter___TEMPLATE_MEME_ID__">__TEMPLATE_MEME_VOTES_NUMBER__</p>
<p class="meme_text">__TEMPLATE_MEME_TEXT__</p> __TEMPLATE_MEME_DOWNVOTE__
</div>
<p class='meme_author' id="meme_author___TEMPLATE_MEME_ID__"><i class="ri-user-line"></i>__TEMPLATE_MEME_AUTHOR__</p>
__TEMPLATE_MEME_DELETE_BUTTON__
<p class='meme_date' id="meme_date___TEMPLATE_MEME_ID__"><i class="ri-calendar-line"></i>__TEMPLATE_MEME_DATE__</p>
</div>
</div>
<div class="meme_body" id="meme_body___TEMPLATE_MEME_ID__">
<img id="meme_image___TEMPLATE_MEME_ID__" src="__TEMPLATE_MEME_IMAGE__" width="500" alt="meme image" class="meme_image">
<p class="meme_text" id="meme_text___TEMPLATE_MEME_ID__">__TEMPLATE_MEME_TEXT__</p>
</div> </div>
</article> </article>