16 Commits

Author SHA1 Message Date
boris
5b0d04b702 (feat): added captcha for invalid login 2024-12-04 01:37:17 +00:00
boris
cafe0b58d0 (fix): added empty get header redirect 2024-12-04 00:25:37 +00:00
boris
a1711afecc (fix): holy shit filters and searching actually works. fix before was completely schizo i think i was just zynbrained 2024-12-04 00:21:29 +00:00
boris
86f778b7ac (feat)(in-progress): added modal for creation 2024-12-03 22:21:22 +00:00
boris
574dcbb119 (fix): i fixed it !! filter workidge extravaganza headsplosion i just put in 3 zyns 2024-12-03 21:59:08 +00:00
boris
f9d625e905 (feat): filter and direction dropdown 2024-12-03 20:05:15 +00:00
boris
214bfe20ac added functionality for CRUD 2024-12-02 20:33:27 +00:00
boris
00a29b9db7 images 2024-12-01 18:15:49 +00:00
boris
6430dc6904 idk 2024-12-01 18:15:35 +00:00
boris
c650dbce01 changed <button> paginators to <a> paginators. 2024-11-29 21:47:38 +00:00
boris
e3a42f4ba3 commit before branching 2024-11-29 21:34:21 +00:00
boris
b7b5fb545b completely flarched it 2024-11-29 17:19:08 +00:00
boris
4005328979 erm did a small amount
output database to view
added basic filters
improve bootstrap theming and positioning
added pagination
2024-11-28 23:40:06 +00:00
boris
5c24228c20 add template files and compose file, fix syntax errors in template 2024-11-21 12:33:55 +00:00
boris
e1b1455ac0 add template files and compose file, fix syntax errors in template 2024-11-21 12:33:26 +00:00
boris
b64c6d835e add template files and compose file, fix syntax errors in template 2024-11-21 12:33:19 +00:00
120 changed files with 67135 additions and 7287 deletions

Binary file not shown.

0
.idea/.gitignore generated vendored Normal file → Executable file
View File

1
.idea/.name generated
View File

@@ -1 +0,0 @@
MVCtemplate

0
.idea/Ecobuddy.iml generated Normal file → Executable file
View File

9
.idea/MVCtemplate.iml generated
View File

@@ -1,9 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="jquery" level="application" />
</component>
</module>

12
.idea/dataSources.xml generated Normal file → Executable file
View File

@@ -1,12 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="DataSourceManagerImpl" format="xml" multifile-model="true"> <component name="DataSourceManagerImpl" format="xml" multifile-model="true">
<data-source source="LOCAL" name="ecobuddy.sqlite" uuid="8da0d10f-48a6-4aa3-9200-f806440fb4ed"> <data-source source="LOCAL" name="ecobuddy" uuid="b932ada6-ed77-47fa-96d8-d6dfa86a6ca2">
<driver-ref>sqlite.xerial</driver-ref> <driver-ref>sqlite.xerial</driver-ref>
<synchronize>true</synchronize> <synchronize>true</synchronize>
<jdbc-driver>org.sqlite.JDBC</jdbc-driver> <jdbc-driver>org.sqlite.JDBC</jdbc-driver>
<jdbc-url>jdbc:sqlite:$PROJECT_DIR$/ecobuddy.sqlite</jdbc-url> <jdbc-url>jdbc:sqlite:$PROJECT_DIR$/Databases/ecobuddy.sqlite</jdbc-url>
<working-dir>$ProjectFileDir$</working-dir> <working-dir>$ProjectFileDir$</working-dir>
<libraries>
<library>
<url>file://$APPLICATION_CONFIG_DIR$/jdbc-drivers/Xerial SQLiteJDBC/3.45.1/org/xerial/sqlite-jdbc/3.45.1.0/sqlite-jdbc-3.45.1.0.jar</url>
</library>
<library>
<url>file://$APPLICATION_CONFIG_DIR$/jdbc-drivers/Xerial SQLiteJDBC/3.45.1/org/slf4j/slf4j-api/1.7.36/slf4j-api-1.7.36.jar</url>
</library>
</libraries>
</data-source> </data-source>
</component> </component>
</project> </project>

0
.idea/encodings.xml generated Normal file → Executable file
View File

6
.idea/jsLibraryMappings.xml generated Executable file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JavaScriptLibraryMappings">
<file url="PROJECT" libraries="{jquery}" />
</component>
</project>

0
.idea/misc.xml generated Normal file → Executable file
View File

3
.idea/modules.xml generated Normal file → Executable file
View File

@@ -2,8 +2,7 @@
<project version="4"> <project version="4">
<component name="ProjectModuleManager"> <component name="ProjectModuleManager">
<modules> <modules>
<module fileurl="file://$PROJECT_DIR$/.idea/MVCtemplate.iml" filepath="$PROJECT_DIR$/.idea/MVCtemplate.iml" /> <module fileurl="file://$PROJECT_DIR$/.idea/Ecobuddy.iml" filepath="$PROJECT_DIR$/.idea/Ecobuddy.iml" />
</modules> </modules>
</component> </component>
</project> </project>

8
.idea/php.xml generated Normal file → Executable file
View File

@@ -10,5 +10,11 @@
<option name="highlightLevel" value="WARNING" /> <option name="highlightLevel" value="WARNING" />
<option name="transferred" value="true" /> <option name="transferred" value="true" />
</component> </component>
<component name="PhpProjectSharedConfiguration" php_language_level="5.5.0" /> <component name="PhpProjectSharedConfiguration" php_language_level="7.1" />
<component name="PhpStanOptionsConfiguration">
<option name="transferred" value="true" />
</component>
<component name="PsalmOptionsConfiguration">
<option name="transferred" value="true" />
</component>
</project> </project>

0
.idea/scopes/scope_settings.xml generated Normal file → Executable file
View File

6
.idea/sqldialects.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="SqlDialectMappings">
<file url="PROJECT" dialect="SQLite" />
</component>
</project>

0
.idea/vcs.xml generated Normal file → Executable file
View File

View File

@@ -1 +0,0 @@
,boris,boris-ThinkPad-T480,07.11.2024 12:14,file:///home/boris/.config/libreoffice/4;

0
Assessment Brief Form 2024-25.docx Normal file → Executable file
View File

BIN
ecobuddy.sqlite → Databases/ecobuddy.sqlite Normal file → Executable file

Binary file not shown.

Binary file not shown.

37
Models/Database.php Normal file
View File

@@ -0,0 +1,37 @@
<?php
class Database {
/**
* @var Database
*/
protected static $_dbInstance = null;
/**
* @var PDO
*/
protected $_dbHandle;
public function getDbConnection(): PDO
{
return $this->_dbHandle;
}
public static function getInstance(): ?Database
{
if(self::$_dbInstance == null) {
self::$_dbInstance = new self();
}
return self::$_dbInstance;
}
private function __construct() {
try {
$this->_dbHandle = new PDO("sqlite:Databases/ecobuddy.sqlite");
$this->_dbHandle->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->_dbHandle->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
}
catch (PDOException $e) {
echo $e->getMessage();
}
}
public function __destruct() {
$this->_dbHandle = null; // destroys the PDO handle when no longer needed
}
}

61
Models/FacilityData.php Normal file
View File

@@ -0,0 +1,61 @@
<?php
class FacilityData {
protected $_id, $_title, $_category, $_status, $_description, $_houseNumber, $_streetName, $_county, $_town, $_postcode, $_lng, $_lat, $_contributor;
public function __construct($dbRow) {
$this->_id = $dbRow['id'];
$this->_title = $dbRow['title'];
$this->_category = $dbRow['category'];
$this->_status = $dbRow['status'];
$this->_description = $dbRow['description'];
$this->_houseNumber = $dbRow['houseNumber'];
$this->_streetName = $dbRow['streetName'];
$this->_county = $dbRow['county'];
$this->_town = $dbRow['town'];
$this->_postcode = $dbRow['postcode'];
$this->_lng = $dbRow['lng'];
$this->_lat = $dbRow['lat'];
$this->_contributor = $dbRow['contributor'];
}
public function getId() {
return $this->_id;
}
public function getTitle() {
return $this->_title;
}
public function getCategory() {
return $this->_category;
}
public function getStatus() {
return $this->_status;
}
public function getDescription() {
return $this->_description;
}
public function getHouseNumber() {
return $this->_houseNumber;
}
public function getStreetName() {
return $this->_streetName;
}
public function getCounty() {
return $this->_county;
}
public function getTown() {
return $this->_town;
}
public function getPostcode() {
return $this->_postcode;
}
public function getLng() {
return $this->_lng;
}
public function getLat() {
return $this->_lat;
}
public function getContributor() {
return $this->_contributor;
}
}

215
Models/FacilityDataSet.php Normal file
View File

