Skip to content

Commit

Permalink
Stands Controller with view of existing stands
Browse files Browse the repository at this point in the history
Report Controller
Fix some issues
  • Loading branch information
sveneld committed Jan 1, 2025
1 parent 521a1f3 commit f4ec05c
Show file tree
Hide file tree
Showing 20 changed files with 433 additions and 163 deletions.
50 changes: 0 additions & 50 deletions actions-web.php
Original file line number Diff line number Diff line change
Expand Up @@ -84,32 +84,6 @@ function listbikes($stand)
response($bicycles, 0, array('notes' => $notes, 'stacktopbike' => $stacktopbike), 0);
}

function liststands()
{
global $db;

response(_('not implemented'), 0, '', 0);
exit;
$result = $db->query('SELECT standId,standName,standDescription,standPhoto,serviceTag,placeName,longitude,latitude FROM stands ORDER BY standName');
while ($row = $result->fetch_assoc()) {
$bikenum = $row['bikeNum'];
$result2 = $db->query("SELECT note FROM notes WHERE bikeNum='$bikenum' AND deleted IS NULL ORDER BY time DESC");
$note = '';
while ($row = $result2->fetch_assoc()) {
$note .= $row['note'] . '; ';
}
$note = substr($note, 0, strlen($note) - 2); // remove last two chars - comma and space
if ($note) {
$bicycles[] = '*' . $bikenum; // bike with note / issue
$notes[] = $note;
} else {
$bicycles[] = $bikenum;
$notes[] = '';
}
}
response($stands, 0, '', 0);
}

function removenote($userId, $bikeNum)
{
global $db;
Expand Down Expand Up @@ -301,30 +275,6 @@ function trips($userId, $bike = 0)
echo json_encode($jsoncontent); // TODO change to response function
}

function getuserstats()
{
global $db;
$result = $db->query('SELECT users.userId,username,count(action) AS count FROM users LEFT JOIN history ON users.userId=history.userId WHERE history.userId IS NOT NULL GROUP BY username ORDER BY count DESC');
while ($row = $result->fetch_assoc()) {
$result2 = $db->query("SELECT count(action) AS rentals FROM history WHERE action='RENT' AND userId=" . $row['userId']);
$row2 = $result2->fetch_assoc();
$result2 = $db->query("SELECT count(action) AS returns FROM history WHERE action='RETURN' AND userId=" . $row['userId']);
$row3 = $result2->fetch_assoc();
$jsoncontent[] = array('userid' => $row['userId'], 'username' => $row['username'], 'count' => $row['count'], 'rentals' => $row2['rentals'], 'returns' => $row3['returns']);
}
echo json_encode($jsoncontent); // TODO change to response function
}

function getusagestats()
{
global $db;
$result = $db->query("SELECT count(action) AS count,DATE(time) AS day,action FROM history WHERE userId IS NOT NULL AND action IN ('RENT','RETURN') GROUP BY day,action ORDER BY day DESC LIMIT 60");
while ($row = $result->fetch_assoc()) {
$jsoncontent[] = array('day' => $row['day'], 'count' => $row['count'], 'action' => $row['action']);
}
echo json_encode($jsoncontent); // TODO change to response function
}

