@@ -21,11 +21,17 @@ require('template/header.phtml')
|
||||
<div class="card-header bg-light py-3">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<div class="d-flex align-items-center">
|
||||
<h5 class="mb-0 fw-bold text-primary">
|
||||
<i class="bi bi-geo-alt-fill me-2 text-success"></i>Facilities
|
||||
</h5>
|
||||
<!-- Badge showing the number of facilities -->
|
||||
<span class="badge bg-success rounded-pill ms-2" id="facilityCount"></span>
|
||||
<!-- Search and filter controls -->
|
||||
<div class="d-flex flex-column flex-lg-row search-controls mx-auto">
|
||||
<form class="d-flex flex-column flex-lg-row gap-2 w-100" role="search" action="" method="POST">
|
||||
<div class="input-group flex-grow-1">
|
||||
<span class="input-group-text bg-light border-end-0">
|
||||
<i class="bi bi-search text-success"></i>
|
||||
</span>
|
||||
<input class="form-control border-start-0" id="searchInput" type="search" name="filter" placeholder="Search..." aria-label="Search">
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Admin-only buttons -->
|
||||
<div id="adminButtons" style="display: none;">
|
||||
@@ -99,33 +105,6 @@ require('template/header.phtml')
|
||||
regularUserView.style.display = isAdmin ? 'none' : 'block';
|
||||
}
|
||||
|
||||
// Update table headers based on user role :DDD (it just shows the ID column for admins...)
|
||||
if (tableHeaderRow) {
|
||||
if (isAdmin) {
|
||||
// Admin view - show all columns and bigger management actions
|
||||
tableHeaderRow.innerHTML = `
|
||||
<th class="fw-semibold" style="width: 40px;">ID</th>
|
||||
<th class="fw-semibold" style="width: 15%;">Title</th>
|
||||
<th class="fw-semibold text-center" style="width: 10%;">Category</th>
|
||||
<th class="fw-semibold" style="width: 25%;">Description</th>
|
||||
<th class="fw-semibold" style="width: 20%;">Address</th>
|
||||
<th class="fw-semibold text-center" style="width: 12%;">Coordinates</th>
|
||||
<th class="fw-semibold text-center" style="width: 8%;">Contributor</th>
|
||||
<th class="fw-semibold text-center" style="width: 10%;">Actions</th>
|
||||
`;
|
||||
} else {
|
||||
// Regular user view - hide ID column and make management actions smaller
|
||||
tableHeaderRow.innerHTML = `
|
||||
<th class="fw-semibold" style="width: 17%;">Title</th>
|
||||
<th class="fw-semibold text-center" style="width: 11%;">Category</th>
|
||||
<th class="fw-semibold" style="width: 27%;">Description</th>
|
||||
<th class="fw-semibold" style="width: 20%;">Address</th>
|
||||
<th class="fw-semibold text-center" style="width: 12%;">Coordinates</th>
|
||||
<th class="fw-semibold text-center" style="width: 8%;">Contributor</th>
|
||||
<th class="fw-semibold text-center" style="width: 5%;">Actions</th>
|
||||
`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update UI when the page loads
|
||||
@@ -139,28 +118,4 @@ require('template/header.phtml')
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- Script to update the facility count badge -->
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Update facility count badge based on data in sessionStorage
|
||||
const updateFacilityCount = () => {
|
||||
const facilityData = JSON.parse(sessionStorage.getItem('facilityData') || '[]');
|
||||
const countBadge = document.getElementById('facilityCount');
|
||||
if (countBadge) {
|
||||
countBadge.textContent = `${facilityData.length} facilities`;
|
||||
}
|
||||
};
|
||||
|
||||
// Initial count update when the page loads
|
||||
updateFacilityCount();
|
||||
|
||||
// Listen for changes in facility data to update the count
|
||||
window.addEventListener('storage', function(e) {
|
||||
if (e.key === 'facilityData') {
|
||||
updateFacilityCount();
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<?php require('template/footer.phtml');?>
|
194
Views/map.phtml
Normal file
194
Views/map.phtml
Normal file
@@ -0,0 +1,194 @@
|
||||
<?php require_once('template/header.phtml') ?>
|
||||
|
||||
<style>
|
||||
#mapOverlay {
|
||||
transition: opacity 0.3s ease-in-out, visibility 0.3s ease-in-out;
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
#mapOverlay.hidden {
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* Custom styles for facility popups */
|
||||
.facility-popup .leaflet-popup-content-wrapper {
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.facility-popup .leaflet-popup-content {
|
||||
margin: 0;
|
||||
min-width: 250px;
|
||||
}
|
||||
|
||||
.facility-details {
|
||||
max-height: 300px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.facility-details::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
}
|
||||
|
||||
.facility-details::-webkit-scrollbar-track {
|
||||
background: #f1f1f1;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.facility-details::-webkit-scrollbar-thumb {
|
||||
background: #198754;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
/* Comment form styles */
|
||||
.comment-form {
|
||||
margin-top: 1rem;
|
||||
padding-top: 1rem;
|
||||
border-top: 1px solid #dee2e6;
|
||||
}
|
||||
|
||||
.comment-form textarea {
|
||||
resize: vertical;
|
||||
min-height: 60px;
|
||||
}
|
||||
|
||||
/* Facility list container styles */
|
||||
.facility-list-container {
|
||||
height: calc(100vh - 400px); /* Adjust based on your layout */
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.facility-list {
|
||||
overflow-y: auto;
|
||||
flex-grow: 1;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.facility-list::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
}
|
||||
|
||||
.facility-list::-webkit-scrollbar-track {
|
||||
background: #f1f1f1;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.facility-list::-webkit-scrollbar-thumb {
|
||||
background: #198754;
|
||||
border-radius: 3px;
|
||||
}
|
||||
</style>
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="alert alert-warning">
|
||||
Notice: Facility locations are currently limited to UK Cities.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container-fluid pt-0 py-4">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-md-4 col-lg-3">
|
||||
<!-- Postcode and radius controls -->
|
||||
<div class="mb-4">
|
||||
<h5 class="mb-3">Location Settings</h5>
|
||||
<form id="postcodeForm" class="mb-3">
|
||||
<div class="mb-3">
|
||||
<label for="postcode" class="form-label">Enter Postcode</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-text bg-light">
|
||||
<i class="bi bi-geo-alt text-success"></i>
|
||||
</span>
|
||||
<input type="text" class="form-control" id="postcode" name="postcode"
|
||||
placeholder="e.g. M1 5GD" required>
|
||||
<button class="btn btn-success" type="submit">
|
||||
<i class="bi bi-search me-1"></i>Search
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="radius" class="form-label">Search Radius (miles)</label>
|
||||
<select class="form-select" id="radius" name="radius">
|
||||
<option value="1">1 mile</option>
|
||||
<option value="5">5 miles</option>
|
||||
<option value="10" selected>10 miles</option>
|
||||
<option value="25">25 miles</option>
|
||||
</select>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<!-- Facility list search and container -->
|
||||
<div class="facility-list-container">
|
||||
<div class="input-group mb-3">
|
||||
<span class="input-group-text bg-light">
|
||||
<i class="bi bi-search text-success"></i>
|
||||
</span>
|
||||
<input type="text" class="form-control" id="facilitySearch"
|
||||
placeholder="Search facilities...">
|
||||
</div>
|
||||
<div id="facilityList" class="list-group list-group-flush facility-list"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-8 col-lg-9">
|
||||
<!-- Map container with blur overlay -->
|
||||
<div class="position-relative" style="height: 700px;">
|
||||
<div id="map" style="height: 100%; width: 100%; z-index: 1;"></div>
|
||||
<div id="mapOverlay" class="position-absolute top-0 start-0 w-100 h-100 d-flex align-items-center justify-content-center"
|
||||
style="backdrop-filter: blur(8px); z-index: 2; background: rgba(255,255,255,0.5);">
|
||||
<div class="text-center">
|
||||
<i class="bi bi-geo-alt text-success" style="font-size: 3rem;"></i>
|
||||
<h4 class="mt-3">Enter a Postcode</h4>
|
||||
<p class="text-muted">Please enter a postcode to view facilities on the map</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Add Leaflet CSS and JS -->
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" crossorigin=""/>
|
||||
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js" crossorigin=""></script>
|
||||
|
||||
<!-- Add our map handler -->
|
||||
<script src="/public/js/mapHandler.js"></script>
|
||||
|
||||
<script>
|
||||
// Add facility search functionality
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const facilitySearch = document.getElementById('facilitySearch');
|
||||
const facilityList = document.getElementById('facilityList');
|
||||
|
||||
if (facilitySearch && facilityList) {
|
||||
facilitySearch.addEventListener('input', function() {
|
||||
const searchTerm = this.value.toLowerCase();
|
||||
const items = facilityList.getElementsByClassName('list-group-item');
|
||||
|
||||
Array.from(items).forEach(item => {
|
||||
const text = item.textContent.toLowerCase();
|
||||
item.style.display = text.includes(searchTerm) ? '' : 'none';
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<?php require('template/statusModal.phtml') ?>
|
||||
<?php require_once('template/footer.phtml') ?>
|
@@ -10,7 +10,7 @@
|
||||
</div>
|
||||
<div class="modal-body p-4">
|
||||
<!-- Create facility form -->
|
||||
<form id="createFacilityForm">
|
||||
<form id="createForm">
|
||||
<!-- Form fields -->
|
||||
<div class="mb-3">
|
||||
<label for="createTitle" class="form-label">Facility Name</label>
|
||||
@@ -41,53 +41,49 @@
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-3">
|
||||
<label for="createLatitude" class="form-label">Latitude</label>
|
||||
<input type="number" step="any" class="form-control" id="createLatitude" name="latitude" required>
|
||||
<input type="number" step="any" class="form-control" id="createLatitude" name="lat" required>
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<label for="createLongitude" class="form-label">Longitude</label>
|
||||
<input type="number" step="any" class="form-control" id="createLongitude" name="longitude" required>
|
||||
<input type="number" step="any" class="form-control" id="createLongitude" name="lng" required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="createAddress" class="form-label">Address</label>
|
||||
<input type="text" class="form-control" id="createAddress" name="address" required>
|
||||
<label for="createHouseNumber" class="form-label">House Number/Name</label>
|
||||
<input type="text" class="form-control" id="createHouseNumber" name="houseNumber" required>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="createContact" class="form-label">Contact Information</label>
|
||||
<input type="text" class="form-control" id="createContact" name="contact">
|
||||
<label for="createStreetName" class="form-label">Street Name</label>
|
||||
<input type="text" class="form-control" id="createStreetName" name="streetName" required>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="createWebsite" class="form-label">Website</label>
|
||||
<input type="url" class="form-control" id="createWebsite" name="website" placeholder="https://">
|
||||
<label for="createTown" class="form-label">Town/City</label>
|
||||
<input type="text" class="form-control" id="createTown" name="town" required>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="createHours" class="form-label">Operating Hours</label>
|
||||
<input type="text" class="form-control" id="createHours" name="hours" placeholder="e.g., Mon-Fri: 9am-5pm">
|
||||
<label for="createCounty" class="form-label">County</label>
|
||||
<input type="text" class="form-control" id="createCounty" name="county" required>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="createStatus" class="form-label">Status</label>
|
||||
<select class="form-select" id="createStatus" name="status" required>
|
||||
<option value="operational">Operational</option>
|
||||
<option value="limited">Limited Service</option>
|
||||
<option value="closed">Temporarily Closed</option>
|
||||
<option value="planned">Planned</option>
|
||||
</select>
|
||||
<label for="createPostcode" class="form-label">Postcode</label>
|
||||
<input type="text" class="form-control" id="createPostcode" name="postcode" required>
|
||||
</div>
|
||||
|
||||
<div id="createError" class="alert alert-danger" style="display: none;"></div>
|
||||
|
||||
<div class="modal-footer bg-light">
|
||||
<button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">Cancel</button>
|
||||
<button type="submit" class="btn btn-success">
|
||||
<i class="bi bi-plus-circle me-1"></i>Create Facility
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer bg-light">
|
||||
<button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">Cancel</button>
|
||||
<button type="button" class="btn btn-success" id="createFacilityButton">
|
||||
<i class="bi bi-plus-circle me-1"></i>Create Facility
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -19,16 +19,16 @@
|
||||
<!-- Note: facilityData.js is already included in the header -->
|
||||
<script src="/public/js/comments.js"></script>
|
||||
|
||||
<!-- Initialize components -->
|
||||
<!-- initialise components -->
|
||||
<script>
|
||||
// Only run initialization if not already done
|
||||
if (!window.initializationComplete) {
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Initialize auth service
|
||||
// initialise auth service
|
||||
const loginButton = document.querySelector('[data-bs-toggle="modal"]');
|
||||
const loginModal = document.getElementById('loginModal');
|
||||
|
||||
// Initialize all modals
|
||||
// initialise all modals
|
||||
try {
|
||||
const modalElements = document.querySelectorAll('.modal');
|
||||
modalElements.forEach(modalElement => {
|
||||
@@ -53,7 +53,20 @@
|
||||
console.error('Error initializing modals:', error);
|
||||
}
|
||||
|
||||
// Initialize auth form handlers
|
||||
// initialise CommentsManager
|
||||
CommentsManager.state.isDomReady = true;
|
||||
if (window.simpleAuth) {
|
||||
CommentsManager.state.isAuthReady = true;
|
||||
CommentsManager.checkinitialise();
|
||||
} else {
|
||||
window.addEventListener('simpleAuthReady', () => {
|
||||
console.log('SimpleAuth is now ready');
|
||||
CommentsManager.state.isAuthReady = true;
|
||||
CommentsManager.checkinitialise();
|
||||
});
|
||||
}
|
||||
|
||||
// initialise auth form handlers
|
||||
const loginForm = document.querySelector('#loginModal form');
|
||||
const loginError = document.querySelector('#loginError');
|
||||
const captchaContainer = document.querySelector('.captcha-container');
|
||||
|
@@ -12,7 +12,7 @@
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
|
||||
|
||||
<!-- CSS theme -->
|
||||
<link href="/public/css/my-style.css" rel="stylesheet">
|
||||
<link href="/public/css/default.css" rel="stylesheet">
|
||||
|
||||
<!-- Bootstrap Icons -->
|
||||
<link href="/public/css/bootstrap-icons.css" rel="stylesheet">
|
||||
@@ -49,7 +49,7 @@
|
||||
if (Array.isArray(initialData) && initialData.length > 0) {
|
||||
sessionStorage.setItem('facilityData', JSON.stringify(initialData));
|
||||
|
||||
// Initialize based on DOM state to ensure scripts run at the right time
|
||||
// initialise based on DOM state to ensure scripts run at the right time
|
||||
if (document.readyState === 'complete' || document.readyState === 'interactive') {
|
||||
if (typeof initialiseFacilityData === 'function') {
|
||||
initialiseFacilityData(initialData);
|
||||
@@ -165,54 +165,7 @@
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<!-- Search and filter controls -->
|
||||
<div class="d-flex flex-column flex-lg-row search-controls mx-auto">
|
||||
<form class="d-flex flex-column flex-lg-row gap-2 w-100" role="search" action="" method="POST">
|
||||
<div class="input-group">
|
||||
<span class="input-group-text bg-light border-end-0">
|
||||
<i class="bi bi-sort-alpha-down text-success"></i>
|
||||
</span>
|
||||
<select name="sort" class="form-select border-start-0 filter-control" id="sort">
|
||||
<option selected value="title">Title</option>
|
||||
<option value="category">Category</option>
|
||||
<option value="description">Description</option>
|
||||
<option value="streetName">Street</option>
|
||||
<option value="county">County</option>
|
||||
<option value="town">Town</option>
|
||||
<option value="postcode">Postcode</option>
|
||||
<option value="contributor">Contributor</option>
|
||||
</select>
|
||||
<select class="form-select sort-control" name="dir" id="dir" data-order="asc">
|
||||
<option value="asc">Asc</option>
|
||||
<option value="desc">Desc</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="input-group">
|
||||
<span class="input-group-text bg-light border-end-0">
|
||||
<i class="bi bi-filter-circle-fill text-success"></i>
|
||||
</span>
|
||||
<select name="filterCat" class="form-select border-start-0 filter-control" id="filterCat">
|
||||
<option value="title">Title</option>
|
||||
<option value="category">Category</option>
|
||||
<option value="description">Description</option>
|
||||
<option value="streetName">Street</option>
|
||||
<option value="county">County</option>
|
||||
<option value="town">Town</option>
|
||||
<option value="postcode">Postcode</option>
|
||||
<option value="contributor">Contributor</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="input-group">
|
||||
<span class="input-group-text bg-light border-end-0">
|
||||
<i class="bi bi-search text-success"></i>
|
||||
</span>
|
||||
<input class="form-control border-start-0" id="searchInput" type="search" name="filter" placeholder="Search..." aria-label="Search">
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- User account section -->
|
||||
<div class="ms-lg-3 mt-3 mt-lg-0" id="userAuthSection">
|
||||
@@ -374,14 +327,14 @@
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer bg-light">
|
||||
<p class="small text-muted mb-0">Don't have an account? <a href="#" class="text-success">Register</a></p>
|
||||
<p class="small text-muted mb-0">Don't have an account? <a href="#" onclick="alert('Please contact the administrator to create an account.');" class="text-success">Register</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Initialize login modal functionality
|
||||
// initialise login modal functionality
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const loginModal = document.getElementById('loginModal');
|
||||
const loginForm = document.getElementById('loginForm');
|
||||
|
@@ -1,4 +1,4 @@
|
||||
<div class="d-flex flex-column flex-md-row justify-content-between align-items-center gap-2">
|
||||
<div class="d-flex flex-column flex-md-row justify-content-between align-items-center gap-3">
|
||||
<div class="text-muted small">
|
||||
<span id="paginationInfo" class="d-flex align-items-center">
|
||||
<i class="bi bi-info-circle me-2 text-success"></i>
|
||||
@@ -7,8 +7,8 @@
|
||||
</div>
|
||||
|
||||
<!-- Pagination controls -->
|
||||
<nav aria-label="Facility table pagination">
|
||||
<ul class="pagination pagination-sm mb-0" id="paginationControls">
|
||||
<nav class="bg-transparent" aria-label="Facility table pagination">
|
||||
<ul class="pagination pagination-sm mb-0 border-2 rounded border-success" id="paginationControls">
|
||||
<!-- First page button -->
|
||||
<li class="page-item">
|
||||
<a class="page-link border-0 text-success" href="#" aria-label="First" id="firstPage">
|
||||
@@ -46,7 +46,6 @@
|
||||
<option value="10">10</option>
|
||||
<option value="25">25</option>
|
||||
<option value="50">50</option>
|
||||
<option value="100">100</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
Reference in New Issue
Block a user