@@ -0,0 +1,215 @@
<?php
require_once ('Database.php');
require_once ('FacilityData.php');
class FacilityDataSet
{
protected $_dbHandle, $_dbInstance;
public function __construct()
{
$this->_dbInstance = Database::getInstance();
$this->_dbHandle = $this->_dbInstance->getDbConnection();
}
/**
* @param $data
* @return bool
*/
public function addFacility($data): bool
{
$sqlQuery = "
INSERT INTO ecoFacilities
(title,
category,
description,
houseNumber,
streetName,
county,
town,
postcode,
lng,
lat,
contributor)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
;";
$stmt = $this->_dbHandle->prepare($sqlQuery);
// Ensures only one value is returned per column name
$stmt->setFetchMode(\PDO::FETCH_ASSOC);
// Initialize index for binding
$bindIndex = 1;
// Bind other filters
for ($i = 1; $i <= 8; $i++) { // Assuming 8 other filters
$value = !empty($data[$i]) ? "%" . $data[$i] . "%" : "%";
$stmt->bindValue($bindIndex++, $value, \PDO::PARAM_STR);
}
return !($stmt->rowCount());
}
public function deleteFacility($id): bool
{
$sqlQuery = "DELETE FROM ecoFacilities WHERE id = ?";
$stmt = $this->_dbHandle->prepare($sqlQuery);
$stmt->setFetchMode(\PDO::FETCH_ASSOC);
$stmt->bindValue(1, $id, \PDO::PARAM_INT);
$stmt->execute();
return !($stmt->rowCount() == 0);
}
public function fetchAll($filterArray, $sortArray): array
{
// Define columns for filtering and sorting
$filterColumns = [
0 => 'ecoFacilityStatus.statusComment',
1 => 'ecoFacilities.title',
2 => 'ecoCategories.name',
3 => 'ecoFacilities.description',
4 => 'ecoFacilities.streetName',
5 => 'ecoFacilities.county',
6 => 'ecoFacilities.town',
7 => 'ecoFacilities.postcode',
8 => 'ecoUser.username'
];
$sortColumns = [
0 => 'ecoFacilityStatus.statusComment',
1 => 'ecoFacilities.title',
2 => 'ecoCategories.name',
3 => 'ecoFacilities.description',
4 => 'ecoFacilities.streetName',
5 => 'ecoFacilities.county',
6 => 'ecoFacilities.town',
7 => 'ecoFacilities.postcode',
8 => 'ecoUser.username'
];
// Validate and select the filter column
$selectedFilterColumn = $filterColumns[$filterArray['category']] ?? 'ecoFacilities.title';
// Validate and select the sort column
$selectedSortColumn = $sortColumns[$sortArray['sort']] ?? 'ecoFacilities.title';
// Validate sort direction
$direction = strtolower($sortArray['dir']) === 'desc' ? 'DESC' : 'ASC';
// Base query for filtering and sorting
$baseQuery = "
FROM ecoFacilities
LEFT JOIN ecoCategories ON ecoCategories.id = ecoFacilities.category
LEFT JOIN ecoUser ON ecoUser.id = ecoFacilities.contributor
LEFT JOIN ecoFacilityStatus ON ecoFacilityStatus.facilityid = ecoFacilities.id
WHERE {$selectedFilterColumn} LIKE :term
";
// Query to count total results
$countQuery = "SELECT COUNT(DISTINCT ecoFacilities.id) AS total {$baseQuery}";
// Query to fetch filtered and sorted results
$dataQuery = "
SELECT DISTINCT ecoFacilities.id,
ecoFacilities.title,
GROUP_CONCAT(ecoFacilityStatus.statusComment, ', ') AS status,
ecoCategories.name AS category,
ecoFacilities.description,
ecoFacilities.houseNumber,
ecoFacilities.streetName,
ecoFacilities.county,
ecoFacilities.town,
ecoFacilities.postcode,
ecoFacilities.lng,
ecoFacilities.lat,
ecoUser.username AS contributor
{$baseQuery}
GROUP BY ecoFacilities.id, ecoFacilities.title, ecoCategories.name,
ecoFacilities.description, ecoFacilities.streetName,
ecoFacilities.county, ecoFacilities.town, ecoFacilities.postcode,
ecoUser.username
ORDER BY {$selectedSortColumn} {$direction};
";
$filterArray['term'] = '%' . $filterArray['term'] . '%' ?? '%';
var_dump($filterArray);
// Prepare and execute the count query
$countStmt = $this->_dbHandle->prepare($countQuery);
$countStmt->bindValue(':term', $filterArray['term'], PDO::PARAM_STR);
$countStmt->execute();
$totalResults = (int)$countStmt->fetchColumn();
// Prepare and execute the data query
$dataStmt = $this->_dbHandle->prepare($dataQuery);
$dataStmt->bindValue(':term', $filterArray['term'], PDO::PARAM_STR);
$dataStmt->execute();
// Fetch results into FacilityData objects
$dataSet = [];
while ($row = $dataStmt->fetch()) {
$dataSet[] = new FacilityData($row);
}
return [
'dataset' => $dataSet,
'count' => $totalResults
];
}
/**
* @param $sqlQuery
* @param $filterArray
* @return false|PDOStatement
* Function for fetchAll() to de-dupe code. Performs binding on PDO statements to facilitate
* filtering of facilities. Returns a bound PDO statement.
*/
// private function populateFields($sqlQuery, $filterArray, $sortBy, $direction)
// {
// $stmt = $this->_dbHandle->prepare($sqlQuery);
// $stmt->setFetchMode(\PDO::FETCH_ASSOC);
//
// // Initialize index for binding
// $bindIndex = 1;
//
// // Bind statusComment filter, required due to comments not being so.
// $statusComment = !empty($filterArray[0]) ? "%" . $filterArray[0] . "%" : null;
// $stmt->bindValue($bindIndex++, $statusComment ?? "%", \PDO::PARAM_STR); // First ?
// $stmt->bindValue($bindIndex++, $statusComment, $statusComment === null ? \PDO::PARAM_NULL : \PDO::PARAM_STR); // Second ?
//
// // Bind other filters
// for ($i = 1; $i <= 8; $i++) { // Assuming 8 other filters
// $value = !empty($filterArray[$i]) ? "%" . $filterArray[$i] . "%" : "%";
// $stmt->bindValue($bindIndex++, $value, \PDO::PARAM_STR);
// }
// return $stmt;
// }
// So i worked on trying to get this to work for 30 minutes and it turns out you
// can never bind column name values to placeholders, and must use column orders
// as integers..... what
// if(isset($sortBy) && isset($direction)) {
// $stmt->bindValue(':sortBy', $sortBy, \PDO::PARAM_STR);
// $stmt->bindValue(':direction', $direction, \PDO::PARAM_STR);
// }
private function populateFields($sqlQuery, $filterArray)
{
$stmt = $this->_dbHandle->prepare($sqlQuery);
$stmt->setFetchMode(\PDO::FETCH_ASSOC);
$bindIndex = 1;
// Bind statusComment (two placeholders required)
$statusComment = $filterArray[0] ?? '%';
$stmt->bindValue($bindIndex++, $statusComment, \PDO::PARAM_STR);
$stmt->bindValue($bindIndex++, $statusComment, \PDO::PARAM_STR);
// Bind other filters
for ($i = 1; $i < count($filterArray); $i++) {
$value = $filterArray[$i] ?? '%';
print_r($i . ":" . $value . "||\n");
$stmt->bindValue($bindIndex++, $value, \PDO::PARAM_STR);
}
// Debugging
//$stmt->debugDumpParams();
return $stmt;
}
}

57
Models/Paginator.php Normal file
View File

@@ -0,0 +1,57 @@
<?php
require_once('FacilityDataSet.php');
class Paginator {
protected $_pages, $_totalPages, $_rowLimit, $_pageMatrix, $_rowCount;
public function __construct($rowLimit, $dataset) {
$this->_rowLimit = $rowLimit;
$this->_totalPages = $this->calculateTotalPages($dataset['count']);
$this->_rowCount = $dataset['count'];
$this->_pages = $dataset['dataset'];
$this->_pageMatrix = $this->Paginate();
}
public function getTotalPages() {
return $this->_totalPages;
}
private function calculateTotalPages(int $count): int {
return $count > 0 ? ceil($count / $this->_rowLimit) : 0;
}
public function Paginate(): array {
$pageMatrix = [];
for ($i = 0; $i < $this->_totalPages; $i++) {
$page = [];
$start = $i * $this->_rowLimit;
$end = min($start + $this->_rowLimit, $this->_rowCount); // Ensure within bounds
for ($j = $start; $j < $end; $j++) {
$page[] = $this->_pages[$j];
}
$pageMatrix[$i] = $page;
}
return $pageMatrix;
}
public function getPageFromUri(): int {
// Retrieve 'page' parameter and default to 0 if missing or invalid
return filter_input(INPUT_GET, 'page', FILTER_VALIDATE_INT, [
'options' => ['default' => 0, 'min_range' => 0] // Default to 1 if invalid or missing
]);
}
public function getPage(int $pageNumber): array {
if ($pageNumber < 0 || $pageNumber >= $this->_totalPages) {
return []; // Return an empty array if the page number is invalid
}
return $this->_pageMatrix[$pageNumber];
}
public function countPageResults(int $pageNumber): int {
if ($pageNumber < 0 || $pageNumber >= $this->_totalPages) {
return 0; // Return 0 if the page number is invalid
}
return count($this->_pageMatrix[$pageNumber]);
}
}

86
Models/User.php Normal file
View File

@@ -0,0 +1,86 @@
<?php
require_once('UserDataSet.php');
class User {
protected $_username, $_loggedIn, $_userId, $_accessLevel;
public function getUsername() {
return $this->_username;
}
public function getUserId() {
return $this->_userId;
}
public function __construct() {
session_start();
$this->_username = "None";
$this->_loggedIn = false;
$this->_userId = "0";
$this->_accessLevel = null;
if(isset($_SESSION['login'])) {
$this->_username = $_SESSION['login'];
$this->_userId = $_SESSION['uid'];
$this->_loggedIn = true;
$this->_accessLevel = $_SESSION['accessLevel'];
}
}
public function init() {
$this->_username = "None";
$this->_userId = "0";
$this->_loggedIn = false;
if(isset($_SESSION['login'])) {
$this->_username = $_SESSION['login'];
$this->_userId = $_SESSION['uid'];
$this->_loggedIn = true;
}
}
private function setAccessLevel($level) {
$this->_accessLevel = $level;
$_SESSION['accessLevel'] = $level;
}
public function getAccessLevel() {
return $this->_accessLevel;
}
public function Authenticate($username, $password): bool
{
$users = new UserDataSet();
$userDataSet = $users->checkUserCredentials($username, $password);
$accessLevel = $users->checkAccessLevel($username);
if(count($userDataSet) > 0) {
$_SESSION['login'] = $username;
$_SESSION['uid'] = $userDataSet[0]->getId();
$this->setAccessLevel($accessLevel);
$this->_loggedIn = true;
$this->_username = $username;
$this->_userId = $userDataSet[0]->getId();
return true;
}
else {
$this->_loggedIn = false;
return false;
}
}
public function logout() {
unset($_SESSION['login']);
unset($_SESSION['uid']);
$this->_loggedIn = false;
$this->_username = "None";
$this->_userId = "0";
session_destroy();
}
public function isLoggedIn(): bool
{
return $this->_loggedIn;
}
public function __destruct()
{
}
}

