Browse Source

can now like and dislike tunes

master
Cerys 4 weeks ago
parent
commit
9a2391bac1
  1. 5
      App/Wrappers/DatabaseInteractions.php
  2. 14
      App/Wrappers/SQLQueryBuilderWrapper.php
  3. 13
      Pages/tune/uuid.php
  4. 87
      Public/API/V1/RateTune.php
  5. 29
      Public/Static/CSS/Elements/Rating.css
  6. 1
      Public/Static/CSS/Mapper.css
  7. 19
      Public/Static/JS/General/APIInteractions.js
  8. 1
      Templates/Bases/StandardWebPage.html.twig
  9. 2
      Templates/Pages/profile.html.twig
  10. 33
      Templates/Pages/tune/uuid.html.twig

5
App/Wrappers/DatabaseInteractions.php

@ -68,6 +68,11 @@ class DatabaseInteractions
$sth = $this->pdo->prepare($queryBuilder->getStatement());
return $sth->execute($queryBuilder->getBindValues());
}
public function RunUpdate(UpdateInterface $queryBuilder): bool
{
$sth = $this->pdo->prepare($queryBuilder->getStatement());
return $sth->execute($queryBuilder->getBindValues());
}
public function RunDelete(DeleteInterface $queryBuilder): bool
{

14
App/Wrappers/SQLQueryBuilderWrapper.php

@ -38,4 +38,18 @@ class SQLQueryBuilderWrapper
->bindValue(name: "__parent_id__", value: $parentIDValue)
;
}
public static function INSERT(string $table)
{
$query_factory = new QueryFactory(db: 'mysql');
return $query_factory->newInsert()
->into("$table")
;
}
public static function UPDATE(string $table)
{
$query_factory = new QueryFactory(db: 'mysql');
return $query_factory->newUpdate()
->table(table: "$table")
;
}
}

13
Pages/tune/uuid.php

@ -12,9 +12,20 @@ $tuneDetails = $db->RunOneSelect(
queryBuilder: SQLQueryBuilderWrapper::SELECT_ONE(
table: 'Tunes',
id: $_GET["tune-id"]
),
)
->cols(cols: [
'SUM(CASE WHEN T_TR.Rating = 1 THEN 1 ELSE 0 END) AS Likes',
'SUM(CASE WHEN T_TR.Rating = -1 THEN 1 ELSE 0 END) AS Dislikes',
])
->join(
join: 'LEFT',
spec: 'TuneRatings AS T_TR',
cond: 'T.ID=T_TR.TuneID',
)
);
$dances = $db->RunSelect(
queryBuilder: SQLQueryBuilderWrapper::SELECT(
table: 'Dances',

87
Public/API/V1/RateTune.php

@ -0,0 +1,87 @@
<?php
use App\Enumerators\SessionElement;
use App\Wrappers\DatabaseInteractions;
use App\Wrappers\SQLQueryBuilderWrapper;
require_once __DIR__ . "/../../../vendor/autoload.php";
if(!$_SESSION[SessionElement::IS_LOGGED_IN->value])
{
die();
}
$ratingValue = 0;
if($_GET['type'] == "LIKE")
$ratingValue = 1;
elseif($_GET['type'] == "DISLIKE")
$ratingValue = -1;
else
die();
$db = new DatabaseInteractions();
$tuneDetails = $db->RunOneSelect(
queryBuilder: SQLQueryBuilderWrapper::SELECT_ONE(
table: 'Tunes',
id: $_GET['tune-id']
)
);
$existingRating = $db->RunSelect(
queryBuilder: SQLQueryBuilderWrapper::SELECT(
table: 'TuneRatings',
)
->where(cond: 'CreatedBy=:__user_id__')
->where(cond: 'TuneID=:__tune_id__')
->bindValue(name: '__user_id__', value: $_SESSION[SessionElement::USER_ID->value])
->bindValue(name: '__tune_id__', value: $_GET['tune-id'])
);
if(sizeof($existingRating) == 0)
{
$db->RunInsert(
queryBuilder: SQLQueryBuilderWrapper::INSERT(
table: 'TuneRatings'
)
->set(col: 'CreatedBy', value: ':__user_id__')
->set(col: 'TuneID', value: ':__tune_id__')
->set(col: 'Rating', value: ':__rating__')
->bindValue(name: '__user_id__', value: $_SESSION[SessionElement::USER_ID->value])
->bindValue(name: '__tune_id__', value: $_GET['tune-id'])
->bindValue(name: '__rating__', value: $ratingValue)
);
}
elseif(sizeof($existingRating) == 1)
{
$db->RunUpdate(
queryBuilder: SQLQueryBuilderWrapper::UPDATE(
table: 'TuneRatings'
)
->set(col: 'Rating', value: ':__rating__')
->where(cond: 'CreatedBy=:__user_id__')
->where(cond: 'TuneID=:__tune_id__')
->bindValue(name: '__user_id__', value: $_SESSION[SessionElement::USER_ID->value])
->bindValue(name: '__tune_id__', value: $_GET['tune-id'])
->bindValue(name: '__rating__', value: $ratingValue)
);
}
$tuneRatings = $db->RunSelect(
queryBuilder: SQLQueryBuilderWrapper::SELECT(
table: 'TuneRatings',
)
->cols(cols: [
'SUM(CASE WHEN T.Rating = 1 THEN 1 ELSE 0 END) AS Likes',
'SUM(CASE WHEN T.Rating = -1 THEN 1 ELSE 0 END) AS Dislikes',
])
->where(cond: 'TuneID=:__tune_id__')
->bindValue(name: '__tune_id__', value: $_GET['tune-id'])
);
echo json_encode([
"LikeCount" => $tuneRatings[0]["Likes"],
"DislikeCount" => $tuneRatings[0]["Dislikes"],
]);
die();

29
Public/Static/CSS/Elements/Rating.css

@ -0,0 +1,29 @@
.RatingButtons {
display: flex;
gap: 1rem;
justify-content: center;
margin-top: 1rem;
}
#RatingContainer button {
background: none;
border: none;
cursor: pointer;
font-size: 2rem;
transition: transform 0.2s, color 0.2s;
}
#RatingContainer button:hover {
transform: scale(1.2);
}
#ThumbUp {
color: green;
}
#ThumbDown {
color: red;
}
.Counts {
margin-top: 1rem;
font-size: 1.2rem;
}