function validatecoupon($userid, $coupon)
{
global $db, $creditSystem;
Expand Down
18 changes: 0 additions & 18 deletions command.php
Original file line number Diff line number Diff line change
Expand Up @@ -100,24 +100,6 @@
checkbikeno($bikeno);
revert($userid,$bikeno);
break;
case "stands": #"operationId": "stand.get",
logrequest($userid,$action);
$auth->refreshSession();
checkprivileges($userid);
liststands();
break;
case "userstats":
logrequest($userid,$action);
$auth->refreshSession();
checkprivileges($userid);
getuserstats();
break;
case "usagestats":
logrequest($userid,$action);
$auth->refreshSession();
checkprivileges($userid);
getusagestats();
break;
case "trips":
logrequest($userid,$action);
$auth->refreshSession();
Expand Down
21 changes: 19 additions & 2 deletions config/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
$routes->add('command', '/command.php')
->controller([\BikeShare\Controller\CommandController::class, 'index']);
$routes->add('scan', '/scan.php/{action}/{id}')
->requirements(['id' => '\d+'])
->requirements(['action' => 'rent|return'])
->controller([\BikeShare\Controller\ScanController::class, 'index']);
$routes->add('admin_old', '/admin.php')
->controller([\BikeShare\Controller\AdminController::class, 'index']);
$routes->add('admin', '/admin')
->controller([\BikeShare\Controller\AdminController::class, 'index']);
$routes->add('register', '/register.php')
Expand All @@ -28,14 +28,19 @@
$routes->add('reset_password', '/resetPassword')
->controller([\BikeShare\Controller\SecurityController::class, 'resetPassword']);

$routes->add('api_stand_index', '/api/stand')
->methods(['GET'])
->controller([\BikeShare\Controller\Api\StandController::class, 'index']);
$routes->add('api_bike_index', '/api/bike')
->methods(['GET'])
->controller([\BikeShare\Controller\Api\BikeController::class, 'index']);
$routes->add('api_bike_item', '/api/bike/{bikeNumber}')
->requirements(['bikeNumber' => '\d+'])
->methods(['GET'])
->controller([\BikeShare\Controller\Api\BikeController::class, 'item']);
$routes->add('api_bike_last_usage', '/api/bikeLastUsage/{bikeNumber}')
->methods(['GET'])
->requirements(['bikeNumber' => '\d+'])
->controller([\BikeShare\Controller\Api\BikeController::class, 'lastUsage']);
$routes->add('api_coupon_index', '/api/coupon')
->methods(['GET'])
Expand All @@ -51,15 +56,27 @@
->controller([\BikeShare\Controller\Api\UserController::class, 'index']);
$routes->add('api_user_item', '/api/user/{userId}')
->methods(['GET'])
->requirements(['userId' => '\d+'])
->controller([\BikeShare\Controller\Api\UserController::class, 'item']);
$routes->add('api_user_item_update', '/api/user/{userId}')
->methods(['PUT'])
->requirements(['userId' => '\d+'])
->controller([\BikeShare\Controller\Api\UserController::class, 'update']);
$routes->add('api_credit_add', '/api/credit')
->methods(['PUT'])
->controller([\BikeShare\Controller\Api\CreditController::class, 'add']);
$routes->add('api_report_daily', '/api/report/daily')
->methods(['GET'])
->controller([\BikeShare\Controller\Api\ReportController::class, 'daily']);
$routes->add('api_report_users', '/api/report/user/{year}')
->methods(['GET'])
->defaults(['year' => date('Y')])
->requirements(['year' => '\d+'])
->controller([\BikeShare\Controller\Api\ReportController::class, 'user']);

$routes->add('personal_stats_year', '/personalStats/year/{year}')
->methods(['GET'])
->defaults(['year' => date('Y')])
->requirements(['year' => '\d+'])
->controller([\BikeShare\Controller\PersonalStatsController::class, 'yearStats']);
};
150 changes: 116 additions & 34 deletions public/js/admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ $(document).ready(function () {
stands();
break;
case "#reports":
userstats();
usagestats();
break;
case "#credit":
if (window.ga) ga('send', 'event', 'buttons', 'click', 'admin-couponlist');
Expand Down Expand Up @@ -189,12 +189,53 @@ function last(bikeNumber) {
});
}