20
Models/UserData.php Normal file
View File

@@ -0,0 +1,20 @@
<?php
class UserData {
protected $_id, $_username, $_name, $_password, $_usertype;
public function __construct($dbRow) {
$this->_id = $dbRow['id'];
$this->_username = $dbRow['username'];
$this->_password = $dbRow['password'];
$this->_usertype = $dbRow['userType'];
}
public function getId() {
return $this->_id;
}
public function getUsername() {
return $this->_username;
}
}

67
Models/UserDataSet.php Normal file
View File

@@ -0,0 +1,67 @@
<?php
require_once ('Database.php');
require_once ('UserData.php');
class UserDataSet {
protected $_dbHandle, $_dbInstance;
public function __construct() {
$this->_dbInstance = Database::getInstance();
$this->_dbHandle = $this->_dbInstance->getDbConnection();
}
public function checkAccessLevel($username) {
$sqlQuery = "SELECT ecoUser.userType FROM ecoUser
LEFT JOIN ecoUsertypes ON ecoUser.userType = ecoUsertypes.userType
WHERE ecoUser.username = ?";
$statement = $this->_dbHandle->prepare($sqlQuery);
$statement->bindValue(1, $username);
$statement->execute();
return $statement->fetch(PDO::FETCH_ASSOC)['userType'];
}
public function fetchAll(): array
{
$sqlQuery = 'SELECT * FROM ecoUser;';
$statement = $this->_dbHandle->prepare($sqlQuery); // prepare a PDO statement
$statement->execute(); // execute the PDO statement
$dataSet = [];
// loop through and read the results of the query and cast
// them into a matching object
while ($row = $statement->fetch()) {
$dataSet[] = new UserData($row);
}
return $dataSet;
}
/**
* @param $username
* @param $password
* @return array
*/
public function checkUserCredentials($username, $password): array
{
$sqlQuery = 'SELECT * FROM ecoUser WHERE username = ? AND password = ?;';
$statement = $this->_dbHandle->prepare($sqlQuery);
$statement->bindParam(1, $username);
$statement->bindParam(2, $password);
$statement->execute();
$dataSet = [];
while ($row = $statement->fetch()) {
$dataSet[] = new UserData($row);
}
return $dataSet;
}
public function fetchUser($username): array
{
$sqlQuery = 'SELECT * FROM ecoUser WHERE username = ?';
$statement = $this->_dbHandle->prepare($sqlQuery);
$statement->execute([$username]);
$dataSet = [];
while ($row = $statement->fetch()) {
$dataSet[] = new UserData($row);
}
return $dataSet;
}
}

0
README.md Normal file → Executable file
View File

View File

@@ -1,11 +1,60 @@
<?php require('template/header.phtml') ?> <?php require('template/header.phtml') ?>
<div class="row">
<div class="col-5">
<p><?php echo $view->dbMessage; ?></p>
</div>
<div class="col-auto">
<p>Current script <?php echo $_SERVER["PHP_SELF"]; ?></p>
</div>
</div>
<h3>Welcome to the web-site </h3> <div class="row">
<div class="container-fluid p-3">
<table class="table table-bordered">
<thead>
<tr>
<th>Facility ID</th>
<th>Title</th>
<th>Category</th>
<th>Status</th>
<th>Description</th>
<th>Address</th>
<th>Postcode</th>
<th>Lat/Long</th>
<th>Contributor</th>
<?php if($view->user->getAccessLevel() == 1): ?>
<th>Actions</th>
<?php endif; ?>
</tr>
</thead>
<tbody>
<?php foreach ($view->pageData as $facilityData): ?>
<tr>
<td><?= htmlspecialchars($facilityData->getId() ?? 'N/A') ?></td>
<td><?= htmlspecialchars($facilityData->getTitle() ?? 'N/A') ?></td>
<td><?= htmlspecialchars($facilityData->getCategory() ?? 'N/A') ?></td>
<td><?= htmlspecialchars($facilityData->getStatus() ?? 'N/A') ?></td>
<td><?= htmlspecialchars($facilityData->getDescription() ?? 'N/A') ?></td>
<td><?= htmlspecialchars(trim(($facilityData->getHouseNumber() ?? '') . ' ' .
($facilityData->getStreetName() ?? '') . ' ' .
($facilityData->getCounty() ?? '') . ' ' .
($facilityData->getTown() ?? ''))) ?></td>
<td><?= htmlspecialchars($facilityData->getPostcode() ?? 'N/A') ?></td>
<td><?= htmlspecialchars(($facilityData->getLat() ?? 'N/A') . ', ' .
($facilityData->getLng() ?? 'N/A')) ?></td>
<td><?= htmlspecialchars($facilityData->getContributor() ?? 'N/A') ?></td>
<?php if($view->user->getAccessLevel() == 1): ?>
<td class="btn-group">
<?php require("template/updateModal.phtml") ?>
<?php require("template/deleteModal.phtml") ?>
</td>
<?php endif; ?>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<h3>A template for web-site development using the <i>Model-View-Controller</i> design pattern and <a href="http://www.getbootstrap.com/css"><i>Bootstrap</i></a>.</h3>
<p>The <i>Views/template</i> directory contains a <i>header.phtl</i> and a <i>footer.phtml</i> which should be included on every new page generated.
To add additional pages just edit the file <i>header.phtml</i> to add the extra link and then add a new <i>Controller (pageN.php)</i> and a new <i>View (pageN.phtml)</i>, for each page required.</p>
<p>The <i>Model</i> code files are placed in the <i>Models</i> directory.</p>
<p>Do not change any of the css files in the <i>css</> directory!<p>
<?php require('template/footer.phtml') ?> <?php require('template/footer.phtml') ?>

View File

@@ -1,5 +0,0 @@
<?php require('template/header.phtml') ?>
<h3>Welcome to Page1</h3>
<?php require('template/footer.phtml') ?>

View File

@@ -1,5 +0,0 @@
<?php require('template/header.phtml') ?>
<h3>Welcome to Page2</h3>
<?php require('template/footer.phtml') ?>

View File

@@ -0,0 +1,32 @@
<button type="button" class="col btn bg-primary btn-outline-primary text-light" data-bs-toggle="modal" data-bs-target="#createModal">
<span class="bi bi-pen-fill"></span>
</button>
<div class="modal fade" id="createModal" tabindex="-1" aria-labelledby="updateModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="updateModalLabel">Add Facility</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form method="post" action="<?php echo htmlspecialchars($_SERVER['PHP_SELF']); ?>">
<form class="form-inline" method="post" action="<?php echo $_SERVER['PHP_SELF']; ?> ">
<input name="titlCreate" class="form-control rounded mb-2" placeholder="Title">
<input name="cateCreate" class="form-control rounded mb-2" placeholder="Category">
<input name="descCreate" class="form-control rounded mb-2" placeholder="Description">
<input name="statCreate" class="form-control rounded mb-2" placeholder="Status">
<input name="strtCreate" class="form-control rounded mb-2" placeholder="Street Name">
<input name="cntyCreate" class="form-control rounded mb-2" placeholder="County">
<input name="townCreate" class="form-control rounded mb-2" placeholder="Town">
<input name="postCreate" class="form-control rounded mb-2" placeholder="Postcode">
<input name="contCreate" class="form-control rounded mb-2" placeholder="Contributor">
</form>
<button type="submit" class="btn bg-primary btn-outline-primary text-light" name="updateButton">Add</button>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-warning" data-bs-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,19 @@
<button type="button" class="col btn bg-danger btn-outline-danger text-light" data-bs-toggle="modal" data-bs-target="#deleteModal">
<span class="bi bi-trash-fill">
</button>
<div class="modal fade" id="deleteModal" tabindex="-1" aria-labelledby="deleteModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="deleteModalLabel">Delete Facility Record</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form method="post" action="<?php echo htmlspecialchars($_SERVER['PHP_SELF']); ?>">
<button type="submit" class="btn bg-danger btn-outline-danger text-light" name="deleteButton">Yes</button>
<button type="button" class="btn btn-outline primary btn-primary" data-bs-dismiss="modal">No</button>
</form>
</div>
</div>
</div>
</div>

View File

@@ -1,15 +1,19 @@
</div> </div>
<div class="fixed-bottom mt-auto">
<div class="col-auto">
<?php require_once('pagination.phtml'); ?>
</div>
<div class="row"> <div class="row">
<div id="footer" class="col-xs-12"> <div id="footer" class="col-xs-12">
<p>Web-site development using the MVC design pattern and the Bootstrap CSS framework</p> <p class="m-0">George Wilkinson @2024</p>
<p class="m-0">Powered by Bootstrap</p>
</div>
</div> </div>
</div> </div>
<!-- Bootstrap core JavaScript <!-- Bootstrap core JavaScript
================================================== --> ================================================== -->
<!-- Placed at the end of the document so the pages load faster --> <!-- Placed at the end of the document so the pages load faster -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script> <!-- script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script -->
<script src="/js/bootstrap.min.js"></script> <script src="/js/bootstrap.min.js"></script>
</body> </body>
</html> </html>

View File

