Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
85893154df | ||
|
|
5b188f6e9c |
1
assets/cache/pexels_auli.json
vendored
Normal file
1
assets/cache/pexels_auli.json
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"local_url":"assets\/images\/destinations\/pexels-9963746.jpg","alt":"Scenic landscape of Auli, India with snowy mountains and a serene lake in winter.","photographer":"Kushal Verma","photographer_url":"https:\/\/www.pexels.com\/@kushal-verma-123877130"}
|
||||||
56
assets/css/custom.css
Normal file
56
assets/css/custom.css
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
|
||||||
|
@import url('https://fonts.googleapis.com/css2?family=Playfair+Display:wght@700&family=Roboto:wght@400;500&display=swap');
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: 'Roboto', sans-serif;
|
||||||
|
background-color: #F8F9FA;
|
||||||
|
color: #212529;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1, h2, h3, h4, h5, h6 {
|
||||||
|
font-family: 'Playfair Display', serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero {
|
||||||
|
background: linear-gradient(rgba(13, 110, 253, 0.1), rgba(0, 198, 255, 0.1)), url('https://picsum.photos/1600/900') no-repeat center center;
|
||||||
|
background-size: cover;
|
||||||
|
height: 100vh;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero .display-4 {
|
||||||
|
font-size: 4.5rem;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary {
|
||||||
|
background-color: #0D6EFD;
|
||||||
|
border-color: #0D6EFD;
|
||||||
|
border-radius: 0.75rem;
|
||||||
|
padding: 0.75rem 1.5rem;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary:hover {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.section {
|
||||||
|
padding: 6rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
border: none;
|
||||||
|
border-radius: 0.75rem;
|
||||||
|
box-shadow: 0 4px 12px rgba(0,0,0,0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar {
|
||||||
|
transition: background-color 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar.scrolled {
|
||||||
|
background-color: rgba(255, 255, 255, 0.9);
|
||||||
|
box-shadow: 0 2px 4px rgba(0,0,0,0.05);
|
||||||
|
}
|
||||||
BIN
assets/images/destinations/pexels-9963746.jpg
Normal file
BIN
assets/images/destinations/pexels-9963746.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 361 KiB |
41
assets/js/main.js
Normal file
41
assets/js/main.js
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', function () {
|
||||||
|
// Navbar scroll effect
|
||||||
|
const navbar = document.querySelector('.navbar');
|
||||||
|
window.addEventListener('scroll', () => {
|
||||||
|
if (window.scrollY > 50) {
|
||||||
|
navbar.classList.add('scrolled');
|
||||||
|
} else {
|
||||||
|
navbar.classList.remove('scrolled');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Smooth scrolling for anchor links
|
||||||
|
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
|
||||||
|
anchor.addEventListener('click', function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
document.querySelector(this.getAttribute('href')).scrollIntoView({
|
||||||
|
behavior: 'smooth'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Contact form validation
|
||||||
|
const form = document.querySelector('.contact-form');
|
||||||
|
form.addEventListener('submit', function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
// Basic validation
|
||||||
|
const name = form.querySelector('#name').value;
|
||||||
|
const email = form.querySelector('#email').value;
|
||||||
|
const message = form.querySelector('#message').value;
|
||||||
|
|
||||||
|
if (name === '' || email === '' || message === '') {
|
||||||
|
alert('Please fill out all fields.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// On success
|
||||||
|
alert('Thank you for your message!');
|
||||||
|
form.reset();
|
||||||
|
});
|
||||||
|
});
|
||||||
50
community.php
Normal file
50
community.php
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
<?php
|
||||||
|
require_once __DIR__ . '/includes/header.php';
|
||||||
|
require_once __DIR__ . '/db/config.php';
|
||||||
|
|
||||||
|
$posts = [];
|
||||||
|
try {
|
||||||
|
$pdo = db();
|
||||||
|
$stmt = $pdo->query("SELECT posts.*, users.username FROM posts JOIN users ON posts.user_id = users.id ORDER BY posts.created_at DESC");
|
||||||
|
$posts = $stmt->fetchAll();
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
// Handle error
|
||||||
|
echo "<div class='alert alert-danger'>Error fetching posts: " . $e->getMessage() . "</div>";
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
|
||||||
|
<div class="container" style="margin-top: 100px;">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||||
|
<h1>Community Feed</h1>
|
||||||
|
<?php if (isset($_SESSION['user_id'])): ?>
|
||||||
|
<a href="create_post.php" class="btn btn-primary">Create Post</a>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php if (empty($posts)): ?>
|
||||||
|
<div class="card text-center">
|
||||||
|
<div class="card-body">
|
||||||
|
<p class="card-text">No posts yet. Be the first to share your story!</p>
|
||||||
|
<?php if (!isset($_SESSION['user_id'])): ?>
|
||||||
|
<a href="login.php" class="btn btn-primary">Login to Post</a>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php else: ?>
|
||||||
|
<?php foreach ($posts as $post): ?>
|
||||||
|
<div class="card mb-4">
|
||||||
|
<div class="card-body">
|
||||||
|
<h2 class="card-title"><?php echo htmlspecialchars($post['title']); ?></h2>
|
||||||
|
<p class="card-text"><?php echo nl2br(htmlspecialchars($post['content'])); ?></p>
|
||||||
|
<p class="card-text"><small class="text-muted">Posted by <?php echo htmlspecialchars($post['username']); ?> on <?php echo date('F j, Y', strtotime($post['created_at'])); ?></small></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php require_once __DIR__ . '/includes/footer.php'; ?>
|
||||||
72
create_post.php
Normal file
72
create_post.php
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
<?php
|
||||||
|
require_once __DIR__ . '/includes/header.php';
|
||||||
|
require_once __DIR__ . '/db/config.php';
|
||||||
|
|
||||||
|
if (!isset($_SESSION['user_id'])) {
|
||||||
|
header('Location: login.php');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$errors = [];
|
||||||
|
$title = '';
|
||||||
|
$content = '';
|
||||||
|
|
||||||
|
if ($_SERVER["REQUEST_METHOD"] == "POST") {
|
||||||
|
$title = trim($_POST['title']);
|
||||||
|
$content = trim($_POST['content']);
|
||||||
|
|
||||||
|
if (empty($title)) {
|
||||||
|
$errors[] = 'Title is required';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($content)) {
|
||||||
|
$errors[] = 'Content is required';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($errors)) {
|
||||||
|
try {
|
||||||
|
$pdo = db();
|
||||||
|
$stmt = $pdo->prepare("INSERT INTO posts (user_id, title, content) VALUES (?, ?, ?)");
|
||||||
|
$stmt->execute([$_SESSION['user_id'], $title, $content]);
|
||||||
|
header("Location: community.php");
|
||||||
|
exit;
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
$errors[] = "Database error: " . $e->getMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
|
||||||
|
<div class="container" style="margin-top: 100px;">
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-md-8">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<h2 class="card-title text-center">Create a New Post</h2>
|
||||||
|
|
||||||
|
<?php if (!empty($errors)): ?>
|
||||||
|
<div class="alert alert-danger">
|
||||||
|
<?php foreach ($errors as $error): ?>
|
||||||
|
<p><?php echo $error; ?></p>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<form action="create_post.php" method="POST">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="title" class="form-label">Title</label>
|
||||||
|
<input type="text" class="form-control" id="title" name="title" value="<?php echo htmlspecialchars($title); ?>" required>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="content" class="form-label">Content</label>
|
||||||
|
<textarea class="form-control" id="content" name="content" rows="10" required><?php echo htmlspecialchars($content); ?></textarea>
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-primary w-100">Create Post</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php require_once __DIR__ . '/includes/footer.php'; ?>
|
||||||
53
dashboard.php
Normal file
53
dashboard.php
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
<?php
|
||||||
|
require_once __DIR__ . '/includes/header.php';
|
||||||
|
|
||||||
|
if (!isset($_SESSION['user_id'])) {
|
||||||
|
header('Location: login.php');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$page = $_GET['page'] ?? 'my_trips';
|
||||||
|
?>
|
||||||
|
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row">
|
||||||
|
<nav id="sidebar" class="col-md-3 col-lg-2 d-md-block bg-light sidebar collapse">
|
||||||
|
<div class="position-sticky pt-3">
|
||||||
|
<ul class="nav flex-column">
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link <?php echo ($page === 'my_trips') ? 'active' : ''; ?>" href="dashboard.php?page=my_trips">
|
||||||
|
My Trips
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link <?php echo ($page === 'plan_trip') ? 'active' : ''; ?>" href="dashboard.php?page=plan_trip">
|
||||||
|
Plan a Trip
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link <?php echo ($page === 'profile') ? 'active' : ''; ?>" href="dashboard.php?page=profile">
|
||||||
|
Profile
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<main class="col-md-9 ms-sm-auto col-lg-10 px-md-4">
|
||||||
|
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
|
||||||
|
<h1 class="h2">Dashboard</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
$page_path = __DIR__ . '/' . $page . '.php';
|
||||||
|
if (file_exists($page_path)) {
|
||||||
|
include $page_path;
|
||||||
|
} else {
|
||||||
|
echo '<div class="alert alert-danger">Page not found.</div>';
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php require_once __DIR__ . '/includes/footer.php'; ?>
|
||||||
32
db/migrate.php
Normal file
32
db/migrate.php
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
require_once __DIR__ . '/config.php';
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Connect to MySQL server without specifying a database
|
||||||
|
$pdo_server = new PDO('mysql:host='.DB_HOST, DB_USER, DB_PASS, [
|
||||||
|
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Create the database if it doesn't exist
|
||||||
|
$pdo_server->exec('CREATE DATABASE IF NOT EXISTS `'.DB_NAME.'`');
|
||||||
|
echo "Database `".DB_NAME."` created or already exists.\n";
|
||||||
|
|
||||||
|
// Now, connect to the specific database
|
||||||
|
$pdo_db = db();
|
||||||
|
|
||||||
|
// Run all migrations
|
||||||
|
$migration_files = glob(__DIR__ . '/migrations/*.sql');
|
||||||
|
sort($migration_files);
|
||||||
|
|
||||||
|
foreach ($migration_files as $file) {
|
||||||
|
$sql = file_get_contents($file);
|
||||||
|
$pdo_db->exec($sql);
|
||||||
|
echo "Executed migration: " . basename($file) . "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "All migrations successful!\n";
|
||||||
|
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
die("Migration failed: " . $e->getMessage() . "\n");
|
||||||
|
}
|
||||||
|
|
||||||
9
db/migrations/001_create_users_table.sql
Normal file
9
db/migrations/001_create_users_table.sql
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
CREATE TABLE IF NOT EXISTS `users` (
|
||||||
|
`id` INT NOT NULL AUTO_INCREMENT,
|
||||||
|
`username` VARCHAR(255) NOT NULL,
|
||||||
|
`email` VARCHAR(255) NOT NULL,
|
||||||
|
`password` VARCHAR(255) NOT NULL,
|
||||||
|
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
UNIQUE KEY `email` (`email`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||||
9
db/migrations/002_create_posts_table.sql
Normal file
9
db/migrations/002_create_posts_table.sql
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
CREATE TABLE IF NOT EXISTS `posts` (
|
||||||
|
`id` INT NOT NULL AUTO_INCREMENT,
|
||||||
|
`user_id` INT NOT NULL,
|
||||||
|
`title` VARCHAR(255) NOT NULL,
|
||||||
|
`content` TEXT NOT NULL,
|
||||||
|
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE CASCADE
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||||
17
includes/footer.php
Normal file
17
includes/footer.php
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<!-- Footer -->
|
||||||
|
<footer class="py-5 bg-dark text-white">
|
||||||
|
<div class="container text-center">
|
||||||
|
<p class="mb-0">© <?php echo date('Y'); ?> TripEase. All Rights Reserved.</p>
|
||||||
|
<p><a href="/privacy.php" class="text-white">Privacy Policy</a></p>
|
||||||
|
<div>
|
||||||
|
<a href="#" class="text-white me-3"><i class="bi bi-twitter"></i></a>
|
||||||
|
<a href="#" class="text-white me-3"><i class="bi bi-instagram"></i></a>
|
||||||
|
<a href="#" class="text-white"><i class="bi bi-facebook"></i></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
|
<script src="assets/js/main.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
46
includes/header.php
Normal file
46
includes/header.php
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
<?php session_start(); ?>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>TripEase</title>
|
||||||
|
<meta name="description" content="TripEase ignites wanderlust with curated travel inspiration and immersive experiences for your next adventure.">
|
||||||
|
<meta name="keywords" content="travel, trip planner, vacation, itinerary, travel community, travel blog, wanderlust, adventure travel, budget travel, luxury travel, travel deals, destination guide">
|
||||||
|
<meta property="og:title" content="TripEase">
|
||||||
|
<meta property="og:description" content="TripEase ignites wanderlust with curated travel inspiration and immersive experiences for your next adventure.">
|
||||||
|
<meta property="og:image" content="https://project-screens.s3.amazonaws.com/screenshots/34692/app-hero-20251005-150709.png">
|
||||||
|
<meta name="twitter:card" content="summary_large_image">
|
||||||
|
<meta name="twitter:image" content="https://project-screens.s3.amazonaws.com/screenshots/34692/app-hero-20251005-150709.png">
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.5/font/bootstrap-icons.css">
|
||||||
|
<link rel="stylesheet" href="assets/css/custom.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<!-- Header -->
|
||||||
|
<nav class="navbar navbar-expand-lg navbar-light fixed-top">
|
||||||
|
<div class="container">
|
||||||
|
<a class="navbar-brand fw-bold" href="/">TripEase</a>
|
||||||
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
|
||||||
|
<span class="navbar-toggler-icon"></span>
|
||||||
|
</button>
|
||||||
|
<div class="collapse navbar-collapse" id="navbarNav">
|
||||||
|
<ul class="navbar-nav ms-auto">
|
||||||
|
<li class="nav-item"><a class="nav-link" href="/">Home</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="/#about">About</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="/#portfolio">Destination</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="/#testimonials">Testimonials</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="/community.php">Community</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="/#contact">Contact</a></li>
|
||||||
|
</ul>
|
||||||
|
<?php if (isset($_SESSION['user_id'])): ?>
|
||||||
|
<a href="/dashboard.php" class="btn btn-secondary ms-lg-3">Dashboard</a>
|
||||||
|
<a href="/logout.php" class="btn btn-primary ms-lg-3">Logout</a>
|
||||||
|
<?php else: ?>
|
||||||
|
<a href="/login.php" class="btn btn-secondary ms-lg-3">Login</a>
|
||||||
|
<a href="/signup.php" class="btn btn-primary ms-lg-3">Sign Up</a>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
40
includes/pexels.php
Normal file
40
includes/pexels.php
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
function pexels_key() {
|
||||||
|
$k = getenv('PEXELS_KEY');
|
||||||
|
return $k && strlen($k) > 0 ? $k : 'Vc99rnmOhHhJAbgGQoKLZtsaIVfkeownoQNbTj78VemUjKh08ZYRbf18';
|
||||||
|
}
|
||||||
|
|
||||||
|
function pexels_get($url) {
|
||||||
|
$ch = curl_init();
|
||||||
|
curl_setopt_array($ch, [
|
||||||
|
CURLOPT_URL => $url,
|
||||||
|
CURLOPT_RETURNTRANSFER => true,
|
||||||
|
CURLOPT_HTTPHEADER => [ 'Authorization: '. pexels_key() ],
|
||||||
|
CURLOPT_TIMEOUT => 20,
|
||||||
|
CURLOPT_USERAGENT => 'Flatlogic/Gemini-CLI'
|
||||||
|
]);
|
||||||
|
$resp = curl_exec($ch);
|
||||||
|
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||||
|
curl_close($ch);
|
||||||
|
if ($code >= 200 && $code < 300 && $resp) return json_decode($resp, true);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function download_to($srcUrl, $destPath) {
|
||||||
|
if (!is_dir(dirname($destPath))) {
|
||||||
|
mkdir(dirname($destPath), 0775, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
$ch = curl_init($srcUrl);
|
||||||
|
$fp = fopen($destPath, 'wb');
|
||||||
|
curl_setopt($ch, CURLOPT_FILE, $fp);
|
||||||
|
curl_setopt($ch, CURLOPT_HEADER, 0);
|
||||||
|
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
|
||||||
|
curl_setopt($ch, CURLOPT_TIMEOUT, 60);
|
||||||
|
$result = curl_exec($ch);
|
||||||
|
curl_close($ch);
|
||||||
|
fclose($fp);
|
||||||
|
|
||||||
|
return $result !== false;
|
||||||
|
}
|
||||||
295
index.php
295
index.php
@ -1,150 +1,151 @@
|
|||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
require_once __DIR__ . '/includes/pexels.php';
|
||||||
@ini_set('display_errors', '1');
|
|
||||||
@error_reporting(E_ALL);
|
|
||||||
@date_default_timezone_set('UTC');
|
|
||||||
|
|
||||||
$phpVersion = PHP_VERSION;
|
$destination_query = 'Auli India';
|
||||||
$now = date('Y-m-d H:i:s');
|
$destination_image = [
|
||||||
|
'local_url' => 'https://via.placeholder.com/1200x800.png?text=Auli,+India', // Fallback
|
||||||
|
'alt' => 'A beautiful landscape of Auli, India',
|
||||||
|
'photographer' => 'N/A',
|
||||||
|
'photographer_url' => '#',
|
||||||
|
];
|
||||||
|
|
||||||
|
// Path for the cached JSON data
|
||||||
|
$cache_file = __DIR__ . '/assets/cache/pexels_auli.json';
|
||||||
|
$cache_ttl = 86400; // Cache for 24 hours
|
||||||
|
|
||||||
|
$image_data = null;
|
||||||
|
|
||||||
|
if (file_exists($cache_file) && (time() - filemtime($cache_file)) < $cache_ttl) {
|
||||||
|
$image_data = json_decode(file_get_contents($cache_file), true);
|
||||||
|
} else {
|
||||||
|
$url = 'https://api.pexels.com/v1/search?query=' . urlencode($destination_query) . '&orientation=landscape&per_page=1&page=1';
|
||||||
|
$api_data = pexels_get($url);
|
||||||
|
|
||||||
|
if ($api_data && !empty($api_data['photos'])) {
|
||||||
|
$photo = $api_data['photos'][0];
|
||||||
|
$src = $photo['src']['large2x'] ?? $photo['src']['large'] ?? $photo['src']['original'];
|
||||||
|
$filename = 'pexels-' . $photo['id'] . '.jpg';
|
||||||
|
$targetDir = __DIR__ . '/assets/images/destinations/';
|
||||||
|
$targetPath = $targetDir . $filename;
|
||||||
|
$localUrl = 'assets/images/destinations/' . $filename;
|
||||||
|
|
||||||
|
if (!file_exists($targetPath)) {
|
||||||
|
download_to($src, $targetPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file_exists($targetPath)) {
|
||||||
|
$image_data = [
|
||||||
|
'local_url' => $localUrl,
|
||||||
|
'alt' => $photo['alt'] ?? 'Image of ' . $destination_query,
|
||||||
|
'photographer' => $photo['photographer'] ?? 'Unknown',
|
||||||
|
'photographer_url' => $photo['photographer_url'] ?? '#',
|
||||||
|
];
|
||||||
|
|
||||||
|
// Cache the data
|
||||||
|
if (!is_dir(dirname($cache_file))) mkdir(dirname($cache_file), 0775, true);
|
||||||
|
file_put_contents($cache_file, json_encode($image_data));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($image_data) {
|
||||||
|
$destination_image = $image_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
require_once __DIR__ . '/includes/header.php';
|
||||||
?>
|
?>
|
||||||
<!doctype html>
|
|
||||||
<html lang="en">
|
<!-- Hero Section -->
|
||||||
<head>
|
<header id="home" class="hero d-flex align-items-center text-center">
|
||||||
<meta charset="utf-8" />
|
<div class="container">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<h1 class="display-4">Plan. Share. Explore.</h1>
|
||||||
<title>New Style</title>
|
<p class="lead my-4">Your next adventure starts here. Discover, plan, and share your travels with a community of wanderers.</p>
|
||||||
<?php
|
<a href="#about" class="btn btn-primary btn-lg">Explore Trips</a>
|
||||||
// Read project preview data from environment
|
</div>
|
||||||
$projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? '';
|
</header>
|
||||||
$projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
|
|
||||||
?>
|
<!-- About Section -->
|
||||||
<?php if ($projectDescription): ?>
|
<section id="about" class="section">
|
||||||
<!-- Meta description -->
|
<div class="container">
|
||||||
<meta name="description" content='<?= htmlspecialchars($projectDescription) ?>' />
|
<div class="row align-items-center">
|
||||||
<!-- Open Graph meta tags -->
|
<div class="col-lg-6">
|
||||||
<meta property="og:description" content="<?= htmlspecialchars($projectDescription) ?>" />
|
<img src="https://picsum.photos/800/600" alt="A group of friends laughing and planning a trip together." class="img-fluid rounded-3">
|
||||||
<!-- Twitter meta tags -->
|
</div>
|
||||||
<meta property="twitter:description" content="<?= htmlspecialchars($projectDescription) ?>" />
|
<div class="col-lg-6">
|
||||||
<?php endif; ?>
|
<h2>About TripEase</h2>
|
||||||
<?php if ($projectImageUrl): ?>
|
<p>TripEase is more than just a travel app; it's a community-driven platform designed to inspire and empower travelers. From finding your next destination to planning every detail and sharing your experiences, we provide the tools you need to make every trip unforgettable.</p>
|
||||||
<!-- Open Graph image -->
|
</div>
|
||||||
<meta property="og:image" content="<?= htmlspecialchars($projectImageUrl) ?>" />
|
</div>
|
||||||
<!-- Twitter image -->
|
</div>
|
||||||
<meta property="twitter:image" content="<?= htmlspecialchars($projectImageUrl) ?>" />
|
</section>
|
||||||
<?php endif; ?>
|
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<!-- Portfolio Section -->
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
<section id="portfolio" class="section bg-light">
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap" rel="stylesheet">
|
<div class="container text-center">
|
||||||
<style>
|
<h2>Destination of the Month</h2>
|
||||||
:root {
|
<p class="lead mb-5">Discover Auli, India - a Himalayan ski resort and hill station.</p>
|
||||||
--bg-color-start: #6a11cb;
|
<div class="row">
|
||||||
--bg-color-end: #2575fc;
|
<div class="col-md-12">
|
||||||
--text-color: #ffffff;
|
<div class="card">
|
||||||
--card-bg-color: rgba(255, 255, 255, 0.01);
|
<img src="<?php echo htmlspecialchars($destination_image['local_url']); ?>" alt="<?php echo htmlspecialchars($destination_image['alt']); ?>" class="card-img-top">
|
||||||
--card-border-color: rgba(255, 255, 255, 0.1);
|
<div class="card-body">
|
||||||
}
|
<h5 class="card-title">Auli, India</h5>
|
||||||
body {
|
<p class="card-text">With its pristine slopes and stunning mountain views, Auli is a paradise for skiers and nature lovers alike. Photo by <a href="<?php echo htmlspecialchars($destination_image['photographer_url']); ?>"><?php echo htmlspecialchars($destination_image['photographer']); ?></a> on Pexels.</p>
|
||||||
margin: 0;
|
</div>
|
||||||
font-family: 'Inter', sans-serif;
|
</div>
|
||||||
background: linear-gradient(45deg, var(--bg-color-start), var(--bg-color-end));
|
</div>
|
||||||
color: var(--text-color);
|
</div>
|
||||||
display: flex;
|
</div>
|
||||||
justify-content: center;
|
</section>
|
||||||
align-items: center;
|
|
||||||
min-height: 100vh;
|
<!-- Testimonials Section -->
|
||||||
text-align: center;
|
<section id="testimonials" class="section">
|
||||||
overflow: hidden;
|
<div class="container">
|
||||||
position: relative;
|
<h2 class="text-center mb-5">What Our Travelers Say</h2>
|
||||||
}
|
<div class="row">
|
||||||
body::before {
|
<div class="col-md-4">
|
||||||
content: '';
|
<div class="card p-4 text-center">
|
||||||
position: absolute;
|
<p>"TripEase made planning our group trip a breeze. The collaborative features are a game-changer!"</p>
|
||||||
top: 0;
|
<footer class="blockquote-footer mt-3">Jane Doe</footer>
|
||||||
left: 0;
|
</div>
|
||||||
width: 100%;
|
</div>
|
||||||
height: 100%;
|
<div class="col-md-4">
|
||||||
background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100"><path d="M-10 10L110 10M10 -10L10 110" stroke-width="1" stroke="rgba(255,255,255,0.05)"/></svg>');
|
<div class="card p-4 text-center">
|
||||||
animation: bg-pan 20s linear infinite;
|
<p>"I love the travel style quiz! The recommendations were spot on and introduced me to places I wouldn't have found otherwise."</p>
|
||||||
z-index: -1;
|
<footer class="blockquote-footer mt-3">John Smith</footer>
|
||||||
}
|
</div>
|
||||||
@keyframes bg-pan {
|
</div>
|
||||||
0% { background-position: 0% 0%; }
|
<div class="col-md-4">
|
||||||
100% { background-position: 100% 100%; }
|
<div class="card p-4 text-center">
|
||||||
}
|
<p>"The community is so inspiring. I've discovered so many hidden gems through other travelers' stories."</p>
|
||||||
main {
|
<footer class="blockquote-footer mt-3">Emily White</footer>
|
||||||
padding: 2rem;
|
</div>
|
||||||
}
|
</div>
|
||||||
.card {
|
</div>
|
||||||
background: var(--card-bg-color);
|
</div>
|
||||||
border: 1px solid var(--card-border-color);
|
</section>
|
||||||
border-radius: 16px;
|
|
||||||
padding: 2rem;
|
<!-- Contact Section -->
|
||||||
backdrop-filter: blur(20px);
|
<section id="contact" class="section bg-light">
|
||||||
-webkit-backdrop-filter: blur(20px);
|
<div class="container">
|
||||||
box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.1);
|
<h2 class="text-center mb-5">Get in Touch</h2>
|
||||||
}
|
<div class="row justify-content-center">
|
||||||
.loader {
|
<div class="col-lg-6">
|
||||||
margin: 1.25rem auto 1.25rem;
|
<form class="contact-form">
|
||||||
width: 48px;
|
<div class="mb-3">
|
||||||
height: 48px;
|
<input type="text" class="form-control" id="name" placeholder="Your Name">
|
||||||
border: 3px solid rgba(255, 255, 255, 0.25);
|
</div>
|
||||||
border-top-color: #fff;
|
<div class="mb-3">
|
||||||
border-radius: 50%;
|
<input type="email" class="form-control" id="email" placeholder="Your Email">
|
||||||
animation: spin 1s linear infinite;
|
</div>
|
||||||
}
|
<div class="mb-3">
|
||||||
@keyframes spin {
|
<textarea class="form-control" id="message" rows="5" placeholder="Your Message"></textarea>
|
||||||
from { transform: rotate(0deg); }
|
</div>
|
||||||
to { transform: rotate(360deg); }
|
<button type="submit" class="btn btn-primary w-100">Send Message</button>
|
||||||
}
|
</form>
|
||||||
.hint {
|
</div>
|
||||||
opacity: 0.9;
|
</div>
|
||||||
}
|
</div>
|
||||||
.sr-only {
|
</section>
|
||||||
position: absolute;
|
|
||||||
width: 1px; height: 1px;
|
<?php require_once __DIR__ . '/includes/footer.php'; ?>
|
||||||
padding: 0; margin: -1px;
|
|
||||||
overflow: hidden;
|
|
||||||
clip: rect(0, 0, 0, 0);
|
|
||||||
white-space: nowrap; border: 0;
|
|
||||||
}
|
|
||||||
h1 {
|
|
||||||
font-size: 3rem;
|
|
||||||
font-weight: 700;
|
|
||||||
margin: 0 0 1rem;
|
|
||||||
letter-spacing: -1px;
|
|
||||||
}
|
|
||||||
p {
|
|
||||||
margin: 0.5rem 0;
|
|
||||||
font-size: 1.1rem;
|
|
||||||
}
|
|
||||||
code {
|
|
||||||
background: rgba(0,0,0,0.2);
|
|
||||||
padding: 2px 6px;
|
|
||||||
border-radius: 4px;
|
|
||||||
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
||||||
}
|
|
||||||
footer {
|
|
||||||
position: absolute;
|
|
||||||
bottom: 1rem;
|
|
||||||
font-size: 0.8rem;
|
|
||||||
opacity: 0.7;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<main>
|
|
||||||
<div class="card">
|
|
||||||
<h1>Analyzing your requirements and generating your website…</h1>
|
|
||||||
<div class="loader" role="status" aria-live="polite" aria-label="Applying initial changes">
|
|
||||||
<span class="sr-only">Loading…</span>
|
|
||||||
</div>
|
|
||||||
<p class="hint"><?= ($_SERVER['HTTP_HOST'] ?? '') === 'appwizzy.com' ? 'AppWizzy' : 'Flatlogic' ?> AI is collecting your requirements and applying the first changes.</p>
|
|
||||||
<p class="hint">This page will update automatically as the plan is implemented.</p>
|
|
||||||
<p>Runtime: PHP <code><?= htmlspecialchars($phpVersion) ?></code> — UTC <code><?= htmlspecialchars($now) ?></code></p>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
<footer>
|
|
||||||
Page updated: <?= htmlspecialchars($now) ?> (UTC)
|
|
||||||
</footer>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|||||||
78
login.php
Normal file
78
login.php
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
<?php
|
||||||
|
require_once __DIR__ . '/includes/header.php';
|
||||||
|
require_once __DIR__ . '/db/config.php';
|
||||||
|
|
||||||
|
$errors = [];
|
||||||
|
$email = '';
|
||||||
|
|
||||||
|
if (isset($_GET['registered'])) {
|
||||||
|
echo '<div class="alert alert-success">Registration successful! Please log in.</div>';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($_SERVER["REQUEST_METHOD"] == "POST") {
|
||||||
|
$email = trim($_POST['email']);
|
||||||
|
$password = $_POST['password'];
|
||||||
|
|
||||||
|
if (empty($email) || !filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||||||
|
$errors[] = 'A valid email is required';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($password)) {
|
||||||
|
$errors[] = 'Password is required';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($errors)) {
|
||||||
|
try {
|
||||||
|
$pdo = db();
|
||||||
|
$stmt = $pdo->prepare("SELECT * FROM users WHERE email = ?");
|
||||||
|
$stmt->execute([$email]);
|
||||||
|
$user = $stmt->fetch();
|
||||||
|
|
||||||
|
if ($user && password_verify($password, $user['password'])) {
|
||||||
|
$_SESSION['user_id'] = $user['id'];
|
||||||
|
$_SESSION['username'] = $user['username'];
|
||||||
|
header("Location: dashboard.php");
|
||||||
|
exit;
|
||||||
|
} else {
|
||||||
|
$errors[] = 'Invalid email or password';
|
||||||
|
}
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
$errors[] = "Database error: " . $e->getMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
|
||||||
|
<div class="container" style="margin-top: 100px;">
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<h2 class="card-title text-center">Login</h2>
|
||||||
|
|
||||||
|
<?php if (!empty($errors)): ?>
|
||||||
|
<div class="alert alert-danger">
|
||||||
|
<?php foreach ($errors as $error): ?>
|
||||||
|
<p><?php echo $error; ?></p>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<form action="login.php" method="POST">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="email" class="form-label">Email address</label>
|
||||||
|
<input type="email" class="form-control" id="email" name="email" value="<?php echo htmlspecialchars($email); ?>" required>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="password" class="form-label">Password</label>
|
||||||
|
<input type="password" class="form-control" id="password" name="password" required>
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-primary w-100">Login</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php require_once __DIR__ . '/includes/footer.php'; ?>
|
||||||
6
logout.php
Normal file
6
logout.php
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?php
|
||||||
|
session_start();
|
||||||
|
session_unset();
|
||||||
|
session_destroy();
|
||||||
|
header('Location: /index.php');
|
||||||
|
exit;
|
||||||
2
my_trips.php
Normal file
2
my_trips.php
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
<h2>My Trips</h2>
|
||||||
|
<p>Here you can see and manage your planned trips.</p>
|
||||||
2
plan_trip.php
Normal file
2
plan_trip.php
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
<h2>Plan a New Trip</h2>
|
||||||
|
<p>Use this form to plan a new trip.</p>
|
||||||
16
privacy.php
Normal file
16
privacy.php
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Privacy Policy - TripEase</title>
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container py-5">
|
||||||
|
<h1>Privacy Policy</h1>
|
||||||
|
<p>This is a placeholder for the privacy policy.</p>
|
||||||
|
<a href="/" class="btn btn-primary">Back to Home</a>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
2
profile.php
Normal file
2
profile.php
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
<h2>My Profile</h2>
|
||||||
|
<p>Here you can view and edit your profile information.</p>
|
||||||
99
signup.php
Normal file
99
signup.php
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
<?php
|
||||||
|
require_once __DIR__ . '/includes/header.php';
|
||||||
|
require_once __DIR__ . '/db/config.php';
|
||||||
|
|
||||||
|
$errors = [];
|
||||||
|
$username = '';
|
||||||
|
$email = '';
|
||||||
|
|
||||||
|
if ($_SERVER["REQUEST_METHOD"] == "POST") {
|
||||||
|
$username = trim($_POST['username']);
|
||||||
|
$email = trim($_POST['email']);
|
||||||
|
$password = $_POST['password'];
|
||||||
|
$password_confirm = $_POST['password_confirm'];
|
||||||
|
|
||||||
|
if (empty($username)) {
|
||||||
|
$errors[] = 'Username is required';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($email) || !filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||||||
|
$errors[] = 'A valid email is required';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($password)) {
|
||||||
|
$errors[] = 'Password is required';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($password !== $password_confirm) {
|
||||||
|
$errors[] = 'Passwords do not match';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($errors)) {
|
||||||
|
try {
|
||||||
|
$pdo = db();
|
||||||
|
|
||||||
|
// Check if email already exists
|
||||||
|
$stmt = $pdo->prepare("SELECT id FROM users WHERE email = ?");
|
||||||
|
$stmt->execute([$email]);
|
||||||
|
if ($stmt->fetch()) {
|
||||||
|
$errors[] = 'Email address is already registered.';
|
||||||
|
} else {
|
||||||
|
// Hash password
|
||||||
|
$hashed_password = password_hash($password, PASSWORD_DEFAULT);
|
||||||
|
|
||||||
|
// Insert user into database
|
||||||
|
$stmt = $pdo->prepare("INSERT INTO users (username, email, password) VALUES (?, ?, ?)");
|
||||||
|
$stmt->execute([$username, $email, $hashed_password]);
|
||||||
|
|
||||||
|
// Redirect to login page
|
||||||
|
header("Location: login.php?registered=true");
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
$errors[] = "Database error: " . $e->getMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
|
||||||
|
<div class="container" style="margin-top: 100px;">
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<h2 class="card-title text-center">Sign Up</h2>
|
||||||
|
|
||||||
|
<?php if (!empty($errors)): ?>
|
||||||
|
<div class="alert alert-danger">
|
||||||
|
<?php foreach ($errors as $error): ?>
|
||||||
|
<p><?php echo $error; ?></p>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<form action="signup.php" method="POST">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="username" class="form-label">Username</label>
|
||||||
|
<input type="text" class="form-control" id="username" name="username" value="<?php echo htmlspecialchars($username); ?>" required>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="email" class="form-label">Email address</label>
|
||||||
|
<input type="email" class="form-control" id="email" name="email" value="<?php echo htmlspecialchars($email); ?>" required>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="password" class="form-label">Password</label>
|
||||||
|
<input type="password" class="form-control" id="password" name="password" required>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="password_confirm" class="form-label">Confirm Password</label>
|
||||||
|
<input type="password" class="form-control" id="password_confirm" name="password_confirm" required>
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-primary w-100">Sign Up</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php require_once __DIR__ . '/includes/footer.php'; ?>
|
||||||
Loading…
x
Reference in New Issue
Block a user