1
Public/Static/CSS/Mapper.css

@ -13,4 +13,5 @@
@import "/Static/CSS/Elements/DescriptionLists.css";
@import "/Static/CSS/Elements/HomePage.css";
@import "/Static/CSS/Elements/NavBar.css";
@import "/Static/CSS/Elements/Rating.css";

19
Public/Static/JS/General/APIInteractions.js

@ -1,9 +1,9 @@
const API_SERVER = "https://ceilidhkit.com/API";
const API_SERVER = "/API";
async function API_GET(target) {
async function API_GET_TEXT(target) {
try {
const response = await fetch(API_SERVER + target, {
method: 'GET',
@ -16,3 +16,18 @@ async function API_GET(target) {
return {error: error.message};
}
}
async function API_GET(target) {
try {
const response = await fetch(API_SERVER + target, {
method: 'GET',
headers: {
},
credentials: 'include',
});
return await response.json();
} catch (error) {
return {error: error.message};
}
}

1
Templates/Bases/StandardWebPage.html.twig

@ -38,6 +38,7 @@
{% endif %}
</ul>
</nav>
<br><br>
<main>
{% block content %}{% endblock %}
</main>

2
Templates/Pages/profile.html.twig

@ -45,4 +45,4 @@
</thead>
</table>
</div>
{% endblock %}
{% endblock %}

33
Templates/Pages/tune/uuid.html.twig

@ -6,6 +6,23 @@
<!--<script src="/Static/JS/ThirdParty/abcjs-plugin-min.js"></script>-->
<link rel="stylesheet" href="/Static/CSS/ThirdParty/abcjs-audio.css">
<script>
var lastVoteAction = "";
function VoteOnTune(type)
{
if(lastVoteAction === type) return;
lastVoteAction = type;
API_GET('/V1/RateTune.php?tune-id={{ TuneDetails.ID }}&type='+type)
.then(payload => {
document.getElementById('LikeCount').innerHTML = payload['LikeCount'];
document.getElementById('DislikeCount').innerHTML = payload['DislikeCount'];
})
.catch(error => {
console.error("Error fetching ABC data:", error);
});
}
</script>
<div class="InnerContent">
<div>
@ -27,6 +44,20 @@
<dd>{{ TuneDetails.Parts|json_encode }}</dd>
</dl>
</div>
<div id="RatingContainer">
<h2>{{ "Rating"|translate }}</h2>
<div class="RatingButtons">
<button id="ThumbUp" onclick="VoteOnTune('LIKE');">👍</button>
<button id="ThumbDown" onclick="VoteOnTune('DISLIKE');">👎</button>
</div>
<div class="Counts">
|
<span>👍 <span id="LikeCount">{{ TuneDetails.Likes }}</span></span>
|
<span>👎 <span id="DislikeCount">{{ TuneDetails.Dislikes }}</span></span>
|
</div>
</div>
</div>
<div class="center">
<div id="NotationContainer--{{ TuneDetails.ID }}"></div>
@ -54,7 +85,7 @@
<script>
document.addEventListener("DOMContentLoaded", function () {
const targetTuneID = '{{ TuneDetails.ID }}';
API_GET("/V1/GetABCFile.php?tune-variant-id=" + targetTuneID)
API_GET_TEXT("/V1/GetABCFile.php?tune-variant-id=" + targetTuneID)
.then(payload => {
// Ensure required DOM elements exist
const notationContainer = document.getElementById("NotationContainer--" + targetTuneID);

Loading…
Cancel
Save