@@ -6,63 +6,105 @@
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content=""> <meta name="description" content="">
<meta name="author" content=""> <meta name="author" content="">
<link rel="icon" type="image/x-icon" href="/images/ecoBuddy_x32.png"
<!-- Bootstrap core CSS --> <!-- Bootstrap core CSS -->
<link href="/css/bootstrap.css" rel="stylesheet"> <link href="/css/bootstrap.css" rel="stylesheet">
<!-- Bootstrap theme --> <!-- Bootstrap theme -->
<link href="/css/bootstrap-theme.css" rel="stylesheet"> <link href="/css/bootstrap-theme.css" rel="stylesheet">
<link href="/css/my-style.css" rel="stylesheet"> <link href="/css/my-style.css" rel="stylesheet">
<!-- Bootstrap Icons -->
<link href="/css/bootstrap-icons.css" rel="stylesheet">
<title>Server-Side Programming - <?php echo $view->pageTitle; ?></title> <title>Ecobuddy - <?php echo $view->pageTitle; ?></title>
</head> </head>
<body role="document"> <nav class="navbar navbar-expand-lg p-0 m-2 border rounded-2">
<div class="container-fluid">
<div class="container"> <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarTogglerDemo03" aria-controls="navbarTogglerDemo03" aria-expanded="false" aria-label="Toggle navigation">
<div class="row"> <span class="navbar-toggler-icon"></span>
<div id="title" class="col-xs-12"> </button>
<img src="/images/new_uos_logo.jpg" alt="Salford University" /> <a class="navbar-brand" href="/index.php"><img id="navIcon" class="img-thumbnail bg-transparent border-3 border-success border-opacity-25 rounded my-1 me-2" height="64px" width="64px" src="/images/ecoBuddy_x64.png" alt=""/><span class="pt-5 mb-auto">Ecobuddy</span></a>
<div class="pull-right"> <h1><?php echo $view->pageTitle ?> </h1></div> <div class="collapse navbar-collapse" id="navbarTogglerDemo03">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="/index.php">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Link</a>
</li>
</ul>
<form class="row m-0 me-2 align-content-center align-content-center align-items-center" role="search" action="" method="POST">
<div class="col">
<div class="form-floating input-group">
<select name="sort" class="form-select border-3 border-success-subtle" id="sort">
<option value="1" <?php if(isset($_GET['sort']) && $_GET['sort'] == '1') echo 'selected'; ?>>Title</option>
<option value="2" <?php if(isset($_GET['sort']) && $_GET['sort'] == '2') echo 'selected'; ?>>Category</option>
<option value="0" <?php if(isset($_GET['sort']) && $_GET['sort'] == '0') echo 'selected'; ?>>Status</option>
<option value="3" <?php if(isset($_GET['sort']) && $_GET['sort'] == '3') echo 'selected'; ?>>Description</option>
<option value="4" <?php if(isset($_GET['sort']) && $_GET['sort'] == '4') echo 'selected'; ?>>Street Name</option>
<option value="5" <?php if(isset($_GET['sort']) && $_GET['sort'] == '5') echo 'selected'; ?>>County</option>
<option value="6" <?php if(isset($_GET['sort']) && $_GET['sort'] == '6') echo 'selected'; ?>>Town</option>
<option value="7" <?php if(isset($_GET['sort']) && $_GET['sort'] == '7') echo 'selected'; ?>>Postcode</option>
<option value="8" <?php if(isset($_GET['sort']) && $_GET['sort'] == '8') echo 'selected'; ?>>Contributor</option>
</select>
<span class="form-floating input-group">
<select class="form-select border-3 border-start-0 rounded-end border-success-subtle" name="dir" id="dir">
<option value="asc" <?php if($_GET['dir'] == 'asc') echo 'selected'; ?>>Asc</option>
<option value="desc" <?php if($_GET['dir'] == 'desc') echo 'selected'; ?>>Desc</option>
</select>
<label for="dir">Order</label>
</span>
<label for="sort">Sort By</label>
</div> </div>
</div> </div>
<div class="col">
<div class="form-floating input-group">
<div class="row"> <select name="filterCat" class="form-select border-3 border-success-subtle" id="filterCat">
<div id="menu" class="col-xs-6 col-sm-3 col-md-2"> <option value="1" <?php if(isset($_GET['category']) && $_GET['category'] == '1') echo 'selected'; ?>>Title</option>
<ul class="nav navbar_default nav-stacked"> <option value="2" <?php if(isset($_GET['category']) && $_GET['category'] == '2') echo 'selected'; ?>>Category</option>
<option value="0" <?php if(isset($_GET['category']) && $_GET['category'] == '0') echo 'selected'; ?>>Status</option>
<option value="3" <?php if(isset($_GET['category']) && $_GET['category'] == '3') echo 'selected'; ?>>Description</option>
<option value="4" <?php if(isset($_GET['category']) && $_GET['category'] == '4') echo 'selected'; ?>>Street Name</option>
<option value="5" <?php if(isset($_GET['category']) && $_GET['category'] == '5') echo 'selected'; ?>>County</option>
<option value="6" <?php if(isset($_GET['category']) && $_GET['category'] == '6') echo 'selected'; ?>>Town</option>
<option value="7" <?php if(isset($_GET['category']) && $_GET['category'] == '7') echo 'selected'; ?>>Postcode</option>
<option value="8" <?php if(isset($_GET['category']) && $_GET['category'] == '8') echo 'selected'; ?>>Contributor</option>
</select>
<span class="input-group-text bi bi-filter-circle bg-success-subtle border-0 rounded-end" id="filterCat"></span>
<label for="filterCat">Column Filter</label>
</div>
</div>
<div class="col">
<div class="form-floating input-group">
<label for="search"></label>
<input placeholder="<?php if(isset($_GET['filter'])) echo $_GET['filter']; ?>" class="form-control border-3 border-success-subtle" id="search" type="search" name="filter" aria-label="Search">
<span class="input-group-text bg-success-subtle border-0 rounded-end" id="search">
<button class="btn bg-light bg-success-subtle" type="submit"><span class="bi bi-search"></span></button>
</span>
</div>
</div>
</form>
<div class="me-2 ms-2">
<div class="col-sm" id="loginStatus">
<?php <?php
if (!isset($_SESSION["login"])) { if(!$view->user->isLoggedIn()) {
echo ' require_once('Views/template/loginModal.phtml');
<form method="post" action="" class="form text-primary">
<label for="username">Username</label>
<input type="text" name="username">
<label for="password">Password</label>
<input type="text" name="password">
<input type="submit" name="loginbutton" value="Login">
</form>';
} }
else if($view->user->isLoggedIn()) {
{ require_once('Views/template/logoutButton.phtml');
echo '
<form method="post" action="" class="form text-primary">
<input type="submit" name="logoutbutton" value="Logout">
</form>';
} }
?> ?>
<li><a href="/index.php">Home</a></li>
<li><a href="/page1.php">Page1</a></li>
<li><a href="/page2.php">Page2</a></li>
</ul>
</div> </div>
</div>
</div>
</div>
</nav>
<body role="document">
<div id="content" class="col-xs-6 col-sm-9 col-md-10"> <div class="container-fluid">
<?php /*require_once("sidebar.phtml");*/?>
<div class="col" id="content">

View File

@@ -0,0 +1,18 @@
<span class="ms-5 me-5 row alert alert-danger" role="alert"><?= $view->loginError ?></span>
<div class="row captcha-container">
<!-- CAPTCHA Display -->
<div class="form-floating mb-3 col">
<input type="text" class="form-control" id="captchaCode" value="<?php
// Generate a simple 5-character CAPTCHA
$captcha = substr(str_shuffle("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"), 0, 5);
echo $captcha;
?>" readonly>
<label for="captchaCode">CAPTCHA Code</label>
</div>
<!-- CAPTCHA Input -->
<div class="form-floating mb-3 col">
<input type="text" class="form-control" id="captchaInput" name="captchaInput" placeholder="Enter CAPTCHA" required>
<label for="captchaInput">Enter CAPTCHA</label>
</div>
</div>

View File

@@ -0,0 +1,39 @@
<button type="button" class="btn bg-primary btn-outline-primary text-light m-auto" data-bs-toggle="modal"
data-bs-target="#loginModal">
Login
</button>
<?= isset($view->loginError) ? '<div class="modal-backdrop fade show"></div>' : '' ?>
<div class="modal fade <?= isset($view->loginError) ? 'show' : '' ?>" id="loginModal" tabindex="-1"
aria-labelledby="loginModalLabel" aria-hidden="<?= isset($view->loginError) ? 'false' : 'true' ?>"
style="<?= isset($view->loginError) ? 'display: block;' : '' ?>">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="loginModalLabel">Login</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form method="post" action="<?php echo htmlspecialchars($_SERVER['PHP_SELF']); ?>">
<div class="mb-3">
<label for="username" class="form-label">Username</label>
<input type="text" class="form-control" id="username" name="username" placeholder="Username"
required>
</div>
<div class="mb-3">
<label for="password" class="form-label">Password</label>
<input type="password" class="form-control" id="password" name="password" placeholder="Password"
required>
</div>
<?php if (isset($view->loginError)) { include('Views/template/loginError.phtml');} ?>
<button type="submit" class="btn bg-primary btn-outline-primary text-light" name="loginButton">Login
</button>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-warning btn-outline-warning text-light" data-bs-dismiss="modal">
Close
</button>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,4 @@
<form class="form-floating my-auto" method="post" action="<?php echo $_SERVER['PHP_SELF']; ?> ">
<?php echo "<p class='text-center bg-light border-0 rounded mb-1' style='color: black;'>" . $user->getUsername() . "<span class='bi bi-person-fill'></span></p>"?>
<button class="btn bg-danger btn-outline-danger text-light" type="submit" name="logoutButton">Logout</button>
</form>

View File

