// File: add_booking.
php
<?php
header('Content-Type: application/json');
require 'db.php';
$data = json_decode(file_get_contents('php://input'), true);
if (!$data) { echo json_encode(['error'=>'No data']); exit; }
$stmt = $pdo->prepare('INSERT INTO bookings (customer_name, customer_email, package_id,
booking_date, status) VALUES (?, ?, ?, ?, ?)');
$stmt->execute([
$data['customer_name'],
$data['customer_email'],
$data['package_id'],
$data['booking_date'],
$data['status']
]);
echo json_encode(['success'=>true,'id'=>$pdo->lastInsertId()]);
?>
// File: add_destination.php
<?php
header('Content-Type: application/json');
require 'db.php';
$data = json_decode(file_get_contents('php://input'), true);
if (!$data) { echo json_encode(['error'=>'No data']); exit; }
$stmt = $pdo->prepare('INSERT INTO destinations (name, location, type, price, image,
description) VALUES (?, ?, ?, ?, ?, ?)');
$stmt->execute([
$data['name'],
$data['location'],
$data['type'],
$data['price'],
$data['image'],
$data['description']
]);
echo json_encode(['success'=>true,'id'=>$pdo->lastInsertId()]);
?>
// File: add_gallery.php
<?php
header('Content-Type: application/json');
require 'db.php';
$data = json_decode(file_get_contents('php://input'), true);
if (!$data) { echo json_encode(['error'=>'No data']); exit; }
$stmt = $pdo->prepare('INSERT INTO gallery (image_url, caption, destination_id) VALUES
(?, ?, ?)');
$stmt->execute([
$data['image_url'],
$data['caption'],
$data['destination_id']
Page 1
]);
echo json_encode(['success'=>true,'id'=>$pdo->lastInsertId()]);
?>
// File: add_package.php
<?php
header('Content-Type: application/json');
require 'db.php';
$data = json_decode(file_get_contents('php://input'), true);
if (!$data) { echo json_encode(['error'=>'No data']); exit; }
$stmt = $pdo->prepare('INSERT INTO packages (name, destination_id, price, details)
VALUES (?, ?, ?, ?)');
$stmt->execute([
$data['name'],
$data['destination_id'],
$data['price'],
$data['details']
]);
echo json_encode(['success'=>true,'id'=>$pdo->lastInsertId()]);
?>
// File: admin-login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Admin Login - TripVista</title>
<link rel="stylesheet" href="admin.css">
<link rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
<style>
body { background: #f6fafd; font-family: 'Poppins', sans-serif; }
.admin-login-container { min-height: 100vh; display: flex; align-items: center;
justify-content: center; }
.admin-login-box { background: #fff; padding: 2.5rem 2rem; border-radius: 10px;
box-shadow: 0 0 20px rgba(44,62,80,0.08); max-width: 400px; width: 100%; }
.admin-login-title { text-align: center; color: #2c3e50; margin-bottom: 2rem; }
.form-group { margin-bottom: 1.5rem; }
.form-group label { display: block; margin-bottom: 0.5rem; color: #2c3e50; }
.form-group input { width: 100%; padding: 0.75rem; border: 1px solid #ddd;
border-radius: 5px; font-size: 1rem; }
.auth-btn { width: 100%; padding: 0.75rem; background: #3498db; color: white;
border: none; border-radius: 5px; font-size: 1rem; cursor: pointer; transition:
background 0.3s ease; }
.auth-btn:hover { background: #217dbb; }
.error-msg { color: #e74c3c; font-size: 0.98rem; text-align: center;
margin-bottom: 1rem; display: none; }
</style>
Page 2
</head>
<body>
<div class="admin-login-container">
<div class="admin-login-box">
<h2 class="admin-login-title">Admin Login</h2>
<form id="adminLoginForm">
<div class="form-group">
<label for="adminEmail">Email</label>
<input type="email" id="adminEmail" required>
</div>
<div class="form-group">
<label for="adminPassword">Password</label>
<div style="position:relative;">
<input type="password" id="adminPassword" required
style="padding-right:40px;">
<span id="toggleAdminPassword"
style="position:absolute;right:12px;top:50%;transform:translateY(-50%);cursor:pointer;co
lor:#888;font-size:1.2rem;">
<i class="fas fa-eye"></i>
</span>
</div>
</div>
<div class="error-msg" id="adminLoginError"></div>
<button type="submit" class="auth-btn">Login</button>
</form>
</div>
</div>
<script>
document.getElementById('adminLoginForm').addEventListener('submit', function(e)
{
e.preventDefault();
const email = document.getElementById('adminEmail').value.trim();
const password = document.getElementById('adminPassword').value.trim();
const errorMsg = document.getElementById('adminLoginError');
// For demo: hardcoded admin credentials (change as needed)
if(email === '[email protected]' && password === 'Admin@123') {
localStorage.setItem('tripvista_admin_logged_in', 'true');
window.location.href = 'admin.html';
} else {
errorMsg.textContent = 'Invalid admin credentials.';
errorMsg.style.display = 'block';
}
});
// Eye icon toggle for password
const adminPasswordInput = document.getElementById('adminPassword');
const toggleAdminPassword = document.getElementById('toggleAdminPassword');
toggleAdminPassword.addEventListener('click', function() {
const type = adminPasswordInput.type === 'password' ? 'text' : 'password';
adminPasswordInput.type = type;
this.innerHTML = type === 'password' ? '<i class="fas fa-eye"></i>' : '<i
class="fas fa-eye-slash"></i>';
Page 3
});
</script>
</body>
</html>
// File: admin.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>TripVista Admin Panel</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<header>
<h1>TripVista Admin Panel</h1>
<button id="logout-btn">Logout</button>
</header>
<div class="container">
<div class="sidebar">
<div class="menu-item" onclick="showSection('manageDestinations')">Manage
Destinations</div>
<div class="menu-item" onclick="showSection('managePackages')">Manage
Packages</div>
<div class="menu-item" onclick="showSection('viewBookings')">View
Bookings</div>
<div class="menu-item" onclick="showSection('manageGallery')">Manage
Gallery</div>
</div>
<div class="content">
<!-- Manage Destinations Section -->
<div id="manageDestinations" class="section">
<h2>Manage Destinations</h2>
<button id="add-destination-btn" onclick="showAddDestinationForm()">+
Add Destination</button>
<!-- Destinations content -->
</div>
<!-- Manage Packages Section -->
<div id="managePackages" class="section">
<h2>Manage Packages</h2>
<button id="add-package-btn" onclick="showAddPackageForm()">+ Add
Package</button>
<!-- Packages content -->
</div>
<!-- View Bookings Section -->
Page 4
<div id="viewBookings" class="section">
<h2>View Bookings</h2>
<div class="filter-container">
<div class="filter-group">
<label for="booking-status-filter">Filter by Status:</label>
<select id="booking-status-filter" onchange="filterBookings()">
<option value="all">All Bookings</option>
<option value="confirmed">Confirmed</option>
<option value="pending">Pending</option>
<option value="cancelled">Cancelled</option>
</select>
</div>
<div class="filter-group">
<label for="booking-date-filter">Filter by Date:</label>
<input type="date" id="booking-date-filter"
onchange="filterBookings()">
</div>
<button onclick="resetFilters()" class="reset-btn">Reset
Filters</button>
</div>
<table id="bookings-table">
<thead>
<tr>
<th>Booking ID</th>
<th>Customer Name</th>
<th>Destination/Package</th>
<th>Travel Date</th>
<th>Booking Status</th>
<th>Total Amount</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<!-- Sample booking data for demonstration -->
<tr>
<td>BK001</td>
<td>John Doe</td>
<td>Bali Beach Resort</td>
<td>2023-12-15</td>
<td><span class="status-confirmed">Confirmed</span></td>
<td>$1,200</td>
<td>
<button onclick="editBooking('BK001')"
class="edit-btn">Edit</button>
<button onclick="cancelBooking('BK001')"
class="cancel-btn">Cancel</button>
</td>
Page 5
</tr>
<tr>
<td>BK002</td>
<td>Jane Smith</td>
<td>Paris City Tour</td>
<td>2023-11-20</td>
<td><span class="status-pending">Pending</span></td>
<td>$950</td>
<td>
<button onclick="editBooking('BK002')"
class="edit-btn">Edit</button>
<button onclick="cancelBooking('BK002')"
class="cancel-btn">Cancel</button>
</td>
</tr>
<tr>
<td>BK003</td>
<td>Robert Johnson</td>
<td>Mountain Adventure Package</td>
<td>2023-10-05</td>
<td><span class="status-cancelled">Cancelled</span></td>
<td>$800</td>
<td>
<button onclick="editBooking('BK003')"
class="edit-btn">Edit</button>
<button onclick="restoreBooking('BK003')"
class="restore-btn">Restore</button>
</td>
</tr>
</tbody>
</table>
<!-- Booking Details Modal (initially hidden) -->
<div id="booking-details-modal" class="modal">
<div class="modal-content">
<span class="close-modal"
onclick="closeBookingModal()">×</span>
<h3>Edit Booking</h3>
<form id="edit-booking-form">
<input type="hidden" id="booking-id">
<div class="form-group">
<label for="customer-name">Customer Name:</label>
<input type="text" id="customer-name" required>
</div>
<div class="form-group">
<label
for="booking-destination">Destination/Package:</label>
<input type="text" id="booking-destination" required>
</div>
Page 6
<div class="form-group">
<label for="travel-date">Travel Date:</label>
<input type="date" id="travel-date" required>
</div>
<div class="form-group">
<label for="booking-status">Status:</label>
<select id="booking-status" required>
<option value="confirmed">Confirmed</option>
<option value="pending">Pending</option>
<option value="cancelled">Cancelled</option>
</select>
</div>
<div class="form-group">
<label for="booking-amount">Total Amount:</label>
<input type="number" id="booking-amount" min="0"
step="0.01" required>
</div>
<div class="form-actions">
<button type="submit">Update Booking</button>
<button type="button"
onclick="closeBookingModal()">Cancel</button>
</div>
</form>
</div>
</div>
</div>
<!-- Manage Gallery Section -->
<div id="manageGallery" class="section">
<h2>Manage Gallery</h2>
<div class="gallery-container">
<div class="upload-section">
<h3>Upload New Image</h3>
<form id="image-upload-form">
<div class="form-group">
<label for="image-title">Image Title:</label>
<input type="text" id="image-title" required>
</div>
<div class="form-group">
<label for="image-category">Category:</label>
<select id="image-category" required>
<option value="">Select Category</option>
<option value="Destinations">Destinations</option>
<option value="Activities">Activities</option>
<option
Page 7
value="Accommodations">Accommodations</option>
<option value="Food">Food & Cuisine</option>
<option
value="Transportation">Transportation</option>
</select>
</div>
<div class="form-group">
<label for="image-file">Select Image:</label>
<input type="file" id="image-file" accept="image/*"
required>
<div class="image-preview" id="image-preview"></div>
</div>
<div class="form-group">
<label for="image-description">Description
(optional):</label>
<textarea id="image-description" rows="3"></textarea>
</div>
<div class="form-actions">
<button type="submit" id="upload-image-btn">Upload
Image</button>
</div>
</form>
</div>
<div class="gallery-view">
<h3>Image Gallery</h3>
<div class="gallery-filters">
<select id="gallery-filter"
onchange="filterGalleryImages()">
<option value="all">All Categories</option>
<option value="Destinations">Destinations</option>
<option value="Activities">Activities</option>
<option value="Accommodations">Accommodations</option>
<option value="Food">Food & Cuisine</option>
<option value="Transportation">Transportation</option>
</select>
<input type="text" id="gallery-search" placeholder="Search
by title..." onkeyup="filterGalleryImages()">
<button onclick="resetGalleryFilters()"
class="reset-btn">Reset Filters</button>
</div>
<div class="gallery-grid" id="gallery-grid">
<!-- Sample gallery items for demonstration -->
<div class="gallery-item" data-category="Destinations">
Page 8
<div class="gallery-image">
<img
src="https://via.placeholder.com/300x200?text=Beach+Resort" alt="Beach Resort">
</div>
<div class="gallery-info">
<h4>Beach Resort</h4>
<p>Beautiful beach resort with stunning views</p>
<span class="gallery-category">Destinations</span>
</div>
<div class="gallery-actions">
<button onclick="editGalleryImage(this)"
class="edit-btn">Edit</button>
<button onclick="deleteGalleryImage(this)"
class="delete-btn">Delete</button>
</div>
</div>
<div class="gallery-item" data-category="Activities">
<div class="gallery-image">
<img
src="https://via.placeholder.com/300x200?text=Scuba+Diving" alt="Scuba Diving">
</div>
<div class="gallery-info">
<h4>Scuba Diving</h4>
<p>Explore the underwater world</p>
<span class="gallery-category">Activities</span>
</div>
<div class="gallery-actions">
<button onclick="editGalleryImage(this)"
class="edit-btn">Edit</button>
<button onclick="deleteGalleryImage(this)"
class="delete-btn">Delete</button>
</div>
</div>
<div class="gallery-item" data-category="Accommodations">
<div class="gallery-image">
<img
src="https://via.placeholder.com/300x200?text=Luxury+Suite" alt="Luxury Suite">
</div>
<div class="gallery-info">
<h4>Luxury Suite</h4>
<p>Comfortable and elegant accommodation</p>
<span class="gallery-category">Accommodations</span>
</div>
<div class="gallery-actions">
<button onclick="editGalleryImage(this)"
class="edit-btn">Edit</button>
<button onclick="deleteGalleryImage(this)"
class="delete-btn">Delete</button>
</div>
Page 9
</div>
</div>
</div>
<!-- Edit Image Modal (initially hidden) -->
<div id="edit-image-modal" class="modal">
<div class="modal-content">
<span class="close-modal"
onclick="closeImageModal()">×</span>
<h3>Edit Image</h3>
<form id="edit-image-form">
<div class="form-group">
<label for="edit-image-title">Image Title:</label>
<input type="text" id="edit-image-title" required>
</div>
<div class="form-group">
<label for="edit-image-category">Category:</label>
<select id="edit-image-category" required>
<option
value="Destinations">Destinations</option>
<option value="Activities">Activities</option>
<option
value="Accommodations">Accommodations</option>
<option value="Food">Food & Cuisine</option>
<option
value="Transportation">Transportation</option>
</select>
</div>
<div class="form-group">
<label for="edit-image-file">Change Image
(optional):</label>
<input type="file" id="edit-image-file"
accept="image/*">
<div class="image-preview" id="edit-image-preview">
<img id="current-image-preview" src=""
alt="Current Image">
</div>
</div>
<div class="form-group">
<label
for="edit-image-description">Description:</label>
<textarea id="edit-image-description"
rows="3"></textarea>
</div>
<div class="form-actions">
<button type="submit">Update Image</button>
<button type="button"
Page 10
onclick="closeImageModal()">Cancel</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
<script src="src/adminPanel.js"></script>
</body>
</html>
// File: admin.js
// Admin Panel JS for TripVista
document.addEventListener('DOMContentLoaded', function() {
// Sidebar navigation
document.querySelectorAll('.admin-sidebar a').forEach(link => {
link.addEventListener('click', function(e){
e.preventDefault();
document.querySelectorAll('.admin-sidebar a').forEach(l =>
l.classList.remove('active'));
this.classList.add('active');
const section = this.getAttribute('href').substring(1);
if(section === 'destinations') {
renderDestinationsSection();
} else {
document.getElementById('adminContent').innerHTML = `<h2>Feature coming
soon</h2>`;
}
});
});
// Initial load
if(window.location.hash === '#destinations') {
renderDestinationsSection();
document.querySelector('.admin-sidebar
a[href="#destinations"]').classList.add('active');
}
});
function renderDestinationsSection() {
const destinations = getDestinations();
let html = `<h2>Manage Destinations</h2>
<button id="addDestBtn" style="background:#3498db;color:#fff;padding:8px
22px;border:none;border-radius:5px;font-size:1rem;margin-bottom:20px;cursor:pointer;">+
Add Destination</button>
<table style="width:100%;border-collapse:collapse;">
Page 11
<thead><tr
style="background:#f6fafd;"><th>Name</th><th>Location</th><th>Type</th><th>Price</th><th
>Image</th><th>Actions</th></tr></thead>
<tbody>`;
if(destinations.length === 0) {
html += `<tr><td colspan="6" style="text-align:center;padding:24px;">No
destinations added yet.</td></tr>`;
} else {
destinations.forEach((dest, i) => {
html += `<tr>
<td>${dest.name}</td>
<td>${dest.location}</td>
<td>${dest.type}</td>
<td>${dest.price}</td>
<td><img src="${dest.image}" alt=""
style="width:60px;height:40px;object-fit:cover;border-radius:4px;"></td>
<td>
<button class="editDestBtn" data-idx="${i}"
style="margin-right:8px;background:#2ecc71;color:#fff;border:none;padding:4px
12px;border-radius:4px;cursor:pointer;">Edit</button>
<button class="deleteDestBtn" data-idx="${i}"
style="background:#e74c3c;color:#fff;border:none;padding:4px
12px;border-radius:4px;cursor:pointer;">Delete</button>
</td>
</tr>`;
});
}
html += `</tbody></table>`;
document.getElementById('adminContent').innerHTML = html;
document.getElementById('addDestBtn').onclick = showAddDestinationForm;
document.querySelectorAll('.editDestBtn').forEach(btn => btn.onclick =
showEditDestinationForm);
document.querySelectorAll('.deleteDestBtn').forEach(btn => btn.onclick =
deleteDestination);
}
function getDestinations() {
return JSON.parse(localStorage.getItem('tripvista_destinations') || '[]');
}
function saveDestinations(dests) {
localStorage.setItem('tripvista_destinations', JSON.stringify(dests));
}
function showAddDestinationForm() {
const html = `<h2>Add Destination</h2>
<form id="destForm">
<label>Name</label><input type="text" name="name" required
style="width:100%;margin-bottom:12px;">
<label>Location</label><input type="text" name="location" required
Page 12
style="width:100%;margin-bottom:12px;">
<label>Type</label>
<select name="type" required style="width:100%;margin-bottom:12px;">
<option value="Indian">Indian</option>
<option value="International">International</option>
</select>
<label>Price</label><input type="text" name="price" required
style="width:100%;margin-bottom:12px;">
<label>Image URL</label><input type="text" name="image" required
style="width:100%;margin-bottom:12px;">
<label>Description</label><textarea name="description" required
style="width:100%;margin-bottom:16px;"></textarea>
<button type="submit" style="background:#3498db;color:#fff;padding:8px
22px;border:none;border-radius:5px;font-size:1rem;">Save</button>
<button type="button" id="cancelDestBtn"
style="margin-left:12px;background:#ccc;color:#333;padding:8px
22px;border:none;border-radius:5px;font-size:1rem;">Cancel</button>
</form>`;
document.getElementById('adminContent').innerHTML = html;
document.getElementById('destForm').onsubmit = addDestination;
document.getElementById('cancelDestBtn').onclick = renderDestinationsSection;
}
function addDestination(e) {
e.preventDefault();
const form = e.target;
const newDest = {
name: form.name.value,
location: form.location.value,
type: form.type.value,
price: form.price.value,
image: form.image.value,
description: form.description.value
};
const dests = getDestinations();
dests.push(newDest);
saveDestinations(dests);
renderDestinationsSection();
}
function showEditDestinationForm(e) {
const idx = +e.target.getAttribute('data-idx');
const dests = getDestinations();
const dest = dests[idx];
const html = `<h2>Edit Destination</h2>
<form id="destForm">
<label>Name</label><input type="text" name="name" value="${dest.name}"
required style="width:100%;margin-bottom:12px;">
<label>Location</label><input type="text" name="location"
value="${dest.location}" required style="width:100%;margin-bottom:12px;">
<label>Type</label>
Page 13
<select name="type" required style="width:100%;margin-bottom:12px;">
<option value="Indian"${dest.type==='Indian'?'
selected':''}>Indian</option>
<option value="International"${dest.type==='International'?'
selected':''}>International</option>
</select>
<label>Price</label><input type="text" name="price" value="${dest.price}"
required style="width:100%;margin-bottom:12px;">
<label>Image URL</label><input type="text" name="image"
value="${dest.image}" required style="width:100%;margin-bottom:12px;">
<label>Description</label><textarea name="description" required
style="width:100%;margin-bottom:16px;">${dest.description}</textarea>
<button type="submit" style="background:#3498db;color:#fff;padding:8px
22px;border:none;border-radius:5px;font-size:1rem;">Update</button>
<button type="button" id="cancelDestBtn"
style="margin-left:12px;background:#ccc;color:#333;padding:8px
22px;border:none;border-radius:5px;font-size:1rem;">Cancel</button>
</form>`;
document.getElementById('adminContent').innerHTML = html;
document.getElementById('destForm').onsubmit = function(ev) { updateDestination(ev,
idx); };
document.getElementById('cancelDestBtn').onclick = renderDestinationsSection;
}
function updateDestination(e, idx) {
e.preventDefault();
const form = e.target;
const dests = getDestinations();
dests[idx] = {
name: form.name.value,
location: form.location.value,
type: form.type.value,
price: form.price.value,
image: form.image.value,
description: form.description.value
};
saveDestinations(dests);
renderDestinationsSection();
}
function deleteDestination(e) {
if(!confirm('Delete this destination?')) return;
const idx = +e.target.getAttribute('data-idx');
const dests = getDestinations();
dests.splice(idx, 1);
saveDestinations(dests);
renderDestinationsSection();
}
// File: app.py
Page 14
from flask import Flask, render_template, send_from_directory
import os
from flask import Flask, send_from_directory, url_for
app = Flask(__name__, static_url_path='', static_folder='assets')
@app.route('/')
def index():
return send_from_directory('.', 'index.html')
@app.route('/<path:path>')
def serve_file(path):
if path.startswith('assets/'):
return send_from_directory('.', path)
return send_from_directory('.', path)
if __name__ == '__main__':
app.run(debug=True)
// File: book.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Book Your Trip | TripVista</title>
<link
href="https://fonts.googleapis.com/css2?family=Playfair+Display:wght@700&family=Poppins:
wght@400;500&display=swap" rel="stylesheet">
<style>
body { background: #f9fafc; font-family: 'Poppins', Arial, sans-serif; color:
#2c3e50; margin: 0; }
.container { max-width: 550px; margin: 48px auto; background: #fff;
border-radius: 12px; box-shadow: 0 8px 32px rgba(44,62,80,0.08); padding: 36px 28px; }
h1 { font-family: 'Playfair Display', serif; font-size: 2rem; margin-bottom:
18px; }
.form-group { margin-bottom: 18px; }
label { display: block; margin-bottom: 6px; font-weight: 500; }
input, select, textarea { width: 100%; padding: 10px 12px; border-radius: 5px;
border: 1px solid #bfc9d1; font-size: 1rem; font-family: 'Poppins', sans-serif; }
button { background: #3498db; color: #fff; border: none; border-radius: 8px;
padding: 12px 0; width: 100%; font-size: 1.08rem; font-family: 'Poppins', sans-serif;
font-weight: 500; cursor: pointer; margin-top: 10px; }
Page 15