function stands() {
function generateStandCards(data) {
const $container = $("#standsconsole");
const $template = $("#stand-card-template");
$container.empty();

$.each(data, function (index, item) {
const $card = $template.clone().removeAttr("id").removeClass("d-none");

$card.find(".stand-name").text(item.standName);

const $photo = $card.find(".stand-photo");
if (item.standPhoto) {
$photo.attr("src", item.standPhoto).removeClass("d-none");
} else {
$photo.addClass("d-none");
}

$card.find(".stand-description").text(item.standDescription);

if (parseInt(item.latitude) !== 0 && parseInt(item.longitude) !== 0) {
const googleMapsUrl = `https://www.google.com/maps?q=${item.latitude},${item.longitude}`;
$card.find(".stand-location")
.removeClass("d-none")
.attr("href", googleMapsUrl);
}

if (item.standName.toLowerCase().includes("servis")) {
$card.find(".service-stand").removeClass("d-none");
} else if (item.standName.toLowerCase().includes("zruseny")) {
$card.find(".removed-stand").removeClass("d-none");
}

$container.append($card);
});
}

function stands(standId) {
$.ajax({
url: "command.php?action=stands"
}).done(function (jsonresponse) {
jsonobject = $.parseJSON(jsonresponse);
handleresponse("standsconsole", jsonobject);
url: "/api/stand" + (standId ? "/" + standId : ""),
method: "GET",
dataType: "json",
success: function(response) {
generateStandCards(response);
},
error: function(xhr, status, error) {
console.error("Error fetching stand data:", error);
}
});
}

Expand All @@ -207,7 +248,9 @@ function userlist() {
dataSrc: '',
cache: true
},
dom: 'lrtip',
layout: {
topEnd: null //disable default searchField
},
columns: [
{
data: 'username',
Expand All @@ -220,15 +263,18 @@ function userlist() {
},
{
data: 'privileges',
name: 'privileges'
name: 'privileges',
type: 'num'
},
{
data: 'userLimit',
name: 'userLimit'
name: 'userLimit',
type: 'num'
},
{
data: 'credit',
name: 'credit',
type: 'num-fmt',
visible: creditenabled === 1,
render: function(data, type, row) {
return `${data} ${creditcurrency}`;
Expand Down Expand Up @@ -260,37 +306,73 @@ function userlist() {
}

function userstats() {
var code = "";
$.ajax({
url: "command.php?action=userstats"
}).done(function (jsonresponse) {
jsonobject = $.parseJSON(jsonresponse);
if (jsonobject.length > 0) code = '<table class="table table-striped" id="userstatstable"><thead><tr><th>User</th><th>Actions</th><th>Rentals</th><th>Returns</th></tr></thead>';
for (var i = 0, len = jsonobject.length; i < len; i++) {
code = code + '<tr><td><a href="#" class="edituser" data-userid="' + jsonobject[i]["userid"] + '">' + jsonobject[i]["username"] + '</a></td><td>' + jsonobject[i]["count"] + '</td><td>' + jsonobject[i]["rentals"] + '</td><td>' + jsonobject[i]["returns"] + '</td></tr>';
$('#report-daily-table').addClass('d-none').closest('#stats-report-table_wrapper').addClass('d-none');
$('#report-user-year').removeClass('d-none');
let table = $('#report-user-table').removeClass('d-none').DataTable({
destroy: true,
paging: false,
info: false,
searching: false,
ajax: {
url: '/api/report/user/',
dataSrc: '',
cache: true,
},
order: [[3, 'desc']],
columns: [
{
data: 'username',
name: 'username',
},
{
data: 'rentCount',
},
{
data: 'returnCount',
},
{
data: 'totalActionCount',
}
],
error: function(xhr, error, code) {
console.error('Error loading daily report data:', error);
}
if (jsonobject.length > 0) code = code + '</table>';
$('#reportsconsole').html(code);
$('#userstatstable').dataTable({
"paging": false,
"ordering": false,
"info": false
});
});

$('#year').on('change', function() {
table.ajax.url('/api/report/user/' + $('#year').val());
table.ajax.reload();
});
}

function usagestats() {
var code = "";
$.ajax({
url: "command.php?action=usagestats"
}).done(function (jsonresponse) {
jsonobject = $.parseJSON(jsonresponse);
if (jsonobject.length > 0) code = '<table class="table table-striped" id="usagestatstable"><thead><tr><th>Day</th><th>Action</th><th>Count</th></tr></thead>';
for (var i = 0, len = jsonobject.length; i < len; i++) {
code = code + '<tr><td>' + jsonobject[i]["day"] + '</td><td>' + jsonobject[i]["action"] + '</td><td>' + jsonobject[i]["count"] + '</td></tr>';
$('#report-user-table').addClass('d-none').closest('#report-user-table_wrapper').addClass('d-none');
$('#report-user-year').addClass('d-none');
$('#report-daily-table').removeClass('d-none').DataTable({
destroy: true,
paging: false,
info: false,
searching: false,
ajax: {
url: '/api/report/daily',
dataSrc: '',
cache: true,
},
order: [[0, 'desc']],
columns: [
{
data: 'day',
},
{
data: 'rentCount',
},
{
data: 'returnCount',
}
],
error: function(xhr, error, code) {
console.error('Error loading user report data:', error);
}
if (jsonobject.length > 0) code = code + '</table>';
$('#reportsconsole').html(code);
});
}

Expand Down
1 change: 1 addition & 0 deletions src/Controller/AdminController.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public function index(
[
'configuration' => $configuration,
'creditSystem' => $creditSystem,
'currentYear' => date('Y'),
]
);
}
Expand Down
2 changes: 1 addition & 1 deletion src/Controller/Api/BikeController.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public function index(
}

/**
* @Route("/api/bike/{bikeNumber}", name="api_bike_item", methods={"GET"})
* @Route("/api/bike/{bikeNumber}", name="api_bike_item", methods={"GET"}, requirements: {"bikeNumber"="\d+"})
*/
public function item(
$bikeNumber,
Expand Down
Loading

0 comments on commit f4ec05c

Please sign in to comment.