@@ -0,0 +1,37 @@
<div>
<div class="row mb-2">
<!-- Form for Pagination -->
<div id="paginationButtons" class="col-auto m-auto btn-group">
<?php
$params = $_GET;
unset($params['page']); // Remove the page parameter to avoid duping
function buildUrl($page, $params): string
{
$params['page'] = $page;
return '?' . http_build_query($params);
}
?>
<!-- Start Button -->
<a class="btn btn-outline-primary" href="<?= buildUrl(0, $params) ?>0" <?= $view->pageNumber <= 0 ? 'disabled' : '' ?>><i class="bi bi-chevron-double-left"></i> Start</a>
<!-- Back Button -->
<a class="btn btn-outline-primary" href="<?= buildUrl(max($view->pageNumber - 1, 0), $params)?> " <?= $view->pageNumber <= 0 ? 'disabled' : '' ?>><i class="bi bi-chevron-left"></i> Back</a>
<!-- Dynamic Page Buttons -->
<?php
$totalPages = $view->paginator->getTotalPages();
for ($i = $view->pageNumber - 2; $i <= $view->pageNumber + 2; $i++) {
if ($i >= 0 && $i < $totalPages): ?>
<a href="<?= buildUrl($i, $params) ?>"
class="btn <?= $i === $view->pageNumber ? 'btn-dark' : 'btn-outline-primary' ?>"
<?= $i === $view->pageNumber ? 'disabled' : '' ?>>
<?= $i + 1 ?>
</a>
<?php endif;
} ?>
<!-- Forward Button -->
<a class="btn btn-outline-primary" href="<?=buildUrl(min($view->pageNumber + 1, $totalPages), $params)?>" <?= $view->pageNumber >= $totalPages - 1 ? 'disabled' : '' ?>>Forward <i class="bi bi-chevron-right"></i></a>
<!-- End Button -->
<a class="btn btn-outline-primary" href="<?= buildUrl($totalPages - 1, $params) ?>"<?= $view->pageNumber >= $totalPages - 1 ? 'disabled' : '' ?>>End <i class="bi bi-chevron-double-right"></i></a>
</div>
</div>
</div>

View File

@@ -0,0 +1,34 @@
<div class="col-2" id="sidebar">
<div class="row mt-1 m-0 p-3 border rounded" id="loginStatus">
<?php
if ($view->loginError) {
require_once('Views/template/loginError.phtml');
}
if(!$user->isLoggedIn()) {
require_once('Views/template/loginModal.phtml');
}
if($user->isLoggedIn()) {
require_once('Views/template/logoutButton.phtml');
}
?>
</div>
<div class="row mt-1 m-4 p-3 border rounded" id="filters">
<h4 class="mb-4 text-center">Filter Options</h4>
<form class="form-inline my-2 my-lg-0" method="post" action="<?php echo $_SERVER['PHP_SELF']; ?> ">
<!--<input class="btn bg-primary btn-outline-primary text-light" type="submit" name="addFilter" value="+">-->
<input name="0" class="form-control rounded mb-2" placeholder="Title">
<input name="1" class="form-control rounded mb-2" placeholder="Category">
<input name="2" class="form-control rounded mb-2" placeholder="Description">
<input name="3" class="form-control rounded mb-2" placeholder="Status">
<input name="4" class="form-control rounded mb-2" placeholder="Street Name">
<input name="5" class="form-control rounded mb-2" placeholder="County">
<input name="6" class="form-control rounded mb-2" placeholder="Town">
<input name="7" class="form-control rounded mb-2" placeholder="Postcode">
<input name="8" class="form-control rounded mb-2" placeholder="Contributor">
<button name="applyFilters" class="form-control rounded mb-2 mt-3 btn bg-primary border-primary">Update</button>
<button name="clearFilters" class="form-control rounded mb-2 btn bg-danger border-danger">Clear</button>
</form>
</div>
</div>

View File

@@ -0,0 +1,32 @@
<button type="button" class="col btn bg-primary btn-outline-primary text-light" data-bs-toggle="modal" data-bs-target="#updateModal">
<span class="bi bi-pen-fill"></span>
</button>
<div class="modal fade" id="updateModal" tabindex="-1" aria-labelledby="updateModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="updateModalLabel">Update Facility</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form method="post" action="<?php echo htmlspecialchars($_SERVER['PHP_SELF']); ?>">
<form class="form-inline" method="post" action="<?php echo $_SERVER['PHP_SELF']; ?> ">
<input name="titlUpdate" class="form-control rounded mb-2" placeholder="Title">
<input name="cateUpdate" class="form-control rounded mb-2" placeholder="Category">
<input name="descUpdate" class="form-control rounded mb-2" placeholder="Description">
<input name="statUpdate" class="form-control rounded mb-2" placeholder="Status">
<input name="strtUpdate" class="form-control rounded mb-2" placeholder="Street Name">
<input name="cntyUpdate" class="form-control rounded mb-2" placeholder="County">
<input name="townUpdate" class="form-control rounded mb-2" placeholder="Town">
<input name="postUpdate" class="form-control rounded mb-2" placeholder="Postcode">
<input name="contUpdate" class="form-control rounded mb-2" placeholder="Contributor">
</form>
<button type="submit" class="btn bg-primary btn-outline-primary text-light" name="updateButton">Update</button>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-warning" data-bs-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>

4085
css/bootstrap-grid.css vendored Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

6
css/bootstrap-grid.min.css vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

4084
css/bootstrap-grid.rtl.css vendored Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

6
css/bootstrap-grid.rtl.min.css vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2078
css/bootstrap-icons.css vendored Normal file

File diff suppressed because it is too large Load Diff

2052
css/bootstrap-icons.json Normal file

File diff suppressed because it is too large Load Diff

5
css/bootstrap-icons.min.css vendored Normal file

File diff suppressed because one or more lines are too long

2090
css/bootstrap-icons.scss vendored Normal file

File diff suppressed because it is too large Load Diff

597
css/bootstrap-reboot.css vendored Normal file
View File

@@ -0,0 +1,597 @@
/*!
* Bootstrap Reboot v5.3.3 (https://getbootstrap.com/)
* Copyright 2011-2024 The Bootstrap Authors
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
:root,
[data-bs-theme=light] {
--bs-blue: #0d6efd;
--bs-indigo: #6610f2;
--bs-purple: #6f42c1;
--bs-pink: #d63384;
--bs-red: #dc3545;
--bs-orange: #fd7e14;
--bs-yellow: #ffc107;
--bs-green: #198754;
--bs-teal: #20c997;
--bs-cyan: #0dcaf0;
--bs-black: #000;
--bs-white: #fff;
--bs-gray: #6c757d;
--bs-gray-dark: #343a40;
--bs-gray-100: #f8f9fa;
--bs-gray-200: #e9ecef;
--bs-gray-300: #dee2e6;
--bs-gray-400: #ced4da;
--bs-gray-500: #adb5bd;
--bs-gray-600: #6c757d;
--bs-gray-700: #495057;
--bs-gray-800: #343a40;
--bs-gray-900: #212529;
--bs-primary: #0d6efd;
--bs-secondary: #6c757d;
--bs-success: #198754;
--bs-info: #0dcaf0;
--bs-warning: #ffc107;
--bs-danger: #dc3545;
--bs-light: #f8f9fa;
--bs-dark: #212529;
--bs-primary-rgb: 13, 110, 253;
--bs-secondary-rgb: 108, 117, 125;
--bs-success-rgb: 25, 135, 84;
--bs-info-rgb: 13, 202, 240;
--bs-warning-rgb: 255, 193, 7;
--bs-danger-rgb: 220, 53, 69;
--bs-light-rgb: 248, 249, 250;
--bs-dark-rgb: 33, 37, 41;
--bs-primary-text-emphasis: #052c65;
--bs-secondary-text-emphasis: #2b2f32;
--bs-success-text-emphasis: #0a3622;
--bs-info-text-emphasis: #055160;
--bs-warning-text-emphasis: #664d03;
--bs-danger-text-emphasis: #58151c;
--bs-light-text-emphasis: #495057;
--bs-dark-text-emphasis: #495057;
--bs-primary-bg-subtle: #cfe2ff;
--bs-secondary-bg-subtle: #e2e3e5;
--bs-success-bg-subtle: #d1e7dd;
--bs-info-bg-subtle: #cff4fc;
--bs-warning-bg-subtle: #fff3cd;
--bs-danger-bg-subtle: #f8d7da;
--bs-light-bg-subtle: #fcfcfd;
--bs-dark-bg-subtle: #ced4da;
--bs-primary-border-subtle: #9ec5fe;
--bs-secondary-border-subtle: #c4c8cb;
--bs-success-border-subtle: #a3cfbb;
--bs-info-border-subtle: #9eeaf9;
--bs-warning-border-subtle: #ffe69c;
--bs-danger-border-subtle: #f1aeb5;
--bs-light-border-subtle: #e9ecef;
--bs-dark-border-subtle: #adb5bd;
--bs-white-rgb: 255, 255, 255;
--bs-black-rgb: 0, 0, 0;
--bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
--bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
--bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));
--bs-body-font-family: var(--bs-font-sans-serif);
--bs-body-font-size: 1rem;
--bs-body-font-weight: 400;
--bs-body-line-height: 1.5;
--bs-body-color: #212529;
--bs-body-color-rgb: 33, 37, 41;
--bs-body-bg: #fff;
--bs-body-bg-rgb: 255, 255, 255;
--bs-emphasis-color: #000;
--bs-emphasis-color-rgb: 0, 0, 0;
--bs-secondary-color: rgba(33, 37, 41, 0.75);
--bs-secondary-color-rgb: 33, 37, 41;
--bs-secondary-bg: #e9ecef;
--bs-secondary-bg-rgb: 233, 236, 239;
--bs-tertiary-color: rgba(33, 37, 41, 0.5);
--bs-tertiary-color-rgb: 33, 37, 41;
--bs-tertiary-bg: #f8f9fa;
--bs-tertiary-bg-rgb: 248, 249, 250;
--bs-heading-color: inherit;
--bs-link-color: #0d6efd;
--bs-link-color-rgb: 13, 110, 253;
--bs-link-decoration: underline;
--bs-link-hover-color: #0a58ca;
--bs-link-hover-color-rgb: 10, 88, 202;
--bs-code-color: #d63384;
--bs-highlight-color: #212529;
--bs-highlight-bg: #fff3cd;
--bs-border-width: 1px;
--bs-border-style: solid;
--bs-border-color: #dee2e6;
--bs-border-color-translucent: rgba(0, 0, 0, 0.175);
--bs-border-radius: 0.375rem;
--bs-border-radius-sm: 0.25rem;
--bs-border-radius-lg: 0.5rem;
--bs-border-radius-xl: 1rem;
--bs-border-radius-xxl: 2rem;
--bs-border-radius-2xl: var(--bs-border-radius-xxl);
--bs-border-radius-pill: 50rem;
--bs-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
--bs-box-shadow-sm: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
--bs-box-shadow-lg: 0 1rem 3rem rgba(0, 0, 0, 0.175);
--bs-box-shadow-inset: inset 0 1px 2px rgba(0, 0, 0, 0.075);
--bs-focus-ring-width: 0.25rem;
--bs-focus-ring-opacity: 0.25;
--bs-focus-ring-color: rgba(13, 110, 253, 0.25);
--bs-form-valid-color: #198754;
--bs-form-valid-border-color: #198754;
--bs-form-invalid-color: #dc3545;
--bs-form-invalid-border-color: #dc3545;
}
[data-bs-theme=dark] {
color-scheme: dark;
--bs-body-color: #dee2e6;
--bs-body-color-rgb: 222, 226, 230;
--bs-body-bg: #212529;
--bs-body-bg-rgb: 33, 37, 41;
--bs-emphasis-color: #fff;
--bs-emphasis-color-rgb: 255, 255, 255;
--bs-secondary-color: rgba(222, 226, 230, 0.75);
--bs-secondary-color-rgb: 222, 226, 230;
--bs-secondary-bg: #343a40;
--bs-secondary-bg-rgb: 52, 58, 64;
--bs-tertiary-color: rgba(222, 226, 230, 0.5);
--bs-tertiary-color-rgb: 222, 226, 230;
--bs-tertiary-bg: #2b3035;
--bs-tertiary-bg-rgb: 43, 48, 53;
--bs-primary-text-emphasis: #6ea8fe;
--bs-secondary-text-emphasis: #a7acb1;
--bs-success-text-emphasis: #75b798;
--bs-info-text-emphasis: #6edff6;
--bs-warning-text-emphasis: #ffda6a;
--bs-danger-text-emphasis: #ea868f;
--bs-light-text-emphasis: #f8f9fa;
--bs-dark-text-emphasis: #dee2e6;
--bs-primary-bg-subtle: #031633;
--bs-secondary-bg-subtle: #161719;
--bs-success-bg-subtle: #051b11;
--bs-info-bg-subtle: #032830;
--bs-warning-bg-subtle: #332701;
--bs-danger-bg-subtle: #2c0b0e;
--bs-light-bg-subtle: #343a40;
--bs-dark-bg-subtle: #1a1d20;
--bs-primary-border-subtle: #084298;
--bs-secondary-border-subtle: #41464b;
--bs-success-border-subtle: #0f5132;
--bs-info-border-subtle: #087990;
--bs-warning-border-subtle: #997404;
--bs-danger-border-subtle: #842029;
--bs-light-border-subtle: #495057;
--bs-dark-border-subtle: #343a40;
--bs-heading-color: inherit;
--bs-link-color: #6ea8fe;
--bs-link-hover-color: #8bb9fe;
--bs-link-color-rgb: 110, 168, 254;
--bs-link-hover-color-rgb: 139, 185, 254;
--bs-code-color: #e685b5;
--bs-highlight-color: #dee2e6;
--bs-highlight-bg: #664d03;
--bs-border-color: #495057;
--bs-border-color-translucent: rgba(255, 255, 255, 0.15);
--bs-form-valid-color: #75b798;
--bs-form-valid-border-color: #75b798;
--bs-form-invalid-color: #ea868f;
--bs-form-invalid-border-color: #ea868f;
}
*,
*::before,
*::after {
box-sizing: border-box;
}
@media (prefers-reduced-motion: no-preference) {
:root {
scroll-behavior: smooth;
}
}
body {
margin: 0;
font-family: var(--bs-body-font-family);
font-size: var(--bs-body-font-size);
font-weight: var(--bs-body-font-weight);
line-height: var(--bs-body-line-height);
color: var(--bs-body-color);
text-align: var(--bs-body-text-align);
background-color: var(--bs-body-bg);
-webkit-text-size-adjust: 100%;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
hr {
margin: 1rem 0;
color: inherit;
border: 0;
border-top: var(--bs-border-width) solid;
opacity: 0.25;
}
h6, h5, h4, h3, h2, h1 {
margin-top: 0;
margin-bottom: 0.5rem;
font-weight: 500;
line-height: 1.2;
color: var(--bs-heading-color);
}
h1 {
font-size: calc(1.375rem + 1.5vw);
}
@media (min-width: 1200px) {
h1 {
font-size: 2.5rem;
}
}
h2 {
font-size: calc(1.325rem + 0.9vw);
}
@media (min-width: 1200px) {
h2 {
font-size: 2rem;
}
}
h3 {
font-size: calc(1.3rem + 0.6vw);
}
@media (min-width: 1200px) {
h3 {
font-size: 1.75rem;
}
}
h4 {
font-size: calc(1.275rem + 0.3vw);
}
@media (min-width: 1200px) {
h4 {
font-size: 1.5rem;
}
}
h5 {
font-size: 1.25rem;
}
h6 {
font-size: 1rem;
}
p {
margin-top: 0;
margin-bottom: 1rem;
}
abbr[title] {
-webkit-text-decoration: underline dotted;
text-decoration: underline dotted;
cursor: help;
-webkit-text-decoration-skip-ink: none;
text-decoration-skip-ink: none;
}
address {
margin-bottom: 1rem;
font-style: normal;
line-height: inherit;
}
ol,
ul {
padding-left: 2rem;
}
ol,
ul,
dl {
margin-top: 0;
margin-bottom: 1rem;
}
ol ol,
ul ul,
ol ul,
ul ol {
margin-bottom: 0;
}
dt {
font-weight: 700;
}
dd {
margin-bottom: 0.5rem;
margin-left: 0;
}
blockquote {
margin: 0 0 1rem;
}
b,
strong {
font-weight: bolder;
}
small {
font-size: 0.875em;
}
mark {
padding: 0.1875em;
color: var(--bs-highlight-color);
background-color: var(--bs-highlight-bg);
}
sub,
sup {
position: relative;
font-size: 0.75em;
line-height: 0;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
a {
color: rgba(var(--bs-link-color-rgb), var(--bs-link-opacity, 1));
text-decoration: underline;
}
a:hover {
--bs-link-color-rgb: var(--bs-link-hover-color-rgb);
}
a:not([href]):not([class]), a:not([href]):not([class]):hover {
color: inherit;
text-decoration: none;
}
pre,
code,
kbd,
samp {
font-family: var(--bs-font-monospace);
font-size: 1em;
}
pre {
display: block;
margin-top: 0;
margin-bottom: 1rem;
overflow: auto;
font-size: 0.875em;
}
pre code {
font-size: inherit;
color: inherit;
word-break: normal;
}
code {
font-size: 0.875em;
color: var(--bs-code-color);
word-wrap: break-word;
}
a > code {
color: inherit;
}
kbd {
padding: 0.1875rem 0.375rem;
font-size: 0.875em;
color: var(--bs-body-bg);
background-color: var(--bs-body-color);
border-radius: 0.25rem;
}
kbd kbd {
padding: 0;
font-size: 1em;
}
figure {
margin: 0 0 1rem;
}
img,
svg {
vertical-align: middle;
}
table {
caption-side: bottom;
border-collapse: collapse;
}
caption {
padding-top: 0.5rem;
padding-bottom: 0.5rem;
color: var(--bs-secondary-color);
text-align: left;
}
th {
text-align: inherit;
text-align: -webkit-match-parent;
}
thead,
tbody,
tfoot,
tr,
td,
th {
border-color: inherit;
border-style: solid;
border-width: 0;
}
label {
display: inline-block;
}
button {
border-radius: 0;
}
button:focus:not(:focus-visible) {
outline: 0;
}
input,
button,
select,
optgroup,
textarea {
margin: 0;
font-family: inherit;
font-size: inherit;
line-height: inherit;
}
button,
select {
text-transform: none;
}
[role=button] {
cursor: pointer;
}
select {
word-wrap: normal;
}
select:disabled {
opacity: 1;
}
[list]:not([type=date]):not([type=datetime-local]):not([type=month]):not([type=week]):not([type=time])::-webkit-calendar-picker-indicator {
display: none !important;
}
button,
[type=button],
[type=reset],
[type=submit] {
-webkit-appearance: button;
}
button:not(:disabled),
[type=button]:not(:disabled),
[type=reset]:not(:disabled),
[type=submit]:not(:disabled) {
cursor: pointer;
}
::-moz-focus-inner {
padding: 0;
border-style: none;
}
textarea {
resize: vertical;
}
fieldset {
min-width: 0;
padding: 0;
margin: 0;
border: 0;
}
legend {
float: left;
width: 100%;
padding: 0;
margin-bottom: 0.5rem;
font-size: calc(1.275rem + 0.3vw);
line-height: inherit;
}
@media (min-width: 1200px) {
legend {
font-size: 1.5rem;
}
}
legend + * {
clear: left;
}
::-webkit-datetime-edit-fields-wrapper,
::-webkit-datetime-edit-text,
::-webkit-datetime-edit-minute,
::-webkit-datetime-edit-hour-field,
::-webkit-datetime-edit-day-field,
::-webkit-datetime-edit-month-field,
::-webkit-datetime-edit-year-field {
padding: 0;
}
::-webkit-inner-spin-button {
height: auto;
}
[type=search] {
-webkit-appearance: textfield;
outline-offset: -2px;
}
/* rtl:raw:
[type="tel"],
[type="url"],
[type="email"],
[type="number"] {
direction: ltr;
}
*/
::-webkit-search-decoration {
-webkit-appearance: none;
}
::-webkit-color-swatch-wrapper {
padding: 0;
}
::-webkit-file-upload-button {
font: inherit;
-webkit-appearance: button;
}
::file-selector-button {
font: inherit;
-webkit-appearance: button;
}
output {
display: inline-block;
}
iframe {
border: 0;
}
summary {
display: list-item;
cursor: pointer;
}
progress {
vertical-align: baseline;
}
[hidden] {
display: none !important;
}
/*# sourceMappingURL=bootstrap-reboot.css.map */

File diff suppressed because one or more lines are too long

6
css/bootstrap-reboot.min.css vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

594
css/bootstrap-reboot.rtl.css vendored Normal file
View File

@@ -0,0 +1,594 @@
/*!
* Bootstrap Reboot v5.3.3 (https://getbootstrap.com/)
* Copyright 2011-2024 The Bootstrap Authors
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
:root,
[data-bs-theme=light] {
--bs-blue: #0d6efd;
--bs-indigo: #6610f2;
--bs-purple: #6f42c1;
--bs-pink: #d63384;
--bs-red: #dc3545;
--bs-orange: #fd7e14;
--bs-yellow: #ffc107;
--bs-green: #198754;
--bs-teal: #20c997;
--bs-cyan: #0dcaf0;
--bs-black: #000;
--bs-white: #fff;
--bs-gray: #6c757d;
--bs-gray-dark: #343a40;
--bs-gray-100: #f8f9fa;
--bs-gray-200: #e9ecef;
--bs-gray-300: #dee2e6;
--bs-gray-400: #ced4da;
--bs-gray-500: #adb5bd;
--bs-gray-600: #6c757d;
--bs-gray-700: #495057;
--bs-gray-800: #343a40;
--bs-gray-900: #212529;
--bs-primary: #0d6efd;
--bs-secondary: #6c757d;
--bs-success: #198754;
--bs-info: #0dcaf0;
--bs-warning: #ffc107;
--bs-danger: #dc3545;
--bs-light: #f8f9fa;
--bs-dark: #212529;
--bs-primary-rgb: 13, 110, 253;
--bs-secondary-rgb: 108, 117, 125;
--bs-success-rgb: 25, 135, 84;
--bs-info-rgb: 13, 202, 240;
--bs-warning-rgb: 255, 193, 7;
--bs-danger-rgb: 220, 53, 69;
--bs-light-rgb: 248, 249, 250;
--bs-dark-rgb: 33, 37, 41;
--bs-primary-text-emphasis: #052c65;
--bs-secondary-text-emphasis: #2b2f32;
--bs-success-text-emphasis: #0a3622;
--bs-info-text-emphasis: #055160;
--bs-warning-text-emphasis: #664d03;
--bs-danger-text-emphasis: #58151c;
--bs-light-text-emphasis: #495057;
--bs-dark-text-emphasis: #495057;
--bs-primary-bg-subtle: #cfe2ff;
--bs-secondary-bg-subtle: #e2e3e5;
--bs-success-bg-subtle: #d1e7dd;
--bs-info-bg-subtle: #cff4fc;
--bs-warning-bg-subtle: #fff3cd;
--bs-danger-bg-subtle: #f8d7da;
--bs-light-bg-subtle: #fcfcfd;
--bs-dark-bg-subtle: #ced4da;
--bs-primary-border-subtle: #9ec5fe;
--bs-secondary-border-subtle: #c4c8cb;
--bs-success-border-subtle: #a3cfbb;
--bs-info-border-subtle: #9eeaf9;
--bs-warning-border-subtle: #ffe69c;
--bs-danger-border-subtle: #f1aeb5;
--bs-light-border-subtle: #e9ecef;
--bs-dark-border-subtle: #adb5bd;
--bs-white-rgb: 255, 255, 255;
--bs-black-rgb: 0, 0, 0;
--bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
--bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
--bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));
--bs-body-font-family: var(--bs-font-sans-serif);
--bs-body-font-size: 1rem;
--bs-body-font-weight: 400;
--bs-body-line-height: 1.5;
--bs-body-color: #212529;
--bs-body-color-rgb: 33, 37, 41;
--bs-body-bg: #fff;
--bs-body-bg-rgb: 255, 255, 255;
--bs-emphasis-color: #000;
--bs-emphasis-color-rgb: 0, 0, 0;
--bs-secondary-color: rgba(33, 37, 41, 0.75);
--bs-secondary-color-rgb: 33, 37, 41;
--bs-secondary-bg: #e9ecef;
--bs-secondary-bg-rgb: 233, 236, 239;
--bs-tertiary-color: rgba(33, 37, 41, 0.5);
--bs-tertiary-color-rgb: 33, 37, 41;
--bs-tertiary-bg: #f8f9fa;
--bs-tertiary-bg-rgb: 248, 249, 250;
--bs-heading-color: inherit;
--bs-link-color: #0d6efd;
--bs-link-color-rgb: 13, 110, 253;
--bs-link-decoration: underline;
--bs-link-hover-color: #0a58ca;
--bs-link-hover-color-rgb: 10, 88, 202;
--bs-code-color: #d63384;
--bs-highlight-color: #212529;
--bs-highlight-bg: #fff3cd;
--bs-border-width: 1px;
--bs-border-style: solid;
--bs-border-color: #dee2e6;
--bs-border-color-translucent: rgba(0, 0, 0, 0.175);
--bs-border-radius: 0.375rem;
--bs-border-radius-sm: 0.25rem;
--bs-border-radius-lg: 0.5rem;
--bs-border-radius-xl: 1rem;
--bs-border-radius-xxl: 2rem;
--bs-border-radius-2xl: var(--bs-border-radius-xxl);
--bs-border-radius-pill: 50rem;
--bs-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
--bs-box-shadow-sm: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
--bs-box-shadow-lg: 0 1rem 3rem rgba(0, 0, 0, 0.175);
--bs-box-shadow-inset: inset 0 1px 2px rgba(0, 0, 0, 0.075);
--bs-focus-ring-width: 0.25rem;
--bs-focus-ring-opacity: 0.25;
--bs-focus-ring-color: rgba(13, 110, 253, 0.25);
--bs-form-valid-color: #198754;
--bs-form-valid-border-color: #198754;
--bs-form-invalid-color: #dc3545;
--bs-form-invalid-border-color: #dc3545;
}
[data-bs-theme=dark] {
color-scheme: dark;
--bs-body-color: #dee2e6;
--bs-body-color-rgb: 222, 226, 230;
--bs-body-bg: #212529;
--bs-body-bg-rgb: 33, 37, 41;
--bs-emphasis-color: #fff;
--bs-emphasis-color-rgb: 255, 255, 255;
--bs-secondary-color: rgba(222, 226, 230, 0.75);
--bs-secondary-color-rgb: 222, 226, 230;
--bs-secondary-bg: #343a40;
--bs-secondary-bg-rgb: 52, 58, 64;
--bs-tertiary-color: rgba(222, 226, 230, 0.5);
--bs-tertiary-color-rgb: 222, 226, 230;
--bs-tertiary-bg: #2b3035;
--bs-tertiary-bg-rgb: 43, 48, 53;
--bs-primary-text-emphasis: #6ea8fe;
--bs-secondary-text-emphasis: #a7acb1;
--bs-success-text-emphasis: #75b798;
--bs-info-text-emphasis: #6edff6;
--bs-warning-text-emphasis: #ffda6a;
--bs-danger-text-emphasis: #ea868f;
--bs-light-text-emphasis: #f8f9fa;
--bs-dark-text-emphasis: #dee2e6;
--bs-primary-bg-subtle: #031633;
--bs-secondary-bg-subtle: #161719;
--bs-success-bg-subtle: #051b11;
--bs-info-bg-subtle: #032830;
--bs-warning-bg-subtle: #332701;
--bs-danger-bg-subtle: #2c0b0e;
--bs-light-bg-subtle: #343a40;
--bs-dark-bg-subtle: #1a1d20;
--bs-primary-border-subtle: #084298;
--bs-secondary-border-subtle: #41464b;
--bs-success-border-subtle: #0f5132;
--bs-info-border-subtle: #087990;
--bs-warning-border-subtle: #997404;
--bs-danger-border-subtle: #842029;
--bs-light-border-subtle: #495057;
--bs-dark-border-subtle: #343a40;
--bs-heading-color: inherit;
--bs-link-color: #6ea8fe;
--bs-link-hover-color: #8bb9fe;
--bs-link-color-rgb: 110, 168, 254;
--bs-link-hover-color-rgb: 139, 185, 254;
--bs-code-color: #e685b5;
--bs-highlight-color: #dee2e6;
--bs-highlight-bg: #664d03;
--bs-border-color: #495057;
--bs-border-color-translucent: rgba(255, 255, 255, 0.15);
--bs-form-valid-color: #75b798;
--bs-form-valid-border-color: #75b798;
--bs-form-invalid-color: #ea868f;
--bs-form-invalid-border-color: #ea868f;
}
*,
*::before,
*::after {
box-sizing: border-box;
}
@media (prefers-reduced-motion: no-preference) {
:root {
scroll-behavior: smooth;
}
}
body {
margin: 0;
font-family: var(--bs-body-font-family);
font-size: var(--bs-body-font-size);
font-weight: var(--bs-body-font-weight);
line-height: var(--bs-body-line-height);
color: var(--bs-body-color);
text-align: var(--bs-body-text-align);
background-color: var(--bs-body-bg);
-webkit-text-size-adjust: 100%;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
hr {
margin: 1rem 0;
color: inherit;
border: 0;
border-top: var(--bs-border-width) solid;
opacity: 0.25;
}
h6, h5, h4, h3, h2, h1 {
margin-top: 0;
margin-bottom: 0.5rem;
font-weight: 500;
line-height: 1.2;
color: var(--bs-heading-color);
}
h1 {
font-size: calc(1.375rem + 1.5vw);
}
@media (min-width: 1200px) {
h1 {
font-size: 2.5rem;
}
}
h2 {
font-size: calc(1.325rem + 0.9vw);
}
@media (min-width: 1200px) {
h2 {
font-size: 2rem;
}
}
h3 {
font-size: calc(1.3rem + 0.6vw);
}
@media (min-width: 1200px) {
h3 {
font-size: 1.75rem;
}
}
h4 {
font-size: calc(1.275rem + 0.3vw);
}
@media (min-width: 1200px) {
h4 {
font-size: 1.5rem;
}
}
h5 {
font-size: 1.25rem;
}
h6 {
font-size: 1rem;
}
p {
margin-top: 0;
margin-bottom: 1rem;
}
abbr[title] {
-webkit-text-decoration: underline dotted;
text-decoration: underline dotted;
cursor: help;
-webkit-text-decoration-skip-ink: none;
text-decoration-skip-ink: none;
}
address {
margin-bottom: 1rem;
font-style: normal;
line-height: inherit;
}
ol,
ul {
padding-right: 2rem;
}
ol,
ul,
dl {
margin-top: 0;
margin-bottom: 1rem;
}
ol ol,
ul ul,
ol ul,
ul ol {
margin-bottom: 0;
}
dt {
font-weight: 700;
}
dd {
margin-bottom: 0.5rem;
margin-right: 0;
}
blockquote {
margin: 0 0 1rem;
}
b,
strong {
font-weight: bolder;
}
small {
font-size: 0.875em;
}
mark {
padding: 0.1875em;
color: var(--bs-highlight-color);
background-color: var(--bs-highlight-bg);
}
sub,
sup {
position: relative;
font-size: 0.75em;
line-height: 0;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
a {
color: rgba(var(--bs-link-color-rgb), var(--bs-link-opacity, 1));
text-decoration: underline;
}
a:hover {
--bs-link-color-rgb: var(--bs-link-hover-color-rgb);
}
a:not([href]):not([class]), a:not([href]):not([class]):hover {
color: inherit;
text-decoration: none;
}
pre,
code,
kbd,
samp {
font-family: var(--bs-font-monospace);
font-size: 1em;
}
pre {
display: block;
margin-top: 0;
margin-bottom: 1rem;
overflow: auto;
font-size: 0.875em;
}
pre code {
font-size: inherit;
color: inherit;
word-break: normal;
}
code {
font-size: 0.875em;
color: var(--bs-code-color);
word-wrap: break-word;
}
a > code {
color: inherit;
}
kbd {
padding: 0.1875rem 0.375rem;
font-size: 0.875em;
color: var(--bs-body-bg);
background-color: var(--bs-body-color);
border-radius: 0.25rem;
}
kbd kbd {
padding: 0;
font-size: 1em;
}
figure {
margin: 0 0 1rem;
}
img,
svg {
vertical-align: middle;
}
table {
caption-side: bottom;
border-collapse: collapse;
}
caption {
padding-top: 0.5rem;
padding-bottom: 0.5rem;
color: var(--bs-secondary-color);
text-align: right;
}
th {
text-align: inherit;
text-align: -webkit-match-parent;
}
thead,
tbody,
tfoot,
tr,
td,
th {
border-color: inherit;
border-style: solid;
border-width: 0;
}
label {
display: inline-block;
}
button {
border-radius: 0;
}
button:focus:not(:focus-visible) {
outline: 0;
}
input,
button,
select,
optgroup,
textarea {
margin: 0;
font-family: inherit;
font-size: inherit;
line-height: inherit;
}
button,
select {
text-transform: none;
}
[role=button] {
cursor: pointer;
}
select {
word-wrap: normal;
}
select:disabled {
opacity: 1;
}
[list]:not([type=date]):not([type=datetime-local]):not([type=month]):not([type=week]):not([type=time])::-webkit-calendar-picker-indicator {
display: none !important;
}
button,
[type=button],
[type=reset],
[type=submit] {
-webkit-appearance: button;
}
button:not(:disabled),
[type=button]:not(:disabled),
[type=reset]:not(:disabled),
[type=submit]:not(:disabled) {
cursor: pointer;
}
::-moz-focus-inner {
padding: 0;
border-style: none;
}
textarea {
resize: vertical;
}
fieldset {
min-width: 0;
padding: 0;
margin: 0;
border: 0;
}
legend {
float: right;
width: 100%;
padding: 0;
margin-bottom: 0.5rem;
font-size: calc(1.275rem + 0.3vw);
line-height: inherit;
}
@media (min-width: 1200px) {
legend {
font-size: 1.5rem;
}
}
legend + * {
clear: right;
}
::-webkit-datetime-edit-fields-wrapper,
::-webkit-datetime-edit-text,
::-webkit-datetime-edit-minute,
::-webkit-datetime-edit-hour-field,
::-webkit-datetime-edit-day-field,
::-webkit-datetime-edit-month-field,
::-webkit-datetime-edit-year-field {
padding: 0;
}
::-webkit-inner-spin-button {
height: auto;
}
[type=search] {
-webkit-appearance: textfield;
outline-offset: -2px;
}
[type="tel"],
[type="url"],
[type="email"],
[type="number"] {
direction: ltr;
}
::-webkit-search-decoration {
-webkit-appearance: none;
}
::-webkit-color-swatch-wrapper {
padding: 0;
}
::-webkit-file-upload-button {
font: inherit;
-webkit-appearance: button;
}
::file-selector-button {
font: inherit;
-webkit-appearance: button;
}
output {
display: inline-block;
}
iframe {
border: 0;
}
summary {
display: list-item;
cursor: pointer;
}
progress {
vertical-align: baseline;
}
[hidden] {
display: none !important;
}
/*# sourceMappingURL=bootstrap-reboot.rtl.css.map */

File diff suppressed because one or more lines are too long

6
css/bootstrap-reboot.rtl.min.css vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

0
css/bootstrap-theme.css vendored Normal file → Executable file
View File

0
css/bootstrap-theme.css.map Normal file → Executable file
View File

0
css/bootstrap-theme.min.css vendored Normal file → Executable file
View File

5402
css/bootstrap-utilities.css vendored Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

6
css/bootstrap-utilities.min.css vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

5393
css/bootstrap-utilities.rtl.css vendored Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

6
css/bootstrap-utilities.rtl.min.css vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

16666
css/bootstrap.css vendored

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

13
css/bootstrap.min.css vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

12030
css/bootstrap.rtl.css vendored Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

6
css/bootstrap.rtl.min.css vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

26
css/my-style.css Normal file → Executable file
View File

@@ -1,3 +1,11 @@
nav, #loginStatus, #filters {
background-color: #3cc471;
color: #111
}
/*body {
overflow-y: hidden;
}*/
#title { #title {
margin-top: 12px; margin-top: 12px;
background-color: #fff; background-color: #fff;
@@ -12,13 +20,13 @@
} }
#menu a { #menu a {
background-color: #f00; /*background-color: #f00;*/
color: #fff; color: #fff;
text-decoration: none; text-decoration: none;
display: block; display: block;
} }
#menu a:hover { #menu a:hover {
background-color: #f00; /*background-color: #f00;*/
color: #ddd; color: #ddd;
text-decoration:underline; text-decoration:underline;
display: block; display: block;
@@ -26,13 +34,21 @@
#content { #content {
background-color: #fff; background-color: #fff;
border-top: solid 6px #f00; /*border-top: solid 6px #f00;*/
} }
#footer { #footer {
margin-top: 20px; margin-top: 20px;
text-align: center; text-align: center;
background-color: #000; background-color: #bbb;
color: #fff; color: #111;
}
.modal {
z-index: 1055
}
.modal-backdrop {
z-index: 1040;
} }

View File

@@ -1,27 +0,0 @@
services:
nginx-web:
container_name: nginx-web
image: nginx
volumes:
- ./nginx/configs/:/etc/nginx/
- ./nginx/logs/:/var/log/nginx
#- /home/boris/OneDrive/CSCS-Y2/Client Server Systems/Ecobuddy/nginx/nginx.conf:/etc/nginx/nginx.conf
- ./:/var/www/html
#- /home/boris/OneDrive/CSCS-Y2/Client Server Systems/Ecobuddy/access.log:/var/log/nginx/access.log
#- /home/boris/OneDrive/CSCS-Y2/Client Server Systems/Ecobuddy/error.log:/var/log/nginx/error.log
ports:
- "8088:80"
environment:
- NGINX_HOST=localhost
- NGINX_PORT=8088
links:
- php-fpm
depends_on:
- php-fpm
php-fpm:
container_name: php-fpm
image: php:8-fpm
volumes:
- ./:/var/www/
- /home/boris/OneDrive/CSCS-Y2/Client Server Systems/Ecobuddy/nginx/php/config/www.conf:/usr/local/etc/php-fpm.d/www.conf
- /home/boris/OneDrive/CSCS-Y2/Client Server Systems/Ecobuddy/nginx/php/fpm-php.www.log:/var/log/fpm-php.www.log

0
eco database design v3.docx Normal file → Executable file
View File

0
fonts/glyphicons-halflings-regular.eot Normal file → Executable file
View File

0
fonts/glyphicons-halflings-regular.svg Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 62 KiB

0
fonts/glyphicons-halflings-regular.ttf Normal file → Executable file
View File

0
fonts/glyphicons-halflings-regular.woff Normal file → Executable file
View File

BIN
images/ecoBuddy_x128.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

BIN
images/ecoBuddy_x128.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

BIN
images/ecoBuddy_x32.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

BIN
images/ecoBuddy_x32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

BIN
images/ecoBuddy_x64.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

BIN
images/ecoBuddy_x64.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

View File

@@ -1,10 +1,24 @@
<?php <?php
// load required classes
require_once('Models/UserDataSet.php');
// make a view class
$view = new stdClass(); $view = new stdClass();
$view->pageTitle = 'Homepage'; $view->pageTitle = 'Home';
require_once("logincontroller.php"); require_once("logincontroller.php");
//if (isset($_POST['applyAdvFilters'])) {
// array_push($filterArray, $_POST['titlFilter'], $_POST['cateFilter'],
// $description = $_POST['descFilter'], $status = $_POST['statFilter'],
// $street = $_POST['strtFilter'], $county = $_POST['cntyFilter'],
// $town = $_POST['townFilter'], $postcode = $_POST['postFilter'],
// $contributor = $_POST['contFilter']);
//}
require_once('paginationcontroller.php');
$view->user = new User();
require_once('Views/index.phtml'); require_once('Views/index.phtml');

6314
js/bootstrap.bundle.js vendored Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

7
js/bootstrap.bundle.min.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

4447
js/bootstrap.esm.js vendored Normal file

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More